diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py index 047f46a40f..e62ab5e5dc 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py @@ -7,8 +7,10 @@ SPDX-License-Identifier: Apache-2.0 OR MIT Tests that require a GPU in order to run. """ +import datetime import logging import os +import zipfile import pytest @@ -40,6 +42,33 @@ def golden_images_directory(): return golden_images_dir +def create_screenshots_archive(screenshot_path): + """ + Creates a new zip file archive at archive_path containing all files listed within archive_path. + :param screenshot_path: location containing the files to archive, the zip archive file will also be saved here. + :return: None, but creates a new zip file archive inside path containing all of the files inside archive_path. + """ + files_to_archive = [] + + # Search for .png and .ppm files to add to the zip archive file. + for (folder_name, sub_folders, file_names) in os.walk(screenshot_path): + for file_name in file_names: + if file_name.endswith(".png") or file_name.endswith(".ppm"): + file_path = os.path.join(folder_name, file_name) + files_to_archive.append(file_path) + + # Setup variables for naming the zip archive file. + timestamp = datetime.datetime.now().timestamp() + formatted_timestamp = datetime.datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d_%H-%M-%S") + screenshots_file = os.path.join(screenshot_path, f'zip_archive_{formatted_timestamp}.zip') + + # Write all of the valid .png and .ppm files to the archive file. + with zipfile.ZipFile(screenshots_file, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zip_archive: + for file_path in files_to_archive: + file_name = os.path.basename(file_path) + zip_archive.write(file_path, file_name) + + @pytest.mark.parametrize("project", ["AutomatedTesting"]) @pytest.mark.parametrize("launcher_platform", ["windows_editor"]) @pytest.mark.parametrize("level", ["auto_test"]) @@ -53,8 +82,8 @@ class TestAllComponentsIndepthTests(object): Tests that a basic rendering level setup can be created (lighting, meshes, materials, etc.). """ # Clear existing test screenshots before starting test. - test_screenshots = [os.path.join( - workspace.paths.project(), DEFAULT_SUBFOLDER_PATH, screenshot_name)] + screenshot_directory = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH) + test_screenshots = [os.path.join(screenshot_directory, screenshot_name)] file_system.delete(test_screenshots, True, True) golden_images = [os.path.join(golden_images_directory(), screenshot_name)] @@ -86,6 +115,8 @@ class TestAllComponentsIndepthTests(object): for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images): compare_screenshots(test_screenshot, golden_screenshot) + create_screenshots_archive(screenshot_directory) + def test_LightComponent_ScreenshotMatchesGoldenImage( self, request, editor, workspace, project, launcher_platform, level): """ @@ -105,9 +136,10 @@ class TestAllComponentsIndepthTests(object): "SpotLight_5.ppm", "SpotLight_6.ppm", ] + screenshot_directory = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH) test_screenshots = [] for screenshot in screenshot_names: - screenshot_path = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH, screenshot) + screenshot_path = os.path.join(screenshot_directory, screenshot) test_screenshots.append(screenshot_path) file_system.delete(test_screenshots, True, True) @@ -139,6 +171,8 @@ class TestAllComponentsIndepthTests(object): for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images): compare_screenshots(test_screenshot, golden_screenshot) + create_screenshots_archive(screenshot_directory) + @pytest.mark.parametrize('rhi', ['dx12', 'vulkan']) @pytest.mark.parametrize("project", ["AutomatedTesting"]) diff --git a/AutomatedTesting/Levels/Physics/ScriptCanvas_CollisionEvents/ScriptCanvas_CollisionEvents.ly b/AutomatedTesting/Levels/Physics/ScriptCanvas_CollisionEvents/ScriptCanvas_CollisionEvents.ly index 6c70bbf067..8fcf2dcde2 100644 --- a/AutomatedTesting/Levels/Physics/ScriptCanvas_CollisionEvents/ScriptCanvas_CollisionEvents.ly +++ b/AutomatedTesting/Levels/Physics/ScriptCanvas_CollisionEvents/ScriptCanvas_CollisionEvents.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1b6f5e409a8358ad95b310473046ce1a2f2aa5f7e05d0c3396044aa52aa7f6d -size 9103 +oid sha256:d674eac2070ed0028ceff1e84692c9cf1f69db2192c2295b6d714670ccd50308 +size 8936 diff --git a/AutomatedTesting/Levels/Physics/ScriptCanvas_CollisionEvents/collision_events_script.scriptcanvas b/AutomatedTesting/Levels/Physics/ScriptCanvas_CollisionEvents/collision_events_script.scriptcanvas index a565c64b60..ce545a30b5 100644 --- a/AutomatedTesting/Levels/Physics/ScriptCanvas_CollisionEvents/collision_events_script.scriptcanvas +++ b/AutomatedTesting/Levels/Physics/ScriptCanvas_CollisionEvents/collision_events_script.scriptcanvas @@ -5,7 +5,7 @@ "ClassData": { "m_scriptCanvas": { "Id": { - "id": 70086661081986 + "id": 18841028265353 }, "Name": "collision_events_script", "Components": { @@ -16,7 +16,222 @@ "m_nodes": [ { "Id": { - "id": 70125315787650 + "id": 18896862840201 + }, + "Name": "SC-EventNode(On Collision Persist event)", + "Components": { + "Component_[11051578760533229880]": { + "$type": "AzEventHandler", + "Id": 11051578760533229880, + "Slots": [ + { + "id": { + "m_id": "{D60E85B8-F645-47F8-92BE-0A0251269168}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "ConnectionLimitContract", + "limit": 1 + }, + { + "$type": "RestrictedNodeContract", + "m_nodeId": { + "id": 18866798069129 + } + } + ], + "slotName": "Connect", + "toolTip": "Connect the AZ Event to this AZ Event Handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{BFE76B23-D14A-4C0A-83B9-6BC9BB87E542}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Disconnect", + "toolTip": "Disconnect current AZ Event from this AZ Event Handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{D9A1AFC3-AEF9-4550-877D-D5C8BC460AB9}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "On Connected", + "toolTip": "Signaled when a connection has taken place.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{FB927B57-AC8B-4EE4-96F5-9F5712FFEF53}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "On Disconnected", + "toolTip": "Signaled when this event handler is disconnected.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{6B89E130-60D1-42A4-9C9C-679E84DD6389}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnEvent", + "toolTip": "Triggered when the AZ Event invokes Signal() function.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{2D6BF58F-C430-4795-9470-D1C44EA23B9D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Simulated Body Handle", + "DisplayDataType": { + "m_type": 4, + "m_azType": "{53C0CD3E-D0FC-5D90-9E9B-EF364D430B08}" + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{5DE43B16-4121-4CFF-8BA0-56099371A836}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Collision Event", + "DisplayDataType": { + "m_type": 4, + "m_azType": "{7602AA36-792C-4BDC-BDF8-AA16792151A3}" + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{1C7070F8-D281-414C-BF9B-D6B6B5F12926}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "ConnectionLimitContract", + "limit": 1 + }, + { + "$type": "RestrictedNodeContract", + "m_nodeId": { + "id": 18866798069129 + } + } + ], + "slotName": "On Collision Persist event", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 4, + "m_azType": "{4C19E257-F929-524E-80E3-C910C5F3E2D9}" + }, + "isNullPointer": true, + "label": "On Collision Persist event" + } + ], + "m_azEventEntry": { + "m_eventName": "On Collision Persist event", + "m_parameterSlotIds": [ + { + "m_id": "{2D6BF58F-C430-4795-9470-D1C44EA23B9D}" + }, + { + "m_id": "{5DE43B16-4121-4CFF-8BA0-56099371A836}" + }, + { + "m_id": "{2D6BF58F-C430-4795-9470-D1C44EA23B9D}" + }, + { + "m_id": "{5DE43B16-4121-4CFF-8BA0-56099371A836}" + } + ], + "m_parameterNames": [ + { + "m_id": "{2D6BF58F-C430-4795-9470-D1C44EA23B9D}" + }, + { + "m_id": "{5DE43B16-4121-4CFF-8BA0-56099371A836}" + }, + { + "m_id": "{2D6BF58F-C430-4795-9470-D1C44EA23B9D}" + }, + { + "m_id": "{5DE43B16-4121-4CFF-8BA0-56099371A836}" + } + ], + "m_eventSlotId": { + "m_id": "{1C7070F8-D281-414C-BF9B-D6B6B5F12926}" + } + } + } + } + }, + { + "Id": { + "id": 18939812513161 }, "Name": "SC-Node(Print)", "Components": { @@ -65,7 +280,7 @@ }, { "Id": { - "id": 70095251016578 + "id": 18849618199945 }, "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{bool(const EntityId& )}* IsActiveTraits >)", "Components": { @@ -159,7 +374,7 @@ }, { "Id": { - "id": 70163970493314 + "id": 18871093036425 }, "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{bool(const EntityId& )}* IsActiveTraits >)", "Components": { @@ -253,7 +468,7 @@ }, { "Id": { - "id": 70172560427906 + "id": 18931222578569 }, "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{bool(const EntityId& )}* IsActiveTraits >)", "Components": { @@ -347,7 +562,7 @@ }, { "Id": { - "id": 70121020820354 + "id": 18909747742089 }, "Name": "SC Node(GetVariable)", "Components": { @@ -418,216 +633,7 @@ }, { "Id": { - "id": 70112430885762 - }, - "Name": "SC-EventNode(On Collision Begin event)", - "Components": { - "Component_[14000580813563007620]": { - "$type": "AzEventHandler", - "Id": 14000580813563007620, - "Slots": [ - { - "id": { - "m_id": "{74B54CB0-A72C-4A6A-ABB3-9EA6529DDF78}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - }, - { - "$type": "ConnectionLimitContract", - "limit": 1 - }, - { - "$type": "RestrictedNodeContract", - "m_nodeId": { - "id": 70142495656834 - } - } - ], - "slotName": "Connect", - "toolTip": "Connect the AZ Event to this AZ Event Handler.", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{8DDBE14E-02C2-49A2-ABB1-47EC97B5D970}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "Disconnect", - "toolTip": "Disconnect current AZ Event from this AZ Event Handler.", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{0EE06A10-EB10-4C5D-AB8F-D7B8B7A921E0}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "On Connected", - "toolTip": "Signaled when a connection has taken place.", - "Descriptor": { - "ConnectionType": 2, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{8B0C1988-7783-42F5-A3C5-42184B5DC7FE}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "On Disconnected", - "toolTip": "Signaled when this event handler is disconnected.", - "Descriptor": { - "ConnectionType": 2, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{E32049C5-FF99-4E74-91EC-D007B0D6EF7B}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "OnEvent", - "toolTip": "Triggered when the AZ Event invokes Signal() function.", - "Descriptor": { - "ConnectionType": 2, - "SlotType": 1 - }, - "IsLatent": true - }, - { - "id": { - "m_id": "{B3D58CDB-A773-47CE-B06D-BA3CF619A8E3}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "Simulated Body Handle", - "DisplayDataType": { - "m_type": 4, - "m_azType": "{53C0CD3E-D0FC-5D90-9E9B-EF364D430B08}" - }, - "Descriptor": { - "ConnectionType": 2, - "SlotType": 2 - }, - "DataType": 1 - }, - { - "id": { - "m_id": "{51A6844B-AD3E-48C3-8770-20E425CA125A}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "Collision Event", - "DisplayDataType": { - "m_type": 4, - "m_azType": "{7602AA36-792C-4BDC-BDF8-AA16792151A3}" - }, - "Descriptor": { - "ConnectionType": 2, - "SlotType": 2 - }, - "DataType": 1 - }, - { - "id": { - "m_id": "{F7A6B1A7-EB72-45DE-8A87-7C6E36FCA2A3}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - }, - null, - { - "$type": "ConnectionLimitContract", - "limit": 1 - }, - { - "$type": "RestrictedNodeContract", - "m_nodeId": { - "id": 70142495656834 - } - } - ], - "slotName": "On Collision Begin event", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 2 - }, - "DataType": 1 - } - ], - "Datums": [ - {} - ], - "m_azEventEntry": { - "m_eventName": "On Collision Begin event", - "m_parameterSlotIds": [ - { - "m_id": "{B3D58CDB-A773-47CE-B06D-BA3CF619A8E3}" - }, - { - "m_id": "{51A6844B-AD3E-48C3-8770-20E425CA125A}" - }, - { - "m_id": "{B3D58CDB-A773-47CE-B06D-BA3CF619A8E3}" - }, - { - "m_id": "{51A6844B-AD3E-48C3-8770-20E425CA125A}" - } - ], - "m_parameterNames": [ - { - "m_id": "{B3D58CDB-A773-47CE-B06D-BA3CF619A8E3}" - }, - { - "m_id": "{51A6844B-AD3E-48C3-8770-20E425CA125A}" - }, - { - "m_id": "{B3D58CDB-A773-47CE-B06D-BA3CF619A8E3}" - }, - { - "m_id": "{51A6844B-AD3E-48C3-8770-20E425CA125A}" - } - ], - "m_eventSlotId": { - "m_id": "{F7A6B1A7-EB72-45DE-8A87-7C6E36FCA2A3}" - } - } - } - } - }, - { - "Id": { - "id": 70099545983874 + "id": 18901157807497 }, "Name": "SC Node(GetVariable)", "Components": { @@ -698,108 +704,7 @@ }, { "Id": { - "id": 70142495656834 - }, - "Name": "SC-Node(GetOnCollisionBeginEvent)", - "Components": { - "Component_[14536104846481825629]": { - "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", - "Id": 14536104846481825629, - "Slots": [ - { - "id": { - "m_id": "{C1CC691F-49A7-4348-89AD-F11BFBE3AFAE}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - }, - null - ], - "slotName": "EntityID: 0", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 2 - }, - "DataType": 1 - }, - { - "id": { - "m_id": "{88B3237D-3297-4837-A80A-19ECAB4B4D61}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "In", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{5AD134C7-A8BC-4BE7-B815-68901BBEBE0D}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "Out", - "Descriptor": { - "ConnectionType": 2, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{FCF4B185-2AD4-42BD-A304-B36B437CEA61}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "Result: Event const CollisionEvent& >", - "DisplayDataType": { - "m_type": 4, - "m_azType": "{4C19E257-F929-524E-80E3-C910C5F3E2D9}" - }, - "Descriptor": { - "ConnectionType": 2, - "SlotType": 2 - }, - "DataType": 1 - } - ], - "Datums": [ - { - "scriptCanvasType": { - "m_type": 1 - }, - "isNullPointer": false, - "$type": "EntityId", - "value": { - "id": 2901262558 - }, - "label": "EntityID: 0" - } - ], - "methodType": 2, - "methodName": "GetOnCollisionBeginEvent", - "className": "SimulatedBody", - "resultSlotIDs": [ - {} - ], - "prettyClassName": "SimulatedBody" - } - } - }, - { - "Id": { - "id": 70159675526018 + "id": 18853913167241 }, "Name": "EBusEventHandler", "Components": { @@ -1040,108 +945,7 @@ }, { "Id": { - "id": 70168265460610 - }, - "Name": "SC-Node(GetOnCollisionPersistEvent)", - "Components": { - "Component_[2456924078822417742]": { - "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", - "Id": 2456924078822417742, - "Slots": [ - { - "id": { - "m_id": "{76C563E8-85C7-4E2F-A09A-9D982064F966}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - }, - null - ], - "slotName": "EntityID: 0", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 2 - }, - "DataType": 1 - }, - { - "id": { - "m_id": "{7AE56C6B-CF55-4FC7-AA96-E5845B406017}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "In", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{8A08ADFB-F581-40F8-B900-A5A968A11F6D}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "Out", - "Descriptor": { - "ConnectionType": 2, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{79F0D577-9326-4334-A996-74E400870874}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "Result: Event const CollisionEvent& >", - "DisplayDataType": { - "m_type": 4, - "m_azType": "{4C19E257-F929-524E-80E3-C910C5F3E2D9}" - }, - "Descriptor": { - "ConnectionType": 2, - "SlotType": 2 - }, - "DataType": 1 - } - ], - "Datums": [ - { - "scriptCanvasType": { - "m_type": 1 - }, - "isNullPointer": false, - "$type": "EntityId", - "value": { - "id": 2901262558 - }, - "label": "EntityID: 0" - } - ], - "methodType": 2, - "methodName": "GetOnCollisionPersistEvent", - "className": "SimulatedBody", - "resultSlotIDs": [ - {} - ], - "prettyClassName": "SimulatedBody" - } - } - }, - { - "Id": { - "id": 70090956049282 + "id": 18875388003721 }, "Name": "SC-Node(ActivateGameEntity)", "Components": { @@ -1222,7 +1026,7 @@ }, { "Id": { - "id": 70129610754946 + "id": 18888272905609 }, "Name": "SC-Node(ActivateGameEntity)", "Components": { @@ -1303,7 +1107,7 @@ }, { "Id": { - "id": 70176855395202 + "id": 18914042709385 }, "Name": "SC-Node(ActivateGameEntity)", "Components": { @@ -1384,23 +1188,22 @@ }, { "Id": { - "id": 70133905722242 + "id": 18944107480457 }, "Name": "SC-Node(GetOnCollisionEndEvent)", "Components": { - "Component_[6024679188177357420]": { + "Component_[4035501780545896984]": { "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", - "Id": 6024679188177357420, + "Id": 4035501780545896984, "Slots": [ { "id": { - "m_id": "{4C021C78-C51F-40AD-8D0C-E912A7216BEC}" + "m_id": "{76E6B371-B7EF-43E6-BDBE-8BEB7A6CB444}" }, "contracts": [ { "$type": "SlotTypeContract" - }, - null + } ], "slotName": "EntityID: 0", "Descriptor": { @@ -1411,7 +1214,7 @@ }, { "id": { - "m_id": "{F0E14922-5337-4F26-91ED-E23E557B8723}" + "m_id": "{3933A5FE-5430-41E9-AE89-39DBF93EE427}" }, "contracts": [ { @@ -1426,7 +1229,7 @@ }, { "id": { - "m_id": "{84128820-5F2E-497F-9B13-A262484DE323}" + "m_id": "{1F68015F-AB0F-4A63-8FF3-E4EB3EE000C9}" }, "contracts": [ { @@ -1441,7 +1244,7 @@ }, { "id": { - "m_id": "{B825CA1B-36A9-4634-8D66-0C510EC4D4E8}" + "m_id": "{CBF241C4-DB7C-4DCA-AD01-AA806F28AA1A}" }, "contracts": [ { @@ -1479,23 +1282,238 @@ "resultSlotIDs": [ {} ], + "inputSlots": [ + { + "m_id": "{76E6B371-B7EF-43E6-BDBE-8BEB7A6CB444}" + } + ], "prettyClassName": "SimulatedBody" } } }, { "Id": { - "id": 70181150362498 + "id": 18866798069129 }, - "Name": "SC-EventNode(On Collision Persist event)", + "Name": "SC-Node(GetOnCollisionPersistEvent)", "Components": { - "Component_[6434307319231468785]": { - "$type": "AzEventHandler", - "Id": 6434307319231468785, + "Component_[4924826946960882301]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 4924826946960882301, "Slots": [ { "id": { - "m_id": "{EB9CE3A4-B8A4-4436-9E3C-026580D17AC3}" + "m_id": "{DA0047B5-620F-49A9-9322-DDCE6DFF5B69}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{3EE67098-3620-40AE-9463-4812E39075B9}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{FF7196F6-D599-44FC-8481-9DBE522529DF}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{79056EFB-B34F-4702-B206-C9400F3408D6}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Event const CollisionEvent& >", + "DisplayDataType": { + "m_type": 4, + "m_azType": "{4C19E257-F929-524E-80E3-C910C5F3E2D9}" + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "EntityID: 0" + } + ], + "methodType": 2, + "methodName": "GetOnCollisionPersistEvent", + "className": "SimulatedBody", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{DA0047B5-620F-49A9-9322-DDCE6DFF5B69}" + } + ], + "prettyClassName": "SimulatedBody" + } + } + }, + { + "Id": { + "id": 18845323232649 + }, + "Name": "SC-Node(GetOnCollisionBeginEvent)", + "Components": { + "Component_[6029479490625241424]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 6029479490625241424, + "Slots": [ + { + "id": { + "m_id": "{6B8EFFB6-8208-4BCB-BA1B-221A215AC0E0}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{ADA8C93D-8987-4537-99CD-A96986C8BF74}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{4C7050D8-46F3-4E72-865E-8F2897430750}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{B647ABD6-B8B1-45CB-ACF4-495E416BB744}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Event const CollisionEvent& >", + "DisplayDataType": { + "m_type": 4, + "m_azType": "{4C19E257-F929-524E-80E3-C910C5F3E2D9}" + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "EntityID: 0" + } + ], + "methodType": 2, + "methodName": "GetOnCollisionBeginEvent", + "className": "SimulatedBody", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{6B8EFFB6-8208-4BCB-BA1B-221A215AC0E0}" + } + ], + "prettyClassName": "SimulatedBody" + } + } + }, + { + "Id": { + "id": 18905452774793 + }, + "Name": "SC-EventNode(On Collision Begin event)", + "Components": { + "Component_[7324959113754460428]": { + "$type": "AzEventHandler", + "Id": 7324959113754460428, + "Slots": [ + { + "id": { + "m_id": "{C3576303-C50B-4466-B3C1-A96F40F0B494}" }, "contracts": [ { @@ -1508,7 +1526,7 @@ { "$type": "RestrictedNodeContract", "m_nodeId": { - "id": 70168265460610 + "id": 18845323232649 } } ], @@ -1521,7 +1539,7 @@ }, { "id": { - "m_id": "{E5E8BE86-5B33-452C-BC59-FE4A6482048E}" + "m_id": "{CB06AA39-2756-413B-863E-07A228FAEC7B}" }, "contracts": [ { @@ -1537,7 +1555,7 @@ }, { "id": { - "m_id": "{FBAFC668-BD77-4ABB-8B93-E030D02DF348}" + "m_id": "{4A0BBEC7-22E2-4F4B-A8BF-251A69B33CC3}" }, "contracts": [ { @@ -1553,7 +1571,7 @@ }, { "id": { - "m_id": "{D37C1BFC-8EC1-4C8E-B6C3-FC036891A7ED}" + "m_id": "{2EFD7225-D076-46E0-A998-E1236986A2AD}" }, "contracts": [ { @@ -1569,7 +1587,7 @@ }, { "id": { - "m_id": "{1A994B40-F1C6-4F60-9F44-4CE42732554C}" + "m_id": "{FDC1C72B-2C39-43BA-87B4-2E88D1C2F82A}" }, "contracts": [ { @@ -1586,7 +1604,7 @@ }, { "id": { - "m_id": "{7C28872F-1A80-496F-9D34-467A80D7B4EF}" + "m_id": "{E604218A-3CEF-4B0D-9028-5CF64C814C0B}" }, "contracts": [ { @@ -1606,7 +1624,7 @@ }, { "id": { - "m_id": "{0A68E758-7230-4202-A54E-EC7BDA2BE643}" + "m_id": "{1B8B8A0A-6ABF-4660-932E-E2D62FBB238F}" }, "contracts": [ { @@ -1626,13 +1644,12 @@ }, { "id": { - "m_id": "{210423A5-D203-4C26-9B62-2B7DBA3320BD}" + "m_id": "{D4CACFC7-0F7B-4311-9125-D6624D302C50}" }, "contracts": [ { "$type": "SlotTypeContract" }, - null, { "$type": "ConnectionLimitContract", "limit": 1 @@ -1640,11 +1657,11 @@ { "$type": "RestrictedNodeContract", "m_nodeId": { - "id": 70168265460610 + "id": 18845323232649 } } ], - "slotName": "On Collision Persist event", + "slotName": "On Collision Begin event", "Descriptor": { "ConnectionType": 1, "SlotType": 2 @@ -1653,40 +1670,47 @@ } ], "Datums": [ - {} + { + "scriptCanvasType": { + "m_type": 4, + "m_azType": "{4C19E257-F929-524E-80E3-C910C5F3E2D9}" + }, + "isNullPointer": true, + "label": "On Collision Begin event" + } ], "m_azEventEntry": { - "m_eventName": "On Collision Persist event", + "m_eventName": "On Collision Begin event", "m_parameterSlotIds": [ { - "m_id": "{7C28872F-1A80-496F-9D34-467A80D7B4EF}" + "m_id": "{E604218A-3CEF-4B0D-9028-5CF64C814C0B}" }, { - "m_id": "{0A68E758-7230-4202-A54E-EC7BDA2BE643}" + "m_id": "{1B8B8A0A-6ABF-4660-932E-E2D62FBB238F}" }, { - "m_id": "{7C28872F-1A80-496F-9D34-467A80D7B4EF}" + "m_id": "{E604218A-3CEF-4B0D-9028-5CF64C814C0B}" }, { - "m_id": "{0A68E758-7230-4202-A54E-EC7BDA2BE643}" + "m_id": "{1B8B8A0A-6ABF-4660-932E-E2D62FBB238F}" } ], "m_parameterNames": [ { - "m_id": "{7C28872F-1A80-496F-9D34-467A80D7B4EF}" + "m_id": "{E604218A-3CEF-4B0D-9028-5CF64C814C0B}" }, { - "m_id": "{0A68E758-7230-4202-A54E-EC7BDA2BE643}" + "m_id": "{1B8B8A0A-6ABF-4660-932E-E2D62FBB238F}" }, { - "m_id": "{7C28872F-1A80-496F-9D34-467A80D7B4EF}" + "m_id": "{E604218A-3CEF-4B0D-9028-5CF64C814C0B}" }, { - "m_id": "{0A68E758-7230-4202-A54E-EC7BDA2BE643}" + "m_id": "{1B8B8A0A-6ABF-4660-932E-E2D62FBB238F}" } ], "m_eventSlotId": { - "m_id": "{210423A5-D203-4C26-9B62-2B7DBA3320BD}" + "m_id": "{D4CACFC7-0F7B-4311-9125-D6624D302C50}" } } } @@ -1694,260 +1718,17 @@ }, { "Id": { - "id": 70103840951170 - }, - "Name": "SC-Node(DeactivateGameEntity)", - "Components": { - "Component_[846968981672785962]": { - "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", - "Id": 846968981672785962, - "Slots": [ - { - "id": { - "m_id": "{993AA3E4-ABCF-40FF-9CCB-030F22627151}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - }, - null - ], - "slotName": "EntityID: 0", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 2 - }, - "DataType": 1 - }, - { - "id": { - "m_id": "{A015E6E8-A025-4A2D-B1D4-E7D8732FCE52}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "In", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{925E7BB1-22EB-46A2-98E2-9A9805A4D019}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "Out", - "Descriptor": { - "ConnectionType": 2, - "SlotType": 1 - } - } - ], - "Datums": [ - { - "scriptCanvasType": { - "m_type": 1 - }, - "isNullPointer": false, - "$type": "EntityId", - "value": { - "id": 2901262558 - }, - "label": "EntityID: 0" - } - ], - "methodType": 0, - "methodName": "DeactivateGameEntity", - "className": "GameEntityContextRequestBus", - "resultSlotIDs": [ - {} - ], - "prettyClassName": "GameEntityContextRequestBus" - } - } - }, - { - "Id": { - "id": 70146790624130 - }, - "Name": "SC-Node(DeactivateGameEntity)", - "Components": { - "Component_[846968981672785962]": { - "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", - "Id": 846968981672785962, - "Slots": [ - { - "id": { - "m_id": "{993AA3E4-ABCF-40FF-9CCB-030F22627151}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - }, - null - ], - "slotName": "EntityID: 0", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 2 - }, - "DataType": 1 - }, - { - "id": { - "m_id": "{A015E6E8-A025-4A2D-B1D4-E7D8732FCE52}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "In", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{925E7BB1-22EB-46A2-98E2-9A9805A4D019}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "Out", - "Descriptor": { - "ConnectionType": 2, - "SlotType": 1 - } - } - ], - "Datums": [ - { - "scriptCanvasType": { - "m_type": 1 - }, - "isNullPointer": false, - "$type": "EntityId", - "value": { - "id": 2901262558 - }, - "label": "EntityID: 0" - } - ], - "methodType": 0, - "methodName": "DeactivateGameEntity", - "className": "GameEntityContextRequestBus", - "resultSlotIDs": [ - {} - ], - "prettyClassName": "GameEntityContextRequestBus" - } - } - }, - { - "Id": { - "id": 70151085591426 - }, - "Name": "SC-Node(DeactivateGameEntity)", - "Components": { - "Component_[846968981672785962]": { - "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", - "Id": 846968981672785962, - "Slots": [ - { - "id": { - "m_id": "{993AA3E4-ABCF-40FF-9CCB-030F22627151}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - }, - null - ], - "slotName": "EntityID: 0", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 2 - }, - "DataType": 1 - }, - { - "id": { - "m_id": "{A015E6E8-A025-4A2D-B1D4-E7D8732FCE52}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "In", - "Descriptor": { - "ConnectionType": 1, - "SlotType": 1 - } - }, - { - "id": { - "m_id": "{925E7BB1-22EB-46A2-98E2-9A9805A4D019}" - }, - "contracts": [ - { - "$type": "SlotTypeContract" - } - ], - "slotName": "Out", - "Descriptor": { - "ConnectionType": 2, - "SlotType": 1 - } - } - ], - "Datums": [ - { - "scriptCanvasType": { - "m_type": 1 - }, - "isNullPointer": false, - "$type": "EntityId", - "value": { - "id": 2901262558 - }, - "label": "EntityID: 0" - } - ], - "methodType": 0, - "methodName": "DeactivateGameEntity", - "className": "GameEntityContextRequestBus", - "resultSlotIDs": [ - {} - ], - "prettyClassName": "GameEntityContextRequestBus" - } - } - }, - { - "Id": { - "id": 70185445329794 + "id": 18918337676681 }, "Name": "SC-EventNode(On Collision End event)", "Components": { - "Component_[8849170053396419306]": { + "Component_[7576015398665994859]": { "$type": "AzEventHandler", - "Id": 8849170053396419306, + "Id": 7576015398665994859, "Slots": [ { "id": { - "m_id": "{5F5A4D6A-50EF-4561-B5D3-F8CF1C4530F6}" + "m_id": "{63E9373E-95EC-407F-ACED-A5D50598A0D9}" }, "contracts": [ { @@ -1960,7 +1741,7 @@ { "$type": "RestrictedNodeContract", "m_nodeId": { - "id": 70133905722242 + "id": 18944107480457 } } ], @@ -1973,7 +1754,7 @@ }, { "id": { - "m_id": "{76FBE35A-BD29-4A8D-8B6E-AC6A2AD2306B}" + "m_id": "{5DF49BC4-1EFB-4312-8844-1BCF61E96610}" }, "contracts": [ { @@ -1989,7 +1770,7 @@ }, { "id": { - "m_id": "{2E933E93-BD7E-4B9D-A9F5-E1A15995E00B}" + "m_id": "{48AB5D80-6670-44CC-B38B-E15CDF47420D}" }, "contracts": [ { @@ -2005,7 +1786,7 @@ }, { "id": { - "m_id": "{1773DFC3-FCF8-43C6-8CBC-B2457A05EFD6}" + "m_id": "{6C053A9E-1317-44A4-826D-79B27C6D8A5A}" }, "contracts": [ { @@ -2021,7 +1802,7 @@ }, { "id": { - "m_id": "{FFBDBAC4-AF71-443C-BD6C-6C9E6BFAD858}" + "m_id": "{DFF1C200-D219-4959-8E01-2BD77B973C40}" }, "contracts": [ { @@ -2038,7 +1819,7 @@ }, { "id": { - "m_id": "{785405C8-1F85-4C9C-8ABE-C47A9A801BE3}" + "m_id": "{E316BB0C-7C7A-480F-BEFD-6CAEAC01C0D1}" }, "contracts": [ { @@ -2058,7 +1839,7 @@ }, { "id": { - "m_id": "{734C7A25-3E8A-4E3E-8CB5-E2F3383A3E18}" + "m_id": "{868EF452-C945-4EAA-990A-CC4998AD1B46}" }, "contracts": [ { @@ -2078,13 +1859,12 @@ }, { "id": { - "m_id": "{BBC0A5CC-0C89-47E1-BDEE-2F21BF6053DC}" + "m_id": "{AF5C00D0-E405-4350-B4B2-0B7FB2CDB410}" }, "contracts": [ { "$type": "SlotTypeContract" }, - null, { "$type": "ConnectionLimitContract", "limit": 1 @@ -2092,7 +1872,7 @@ { "$type": "RestrictedNodeContract", "m_nodeId": { - "id": 70133905722242 + "id": 18944107480457 } } ], @@ -2105,40 +1885,47 @@ } ], "Datums": [ - {} + { + "scriptCanvasType": { + "m_type": 4, + "m_azType": "{4C19E257-F929-524E-80E3-C910C5F3E2D9}" + }, + "isNullPointer": true, + "label": "On Collision End event" + } ], "m_azEventEntry": { "m_eventName": "On Collision End event", "m_parameterSlotIds": [ { - "m_id": "{785405C8-1F85-4C9C-8ABE-C47A9A801BE3}" + "m_id": "{E316BB0C-7C7A-480F-BEFD-6CAEAC01C0D1}" }, { - "m_id": "{734C7A25-3E8A-4E3E-8CB5-E2F3383A3E18}" + "m_id": "{868EF452-C945-4EAA-990A-CC4998AD1B46}" }, { - "m_id": "{785405C8-1F85-4C9C-8ABE-C47A9A801BE3}" + "m_id": "{E316BB0C-7C7A-480F-BEFD-6CAEAC01C0D1}" }, { - "m_id": "{734C7A25-3E8A-4E3E-8CB5-E2F3383A3E18}" + "m_id": "{868EF452-C945-4EAA-990A-CC4998AD1B46}" } ], "m_parameterNames": [ { - "m_id": "{785405C8-1F85-4C9C-8ABE-C47A9A801BE3}" + "m_id": "{E316BB0C-7C7A-480F-BEFD-6CAEAC01C0D1}" }, { - "m_id": "{734C7A25-3E8A-4E3E-8CB5-E2F3383A3E18}" + "m_id": "{868EF452-C945-4EAA-990A-CC4998AD1B46}" }, { - "m_id": "{785405C8-1F85-4C9C-8ABE-C47A9A801BE3}" + "m_id": "{E316BB0C-7C7A-480F-BEFD-6CAEAC01C0D1}" }, { - "m_id": "{734C7A25-3E8A-4E3E-8CB5-E2F3383A3E18}" + "m_id": "{868EF452-C945-4EAA-990A-CC4998AD1B46}" } ], "m_eventSlotId": { - "m_id": "{BBC0A5CC-0C89-47E1-BDEE-2F21BF6053DC}" + "m_id": "{AF5C00D0-E405-4350-B4B2-0B7FB2CDB410}" } } } @@ -2146,7 +1933,250 @@ }, { "Id": { - "id": 70108135918466 + "id": 18892567872905 + }, + "Name": "SC-Node(DeactivateGameEntity)", + "Components": { + "Component_[846968981672785962]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 846968981672785962, + "Slots": [ + { + "id": { + "m_id": "{993AA3E4-ABCF-40FF-9CCB-030F22627151}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{A015E6E8-A025-4A2D-B1D4-E7D8732FCE52}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{925E7BB1-22EB-46A2-98E2-9A9805A4D019}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "EntityID: 0" + } + ], + "methodType": 0, + "methodName": "DeactivateGameEntity", + "className": "GameEntityContextRequestBus", + "resultSlotIDs": [ + {} + ], + "prettyClassName": "GameEntityContextRequestBus" + } + } + }, + { + "Id": { + "id": 18926927611273 + }, + "Name": "SC-Node(DeactivateGameEntity)", + "Components": { + "Component_[846968981672785962]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 846968981672785962, + "Slots": [ + { + "id": { + "m_id": "{993AA3E4-ABCF-40FF-9CCB-030F22627151}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{A015E6E8-A025-4A2D-B1D4-E7D8732FCE52}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{925E7BB1-22EB-46A2-98E2-9A9805A4D019}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "EntityID: 0" + } + ], + "methodType": 0, + "methodName": "DeactivateGameEntity", + "className": "GameEntityContextRequestBus", + "resultSlotIDs": [ + {} + ], + "prettyClassName": "GameEntityContextRequestBus" + } + } + }, + { + "Id": { + "id": 18935517545865 + }, + "Name": "SC-Node(DeactivateGameEntity)", + "Components": { + "Component_[846968981672785962]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 846968981672785962, + "Slots": [ + { + "id": { + "m_id": "{993AA3E4-ABCF-40FF-9CCB-030F22627151}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{A015E6E8-A025-4A2D-B1D4-E7D8732FCE52}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{925E7BB1-22EB-46A2-98E2-9A9805A4D019}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "EntityID: 0" + } + ], + "methodType": 0, + "methodName": "DeactivateGameEntity", + "className": "GameEntityContextRequestBus", + "resultSlotIDs": [ + {} + ], + "prettyClassName": "GameEntityContextRequestBus" + } + } + }, + { + "Id": { + "id": 18862503101833 }, "Name": "SC-Node(Gate)", "Components": { @@ -2237,7 +2267,7 @@ }, { "Id": { - "id": 70116725853058 + "id": 18883977938313 }, "Name": "SC-Node(Gate)", "Components": { @@ -2328,7 +2358,7 @@ }, { "Id": { - "id": 70189740297090 + "id": 18922632643977 }, "Name": "SC-Node(Gate)", "Components": { @@ -2419,7 +2449,7 @@ }, { "Id": { - "id": 70138200689538 + "id": 18858208134537 }, "Name": "SC-Node(Print)", "Components": { @@ -2468,7 +2498,7 @@ }, { "Id": { - "id": 70155380558722 + "id": 18879682971017 }, "Name": "SC Node(GetVariable)", "Components": { @@ -2541,7 +2571,7 @@ "m_connections": [ { "Id": { - "id": 70194035264386 + "id": 18948402447753 }, "Name": "srcEndpoint=(IsActive: Result: Boolean), destEndpoint=(If: Condition)", "Components": { @@ -2550,7 +2580,7 @@ "Id": 8790567172666668723, "sourceEndpoint": { "nodeId": { - "id": 70163970493314 + "id": 18871093036425 }, "slotId": { "m_id": "{14EE86BB-E7E2-4210-B5ED-8F543D82F66C}" @@ -2558,7 +2588,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70116725853058 + "id": 18883977938313 }, "slotId": { "m_id": "{3C9FBBC2-3934-4C35-B959-9E26F93AB525}" @@ -2569,7 +2599,7 @@ }, { "Id": { - "id": 70198330231682 + "id": 18952697415049 }, "Name": "srcEndpoint=(IsActive: Out), destEndpoint=(If: In)", "Components": { @@ -2578,7 +2608,7 @@ "Id": 2434331826651875004, "sourceEndpoint": { "nodeId": { - "id": 70163970493314 + "id": 18871093036425 }, "slotId": { "m_id": "{3E203C3C-5BEE-4D9A-B323-C2E4E1FC6A4E}" @@ -2586,7 +2616,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70116725853058 + "id": 18883977938313 }, "slotId": { "m_id": "{6E61BAF4-4F8C-4D6D-8573-960755DEC094}" @@ -2597,7 +2627,7 @@ }, { "Id": { - "id": 70202625198978 + "id": 18956992382345 }, "Name": "srcEndpoint=(If: True), destEndpoint=(DeactivateGameEntity: In)", "Components": { @@ -2606,7 +2636,7 @@ "Id": 11237921104715455686, "sourceEndpoint": { "nodeId": { - "id": 70116725853058 + "id": 18883977938313 }, "slotId": { "m_id": "{7BF2F1C4-4831-4B6B-A63B-1046AD1FACFF}" @@ -2614,7 +2644,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70146790624130 + "id": 18935517545865 }, "slotId": { "m_id": "{A015E6E8-A025-4A2D-B1D4-E7D8732FCE52}" @@ -2625,7 +2655,7 @@ }, { "Id": { - "id": 70206920166274 + "id": 18961287349641 }, "Name": "srcEndpoint=(Get Variable: EntityID), destEndpoint=(IsActive: EntityID: Entity Id)", "Components": { @@ -2634,7 +2664,7 @@ "Id": 14362014279952360310, "sourceEndpoint": { "nodeId": { - "id": 70155380558722 + "id": 18879682971017 }, "slotId": { "m_id": "{473E8586-669E-4DDD-B7A8-3A9F5EC510D5}" @@ -2642,7 +2672,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70163970493314 + "id": 18871093036425 }, "slotId": { "m_id": "{170B4D1A-5D4A-466F-98AF-A51747B2623A}" @@ -2653,7 +2683,7 @@ }, { "Id": { - "id": 70211215133570 + "id": 18965582316937 }, "Name": "srcEndpoint=(If: False), destEndpoint=(ActivateGameEntity: In)", "Components": { @@ -2662,7 +2692,7 @@ "Id": 16755694922186694113, "sourceEndpoint": { "nodeId": { - "id": 70116725853058 + "id": 18883977938313 }, "slotId": { "m_id": "{EDE70327-9E66-4A5E-AFE3-B9C4D099021E}" @@ -2670,7 +2700,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70090956049282 + "id": 18914042709385 }, "slotId": { "m_id": "{53670F84-98ED-4559-A2EC-3D2285DBC8E3}" @@ -2681,7 +2711,7 @@ }, { "Id": { - "id": 70215510100866 + "id": 18969877284233 }, "Name": "srcEndpoint=(Get Variable: EntityID), destEndpoint=(ActivateGameEntity: EntityID: 0)", "Components": { @@ -2690,7 +2720,7 @@ "Id": 1634747738940978819, "sourceEndpoint": { "nodeId": { - "id": 70155380558722 + "id": 18879682971017 }, "slotId": { "m_id": "{473E8586-669E-4DDD-B7A8-3A9F5EC510D5}" @@ -2698,7 +2728,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70090956049282 + "id": 18914042709385 }, "slotId": { "m_id": "{4BCEF1F2-EB16-44C9-837F-CA936DAC9A2F}" @@ -2709,7 +2739,7 @@ }, { "Id": { - "id": 70219805068162 + "id": 18974172251529 }, "Name": "srcEndpoint=(Get Variable: EntityID), destEndpoint=(DeactivateGameEntity: EntityID: 0)", "Components": { @@ -2718,7 +2748,7 @@ "Id": 8821531688847258487, "sourceEndpoint": { "nodeId": { - "id": 70155380558722 + "id": 18879682971017 }, "slotId": { "m_id": "{473E8586-669E-4DDD-B7A8-3A9F5EC510D5}" @@ -2726,7 +2756,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70146790624130 + "id": 18935517545865 }, "slotId": { "m_id": "{993AA3E4-ABCF-40FF-9CCB-030F22627151}" @@ -2737,7 +2767,7 @@ }, { "Id": { - "id": 70224100035458 + "id": 18978467218825 }, "Name": "srcEndpoint=(IsActive: Out), destEndpoint=(If: In)", "Components": { @@ -2746,7 +2776,7 @@ "Id": 8561478604291958262, "sourceEndpoint": { "nodeId": { - "id": 70095251016578 + "id": 18931222578569 }, "slotId": { "m_id": "{3E203C3C-5BEE-4D9A-B323-C2E4E1FC6A4E}" @@ -2754,7 +2784,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70108135918466 + "id": 18862503101833 }, "slotId": { "m_id": "{6E61BAF4-4F8C-4D6D-8573-960755DEC094}" @@ -2765,7 +2795,7 @@ }, { "Id": { - "id": 70228395002754 + "id": 18982762186121 }, "Name": "srcEndpoint=(IsActive: Result: Boolean), destEndpoint=(If: Condition)", "Components": { @@ -2774,7 +2804,7 @@ "Id": 9146734319289132197, "sourceEndpoint": { "nodeId": { - "id": 70095251016578 + "id": 18931222578569 }, "slotId": { "m_id": "{14EE86BB-E7E2-4210-B5ED-8F543D82F66C}" @@ -2782,7 +2812,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70108135918466 + "id": 18862503101833 }, "slotId": { "m_id": "{3C9FBBC2-3934-4C35-B959-9E26F93AB525}" @@ -2793,7 +2823,7 @@ }, { "Id": { - "id": 70232689970050 + "id": 18987057153417 }, "Name": "srcEndpoint=(IsActive: Out), destEndpoint=(If: In)", "Components": { @@ -2802,7 +2832,7 @@ "Id": 11833205937891498095, "sourceEndpoint": { "nodeId": { - "id": 70172560427906 + "id": 18849618199945 }, "slotId": { "m_id": "{3E203C3C-5BEE-4D9A-B323-C2E4E1FC6A4E}" @@ -2810,7 +2840,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70189740297090 + "id": 18922632643977 }, "slotId": { "m_id": "{6E61BAF4-4F8C-4D6D-8573-960755DEC094}" @@ -2821,7 +2851,7 @@ }, { "Id": { - "id": 70236984937346 + "id": 18991352120713 }, "Name": "srcEndpoint=(IsActive: Result: Boolean), destEndpoint=(If: Condition)", "Components": { @@ -2830,7 +2860,7 @@ "Id": 10467104857840052907, "sourceEndpoint": { "nodeId": { - "id": 70172560427906 + "id": 18849618199945 }, "slotId": { "m_id": "{14EE86BB-E7E2-4210-B5ED-8F543D82F66C}" @@ -2838,7 +2868,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70189740297090 + "id": 18922632643977 }, "slotId": { "m_id": "{3C9FBBC2-3934-4C35-B959-9E26F93AB525}" @@ -2849,7 +2879,7 @@ }, { "Id": { - "id": 70241279904642 + "id": 18995647088009 }, "Name": "srcEndpoint=(Get Variable: EntityID), destEndpoint=(IsActive: EntityID: Entity Id)", "Components": { @@ -2858,7 +2888,7 @@ "Id": 1012188603409101617, "sourceEndpoint": { "nodeId": { - "id": 70099545983874 + "id": 18901157807497 }, "slotId": { "m_id": "{6DDB4692-35F9-4570-B914-951F1FFAB089}" @@ -2866,7 +2896,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70095251016578 + "id": 18931222578569 }, "slotId": { "m_id": "{170B4D1A-5D4A-466F-98AF-A51747B2623A}" @@ -2877,7 +2907,7 @@ }, { "Id": { - "id": 70245574871938 + "id": 18999942055305 }, "Name": "srcEndpoint=(Get Variable: EntityID), destEndpoint=(IsActive: EntityID: Entity Id)", "Components": { @@ -2886,7 +2916,7 @@ "Id": 5402619035508314979, "sourceEndpoint": { "nodeId": { - "id": 70121020820354 + "id": 18909747742089 }, "slotId": { "m_id": "{640B69D0-23E0-4A8E-BB94-477CFDE2E5F5}" @@ -2894,7 +2924,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70172560427906 + "id": 18849618199945 }, "slotId": { "m_id": "{170B4D1A-5D4A-466F-98AF-A51747B2623A}" @@ -2905,7 +2935,7 @@ }, { "Id": { - "id": 70249869839234 + "id": 19004237022601 }, "Name": "srcEndpoint=(If: True), destEndpoint=(DeactivateGameEntity: In)", "Components": { @@ -2914,7 +2944,7 @@ "Id": 18435267100506239768, "sourceEndpoint": { "nodeId": { - "id": 70108135918466 + "id": 18862503101833 }, "slotId": { "m_id": "{7BF2F1C4-4831-4B6B-A63B-1046AD1FACFF}" @@ -2922,7 +2952,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70151085591426 + "id": 18892567872905 }, "slotId": { "m_id": "{A015E6E8-A025-4A2D-B1D4-E7D8732FCE52}" @@ -2933,7 +2963,7 @@ }, { "Id": { - "id": 70254164806530 + "id": 19008531989897 }, "Name": "srcEndpoint=(If: False), destEndpoint=(ActivateGameEntity: In)", "Components": { @@ -2942,7 +2972,7 @@ "Id": 15164751479546717561, "sourceEndpoint": { "nodeId": { - "id": 70108135918466 + "id": 18862503101833 }, "slotId": { "m_id": "{EDE70327-9E66-4A5E-AFE3-B9C4D099021E}" @@ -2950,7 +2980,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70176855395202 + "id": 18875388003721 }, "slotId": { "m_id": "{53670F84-98ED-4559-A2EC-3D2285DBC8E3}" @@ -2961,7 +2991,7 @@ }, { "Id": { - "id": 70258459773826 + "id": 19012826957193 }, "Name": "srcEndpoint=(If: True), destEndpoint=(DeactivateGameEntity: In)", "Components": { @@ -2970,7 +3000,7 @@ "Id": 5061560116223750730, "sourceEndpoint": { "nodeId": { - "id": 70189740297090 + "id": 18922632643977 }, "slotId": { "m_id": "{7BF2F1C4-4831-4B6B-A63B-1046AD1FACFF}" @@ -2978,7 +3008,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70103840951170 + "id": 18926927611273 }, "slotId": { "m_id": "{A015E6E8-A025-4A2D-B1D4-E7D8732FCE52}" @@ -2989,7 +3019,7 @@ }, { "Id": { - "id": 70262754741122 + "id": 19017121924489 }, "Name": "srcEndpoint=(If: False), destEndpoint=(ActivateGameEntity: In)", "Components": { @@ -2998,7 +3028,7 @@ "Id": 10711100284272855896, "sourceEndpoint": { "nodeId": { - "id": 70189740297090 + "id": 18922632643977 }, "slotId": { "m_id": "{EDE70327-9E66-4A5E-AFE3-B9C4D099021E}" @@ -3006,7 +3036,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70129610754946 + "id": 18888272905609 }, "slotId": { "m_id": "{53670F84-98ED-4559-A2EC-3D2285DBC8E3}" @@ -3017,7 +3047,7 @@ }, { "Id": { - "id": 70267049708418 + "id": 19021416891785 }, "Name": "srcEndpoint=(Get Variable: EntityID), destEndpoint=(DeactivateGameEntity: EntityID: 0)", "Components": { @@ -3026,7 +3056,7 @@ "Id": 4394555422677501602, "sourceEndpoint": { "nodeId": { - "id": 70099545983874 + "id": 18901157807497 }, "slotId": { "m_id": "{6DDB4692-35F9-4570-B914-951F1FFAB089}" @@ -3034,7 +3064,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70151085591426 + "id": 18892567872905 }, "slotId": { "m_id": "{993AA3E4-ABCF-40FF-9CCB-030F22627151}" @@ -3045,7 +3075,7 @@ }, { "Id": { - "id": 70271344675714 + "id": 19025711859081 }, "Name": "srcEndpoint=(Get Variable: EntityID), destEndpoint=(DeactivateGameEntity: EntityID: 0)", "Components": { @@ -3054,7 +3084,7 @@ "Id": 4685709028181371637, "sourceEndpoint": { "nodeId": { - "id": 70121020820354 + "id": 18909747742089 }, "slotId": { "m_id": "{640B69D0-23E0-4A8E-BB94-477CFDE2E5F5}" @@ -3062,7 +3092,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70103840951170 + "id": 18926927611273 }, "slotId": { "m_id": "{993AA3E4-ABCF-40FF-9CCB-030F22627151}" @@ -3073,7 +3103,7 @@ }, { "Id": { - "id": 70275639643010 + "id": 19030006826377 }, "Name": "srcEndpoint=(Get Variable: EntityID), destEndpoint=(ActivateGameEntity: EntityID: 0)", "Components": { @@ -3082,7 +3112,7 @@ "Id": 3306462520084951475, "sourceEndpoint": { "nodeId": { - "id": 70121020820354 + "id": 18909747742089 }, "slotId": { "m_id": "{640B69D0-23E0-4A8E-BB94-477CFDE2E5F5}" @@ -3090,7 +3120,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70129610754946 + "id": 18888272905609 }, "slotId": { "m_id": "{4BCEF1F2-EB16-44C9-837F-CA936DAC9A2F}" @@ -3101,7 +3131,7 @@ }, { "Id": { - "id": 70279934610306 + "id": 19034301793673 }, "Name": "srcEndpoint=(DeactivateGameEntity: Out), destEndpoint=(Print: In)", "Components": { @@ -3110,7 +3140,7 @@ "Id": 17145465513158447772, "sourceEndpoint": { "nodeId": { - "id": 70146790624130 + "id": 18935517545865 }, "slotId": { "m_id": "{925E7BB1-22EB-46A2-98E2-9A9805A4D019}" @@ -3118,7 +3148,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70125315787650 + "id": 18939812513161 }, "slotId": { "m_id": "{8A68C668-FF05-4B9C-8AF3-20BA7AC5A783}" @@ -3129,7 +3159,7 @@ }, { "Id": { - "id": 70284229577602 + "id": 19038596760969 }, "Name": "srcEndpoint=(ActivateGameEntity: Out), destEndpoint=(Print: In)", "Components": { @@ -3138,7 +3168,7 @@ "Id": 14069026837818796272, "sourceEndpoint": { "nodeId": { - "id": 70090956049282 + "id": 18914042709385 }, "slotId": { "m_id": "{1904FF69-ECF6-47AC-9318-2EBDAA8A5485}" @@ -3146,7 +3176,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70138200689538 + "id": 18858208134537 }, "slotId": { "m_id": "{451A59EF-BD5D-4E7D-82BE-3B4E7EAF9B48}" @@ -3157,7 +3187,7 @@ }, { "Id": { - "id": 70288524544898 + "id": 19042891728265 }, "Name": "srcEndpoint=(DeactivateGameEntity: Out), destEndpoint=(Print: In)", "Components": { @@ -3166,7 +3196,7 @@ "Id": 7728736156493449863, "sourceEndpoint": { "nodeId": { - "id": 70151085591426 + "id": 18892567872905 }, "slotId": { "m_id": "{925E7BB1-22EB-46A2-98E2-9A9805A4D019}" @@ -3174,7 +3204,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70125315787650 + "id": 18939812513161 }, "slotId": { "m_id": "{8A68C668-FF05-4B9C-8AF3-20BA7AC5A783}" @@ -3185,7 +3215,7 @@ }, { "Id": { - "id": 70292819512194 + "id": 19047186695561 }, "Name": "srcEndpoint=(ActivateGameEntity: Out), destEndpoint=(Print: In)", "Components": { @@ -3194,7 +3224,7 @@ "Id": 10386336352272981702, "sourceEndpoint": { "nodeId": { - "id": 70176855395202 + "id": 18875388003721 }, "slotId": { "m_id": "{1904FF69-ECF6-47AC-9318-2EBDAA8A5485}" @@ -3202,7 +3232,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70138200689538 + "id": 18858208134537 }, "slotId": { "m_id": "{451A59EF-BD5D-4E7D-82BE-3B4E7EAF9B48}" @@ -3213,7 +3243,7 @@ }, { "Id": { - "id": 70297114479490 + "id": 19051481662857 }, "Name": "srcEndpoint=(DeactivateGameEntity: Out), destEndpoint=(Print: In)", "Components": { @@ -3222,7 +3252,7 @@ "Id": 16807949046056318365, "sourceEndpoint": { "nodeId": { - "id": 70103840951170 + "id": 18926927611273 }, "slotId": { "m_id": "{925E7BB1-22EB-46A2-98E2-9A9805A4D019}" @@ -3230,7 +3260,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70125315787650 + "id": 18939812513161 }, "slotId": { "m_id": "{8A68C668-FF05-4B9C-8AF3-20BA7AC5A783}" @@ -3241,7 +3271,7 @@ }, { "Id": { - "id": 70301409446786 + "id": 19055776630153 }, "Name": "srcEndpoint=(ActivateGameEntity: Out), destEndpoint=(Print: In)", "Components": { @@ -3250,7 +3280,7 @@ "Id": 13893900813580744359, "sourceEndpoint": { "nodeId": { - "id": 70129610754946 + "id": 18888272905609 }, "slotId": { "m_id": "{1904FF69-ECF6-47AC-9318-2EBDAA8A5485}" @@ -3258,7 +3288,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70138200689538 + "id": 18858208134537 }, "slotId": { "m_id": "{451A59EF-BD5D-4E7D-82BE-3B4E7EAF9B48}" @@ -3269,7 +3299,7 @@ }, { "Id": { - "id": 70305704414082 + "id": 19060071597449 }, "Name": "srcEndpoint=(Get Variable: EntityID), destEndpoint=(ActivateGameEntity: EntityID: 0)", "Components": { @@ -3278,7 +3308,7 @@ "Id": 3566132196647215905, "sourceEndpoint": { "nodeId": { - "id": 70099545983874 + "id": 18901157807497 }, "slotId": { "m_id": "{6DDB4692-35F9-4570-B914-951F1FFAB089}" @@ -3286,7 +3316,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70176855395202 + "id": 18875388003721 }, "slotId": { "m_id": "{4BCEF1F2-EB16-44C9-837F-CA936DAC9A2F}" @@ -3297,7 +3327,7 @@ }, { "Id": { - "id": 70309999381378 + "id": 19064366564745 }, "Name": "srcEndpoint=(Get Variable: Out), destEndpoint=(IsActive: In)", "Components": { @@ -3306,7 +3336,7 @@ "Id": 15737173947743935362, "sourceEndpoint": { "nodeId": { - "id": 70155380558722 + "id": 18879682971017 }, "slotId": { "m_id": "{B36D2C46-0A2B-4C90-B57C-5D9B7D3C1A63}" @@ -3314,7 +3344,7 @@ }, "targetEndpoint": { "nodeId": { - "id": 70163970493314 + "id": 18871093036425 }, "slotId": { "m_id": "{5A9AE174-D5E3-4512-A0BF-BA442C001F00}" @@ -3325,24 +3355,248 @@ }, { "Id": { - "id": 70314294348674 + "id": 19068661532041 }, - "Name": "srcEndpoint=(On Collision Begin event: OnEvent), destEndpoint=(Get Variable: In)", + "Name": "srcEndpoint=(Get Variable: Out), destEndpoint=(IsActive: In)", "Components": { - "Component_[6115424509860805504]": { + "Component_[10250827968868397862]": { "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", - "Id": 6115424509860805504, + "Id": 10250827968868397862, "sourceEndpoint": { "nodeId": { - "id": 70112430885762 + "id": 18901157807497 }, "slotId": { - "m_id": "{E32049C5-FF99-4E74-91EC-D007B0D6EF7B}" + "m_id": "{DF9C6AFF-531F-4E74-80CC-1F6889A1CE9E}" } }, "targetEndpoint": { "nodeId": { - "id": 70155380558722 + "id": 18931222578569 + }, + "slotId": { + "m_id": "{5A9AE174-D5E3-4512-A0BF-BA442C001F00}" + } + } + } + } + }, + { + "Id": { + "id": 19072956499337 + }, + "Name": "srcEndpoint=(Get Variable: Out), destEndpoint=(IsActive: In)", + "Components": { + "Component_[2090477647964111499]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 2090477647964111499, + "sourceEndpoint": { + "nodeId": { + "id": 18909747742089 + }, + "slotId": { + "m_id": "{6B862981-524C-4643-A2C2-9454CB1FD552}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 18849618199945 + }, + "slotId": { + "m_id": "{5A9AE174-D5E3-4512-A0BF-BA442C001F00}" + } + } + } + } + }, + { + "Id": { + "id": 19077251466633 + }, + "Name": "srcEndpoint=(GetOnCollisionBeginEvent: Result: Event const CollisionEvent& >), destEndpoint=(On Collision Begin event: On Collision Begin event)", + "Components": { + "Component_[2569723425229584356]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 2569723425229584356, + "sourceEndpoint": { + "nodeId": { + "id": 18845323232649 + }, + "slotId": { + "m_id": "{B647ABD6-B8B1-45CB-ACF4-495E416BB744}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 18905452774793 + }, + "slotId": { + "m_id": "{D4CACFC7-0F7B-4311-9125-D6624D302C50}" + } + } + } + } + }, + { + "Id": { + "id": 19081546433929 + }, + "Name": "srcEndpoint=(GetOnCollisionBeginEvent: Out), destEndpoint=(On Collision Begin event: Connect)", + "Components": { + "Component_[15942787264105251949]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 15942787264105251949, + "sourceEndpoint": { + "nodeId": { + "id": 18845323232649 + }, + "slotId": { + "m_id": "{4C7050D8-46F3-4E72-865E-8F2897430750}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 18905452774793 + }, + "slotId": { + "m_id": "{C3576303-C50B-4466-B3C1-A96F40F0B494}" + } + } + } + } + }, + { + "Id": { + "id": 19085841401225 + }, + "Name": "srcEndpoint=(EntityBus Handler: ExecutionSlot:OnEntityActivated), destEndpoint=(GetOnCollisionBeginEvent: In)", + "Components": { + "Component_[8910888382874480678]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 8910888382874480678, + "sourceEndpoint": { + "nodeId": { + "id": 18853913167241 + }, + "slotId": { + "m_id": "{4B50FCC8-C542-42E4-B17C-BD56173F1A26}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 18845323232649 + }, + "slotId": { + "m_id": "{ADA8C93D-8987-4537-99CD-A96986C8BF74}" + } + } + } + } + }, + { + "Id": { + "id": 19090136368521 + }, + "Name": "srcEndpoint=(GetOnCollisionPersistEvent: Result: Event const CollisionEvent& >), destEndpoint=(On Collision Persist event: On Collision Persist event)", + "Components": { + "Component_[6698981601680662520]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 6698981601680662520, + "sourceEndpoint": { + "nodeId": { + "id": 18866798069129 + }, + "slotId": { + "m_id": "{79056EFB-B34F-4702-B206-C9400F3408D6}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 18896862840201 + }, + "slotId": { + "m_id": "{1C7070F8-D281-414C-BF9B-D6B6B5F12926}" + } + } + } + } + }, + { + "Id": { + "id": 19094431335817 + }, + "Name": "srcEndpoint=(GetOnCollisionPersistEvent: Out), destEndpoint=(On Collision Persist event: Connect)", + "Components": { + "Component_[2650501895853204017]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 2650501895853204017, + "sourceEndpoint": { + "nodeId": { + "id": 18866798069129 + }, + "slotId": { + "m_id": "{FF7196F6-D599-44FC-8481-9DBE522529DF}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 18896862840201 + }, + "slotId": { + "m_id": "{D60E85B8-F645-47F8-92BE-0A0251269168}" + } + } + } + } + }, + { + "Id": { + "id": 19098726303113 + }, + "Name": "srcEndpoint=(EntityBus Handler: ExecutionSlot:OnEntityActivated), destEndpoint=(GetOnCollisionPersistEvent: In)", + "Components": { + "Component_[7564290783625553287]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 7564290783625553287, + "sourceEndpoint": { + "nodeId": { + "id": 18853913167241 + }, + "slotId": { + "m_id": "{4B50FCC8-C542-42E4-B17C-BD56173F1A26}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 18866798069129 + }, + "slotId": { + "m_id": "{3EE67098-3620-40AE-9463-4812E39075B9}" + } + } + } + } + }, + { + "Id": { + "id": 19103021270409 + }, + "Name": "srcEndpoint=(On Collision Begin event: OnEvent), destEndpoint=(Get Variable: In)", + "Components": { + "Component_[6368337435612519589]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 6368337435612519589, + "sourceEndpoint": { + "nodeId": { + "id": 18905452774793 + }, + "slotId": { + "m_id": "{FDC1C72B-2C39-43BA-87B4-2E88D1C2F82A}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 18879682971017 }, "slotId": { "m_id": "{5A04BA4A-061E-4775-A6CE-713E298D4E9A}" @@ -3353,52 +3607,24 @@ }, { "Id": { - "id": 70318589315970 - }, - "Name": "srcEndpoint=(Get Variable: Out), destEndpoint=(IsActive: In)", - "Components": { - "Component_[10250827968868397862]": { - "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", - "Id": 10250827968868397862, - "sourceEndpoint": { - "nodeId": { - "id": 70099545983874 - }, - "slotId": { - "m_id": "{DF9C6AFF-531F-4E74-80CC-1F6889A1CE9E}" - } - }, - "targetEndpoint": { - "nodeId": { - "id": 70095251016578 - }, - "slotId": { - "m_id": "{5A9AE174-D5E3-4512-A0BF-BA442C001F00}" - } - } - } - } - }, - { - "Id": { - "id": 70322884283266 + "id": 19107316237705 }, "Name": "srcEndpoint=(On Collision Persist event: OnEvent), destEndpoint=(Get Variable: In)", "Components": { - "Component_[13286675358080560883]": { + "Component_[12264834104825978898]": { "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", - "Id": 13286675358080560883, + "Id": 12264834104825978898, "sourceEndpoint": { "nodeId": { - "id": 70181150362498 + "id": 18896862840201 }, "slotId": { - "m_id": "{1A994B40-F1C6-4F60-9F44-4CE42732554C}" + "m_id": "{6B89E130-60D1-42A4-9C9C-679E84DD6389}" } }, "targetEndpoint": { "nodeId": { - "id": 70099545983874 + "id": 18901157807497 }, "slotId": { "m_id": "{245126A2-D7FE-4C59-BF8D-46F791EEE730}" @@ -3409,27 +3635,27 @@ }, { "Id": { - "id": 70327179250562 + "id": 19111611205001 }, - "Name": "srcEndpoint=(Get Variable: Out), destEndpoint=(IsActive: In)", + "Name": "srcEndpoint=(GetOnCollisionEndEvent: Result: Event const CollisionEvent& >), destEndpoint=(On Collision End event: On Collision End event)", "Components": { - "Component_[2090477647964111499]": { + "Component_[7813602739286642138]": { "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", - "Id": 2090477647964111499, + "Id": 7813602739286642138, "sourceEndpoint": { "nodeId": { - "id": 70121020820354 + "id": 18944107480457 }, "slotId": { - "m_id": "{6B862981-524C-4643-A2C2-9454CB1FD552}" + "m_id": "{CBF241C4-DB7C-4DCA-AD01-AA806F28AA1A}" } }, "targetEndpoint": { "nodeId": { - "id": 70172560427906 + "id": 18918337676681 }, "slotId": { - "m_id": "{5A9AE174-D5E3-4512-A0BF-BA442C001F00}" + "m_id": "{AF5C00D0-E405-4350-B4B2-0B7FB2CDB410}" } } } @@ -3437,24 +3663,52 @@ }, { "Id": { - "id": 70331474217858 + "id": 19115906172297 }, - "Name": "srcEndpoint=(On Collision End event: OnEvent), destEndpoint=(Get Variable: In)", + "Name": "srcEndpoint=(GetOnCollisionEndEvent: Out), destEndpoint=(On Collision End event: Connect)", "Components": { - "Component_[9355447111337093492]": { + "Component_[16385427931163233532]": { "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", - "Id": 9355447111337093492, + "Id": 16385427931163233532, "sourceEndpoint": { "nodeId": { - "id": 70185445329794 + "id": 18944107480457 }, "slotId": { - "m_id": "{FFBDBAC4-AF71-443C-BD6C-6C9E6BFAD858}" + "m_id": "{1F68015F-AB0F-4A63-8FF3-E4EB3EE000C9}" } }, "targetEndpoint": { "nodeId": { - "id": 70121020820354 + "id": 18918337676681 + }, + "slotId": { + "m_id": "{63E9373E-95EC-407F-ACED-A5D50598A0D9}" + } + } + } + } + }, + { + "Id": { + "id": 19120201139593 + }, + "Name": "srcEndpoint=(On Collision End event: OnEvent), destEndpoint=(Get Variable: In)", + "Components": { + "Component_[11664109633636291302]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 11664109633636291302, + "sourceEndpoint": { + "nodeId": { + "id": 18918337676681 + }, + "slotId": { + "m_id": "{DFF1C200-D219-4959-8E01-2BD77B973C40}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 18909747742089 }, "slotId": { "m_id": "{7A817841-79D4-41FC-97DA-72E599A770CC}" @@ -3462,6 +3716,34 @@ } } } + }, + { + "Id": { + "id": 19124496106889 + }, + "Name": "srcEndpoint=(EntityBus Handler: ExecutionSlot:OnEntityActivated), destEndpoint=(GetOnCollisionEndEvent: In)", + "Components": { + "Component_[7299601167427661211]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 7299601167427661211, + "sourceEndpoint": { + "nodeId": { + "id": 18853913167241 + }, + "slotId": { + "m_id": "{4B50FCC8-C542-42E4-B17C-BD56173F1A26}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 18944107480457 + }, + "slotId": { + "m_id": "{3933A5FE-5430-41E9-AE89-39DBF93EE427}" + } + } + } + } } ] }, @@ -3474,54 +3756,16 @@ "GraphCanvasData": [ { "Key": { - "id": 70086661081986 + "id": 18841028265353 }, "Value": { "ComponentData": { "{5F84B500-8C45-40D1-8EFC-A5306B241444}": { "$type": "SceneComponentSaveData", - "Constructs": [ - { - "Type": 1, - "DataContainer": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{524D8380-AC09-444E-870E-9CEF2535B4A2}": { - "$type": "CommentNodeTextSaveData", - "Comment": "These are disconnected because a bug in Script Canvas with AZ::Events.\n\nOnce the issue is fixed reconnecting the nodes should make the test to pass", - "BackgroundColor": [ - 0.9800000190734863, - 0.9700000286102295, - 0.6499999761581421 - ], - "FontSettings": { - "PixelSize": 32 - } - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - -1280.0, - -500.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{014DAF90-9434-4257-9670-6378E4D62A11}" - } - } - } - } - ], "ViewParams": { - "Scale": 0.6573655545525766, - "AnchorX": -1186.554443359375, - "AnchorY": -578.06494140625 + "Scale": 0.829105973051423, + "AnchorX": -1567.9539794921875, + "AnchorY": -593.4102783203125 } } } @@ -3529,315 +3773,7 @@ }, { "Key": { - "id": 70090956049282 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "MethodNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 1420.0, - -140.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".method" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{8B43E9D6-660F-4AD8-ABAF-D2CA12714C8C}" - } - } - } - }, - { - "Key": { - "id": 70095251016578 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "DefaultNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 600.0, - 100.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{FA508AFD-513D-4334-9760-909A9D4C765A}" - } - } - } - }, - { - "Key": { - "id": 70099545983874 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "GetVariableNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 200.0, - 100.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".getVariable" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{4970AE58-0BC4-45EE-B2E9-E14AF347E91F}" - } - } - } - }, - { - "Key": { - "id": 70103840951170 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "MethodNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 1420.0, - 380.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".method" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{5DB80931-443B-48A6-9B96-79152E545DE9}" - } - } - } - }, - { - "Key": { - "id": 70108135918466 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "LogicNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 1080.0, - 120.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".logic" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{455C1E31-F37D-4EE7-B954-B0532C66EE2C}" - } - } - } - }, - { - "Key": { - "id": 70112430885762 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "HandlerNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - -280.0, - -280.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".azeventhandler" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{7DBDAF02-24F5-4FEF-97F6-5C71F5596B09}" - } - } - } - }, - { - "Key": { - "id": 70116725853058 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "LogicNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 1080.0, - -220.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".logic" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{D9B0DBAE-33BB-4DD0-853F-3609B859651E}" - } - } - } - }, - { - "Key": { - "id": 70121020820354 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "GetVariableNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 220.0, - 460.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".getVariable" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{D2E4DE42-76F7-4B2E-838A-49EA403EA569}" - } - } - } - }, - { - "Key": { - "id": 70125315787650 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "StringNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 2000.0, - -160.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{389C6D5B-CE48-4C06-9A9C-BF8A63B50375}" - } - } - } - }, - { - "Key": { - "id": 70129610754946 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "MethodNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 1420.0, - 560.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".method" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{DA5DCC2B-9E77-46F7-8CA9-A2FADE367B25}" - } - } - } - }, - { - "Key": { - "id": 70133905722242 + "id": 18845323232649 }, "Value": { "ComponentData": { @@ -3852,98 +3788,6 @@ "$type": "GeometrySaveData", "Position": [ -880.0, - 400.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".method" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{64E2639D-6884-4692-9008-CFDACD35023F}" - } - } - } - }, - { - "Key": { - "id": 70138200689538 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "StringNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 2000.0, - 260.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{6EDB526D-EFA0-44C2-8A0C-9083BE1143D8}" - } - } - } - }, - { - "Key": { - "id": 70142495656834 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "MethodNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - -900.0, - -260.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".method" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{B9CA5B12-F636-47FE-804B-E11C972D4D8F}" - } - } - } - }, - { - "Key": { - "id": 70146790624130 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "MethodNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 1420.0, -300.0 ] }, @@ -3953,14 +3797,14 @@ }, "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { "$type": "PersistentIdComponentSaveData", - "PersistentId": "{453BE3A7-5198-45D2-A8C8-A343CAA048C1}" + "PersistentId": "{E613A2EF-EEC7-48F5-8A25-06D37B765791}" } } } }, { "Key": { - "id": 70151085591426 + "id": 18849618199945 }, "Value": { "ComponentData": { @@ -3969,60 +3813,28 @@ }, "{328FF15C-C302-458F-A43D-E1794DE0904E}": { "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "MethodNodeTitlePalette" + "PaletteOverride": "DefaultNodeTitlePalette" }, "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - 1420.0, - 20.0 + 600.0, + 460.0 ] }, "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".method" + "$type": "StylingComponentSaveData" }, "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { "$type": "PersistentIdComponentSaveData", - "PersistentId": "{0722BECC-EBCA-43E3-8EEC-618BD189E739}" + "PersistentId": "{2B76EE69-5338-4B1A-A4BE-98960F9F71D4}" } } } }, { "Key": { - "id": 70155380558722 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "GetVariableNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 200.0, - -240.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".getVariable" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{6F168FFF-9795-4C98-803C-FC4903E0C0A9}" - } - } - } - }, - { - "Key": { - "id": 70159675526018 + "id": 18853913167241 }, "Value": { "ComponentData": { @@ -4056,7 +3868,99 @@ }, { "Key": { - "id": 70163970493314 + "id": 18858208134537 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "StringNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 2000.0, + 260.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{6EDB526D-EFA0-44C2-8A0C-9083BE1143D8}" + } + } + } + }, + { + "Key": { + "id": 18862503101833 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "LogicNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 1080.0, + 120.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".logic" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{455C1E31-F37D-4EE7-B954-B0532C66EE2C}" + } + } + } + }, + { + "Key": { + "id": 18866798069129 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -880.0, + 60.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{99545608-279F-4AD9-B274-44414E4C23C4}" + } + } + } + }, + { + "Key": { + "id": 18871093036425 }, "Value": { "ComponentData": { @@ -4086,68 +3990,7 @@ }, { "Key": { - "id": 70168265460610 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "MethodNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - -900.0, - 40.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData", - "SubStyle": ".method" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{4B279432-B947-45C5-8BF0-473703906A28}" - } - } - } - }, - { - "Key": { - "id": 70172560427906 - }, - "Value": { - "ComponentData": { - "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { - "$type": "NodeSaveData" - }, - "{328FF15C-C302-458F-A43D-E1794DE0904E}": { - "$type": "GeneralNodeTitleComponentSaveData", - "PaletteOverride": "DefaultNodeTitlePalette" - }, - "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { - "$type": "GeometrySaveData", - "Position": [ - 600.0, - 460.0 - ] - }, - "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { - "$type": "StylingComponentSaveData" - }, - "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { - "$type": "PersistentIdComponentSaveData", - "PersistentId": "{2B76EE69-5338-4B1A-A4BE-98960F9F71D4}" - } - } - } - }, - { - "Key": { - "id": 70176855395202 + "id": 18875388003721 }, "Value": { "ComponentData": { @@ -4178,7 +4021,131 @@ }, { "Key": { - "id": 70181150362498 + "id": 18879682971017 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "GetVariableNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 200.0, + -240.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".getVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{6F168FFF-9795-4C98-803C-FC4903E0C0A9}" + } + } + } + }, + { + "Key": { + "id": 18883977938313 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "LogicNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 1080.0, + -220.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".logic" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{D9B0DBAE-33BB-4DD0-853F-3609B859651E}" + } + } + } + }, + { + "Key": { + "id": 18888272905609 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 1420.0, + 560.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{DA5DCC2B-9E77-46F7-8CA9-A2FADE367B25}" + } + } + } + }, + { + "Key": { + "id": 18892567872905 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 1420.0, + 20.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{0722BECC-EBCA-43E3-8EEC-618BD189E739}" + } + } + } + }, + { + "Key": { + "id": 18896862840201 }, "Value": { "ComponentData": { @@ -4192,8 +4159,8 @@ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - -280.0, - 60.0 + -260.0, + 40.0 ] }, "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { @@ -4202,14 +4169,45 @@ }, "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { "$type": "PersistentIdComponentSaveData", - "PersistentId": "{752364F1-EDC4-42D0-82CB-84FFE27AE3BC}" + "PersistentId": "{81D06A9B-7E9B-4D71-86F3-094C5AE71E6C}" } } } }, { "Key": { - "id": 70185445329794 + "id": 18901157807497 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "GetVariableNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 200.0, + 100.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".getVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{4970AE58-0BC4-45EE-B2E9-E14AF347E91F}" + } + } + } + }, + { + "Key": { + "id": 18905452774793 }, "Value": { "ComponentData": { @@ -4223,8 +4221,8 @@ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - -280.0, - 420.0 + -260.0, + -320.0 ] }, "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { @@ -4233,14 +4231,107 @@ }, "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { "$type": "PersistentIdComponentSaveData", - "PersistentId": "{DFC56761-5B10-4D07-A98F-32E24DFA4649}" + "PersistentId": "{62A35A1F-ED7F-4D4A-8E9F-E8875037EF0C}" } } } }, { "Key": { - "id": 70189740297090 + "id": 18909747742089 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "GetVariableNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 220.0, + 460.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".getVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{D2E4DE42-76F7-4B2E-838A-49EA403EA569}" + } + } + } + }, + { + "Key": { + "id": 18914042709385 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 1420.0, + -140.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{8B43E9D6-660F-4AD8-ABAF-D2CA12714C8C}" + } + } + } + }, + { + "Key": { + "id": 18918337676681 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "HandlerNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -260.0, + 400.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".azeventhandler" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{8FB39DE9-7038-4B5A-81E9-409FFD3ADF1F}" + } + } + } + }, + { + "Key": { + "id": 18922632643977 }, "Value": { "ComponentData": { @@ -4268,6 +4359,159 @@ } } } + }, + { + "Key": { + "id": 18926927611273 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 1420.0, + 380.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{5DB80931-443B-48A6-9B96-79152E545DE9}" + } + } + } + }, + { + "Key": { + "id": 18931222578569 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "DefaultNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 600.0, + 100.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{FA508AFD-513D-4334-9760-909A9D4C765A}" + } + } + } + }, + { + "Key": { + "id": 18935517545865 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 1420.0, + -300.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{453BE3A7-5198-45D2-A8C8-A343CAA048C1}" + } + } + } + }, + { + "Key": { + "id": 18939812513161 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "StringNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 2000.0, + -160.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{389C6D5B-CE48-4C06-9A9C-BF8A63B50375}" + } + } + } + }, + { + "Key": { + "id": 18944107480457 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -900.0, + 400.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{2DF9B4CD-AAD9-4BB8-B35A-6F0C68AB89BC}" + } + } + } } ], "StatisticsHelper": { diff --git a/AutomatedTesting/Levels/Physics/ScriptCanvas_PreUpdateEvent/ScriptCanvas_PreUpdateEvent.ly b/AutomatedTesting/Levels/Physics/ScriptCanvas_PreUpdateEvent/ScriptCanvas_PreUpdateEvent.ly index 1b6fd04102..60cec8af58 100644 --- a/AutomatedTesting/Levels/Physics/ScriptCanvas_PreUpdateEvent/ScriptCanvas_PreUpdateEvent.ly +++ b/AutomatedTesting/Levels/Physics/ScriptCanvas_PreUpdateEvent/ScriptCanvas_PreUpdateEvent.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1e648464adab2e7d3218aa61888676f6f016d65bed18c303273986614fe9a7e -size 6703 +oid sha256:982f085cfb17ce957cd1534e89a6fb5c76bcbe6936caec214ecd422b0a5dbe7b +size 5214 diff --git a/AutomatedTesting/ScriptCanvas/ScriptCanvas_PostUpdateEvent.scriptcanvas b/AutomatedTesting/ScriptCanvas/ScriptCanvas_PostUpdateEvent.scriptcanvas index 2db2f9c88f..bb497e3bf1 100644 --- a/AutomatedTesting/ScriptCanvas/ScriptCanvas_PostUpdateEvent.scriptcanvas +++ b/AutomatedTesting/ScriptCanvas/ScriptCanvas_PostUpdateEvent.scriptcanvas @@ -1,2356 +1,1441 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "ScriptCanvasData", + "ClassData": { + "m_scriptCanvas": { + "Id": { + "id": 7246990957034 + }, + "Name": "ScriptCanvas_PostUpdateEvent", + "Components": { + "Component_[7859303221537826322]": { + "$type": "EditorGraphVariableManagerComponent", + "Id": 7859303221537826322 + }, + "Component_[8048615284941550971]": { + "$type": "{4D755CA9-AB92-462C-B24F-0B3376F19967} Graph", + "Id": 8048615284941550971, + "m_graphData": { + "m_nodes": [ + { + "Id": { + "id": 7255580891626 + }, + "Name": "SC-EventNode(Postsimulate event)", + "Components": { + "Component_[1026420909310573434]": { + "$type": "AzEventHandler", + "Id": 1026420909310573434, + "Slots": [ + { + "id": { + "m_id": "{298E1FBB-EA4C-461A-BDBD-B143B6240DDA}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "ConnectionLimitContract", + "limit": 1 + }, + { + "$type": "RestrictedNodeContract", + "m_nodeId": { + "id": 7259875858922 + } + } + ], + "slotName": "Connect", + "toolTip": "Connect the AZ Event to this AZ Event Handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{0AB59F20-FB04-4F9C-A48D-D2429A97345E}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Disconnect", + "toolTip": "Disconnect current AZ Event from this AZ Event Handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{A933624F-AD95-44B4-95C7-B72E948B28DE}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "On Connected", + "toolTip": "Signaled when a connection has taken place.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{81CFBC65-1257-4553-AADD-28941CA5A394}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "On Disconnected", + "toolTip": "Signaled when this event handler is disconnected.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{9412D23F-5C3C-4BAE-9434-FEF63C61D19F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnEvent", + "toolTip": "Triggered when the AZ Event invokes Signal() function.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{491F4CF1-420C-447C-9347-1286E513D99D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null, + { + "$type": "ConnectionLimitContract", + "limit": 1 + }, + { + "$type": "RestrictedNodeContract", + "m_nodeId": { + "id": 7259875858922 + } + } + ], + "slotName": "Postsimulate event", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 4, + "m_azType": "{F429F985-AF00-529B-8449-16E56694E5F9}" + }, + "isNullPointer": true, + "label": "Postsimulate event" + } + ], + "m_azEventEntry": { + "m_eventName": "Postsimulate event", + "m_eventSlotId": { + "m_id": "{491F4CF1-420C-447C-9347-1286E513D99D}" + } + } + } + } + }, + { + "Id": { + "id": 7264170826218 + }, + "Name": "SC-Node(SetWorldTranslation)", + "Components": { + "Component_[18174025885473549905]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 18174025885473549905, + "Slots": [ + { + "id": { + "m_id": "{517676CA-4595-4065-BEF3-6ACB6863E50D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{903CDBDF-A22B-477B-AA16-8FDC81255835}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "Vector3: 1", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{6F5CB726-93B1-42EB-B489-2A9C4EEAE97A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8E82FC83-E0D2-42BB-864F-BE7F205CD4E9}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "Source" + }, + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Translation" + } + ], + "methodType": 0, + "methodName": "SetWorldTranslation", + "className": "TransformBus", + "resultSlotIDs": [ + {} + ], + "prettyClassName": "TransformBus" + } + } + }, + { + "Id": { + "id": 7259875858922 + }, + "Name": "SC-Node(GetOnPostsimulateEvent)", + "Components": { + "Component_[2298887429127007522]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 2298887429127007522, + "Slots": [ + { + "id": { + "m_id": "{8B02A209-89DE-40B9-882E-851A1C82CFEE}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{F2AFC1DB-F1B3-4A0A-ABC4-FAFB09CC0EDB}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{5331CDE9-F1F6-4EA0-A8E8-DCB099CF5212}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Event<>", + "DisplayDataType": { + "m_type": 4, + "m_azType": "{F429F985-AF00-529B-8449-16E56694E5F9}" + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "methodType": 2, + "methodName": "GetOnPostsimulateEvent", + "className": "PhysicsSystemInterface", + "resultSlotIDs": [ + {} + ], + "prettyClassName": "PhysicsSystemInterface" + } + } + }, + { + "Id": { + "id": 7268465793514 + }, + "Name": "EBusEventHandler", + "Components": { + "Component_[2481096262197714664]": { + "$type": "EBusEventHandler", + "Id": 2481096262197714664, + "Slots": [ + { + "id": { + "m_id": "{6AFF8E96-F047-4379-93F7-A1E3A0DEA69C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Connect", + "toolTip": "Connect this event handler to the specified entity.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{5261B1DD-E9A8-470F-8CC4-68ADDB423CB5}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Disconnect", + "toolTip": "Disconnect this event handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{52AAD5FF-EB9B-49E4-BE42-5776A21B9676}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnConnected", + "toolTip": "Signaled when a connection has taken place.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{A1D62B65-5AC4-4D3E-8F26-4EE6BE9A3A3C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnDisconnected", + "toolTip": "Signaled when this event handler is disconnected.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{EDA8F8A0-47A4-4359-AB6D-A6B7317CF57C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnFailure", + "toolTip": "Signaled when it is not possible to connect this handler.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{5F7A39A0-01D0-4ED5-B6D4-F16D16E367FE}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "Source", + "toolTip": "ID used to connect on a specific Event address (Type: EntityId)", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{FEBDC32A-663D-4C24-9490-E47AE860ED35}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID", + "DisplayDataType": { + "m_type": 1 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{A2CD891C-F7F3-4F87-95C6-3F08456A39C8}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ExecutionSlot:OnEntityActivated", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{BA3D7E71-5ED0-419E-89CC-BED3BB49EB99}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID", + "DisplayDataType": { + "m_type": 1 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{04DDA62D-DEB6-4106-8AB5-3320F4497DBA}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ExecutionSlot:OnEntityDeactivated", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "Source" + } + ], + "m_eventMap": [ + { + "Key": { + "Value": 245425936 + }, + "Value": { + "m_eventName": "OnEntityActivated", + "m_eventId": { + "Value": 245425936 + }, + "m_eventSlotId": { + "m_id": "{A2CD891C-F7F3-4F87-95C6-3F08456A39C8}" + }, + "m_parameterSlotIds": [ + { + "m_id": "{FEBDC32A-663D-4C24-9490-E47AE860ED35}" + } + ], + "m_numExpectedArguments": 1 + } + }, + { + "Key": { + "Value": 4273369222 + }, + "Value": { + "m_eventName": "OnEntityDeactivated", + "m_eventId": { + "Value": 4273369222 + }, + "m_eventSlotId": { + "m_id": "{04DDA62D-DEB6-4106-8AB5-3320F4497DBA}" + }, + "m_parameterSlotIds": [ + { + "m_id": "{BA3D7E71-5ED0-419E-89CC-BED3BB49EB99}" + } + ], + "m_numExpectedArguments": 1 + } + } + ], + "m_ebusName": "EntityBus", + "m_busId": { + "Value": 3358774020 + } + } + } + }, + { + "Id": { + "id": 7251285924330 + }, + "Name": "SC-Node(OperatorAdd)", + "Components": { + "Component_[2947356292726636849]": { + "$type": "OperatorAdd", + "Id": 2947356292726636849, + "Slots": [ + { + "id": { + "m_id": "{365919DD-D8DE-4209-A5B7-1EBF1B84E58C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{4A7D3757-64E3-47D7-B7AF-B27165154631}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{1BDE6B10-A2C0-42D3-B954-EC8F756D9854}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null, + { + "$type": "MathOperatorContract", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 8 + }, + { + "m_type": 9 + }, + { + "m_type": 10 + }, + { + "m_type": 11 + }, + { + "m_type": 12 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Vector3", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 8 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{6DF37237-B149-4FC4-8FF8-245ECCFBC542}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null, + { + "$type": "MathOperatorContract", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 8 + }, + { + "m_type": 9 + }, + { + "m_type": 10 + }, + { + "m_type": 11 + }, + { + "m_type": 12 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Vector3", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 8 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{982F1726-1327-49B5-BEB1-D64D9FC7C0D6}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 8 + }, + { + "m_type": 9 + }, + { + "m_type": 10 + }, + { + "m_type": 11 + }, + { + "m_type": 12 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Result", + "toolTip": "The result of the specified operation", + "DisplayDataType": { + "m_type": 8 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Vector3" + }, + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + -1.0, + 0.0, + 0.0 + ], + "label": "Vector3" + } + ] + } + } + }, + { + "Id": { + "id": 7272760760810 + }, + "Name": "SC-Node(GetWorldTranslation)", + "Components": { + "Component_[7906397568238626559]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 7906397568238626559, + "Slots": [ + { + "id": { + "m_id": "{4D8E536D-BAF4-4AAC-A88E-6B082D58420A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{8D0B9B7A-415D-44B1-B66F-A6C859CDF068}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{1225D555-C7F9-45E8-B625-A2FFC71A60D6}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Vector3", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{EEBEB400-B5D6-4025-87D8-3DE1EFCCE26A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 281697622333 + }, + "label": "Source" + } + ], + "methodType": 0, + "methodName": "GetWorldTranslation", + "className": "TransformBus", + "resultSlotIDs": [ + { + "m_id": "{1225D555-C7F9-45E8-B625-A2FFC71A60D6}" + } + ], + "prettyClassName": "TransformBus" + } + } + } + ], + "m_connections": [ + { + "Id": { + "id": 7277055728106 + }, + "Name": "srcEndpoint=(GetWorldTranslation: Result: Vector3), destEndpoint=(Add (+): Value)", + "Components": { + "Component_[242178999561252379]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 242178999561252379, + "sourceEndpoint": { + "nodeId": { + "id": 7272760760810 + }, + "slotId": { + "m_id": "{1225D555-C7F9-45E8-B625-A2FFC71A60D6}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7251285924330 + }, + "slotId": { + "m_id": "{1BDE6B10-A2C0-42D3-B954-EC8F756D9854}" + } + } + } + } + }, + { + "Id": { + "id": 7281350695402 + }, + "Name": "srcEndpoint=(GetWorldTranslation: Out), destEndpoint=(Add (+): In)", + "Components": { + "Component_[3863909945377931474]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 3863909945377931474, + "sourceEndpoint": { + "nodeId": { + "id": 7272760760810 + }, + "slotId": { + "m_id": "{EEBEB400-B5D6-4025-87D8-3DE1EFCCE26A}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7251285924330 + }, + "slotId": { + "m_id": "{365919DD-D8DE-4209-A5B7-1EBF1B84E58C}" + } + } + } + } + }, + { + "Id": { + "id": 7285645662698 + }, + "Name": "srcEndpoint=(Add (+): Out), destEndpoint=(SetWorldTranslation: In)", + "Components": { + "Component_[11373809959868110927]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 11373809959868110927, + "sourceEndpoint": { + "nodeId": { + "id": 7251285924330 + }, + "slotId": { + "m_id": "{4A7D3757-64E3-47D7-B7AF-B27165154631}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7264170826218 + }, + "slotId": { + "m_id": "{6F5CB726-93B1-42EB-B489-2A9C4EEAE97A}" + } + } + } + } + }, + { + "Id": { + "id": 7289940629994 + }, + "Name": "srcEndpoint=(Add (+): Result), destEndpoint=(SetWorldTranslation: Vector3: 1)", + "Components": { + "Component_[6872695239256977190]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 6872695239256977190, + "sourceEndpoint": { + "nodeId": { + "id": 7251285924330 + }, + "slotId": { + "m_id": "{982F1726-1327-49B5-BEB1-D64D9FC7C0D6}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7264170826218 + }, + "slotId": { + "m_id": "{903CDBDF-A22B-477B-AA16-8FDC81255835}" + } + } + } + } + }, + { + "Id": { + "id": 7294235597290 + }, + "Name": "srcEndpoint=(GetOnPostsimulateEvent: Result: Event<>), destEndpoint=(Postsimulate event: Postsimulate event)", + "Components": { + "Component_[14941476969640620853]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14941476969640620853, + "sourceEndpoint": { + "nodeId": { + "id": 7259875858922 + }, + "slotId": { + "m_id": "{5331CDE9-F1F6-4EA0-A8E8-DCB099CF5212}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7255580891626 + }, + "slotId": { + "m_id": "{491F4CF1-420C-447C-9347-1286E513D99D}" + } + } + } + } + }, + { + "Id": { + "id": 7298530564586 + }, + "Name": "srcEndpoint=(GetOnPostsimulateEvent: Out), destEndpoint=(Postsimulate event: Connect)", + "Components": { + "Component_[14053430938252148760]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14053430938252148760, + "sourceEndpoint": { + "nodeId": { + "id": 7259875858922 + }, + "slotId": { + "m_id": "{F2AFC1DB-F1B3-4A0A-ABC4-FAFB09CC0EDB}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7255580891626 + }, + "slotId": { + "m_id": "{298E1FBB-EA4C-461A-BDBD-B143B6240DDA}" + } + } + } + } + }, + { + "Id": { + "id": 7302825531882 + }, + "Name": "srcEndpoint=(EntityBus Handler: ExecutionSlot:OnEntityActivated), destEndpoint=(GetOnPostsimulateEvent: In)", + "Components": { + "Component_[2413811060506403971]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 2413811060506403971, + "sourceEndpoint": { + "nodeId": { + "id": 7268465793514 + }, + "slotId": { + "m_id": "{A2CD891C-F7F3-4F87-95C6-3F08456A39C8}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7259875858922 + }, + "slotId": { + "m_id": "{8B02A209-89DE-40B9-882E-851A1C82CFEE}" + } + } + } + } + }, + { + "Id": { + "id": 7307120499178 + }, + "Name": "srcEndpoint=(Postsimulate event: OnEvent), destEndpoint=(GetWorldTranslation: In)", + "Components": { + "Component_[1592781785499451182]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 1592781785499451182, + "sourceEndpoint": { + "nodeId": { + "id": 7255580891626 + }, + "slotId": { + "m_id": "{9412D23F-5C3C-4BAE-9434-FEF63C61D19F}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7272760760810 + }, + "slotId": { + "m_id": "{8D0B9B7A-415D-44B1-B66F-A6C859CDF068}" + } + } + } + } + } + ] + }, + "m_assetType": "{3E2AC8CD-713F-453E-967F-29517F331784}", + "versionData": { + "_grammarVersion": 1, + "_runtimeVersion": 1 + }, + "GraphCanvasData": [ + { + "Key": { + "id": 7246990957034 + }, + "Value": { + "ComponentData": { + "{5F84B500-8C45-40D1-8EFC-A5306B241444}": { + "$type": "SceneComponentSaveData", + "ViewParams": { + "Scale": 1.0498028, + "AnchorX": -413.4109802246094, + "AnchorY": -143.83653259277344 + } + } + } + } + }, + { + "Key": { + "id": 7251285924330 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MathNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 640.0, + 120.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{21EF1E23-A534-4534-8AAE-E750DD0BB42F}" + } + } + } + }, + { + "Key": { + "id": 7255580891626 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "HandlerNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -140.0, + 80.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".azeventhandler" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{5BF8EBFB-0DC5-4708-B618-671B47FB9B94}" + } + } + } + }, + { + "Key": { + "id": 7259875858922 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -500.0, + 100.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{8FD53D85-4783-4AAB-B779-6C03BAD63717}" + } + } + } + }, + { + "Key": { + "id": 7264170826218 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 1100.0, + 120.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{A6FDC96D-8B0B-4B9E-84CF-A4A6DA49FF2D}" + } + } + } + }, + { + "Key": { + "id": 7268465793514 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -880.0, + 40.0 + ] + }, + "{9E81C95F-89C0-4476-8E82-63CCC4E52E04}": { + "$type": "EBusHandlerNodeDescriptorSaveData", + "EventIds": [ + { + "Value": 245425936 + } + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{ABEA26C6-312E-4CDB-A78B-22FFFD0C1621}" + } + } + } + }, + { + "Key": { + "id": 7272760760810 + }, + "Value": { + "ComponentData": { + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 180.0, + 120.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{9CC9588E-0054-4615-B627-F8D04CAD5970}" + } + } + } + } + ], + "CRCCacheMap": [ + { + "Key": { + "Value": 418594340 + }, + "Value": { + "String": "AZPhysicalWorld", + "Count": 1 + } + }, + { + "Key": { + "Value": 3249382599 + }, + "Value": { + "String": "DefaultScene", + "Count": 1 + } + } + ], + "StatisticsHelper": { + "InstanceCounter": [ + { + "Key": 1244476766431948410, + "Value": 1 + }, + { + "Key": 4847610523576971761, + "Value": 1 + }, + { + "Key": 5842116761103598202, + "Value": 1 + }, + { + "Key": 6332589079726754678, + "Value": 1 + }, + { + "Key": 13774516554886911373, + "Value": 1 + }, + { + "Key": 13774516556399355685, + "Value": 1 + } + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/AutomatedTesting/ScriptCanvas/ScriptCanvas_PreUpdateEvent.scriptcanvas b/AutomatedTesting/ScriptCanvas/ScriptCanvas_PreUpdateEvent.scriptcanvas index f355b3e6e9..0cfb3c8c48 100644 --- a/AutomatedTesting/ScriptCanvas/ScriptCanvas_PreUpdateEvent.scriptcanvas +++ b/AutomatedTesting/ScriptCanvas/ScriptCanvas_PreUpdateEvent.scriptcanvas @@ -1,2417 +1,1494 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "ScriptCanvasData", + "ClassData": { + "m_scriptCanvas": { + "Id": { + "id": 80662787523977 + }, + "Name": "ScriptCanvas_PreUpdateEvent", + "Components": { + "Component_[7859303221537826322]": { + "$type": "EditorGraphVariableManagerComponent", + "Id": 7859303221537826322 + }, + "Component_[8048615284941550971]": { + "$type": "{4D755CA9-AB92-462C-B24F-0B3376F19967} Graph", + "Id": 8048615284941550971, + "m_graphData": { + "m_nodes": [ + { + "Id": { + "id": 80688557327753 + }, + "Name": "EBusEventHandler", + "Components": { + "Component_[10194282752280979681]": { + "$type": "EBusEventHandler", + "Id": 10194282752280979681, + "Slots": [ + { + "id": { + "m_id": "{E76AE1C2-5BE0-4CEA-B2A1-6B5599877A53}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Connect", + "toolTip": "Connect this event handler to the specified entity.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{D55DEAE2-7FE4-4154-B91A-C392E6450BAE}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Disconnect", + "toolTip": "Disconnect this event handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{16B87363-9D49-4344-88D2-743E51706A64}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnConnected", + "toolTip": "Signaled when a connection has taken place.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{C354C37D-B6FD-4E17-95CA-4EB7B3F75AD9}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnDisconnected", + "toolTip": "Signaled when this event handler is disconnected.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{CA917050-D510-4B13-8158-71C72A56B55B}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnFailure", + "toolTip": "Signaled when it is not possible to connect this handler.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{895BFE09-55D1-4AB7-AB6D-7D7EDC8AB27F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "Source", + "toolTip": "ID used to connect on a specific Event address (Type: EntityId)", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{94B92BA7-AD10-4370-8004-37D6BA6140D0}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID", + "DisplayDataType": { + "m_type": 1 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{6AAE0625-E567-448A-85EC-002727CB0C9B}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ExecutionSlot:OnEntityActivated", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{78A7A34E-7605-42A6-AFDA-B8F33CC997F4}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID", + "DisplayDataType": { + "m_type": 1 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{639510EC-C5CD-442E-9585-DD0014642379}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ExecutionSlot:OnEntityDeactivated", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "Source" + } + ], + "m_eventMap": [ + { + "Key": { + "Value": 245425936 + }, + "Value": { + "m_eventName": "OnEntityActivated", + "m_eventId": { + "Value": 245425936 + }, + "m_eventSlotId": { + "m_id": "{6AAE0625-E567-448A-85EC-002727CB0C9B}" + }, + "m_parameterSlotIds": [ + { + "m_id": "{94B92BA7-AD10-4370-8004-37D6BA6140D0}" + } + ], + "m_numExpectedArguments": 1 + } + }, + { + "Key": { + "Value": 4273369222 + }, + "Value": { + "m_eventName": "OnEntityDeactivated", + "m_eventId": { + "Value": 4273369222 + }, + "m_eventSlotId": { + "m_id": "{639510EC-C5CD-442E-9585-DD0014642379}" + }, + "m_parameterSlotIds": [ + { + "m_id": "{78A7A34E-7605-42A6-AFDA-B8F33CC997F4}" + } + ], + "m_numExpectedArguments": 1 + } + } + ], + "m_ebusName": "EntityBus", + "m_busId": { + "Value": 3358774020 + } + } + } + }, + { + "Id": { + "id": 80684262360457 + }, + "Name": "SC-Node(GetOnPresimulateEvent)", + "Components": { + "Component_[10220237333641525118]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 10220237333641525118, + "Slots": [ + { + "id": { + "m_id": "{671D1A67-1F82-4BB4-9287-099AA81073DF}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{235F1C50-06B0-4793-BD83-C9F3E8B28479}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{13AE2AAB-FBEB-4851-A148-325652B1FDC1}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Event", + "DisplayDataType": { + "m_type": 4, + "m_azType": "{F0A3166F-115C-5C3E-8D65-28FBA4420028}" + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "methodType": 2, + "methodName": "GetOnPresimulateEvent", + "className": "PhysicsSystemInterface", + "resultSlotIDs": [ + {} + ], + "prettyClassName": "PhysicsSystemInterface" + } + } + }, + { + "Id": { + "id": 80675672425865 + }, + "Name": "SC-Node(OperatorAdd)", + "Components": { + "Component_[11406838928576978587]": { + "$type": "OperatorAdd", + "Id": 11406838928576978587, + "Slots": [ + { + "id": { + "m_id": "{F2AB1C73-D779-4306-A336-96D085EFD20C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8C84B74E-F975-4957-8039-19E7719327AD}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{0B1A1CA1-9D6A-4402-8953-E62C9329D70A}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null, + { + "$type": "MathOperatorContract", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 8 + }, + { + "m_type": 9 + }, + { + "m_type": 10 + }, + { + "m_type": 11 + }, + { + "m_type": 12 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Vector3", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 8 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{D9E65807-CFEA-4848-A7DB-DEFF328E1100}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null, + { + "$type": "MathOperatorContract", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 8 + }, + { + "m_type": 9 + }, + { + "m_type": 10 + }, + { + "m_type": 11 + }, + { + "m_type": 12 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Vector3", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 8 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{540EF6ED-F6B9-4BCE-A7A9-8271DE09E28E}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 8 + }, + { + "m_type": 9 + }, + { + "m_type": 10 + }, + { + "m_type": 11 + }, + { + "m_type": 12 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Result", + "toolTip": "The result of the specified operation", + "DisplayDataType": { + "m_type": 8 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Vector3" + }, + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + -1.0, + 0.0, + 0.0 + ], + "label": "Vector3" + } + ] + } + } + }, + { + "Id": { + "id": 80671377458569 + }, + "Name": "SC-Node(SetWorldTranslation)", + "Components": { + "Component_[18174025885473549905]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 18174025885473549905, + "Slots": [ + { + "id": { + "m_id": "{517676CA-4595-4065-BEF3-6ACB6863E50D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{903CDBDF-A22B-477B-AA16-8FDC81255835}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "Vector3: 1", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{6F5CB726-93B1-42EB-B489-2A9C4EEAE97A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8E82FC83-E0D2-42BB-864F-BE7F205CD4E9}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "Source" + }, + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Translation" + } + ], + "methodType": 0, + "methodName": "SetWorldTranslation", + "className": "TransformBus", + "resultSlotIDs": [ + {} + ], + "prettyClassName": "TransformBus" + } + } + }, + { + "Id": { + "id": 80667082491273 + }, + "Name": "SC-Node(GetWorldTranslation)", + "Components": { + "Component_[7906397568238626559]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 7906397568238626559, + "Slots": [ + { + "id": { + "m_id": "{4D8E536D-BAF4-4AAC-A88E-6B082D58420A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{8D0B9B7A-415D-44B1-B66F-A6C859CDF068}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{1225D555-C7F9-45E8-B625-A2FFC71A60D6}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Vector3", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{EEBEB400-B5D6-4025-87D8-3DE1EFCCE26A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 284799455595 + }, + "label": "Source" + } + ], + "methodType": 0, + "methodName": "GetWorldTranslation", + "className": "TransformBus", + "resultSlotIDs": [ + { + "m_id": "{1225D555-C7F9-45E8-B625-A2FFC71A60D6}" + } + ], + "prettyClassName": "TransformBus" + } + } + }, + { + "Id": { + "id": 80679967393161 + }, + "Name": "SC-EventNode(Presimulate event)", + "Components": { + "Component_[9821965988545835220]": { + "$type": "AzEventHandler", + "Id": 9821965988545835220, + "Slots": [ + { + "id": { + "m_id": "{785642C6-C68F-4C78-B388-DB2032C55B8B}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "ConnectionLimitContract", + "limit": 1 + }, + { + "$type": "RestrictedNodeContract", + "m_nodeId": { + "id": 80684262360457 + } + } + ], + "slotName": "Connect", + "toolTip": "Connect the AZ Event to this AZ Event Handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{57857370-96BF-4C14-973A-E11CD3ACEE2F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Disconnect", + "toolTip": "Disconnect current AZ Event from this AZ Event Handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{D4C449D4-34FF-4478-A429-7577FFF9A4D0}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "On Connected", + "toolTip": "Signaled when a connection has taken place.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{A5BADE33-9F5F-494F-95F8-0B88B307F243}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "On Disconnected", + "toolTip": "Signaled when this event handler is disconnected.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{CECB84BC-6AC2-4C51-A38A-63FE7E01A056}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnEvent", + "toolTip": "Triggered when the AZ Event invokes Signal() function.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{141AA0B1-CA62-45CF-9ED2-FB55354FA26F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Tick time", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{477D1D40-3833-46BB-8DC7-E4DCCF688E99}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + null, + { + "$type": "ConnectionLimitContract", + "limit": 1 + }, + { + "$type": "RestrictedNodeContract", + "m_nodeId": { + "id": 80684262360457 + } + } + ], + "slotName": "Presimulate event", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 4, + "m_azType": "{F0A3166F-115C-5C3E-8D65-28FBA4420028}" + }, + "isNullPointer": true, + "label": "Presimulate event" + } + ], + "m_azEventEntry": { + "m_eventName": "Presimulate event", + "m_parameterSlotIds": [ + { + "m_id": "{141AA0B1-CA62-45CF-9ED2-FB55354FA26F}" + }, + { + "m_id": "{141AA0B1-CA62-45CF-9ED2-FB55354FA26F}" + }, + { + "m_id": "{141AA0B1-CA62-45CF-9ED2-FB55354FA26F}" + }, + { + "m_id": "{141AA0B1-CA62-45CF-9ED2-FB55354FA26F}" + } + ], + "m_parameterNames": [ + { + "m_id": "{141AA0B1-CA62-45CF-9ED2-FB55354FA26F}" + }, + { + "m_id": "{141AA0B1-CA62-45CF-9ED2-FB55354FA26F}" + }, + { + "m_id": "{141AA0B1-CA62-45CF-9ED2-FB55354FA26F}" + }, + { + "m_id": "{141AA0B1-CA62-45CF-9ED2-FB55354FA26F}" + } + ], + "m_eventSlotId": { + "m_id": "{477D1D40-3833-46BB-8DC7-E4DCCF688E99}" + } + } + } + } + } + ], + "m_connections": [ + { + "Id": { + "id": 80692852295049 + }, + "Name": "srcEndpoint=(GetWorldTranslation: Result: Vector3), destEndpoint=(Add (+): Value)", + "Components": { + "Component_[14061883664044186409]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14061883664044186409, + "sourceEndpoint": { + "nodeId": { + "id": 80667082491273 + }, + "slotId": { + "m_id": "{1225D555-C7F9-45E8-B625-A2FFC71A60D6}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 80675672425865 + }, + "slotId": { + "m_id": "{0B1A1CA1-9D6A-4402-8953-E62C9329D70A}" + } + } + } + } + }, + { + "Id": { + "id": 80697147262345 + }, + "Name": "srcEndpoint=(GetWorldTranslation: Out), destEndpoint=(Add (+): In)", + "Components": { + "Component_[9507558893143824342]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 9507558893143824342, + "sourceEndpoint": { + "nodeId": { + "id": 80667082491273 + }, + "slotId": { + "m_id": "{EEBEB400-B5D6-4025-87D8-3DE1EFCCE26A}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 80675672425865 + }, + "slotId": { + "m_id": "{F2AB1C73-D779-4306-A336-96D085EFD20C}" + } + } + } + } + }, + { + "Id": { + "id": 80701442229641 + }, + "Name": "srcEndpoint=(Add (+): Out), destEndpoint=(SetWorldTranslation: In)", + "Components": { + "Component_[15133880696098216097]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 15133880696098216097, + "sourceEndpoint": { + "nodeId": { + "id": 80675672425865 + }, + "slotId": { + "m_id": "{8C84B74E-F975-4957-8039-19E7719327AD}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 80671377458569 + }, + "slotId": { + "m_id": "{6F5CB726-93B1-42EB-B489-2A9C4EEAE97A}" + } + } + } + } + }, + { + "Id": { + "id": 80705737196937 + }, + "Name": "srcEndpoint=(Add (+): Result), destEndpoint=(SetWorldTranslation: Vector3: 1)", + "Components": { + "Component_[11733116393313919050]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 11733116393313919050, + "sourceEndpoint": { + "nodeId": { + "id": 80675672425865 + }, + "slotId": { + "m_id": "{540EF6ED-F6B9-4BCE-A7A9-8271DE09E28E}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 80671377458569 + }, + "slotId": { + "m_id": "{903CDBDF-A22B-477B-AA16-8FDC81255835}" + } + } + } + } + }, + { + "Id": { + "id": 80710032164233 + }, + "Name": "srcEndpoint=(GetOnPresimulateEvent: Result: Event), destEndpoint=(Presimulate event: Presimulate event)", + "Components": { + "Component_[8351382586130482188]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 8351382586130482188, + "sourceEndpoint": { + "nodeId": { + "id": 80684262360457 + }, + "slotId": { + "m_id": "{13AE2AAB-FBEB-4851-A148-325652B1FDC1}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 80679967393161 + }, + "slotId": { + "m_id": "{477D1D40-3833-46BB-8DC7-E4DCCF688E99}" + } + } + } + } + }, + { + "Id": { + "id": 80714327131529 + }, + "Name": "srcEndpoint=(GetOnPresimulateEvent: Out), destEndpoint=(Presimulate event: Connect)", + "Components": { + "Component_[14628666297034614869]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14628666297034614869, + "sourceEndpoint": { + "nodeId": { + "id": 80684262360457 + }, + "slotId": { + "m_id": "{235F1C50-06B0-4793-BD83-C9F3E8B28479}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 80679967393161 + }, + "slotId": { + "m_id": "{785642C6-C68F-4C78-B388-DB2032C55B8B}" + } + } + } + } + }, + { + "Id": { + "id": 80718622098825 + }, + "Name": "srcEndpoint=(EntityBus Handler: ExecutionSlot:OnEntityActivated), destEndpoint=(GetOnPresimulateEvent: In)", + "Components": { + "Component_[16571789671982644265]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 16571789671982644265, + "sourceEndpoint": { + "nodeId": { + "id": 80688557327753 + }, + "slotId": { + "m_id": "{6AAE0625-E567-448A-85EC-002727CB0C9B}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 80684262360457 + }, + "slotId": { + "m_id": "{671D1A67-1F82-4BB4-9287-099AA81073DF}" + } + } + } + } + }, + { + "Id": { + "id": 80722917066121 + }, + "Name": "srcEndpoint=(Presimulate event: OnEvent), destEndpoint=(GetWorldTranslation: In)", + "Components": { + "Component_[2247867446063002806]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 2247867446063002806, + "sourceEndpoint": { + "nodeId": { + "id": 80679967393161 + }, + "slotId": { + "m_id": "{CECB84BC-6AC2-4C51-A38A-63FE7E01A056}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 80667082491273 + }, + "slotId": { + "m_id": "{8D0B9B7A-415D-44B1-B66F-A6C859CDF068}" + } + } + } + } + } + ] + }, + "m_assetType": "{3E2AC8CD-713F-453E-967F-29517F331784}", + "versionData": { + "_grammarVersion": 1, + "_runtimeVersion": 1 + }, + "m_variableCounter": 2, + "GraphCanvasData": [ + { + "Key": { + "id": 80662787523977 + }, + "Value": { + "ComponentData": { + "{5F84B500-8C45-40D1-8EFC-A5306B241444}": { + "$type": "SceneComponentSaveData", + "ViewParams": { + "Scale": 0.7791539, + "AnchorX": -1672.326904296875, + "AnchorY": -143.74566650390625 + } + } + } + } + }, + { + "Key": { + "id": 80667082491273 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -1380.0, + 180.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{9CC9588E-0054-4615-B627-F8D04CAD5970}" + } + } + } + }, + { + "Key": { + "id": 80671377458569 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -400.0, + 160.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{A6FDC96D-8B0B-4B9E-84CF-A4A6DA49FF2D}" + } + } + } + }, + { + "Key": { + "id": 80675672425865 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MathNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -860.0, + 140.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{45DAC3F8-C64F-4E4D-BEC5-E4E888D02A5B}" + } + } + } + }, + { + "Key": { + "id": 80679967393161 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "HandlerNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -1720.0, + 140.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".azeventhandler" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{23D34A34-DB1F-4E79-A120-B50777838FE0}" + } + } + } + }, + { + "Key": { + "id": 80684262360457 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -2080.0, + 140.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{A52D0EA0-17F9-4F50-BC1B-D89AF9E82C8F}" + } + } + } + }, + { + "Key": { + "id": 80688557327753 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -2420.0, + 100.0 + ] + }, + "{9E81C95F-89C0-4476-8E82-63CCC4E52E04}": { + "$type": "EBusHandlerNodeDescriptorSaveData", + "EventIds": [ + { + "Value": 245425936 + } + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{FBA5ADF8-A282-4C7F-A3FF-265E075EE6CA}" + } + } + } + } + ], + "CRCCacheMap": [ + { + "Key": { + "Value": 418594340 + }, + "Value": { + "String": "AZPhysicalWorld", + "Count": 3 + } + }, + { + "Key": { + "Value": 2381303867 + }, + "Value": { + "String": "Az", + "Count": 1 + } + }, + { + "Key": { + "Value": 3249382599 + }, + "Value": { + "String": "DefaultScene", + "Count": 1 + } + } + ], + "StatisticsHelper": { + "InstanceCounter": [ + { + "Key": 1244476766431948410, + "Value": 1 + }, + { + "Key": 4847610523576971761, + "Value": 1 + }, + { + "Key": 5842116761103598202, + "Value": 1 + }, + { + "Key": 13774516554886911373, + "Value": 1 + }, + { + "Key": 13774516556399355685, + "Value": 1 + }, + { + "Key": 16012451037867406043, + "Value": 1 + } + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index fe7b0a06be..b5eb4229df 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -33,6 +33,7 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include // Aws Native SDK #include @@ -716,8 +717,24 @@ void CCryEditApp::OnFileSave() } const QScopedValueRollback rollback(m_savingLevel, true); + + bool usePrefabSystemForLevels = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); - GetIEditor()->GetDocument()->DoFileSave(); + if (!usePrefabSystemForLevels) + { + GetIEditor()->GetDocument()->DoFileSave(); + } + else + { + auto* prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + auto* prefabIntegrationInterface = AZ::Interface::Get(); + AZ_Assert(prefabEditorEntityOwnershipInterface != nullptr, "PrefabEditorEntityOwnershipInterface is not found."); + AZ_Assert(prefabIntegrationInterface != nullptr, "PrefabIntegrationInterface is not found."); + AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); + prefabIntegrationInterface->ExecuteSavePrefabDialog(rootPrefabTemplateId, true); + } } @@ -3128,29 +3145,69 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) bool bIsDocModified = GetIEditor()->GetDocument()->IsModified(); if (GetIEditor()->GetDocument()->IsDocumentReady() && bIsDocModified) { - QString str = QObject::tr("Level %1 has been changed. Save Level?").arg(GetIEditor()->GetGameEngine()->GetLevelName()); - int result = QMessageBox::question(AzToolsFramework::GetActiveWindow(), QObject::tr("Save Level"), str, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - if (QMessageBox::Yes == result) + bool usePrefabSystemForLevels = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + if (!usePrefabSystemForLevels) { - if (!GetIEditor()->GetDocument()->DoFileSave()) + QString str = QObject::tr("Level %1 has been changed. Save Level?").arg(GetIEditor()->GetGameEngine()->GetLevelName()); + int result = QMessageBox::question( + AzToolsFramework::GetActiveWindow(), QObject::tr("Save Level"), str, + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + if (QMessageBox::Yes == result) + { + if (!GetIEditor()->GetDocument()->DoFileSave()) + { + // if the file save operation failed, assume that the user was informed of why + // already and treat it as a cancel + wasCreateLevelOperationCancelled = true; + return false; + } + + bIsDocModified = false; + } + else if (QMessageBox::No == result) + { + // Set Modified flag to false to prevent show Save unchanged dialog again + GetIEditor()->GetDocument()->SetModifiedFlag(false); + } + else if (QMessageBox::Cancel == result) { - // if the file save operation failed, assume that the user was informed of why - // already and treat it as a cancel wasCreateLevelOperationCancelled = true; return false; } + } + else + { + auto* prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + auto* prefabIntegrationInterface = AZ::Interface::Get(); + AZ_Assert(prefabEditorEntityOwnershipInterface != nullptr, "PrefabEditorEntityOwnershipInterface is not found."); + AZ_Assert(prefabIntegrationInterface != nullptr, "PrefabIntegrationInterface is not found."); - bIsDocModified = false; - } - else if (QMessageBox::No == result) - { - // Set Modified flag to false to prevent show Save unchanged dialog again - GetIEditor()->GetDocument()->SetModifiedFlag(false); - } - else if (QMessageBox::Cancel == result) - { - wasCreateLevelOperationCancelled = true; - return false; + if (prefabEditorEntityOwnershipInterface == nullptr || prefabIntegrationInterface == nullptr) + { + return false; + } + + AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); + int prefabSaveSelection = prefabIntegrationInterface->ExecuteClosePrefabDialog(rootPrefabTemplateId); + + // In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here. + // For example, QDialog::Rejected(0) is emitted when dialog is closed. But the int value corresponds to + // QDialogButtonBox::AcceptRole(0). + switch (1 - prefabSaveSelection) + { + case QDialogButtonBox::AcceptRole: + bIsDocModified = false; + break; + case QDialogButtonBox::RejectRole: + wasCreateLevelOperationCancelled = true; + return false; + case QDialogButtonBox::InvalidRole: + // Set Modified flag to false to prevent show Save unchanged dialog again + GetIEditor()->GetDocument()->SetModifiedFlag(false); + break; + } } } diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index ec9a00d1ac..a61429fc87 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -13,6 +13,7 @@ // Qt #include +#include // AzCore #include @@ -30,7 +31,6 @@ #include #include #include -#include // Editor #include "Settings.h" @@ -132,6 +132,19 @@ CCryEditDoc::CCryEditDoc() RegisterConsoleVariables(); MainWindow::instance()->GetActionManager()->RegisterActionHandler(ID_FILE_SAVE_AS, this, &CCryEditDoc::OnFileSaveAs); + bool isPrefabSystemEnabled = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult(isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); + if (isPrefabSystemEnabled) + { + m_prefabSystemComponentInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabSystemComponentInterface, "PrefabSystemComponentInterface is not found."); + m_prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabEditorEntityOwnershipInterface, "PrefabEditorEntityOwnershipInterface is not found."); + m_prefabLoaderInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabLoaderInterface, "PrefabLoaderInterface is not found."); + m_prefabIntegrationInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabIntegrationInterface, "PrefabIntegrationInterface is not found."); + } } CCryEditDoc::~CCryEditDoc() @@ -664,19 +677,56 @@ bool CCryEditDoc::SaveModified() return true; } - auto button = QMessageBox::question(AzToolsFramework::GetActiveWindow(), QString(), tr("Save changes to %1?").arg(GetTitle()), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - switch (button) + bool usePrefabSystemForLevels = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + if (!usePrefabSystemForLevels) { - case QMessageBox::Cancel: - return false; - case QMessageBox::Yes: - return DoFileSave(); - case QMessageBox::No: - SetModifiedFlag(false); - return true; + QMessageBox saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); + saveModifiedMessageBox.setText(QString("Save changes to %1?").arg(GetTitle())); + saveModifiedMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + saveModifiedMessageBox.setIcon(QMessageBox::Icon::Question); + + auto button = QMessageBox::question( + AzToolsFramework::GetActiveWindow(), QString(), tr("Save changes to %1?").arg(GetTitle()), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + switch (button) + { + case QMessageBox::Cancel: + return false; + case QMessageBox::Yes: + return DoFileSave(); + case QMessageBox::No: + SetModifiedFlag(false); + return true; + } + Q_UNREACHABLE(); + } + else + { + AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = m_prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); + if (!m_prefabSystemComponentInterface->AreDirtyTemplatesPresent(rootPrefabTemplateId)) + { + return true; + } + + int prefabSaveSelection = m_prefabIntegrationInterface->ExecuteClosePrefabDialog(rootPrefabTemplateId); + + // In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here. + // For example, QDialog::Rejected(0) is emitted when dialog is closed. But the int value corresponds to + // QDialogButtonBox::AcceptRole(0). + switch (1 - prefabSaveSelection) + { + case QDialogButtonBox::AcceptRole: + return true; + case QDialogButtonBox::RejectRole: + return false; + case QDialogButtonBox::InvalidRole: + SetModifiedFlag(false); + return true; + } + Q_UNREACHABLE(); } - Q_UNREACHABLE(); } void CCryEditDoc::OnFileSaveAs() @@ -690,6 +740,15 @@ void CCryEditDoc::OnFileSaveAs() if (OnSaveDocument(levelFileDialog.GetFileName())) { CCryEditApp::instance()->AddToRecentFileList(levelFileDialog.GetFileName()); + bool usePrefabSystemForLevels = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + if (usePrefabSystemForLevels) + { + AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = + m_prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId(); + SetModifiedFlag(m_prefabSystemComponentInterface->AreDirtyTemplatesPresent(rootPrefabTemplateId)); + } } } } @@ -1238,8 +1297,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename) } else { - auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); - if (prefabEditorEntityOwnershipInterface) + if (m_prefabEditorEntityOwnershipInterface) { AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); AZ_Assert(fileIO, "No File IO implementation available"); @@ -1250,7 +1308,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename) if (openResult) { AZ::IO::FileIOStream stream(tempSaveFileHandle, AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary, false); - contentsAllSaved = prefabEditorEntityOwnershipInterface->SaveToStream(stream, AZStd::string_view(filenameStrData.data(), filenameStrData.size())); + contentsAllSaved = m_prefabEditorEntityOwnershipInterface->SaveToStream(stream, AZStd::string_view(filenameStrData.data(), filenameStrData.size())); stream.Close(); } } diff --git a/Code/Editor/CryEditDoc.h b/Code/Editor/CryEditDoc.h index 9c4c4b3fd9..e64bdb1308 100644 --- a/Code/Editor/CryEditDoc.h +++ b/Code/Editor/CryEditDoc.h @@ -13,8 +13,13 @@ #if !defined(Q_MOC_RUN) #include "DocMultiArchive.h" +#include #include +#include +#include +#include #include +#include #include #include #endif @@ -207,6 +212,10 @@ protected: const char* m_envProbeSliceRelativePath = "EngineAssets/Slices/DefaultLevelSetup.slice"; const float m_envProbeHeight = 200.0f; bool m_hasErrors = false; ///< This is used to warn the user that they may lose work when they go to save. + AzToolsFramework::Prefab::PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr; + AzToolsFramework::PrefabEditorEntityOwnershipInterface* m_prefabEditorEntityOwnershipInterface = nullptr; + AzToolsFramework::Prefab::PrefabLoaderInterface* m_prefabLoaderInterface = nullptr; + AzToolsFramework::Prefab::PrefabIntegrationInterface* m_prefabIntegrationInterface = nullptr; }; class CAutoDocNotReady diff --git a/Code/Editor/EditorPreferencesPageGeneral.cpp b/Code/Editor/EditorPreferencesPageGeneral.cpp index 79ecfbdfc7..95b3bc4c50 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageGeneral.cpp @@ -42,6 +42,10 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Field("EnableSceneInspector", &GeneralSettings::m_enableSceneInspector) ->Field("RestoreViewportCamera", &GeneralSettings::m_restoreViewportCamera); + serialize.Class() + ->Version(1) + ->Field("SaveAllPrefabsPreference", &LevelSaveSettings::m_saveAllPrefabsPreference); + serialize.Class() ->Version(2) ->Field("ShowDashboard", &Messaging::m_showDashboard) @@ -64,6 +68,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) serialize.Class() ->Version(1) ->Field("General Settings", &CEditorPreferencesPage_General::m_generalSettings) + ->Field("Level Save Settings", &CEditorPreferencesPage_General::m_levelSaveSettings) ->Field("Messaging", &CEditorPreferencesPage_General::m_messaging) ->Field("Undo", &CEditorPreferencesPage_General::m_undo) ->Field("Deep Selection", &CEditorPreferencesPage_General::m_deepSelection) @@ -92,6 +97,14 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_restoreViewportCamera, EditorPreferencesGeneralRestoreViewportCameraSettingName, "Keep the original editor viewport transform when exiting game mode.") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enableSceneInspector, "Enable Scene Inspector (EXPERIMENTAL)", "Enable the option to inspect the internal data loaded from scene files like .fbx. This is an experimental feature. Restart the Scene Settings if the option is not visible under the Help menu."); + editContext->Class("Level Save Settings", "") + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &LevelSaveSettings::m_saveAllPrefabsPreference, "Save All Prefabs Preference", + "This option controls whether prefabs should be saved along with the level") + ->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::AskEveryTime, "Ask every time") + ->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::SaveAll, "Save all") + ->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::SaveNone, "Save none"); + editContext->Class("Messaging", "") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showDashboard, "Show Welcome to Open 3D Engine at startup", "Show Welcome to Open 3D Engine at startup") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showCircularDependencyError, "Show Error: Circular dependency", "Show an error message when adding a slice instance to the target slice would create a cyclic asset dependency. All other valid overrides will be saved even if this is turned off."); @@ -115,6 +128,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_generalSettings, "General Settings", "General Editor Preferences") + ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_levelSaveSettings, "Level Save Settings", "File>Save") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_messaging, "Messaging", "Messaging") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_undo, "Undo", "Undo Preferences") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_deepSelection, "Selection", "Selection") @@ -161,6 +175,9 @@ void CEditorPreferencesPage_General::OnApply() MainWindow::instance()->AdjustToolBarIconSize(m_generalSettings.m_toolbarIconSize); } + //prefabs + gSettings.levelSaveSettings.saveAllPrefabsPreference = m_levelSaveSettings.m_saveAllPrefabsPreference; + //undo gSettings.undoLevels = m_undo.m_undoLevels; @@ -190,6 +207,9 @@ void CEditorPreferencesPage_General::InitializeSettings() m_generalSettings.m_toolbarIconSize = static_cast(gSettings.gui.nToolbarIconSize); + //prefabs + m_levelSaveSettings.m_saveAllPrefabsPreference = gSettings.levelSaveSettings.saveAllPrefabsPreference; + //Messaging m_messaging.m_showDashboard = gSettings.bShowDashboardAtStartup; m_messaging.m_showCircularDependencyError = gSettings.m_showCircularDependencyError; diff --git a/Code/Editor/EditorPreferencesPageGeneral.h b/Code/Editor/EditorPreferencesPageGeneral.h index 9a3a0f21e8..01700dea88 100644 --- a/Code/Editor/EditorPreferencesPageGeneral.h +++ b/Code/Editor/EditorPreferencesPageGeneral.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "Settings.h" @@ -57,6 +58,12 @@ private: bool m_enableSceneInspector; }; + struct LevelSaveSettings + { + AZ_TYPE_INFO(LevelSaveSettings, "{E297DAE3-3985-4BC2-8B43-45F3B1522F6B}"); + AzToolsFramework::Prefab::SaveAllPrefabsPreference m_saveAllPrefabsPreference; + }; + struct Messaging { AZ_TYPE_INFO(Messaging, "{A6AD87CB-E905-409B-A2BF-C43CDCE63B0C}") @@ -89,6 +96,7 @@ private: }; GeneralSettings m_generalSettings; + LevelSaveSettings m_levelSaveSettings; Messaging m_messaging; Undo m_undo; DeepSelection m_deepSelection; diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index b33469affb..736bbe5feb 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -1087,6 +1087,7 @@ void EditorViewportWidget::ConnectViewportInteractionRequestBus() { AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusConnect(GetViewportId()); AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusConnect(GetViewportId()); + AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(GetViewportId()); m_viewportUi.ConnectViewportUiBus(GetViewportId()); AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusConnect(); @@ -1097,6 +1098,7 @@ void EditorViewportWidget::DisconnectViewportInteractionRequestBus() AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusDisconnect(); m_viewportUi.DisconnectViewportUiBus(); + AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusDisconnect(); } diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index 5d332ae3f0..dff0adb55a 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -91,6 +91,7 @@ class SANDBOX_API EditorViewportWidget final , private AzFramework::InputSystemCursorConstraintRequestBus::Handler , private AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler , private AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler + , private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler , private AzFramework::AssetCatalogEventBus::Handler , private AZ::RPI::SceneNotificationBus::Handler { @@ -128,10 +129,12 @@ private: CameraComponent, ViewSourceTypesCount, }; + enum class PlayInEditorState { Editor, Starting, Started }; + enum class KeyPressedState { AllUp, @@ -142,7 +145,7 @@ private: //////////////////////////////////////////////////////////////////////// // Method overrides ... - // QWidget + // QWidget overrides ... void focusOutEvent(QFocusEvent* event) override; void keyPressEvent(QKeyEvent* event) override; bool event(QEvent* event) override; @@ -150,7 +153,7 @@ private: void paintEvent(QPaintEvent* event) override; void mousePressEvent(QMouseEvent* event) override; - // QtViewport/IDisplayViewport/CViewport + // QtViewport/IDisplayViewport/CViewport overrides ... EViewportType GetType() const override { return ET_ViewportCamera; } void SetType([[maybe_unused]] EViewportType type) override { assert(type == ET_ViewportCamera); }; AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteraction( @@ -176,16 +179,17 @@ private: void Update() override; void UpdateContent(int flags) override; - // SceneNotificationBus + // SceneNotificationBus overrides ... void OnBeginPrepareRender() override; - // Camera::CameraNotificationBus + // Camera::CameraNotificationBus overrides ... void OnActiveViewChanged(const AZ::EntityId&) override; - // IEditorEventListener + // IEditorEventListener overrides ... void OnEditorNotifyEvent(EEditorNotifyEvent event) override; - // AzToolsFramework::EditorEntityContextNotificationBus (handler moved to cpp to resolve link issues in unity builds) + // AzToolsFramework::EditorEntityContextNotificationBus overrides ... + // note: handler moved to cpp to resolve link issues in unity builds void OnStartPlayInEditor(); void OnStopPlayInEditor(); void OnStartPlayInEditorBegin(); @@ -194,10 +198,10 @@ private: void BeginUndoTransaction() override; void EndUndoTransaction() override; - // AzFramework::InputSystemCursorConstraintRequestBus + // AzFramework::InputSystemCursorConstraintRequestBus overrides ... void* GetSystemCursorConstraintWindow() const override; - // AzToolsFramework::ViewportFreezeRequestBus + // AzToolsFramework::ViewportFreezeRequestBus overrides ... bool IsViewportInputFrozen() override; void FreezeViewportInput(bool freeze) override; @@ -205,13 +209,15 @@ private: AZ::EntityId PickEntity(const AzFramework::ScreenPoint& point) override; AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) override; float TerrainHeight(const AZ::Vector2& position) override; - void FindVisibleEntities(AZStd::vector& visibleEntitiesOut) override; bool ShowingWorldSpace() override; QWidget* GetWidgetForViewportContextMenu() override; void BeginWidgetContext() override; void EndWidgetContext() override; - // Camera::EditorCameraRequestBus + // EditorEntityViewportInteractionRequestBus overrides ... + void FindVisibleEntities(AZStd::vector& visibleEntities) override; + + // Camera::EditorCameraRequestBus overrides ... void SetViewFromEntityPerspective(const AZ::EntityId& entityId) override; void SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) override; AZ::EntityId GetCurrentViewEntityId() override; @@ -327,7 +333,7 @@ private: // Determines also if the current camera for this viewport is default editor camera ViewSourceType m_viewSourceType = ViewSourceType::None; - // During play game in editor, holds the editor entity ID of the last + // During play game in editor, holds the editor entity ID of the last AZ::EntityId m_viewEntityIdCachedForEditMode; // The editor camera TM before switching to game mode diff --git a/Code/Editor/Include/ObjectEvent.h b/Code/Editor/Include/ObjectEvent.h index 7d137d7b84..e59bca6111 100644 --- a/Code/Editor/Include/ObjectEvent.h +++ b/Code/Editor/Include/ObjectEvent.h @@ -27,7 +27,6 @@ enum ObjectEvent EVENT_OUTOFGAME, //!< Signals that editor is switching out of the game mode. EVENT_REFRESH, //!< Signals that editor is refreshing level. EVENT_DBLCLICK, //!< Signals that object have been double clicked. - EVENT_KEEP_HEIGHT, //!< Signals that object must preserve its height over changed terrain. EVENT_RELOAD_ENTITY,//!< Signals that entities scripts must be reloaded. EVENT_RELOAD_GEOM, //!< Signals that all possible geometries should be reloaded. EVENT_UNLOAD_GEOM, //!< Signals that all possible geometries should be unloaded. diff --git a/Code/Editor/Objects/BaseObject.cpp b/Code/Editor/Objects/BaseObject.cpp index 14291a3e4d..4ae01faddf 100644 --- a/Code/Editor/Objects/BaseObject.cpp +++ b/Code/Editor/Objects/BaseObject.cpp @@ -618,12 +618,6 @@ bool CBaseObject::SetPos(const Vec3& pos, int flags) StoreUndo("Position", true, flags); } - float terrainElevation = AzFramework::Terrain::TerrainDataRequests::GetDefaultTerrainHeight(); - AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(terrainElevation - , &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats - , pos.x, pos.y, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR, nullptr); - m_height = pos.z - terrainElevation; - if (!bPositionDelegated) { m_pos = pos; @@ -1275,14 +1269,6 @@ void CBaseObject::OnEvent(ObjectEvent event) { switch (event) { - case EVENT_KEEP_HEIGHT: - { - float h = m_height; - float newz = GetIEditor()->GetTerrainElevation(m_pos.x, m_pos.y) + m_height; - SetPos(Vec3(m_pos.x, m_pos.y, newz)); - m_height = h; - } - break; case EVENT_CONFIG_SPEC_CHANGE: UpdateVisibility(!IsHidden()); break; diff --git a/Code/Editor/Objects/BaseObject.h b/Code/Editor/Objects/BaseObject.h index c973b2f293..0b37a3b852 100644 --- a/Code/Editor/Objects/BaseObject.h +++ b/Code/Editor/Objects/BaseObject.h @@ -795,8 +795,6 @@ private: ////////////////////////////////////////////////////////////////////////// //! Area radius around object, where terrain is flatten and static objects removed. float m_flattenArea; - //! Every object keeps for itself height above terrain. - float m_height; //! Object's name. QString m_name; //! Class description for this object. diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index 9feb73a811..80d248e1bf 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -241,6 +241,7 @@ SEditorSettings::SEditorSettings() g_TemporaryLevelName = nullptr; sliceSettings.dynamicByDefault = false; + levelSaveSettings.saveAllPrefabsPreference = AzToolsFramework::Prefab::SaveAllPrefabsPreference::AskEveryTime; } void SEditorSettings::Connect() @@ -643,12 +644,20 @@ void SEditorSettings::Save() AzFramework::ApplicationRequests::Bus::Broadcast( &AzFramework::ApplicationRequests::SetPrefabSystemEnabled, prefabSystem); + AzToolsFramework::Prefab::PrefabLoaderInterface* prefabLoaderInterface = + AZ::Interface::Get(); + prefabLoaderInterface->SetSaveAllPrefabsPreference(levelSaveSettings.saveAllPrefabsPreference); + SaveSettingsRegistryFile(); } ////////////////////////////////////////////////////////////////////////// void SEditorSettings::Load() { + AzToolsFramework::Prefab::PrefabLoaderInterface* prefabLoaderInterface = + AZ::Interface::Get(); + levelSaveSettings.saveAllPrefabsPreference = prefabLoaderInterface->GetSaveAllPrefabsPreference(); + // Load from Settings Registry AzFramework::ApplicationRequests::Bus::BroadcastResult( prefabSystem, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); @@ -1110,11 +1119,17 @@ void SEditorSettings::SaveSettingsRegistryFile() AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings; dumperSettings.m_prettifyOutput = true; - dumperSettings.m_jsonPointerPrefix = "/Amazon/Preferences"; + dumperSettings.m_includeFilter = [](AZStd::string_view path) + { + AZStd::string_view amazonPrefixPath("/Amazon/Preferences"); + AZStd::string_view o3dePrefixPath("/O3DE/Preferences"); + return amazonPrefixPath.starts_with(path.substr(0, amazonPrefixPath.size())) || + o3dePrefixPath.starts_with(path.substr(0, o3dePrefixPath.size())); + }; AZStd::string stringBuffer; AZ::IO::ByteContainerStream stringStream(&stringBuffer); - if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(*registry, "/Amazon/Preferences", stringStream, dumperSettings)) + if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(*registry, "", stringStream, dumperSettings)) { AZ_Warning("SEditorSettings", false, R"(Unable to save changes to the Editor Preferences registry file at "%s"\n)", editorPreferencesFilePath.c_str()); diff --git a/Code/Editor/Settings.h b/Code/Editor/Settings.h index 82f4f11f72..a408822129 100644 --- a/Code/Editor/Settings.h +++ b/Code/Editor/Settings.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -214,6 +215,11 @@ struct SSliceSettings bool dynamicByDefault; }; +struct SLevelSaveSettings +{ + AzToolsFramework::Prefab::SaveAllPrefabsPreference saveAllPrefabsPreference; +}; + ////////////////////////////////////////////////////////////////////////// struct SAssetBrowserSettings { @@ -448,6 +454,8 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING SSliceSettings sliceSettings; + SLevelSaveSettings levelSaveSettings; + bool prefabSystem = true; ///< Toggle to enable/disable the Prefab system for level entities. private: diff --git a/Code/Editor/Style/Editor.qss b/Code/Editor/Style/Editor.qss index b900dbeff3..302b7703a5 100644 --- a/Code/Editor/Style/Editor.qss +++ b/Code/Editor/Style/Editor.qss @@ -244,3 +244,41 @@ QTableWidget#recentLevelTable::item { max-height: 16px; qproperty-iconSize: 16px 16px; } + + +#ClosePrefabDialog, #SavePrefabDialog +{ + min-width : 640px; +} + +#SaveDependentPrefabsCard +{ + margin: 0px 15px 10px 15px; +} + +#PrefabSavedMessageFrame{ + border: 1px solid green; + margin: 10px 15px 10px 15px; + border-radius: 2px; + padding: 5px 2px 5px 2px; +} + +#ClosePrefabDialog #PrefabSaveWarningFrame +{ + border: 1px solid orange; + margin: 10px 15px 10px 15px; + border-radius: 2px; + padding: 5px 2px 5px 2px; + color : white; +} + +#SavePrefabDialog #FooterSeparatorLine +{ + color: gray; +} + +#SavePrefabDialog #PrefabSavePreferenceHint +{ + font: italic; + color: #999999; +} \ No newline at end of file diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index 92e193bddf..9c6088e340 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -1092,9 +1092,8 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo) const int viewportId = GetViewportId(); AzToolsFramework::EntityIdList visibleEntityIds; - AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Event( - viewportId, - &AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequests::FindVisibleEntities, + AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Event( + viewportId, &AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Events::FindVisibleEntities, visibleEntityIds); // Look through all visible entities to find the closest one to the specified mouse point diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetCommon.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetCommon.cpp index af3aba49a3..fdc3053b5c 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetCommon.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetCommon.cpp @@ -213,7 +213,7 @@ namespace AZ void AssetData::Acquire() { - AZ_Assert(m_useCount >= 0, "AssetData has been deleted") + AZ_Assert(m_useCount >= 0, "AssetData has been deleted"); AcquireWeak(); ++m_useCount; diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetCommon.h b/Code/Framework/AzCore/AzCore/Asset/AssetCommon.h index 477677948f..0c8e5209ca 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetCommon.h +++ b/Code/Framework/AzCore/AzCore/Asset/AssetCommon.h @@ -990,7 +990,7 @@ namespace AZ template u8 Asset::GetFlags() const { - AZ_Warning("Asset", false, "Deprecated - replaced by GetAutoLoadBehavior") + AZ_Warning("Asset", false, "Deprecated - replaced by GetAutoLoadBehavior"); return static_cast(m_loadBehavior); } @@ -1012,7 +1012,7 @@ namespace AZ template bool Asset::SetFlags(u8 flags) { - AZ_Warning("Asset", false, "Deprecated - replaced by SetAutoLoadBehavior") + AZ_Warning("Asset", false, "Deprecated - replaced by SetAutoLoadBehavior"); if (!m_assetData) { AZ_Assert(flags < static_cast(AssetLoadBehavior::Count), "Flags value is out of range"); diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp index 6ba69cffd5..98182a9568 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetManager.cpp @@ -2132,7 +2132,7 @@ namespace AZ } else { - AZ_Warning("AssetManager", false, "Couldn't find handler for asset %s (%s)", asset.GetId().ToString().c_str(), asset.GetHint().c_str()) + AZ_Warning("AssetManager", false, "Couldn't find handler for asset %s (%s)", asset.GetId().ToString().c_str(), asset.GetHint().c_str()); } // Notify any dependent jobs. diff --git a/Code/Framework/AzCore/AzCore/Debug/Trace.h b/Code/Framework/AzCore/AzCore/Debug/Trace.h index 5cb8c23821..a1334d334e 100644 --- a/Code/Framework/AzCore/AzCore/Debug/Trace.h +++ b/Code/Framework/AzCore/AzCore/Debug/Trace.h @@ -8,8 +8,7 @@ #pragma once #include -#define AZ_VA_HAS_ARGS(...) ""#__VA_ARGS__[0] != 0 - +#include namespace AZ { @@ -262,17 +261,18 @@ namespace AZ #define AZ_VerifyWarning(window, expression, ...) AZ_Warning(window, 0 != (expression), __VA_ARGS__) #else // !AZ_ENABLE_TRACING - #define AZ_Assert(expression, ...) - #define AZ_Error(window, expression, ...) - #define AZ_ErrorOnce(window, expression, ...) - #define AZ_Warning(window, expression, ...) - #define AZ_WarningOnce(window, expression, ...) - #define AZ_TracePrintf(window, ...) - #define AZ_TracePrintfOnce(window, ...) - #define AZ_Verify(expression, ...) (void)(expression) - #define AZ_VerifyError(window, expression, ...) (void)(expression) - #define AZ_VerifyWarning(window, expression, ...) (void)(expression) + #define AZ_Assert(...) AZ_UNUSED(__VA_ARGS__); + #define AZ_Error(...) AZ_UNUSED(__VA_ARGS__); + #define AZ_ErrorOnce(...) AZ_UNUSED(__VA_ARGS__); + #define AZ_Warning(...) AZ_UNUSED(__VA_ARGS__); + #define AZ_WarningOnce(...) AZ_UNUSED(__VA_ARGS__); + #define AZ_TracePrintf(...) AZ_UNUSED(__VA_ARGS__); + #define AZ_TracePrintfOnce(...) AZ_UNUSED(__VA_ARGS__); + + #define AZ_Verify(...) AZ_UNUSED(__VA_ARGS__); + #define AZ_VerifyError(...) AZ_UNUSED(__VA_ARGS__); + #define AZ_VerifyWarning(...) AZ_UNUSED(__VA_ARGS__); #endif // AZ_ENABLE_TRACING diff --git a/Code/Framework/AzCore/AzCore/Driller/Stream.cpp b/Code/Framework/AzCore/AzCore/Driller/Stream.cpp index 761f964561..14e983b09c 100644 --- a/Code/Framework/AzCore/AzCore/Driller/Stream.cpp +++ b/Code/Framework/AzCore/AzCore/Driller/Stream.cpp @@ -693,7 +693,7 @@ namespace AZ } else { - AZ_Assert(m_isPooledString == false && m_isPooledStringCrc32 == false, "This stream requires using of a string pool as the string is send only once and afterwards only the Crc32 is used!") + AZ_Assert(m_isPooledString == false && m_isPooledStringCrc32 == false, "This stream requires using of a string pool as the string is send only once and afterwards only the Crc32 is used!"); } return srcData; } diff --git a/Code/Framework/AzCore/AzCore/IO/IStreamerTypes.h b/Code/Framework/AzCore/AzCore/IO/IStreamerTypes.h index 6afe078514..901fc5e594 100644 --- a/Code/Framework/AzCore/AzCore/IO/IStreamerTypes.h +++ b/Code/Framework/AzCore/AzCore/IO/IStreamerTypes.h @@ -150,9 +150,7 @@ namespace AZ::IO::IStreamerTypes private: AZStd::atomic_int m_lockCounter{ 0 }; -#ifdef AZ_ENABLE_TRACING AZStd::atomic_int m_allocationCounter{ 0 }; -#endif AZ::IAllocatorAllocate& m_allocator; }; diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp index e4e3141c11..5a35603d0a 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp @@ -222,7 +222,7 @@ namespace AZ int AddRefCount(int value) { - AZ_Assert(value == 1 || value == -1, "ModRefCount is only for incrementing or decrementing on copy or destruction of ExposedLambda") + AZ_Assert(value == 1 || value == -1, "ModRefCount is only for incrementing or decrementing on copy or destruction of ExposedLambda"); lua_rawgeti(m_lua, LUA_REGISTRYINDEX, m_refCountRegistryIndex); // Lua: refCount-old const int refCount = Internal::azlua_tointeger(m_lua, -1) + value; diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.cpp index af35842afc..1a4e7b3e80 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.cpp @@ -240,11 +240,6 @@ namespace AZ { IO::SizeType length = stream.GetLength(); - if (length > AZ::Utils::DefaultMaxFileSize) - { - return AZ::Failure(AZStd::string{ "Data is too large." }); - } - AZStd::vector memoryBuffer; memoryBuffer.resize_no_construct(static_cast::size_type>(static_cast::size_type>(length) + 1)); @@ -259,12 +254,12 @@ namespace AZ return ReadJsonString(AZStd::string_view{memoryBuffer.data(), memoryBuffer.size()}); } - AZ::Outcome ReadJsonFile(AZStd::string_view filePath) + AZ::Outcome ReadJsonFile(AZStd::string_view filePath, size_t maxFileSize) { // Read into memory first and then parse the json, rather than passing a file stream to rapidjson. // This should avoid creating a large number of micro-reads from the file. - auto readResult = AZ::Utils::ReadFile(filePath); + auto readResult = AZ::Utils::ReadFile(filePath, maxFileSize); if(!readResult.IsSuccess()) { return AZ::Failure(readResult.GetError()); @@ -308,6 +303,55 @@ namespace AZ return AZ::Success(); } + AZ::Outcome LoadObjectFromStringByType(void* objectToLoad, const Uuid& classId, AZStd::string_view stream, + const JsonDeserializerSettings* settings) + { + JsonDeserializerSettings loadSettings; + AZStd::string deserializeErrors; + auto prepare = PrepareDeserializerSettings(settings, loadSettings, deserializeErrors); + if (!prepare.IsSuccess()) + { + return AZ::Failure(prepare.GetError()); + } + + auto parseResult = ReadJsonString(stream); + if (!parseResult.IsSuccess()) + { + return AZ::Failure(parseResult.GetError()); + } + + const rapidjson::Document& jsonDocument = parseResult.GetValue(); + + auto validateResult = ValidateJsonClassHeader(jsonDocument); + if (!validateResult.IsSuccess()) + { + return AZ::Failure(validateResult.GetError()); + } + + const char* className = jsonDocument.FindMember(ClassNameTag)->value.GetString(); + + // validate class name + auto classData = loadSettings.m_serializeContext->FindClassData(classId); + if (!classData) + { + return AZ::Failure(AZStd::string::format("Try to load class from Id %s", classId.ToString().c_str())); + } + + if (azstricmp(classData->m_name, className) != 0) + { + return AZ::Failure(AZStd::string::format("Try to load class %s from class %s data", classData->m_name, className)); + } + + JsonSerializationResult::ResultCode result = JsonSerialization::Load(objectToLoad, classId, jsonDocument.FindMember(ClassDataTag)->value, loadSettings); + + if (!WasLoadSuccess(result.GetOutcome()) || !deserializeErrors.empty()) + { + return AZ::Failure(deserializeErrors); + } + + return AZ::Success(); + } + AZ::Outcome LoadObjectFromStreamByType(void* objectToLoad, const Uuid& classId, IO::GenericStream& stream, const JsonDeserializerSettings* settings) { diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.h index c7777feec0..89ef341aff 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonUtils.h @@ -70,13 +70,18 @@ namespace AZ //! Parse json text. Returns a failure with error message if the content is not valid JSON. AZ::Outcome ReadJsonString(AZStd::string_view jsonText); - //! Parse a json file. Returns a failure with error message if the content is not valid JSON. - AZ::Outcome ReadJsonFile(AZStd::string_view filePath); + //! Parse a json file. Returns a failure with error message if the content is not valid JSON or if + //! the file size is larger than the max file size provided. + AZ::Outcome ReadJsonFile( + AZStd::string_view filePath, size_t maxFileSize = AZStd::numeric_limits::max()); //! Parse a json stream. Returns a failure with error message if the content is not valid JSON. AZ::Outcome ReadJsonStream(IO::GenericStream& stream); //! Load object with known class type + AZ::Outcome LoadObjectFromStringByType(void* objectToLoad, const Uuid& objectType, AZStd::string_view source, + const JsonDeserializerSettings* settings = nullptr); + AZ::Outcome LoadObjectFromStreamByType(void* objectToLoad, const Uuid& objectType, IO::GenericStream& stream, const JsonDeserializerSettings* settings = nullptr); diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp index 39132ddb52..7978b8104b 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp @@ -293,7 +293,7 @@ namespace AZ } AZ_Assert(!keyValues.Empty(), "Intermediate array for associative container can't be empty " - "because an empty array would be stored as an empty default object.") + "because an empty array would be stored as an empty default object."); if (CanBeConvertedToObject(keyValues)) { diff --git a/Code/Framework/AzCore/AzCore/Serialization/SerializeContext.cpp b/Code/Framework/AzCore/AzCore/Serialization/SerializeContext.cpp index f326b021e7..b74039c876 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/SerializeContext.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/SerializeContext.cpp @@ -2300,7 +2300,7 @@ namespace AZ { if (classData->m_converter) { - AZ_Assert(false, "A deprecated element with a data converter was passed to CloneObject, this is not supported.") + AZ_Assert(false, "A deprecated element with a data converter was passed to CloneObject, this is not supported."); } // push a dummy node in the stack cloneData->m_parentStack.push_back(); diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 28e5a68e0b..5290c9b02a 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -110,12 +110,12 @@ namespace AZ::Internal { FixedValueString engineName; settingsRegistry.Get(engineName, engineMonikerKey); - AZ_Warning("SettingsRegistryMergeUtils",engineInfo.m_moniker == engineName, + AZ_Warning("SettingsRegistryMergeUtils", engineInfo.m_moniker == engineName, R"(The engine name key "%s" mapped to engine path "%s" within the global manifest of "%s")" R"( does not match the "engine_name" field "%s" in the engine.json)" "\n" "This engine should be re-registered.", engineInfo.m_moniker.c_str(), engineInfo.m_path.c_str(), engineManifestPath.c_str(), - engineName.c_str()) + engineName.c_str()); engineInfo.m_moniker = engineName; } } diff --git a/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp b/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp index 03ed3f6ebb..82a9175cf9 100644 --- a/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Slice/SliceComponent.cpp @@ -3464,7 +3464,7 @@ namespace AZ const SliceComponent::DataFlagsPerEntity* SliceComponent::GetCorrectBundleOfDataFlags(EntityId entityId) const { // It would be possible to search non-instantiated slices by crawling over lists, but we haven't needed the capability yet. - AZ_Assert(IsInstantiated(), "Data flag access is only permitted after slice is instantiated.") + AZ_Assert(IsInstantiated(), "Data flag access is only permitted after slice is instantiated."); if (IsInstantiated()) { diff --git a/Code/Framework/AzCore/AzCore/Utils/Utils.h b/Code/Framework/AzCore/AzCore/Utils/Utils.h index e72a9b3f9c..d8d4290f7f 100644 --- a/Code/Framework/AzCore/AzCore/Utils/Utils.h +++ b/Code/Framework/AzCore/AzCore/Utils/Utils.h @@ -22,10 +22,6 @@ namespace AZ { namespace Utils { - //! Protects from allocating too much memory. The choice of a 1MB threshold is arbitrary. - //! If you need to work with larger files, please use AZ::IO directly instead of these utility functions. - inline constexpr size_t DefaultMaxFileSize = 1024 * 1024; - //! Terminates the application without going through the shutdown procedure. //! This is used when due to abnormal circumstances the application can no //! longer continue. On most platforms and in most configurations this will @@ -115,6 +111,7 @@ namespace AZ //! Read a file into a string. Returns a failure with error message if the content could not be loaded or if //! the file size is larger than the max file size provided. template - AZ::Outcome ReadFile(AZStd::string_view filePath, size_t maxFileSize = DefaultMaxFileSize); + AZ::Outcome ReadFile( + AZStd::string_view filePath, size_t maxFileSize = AZStd::numeric_limits::max()); } } diff --git a/Code/Framework/AzCore/AzCore/base.h b/Code/Framework/AzCore/AzCore/base.h index f6ae39dcda..f2a64c3224 100644 --- a/Code/Framework/AzCore/AzCore/base.h +++ b/Code/Framework/AzCore/AzCore/base.h @@ -143,6 +143,9 @@ * example. AZ_VA_NUM_ARGS(x,y,z) -> expands to 3 */ #ifndef AZ_VA_NUM_ARGS + +# define AZ_VA_HAS_ARGS(...) ""#__VA_ARGS__[0] != 0 + // we add the zero to avoid the case when we require at least 1 param at the end... # define AZ_VA_NUM_ARGS(...) AZ_VA_NUM_ARGS_IMPL_((__VA_ARGS__, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) # define AZ_VA_NUM_ARGS_IMPL_(tuple) AZ_VA_NUM_ARGS_IMPL tuple @@ -170,15 +173,15 @@ // This is a pain they we use macros to call functions (with no params). // we implement functions for up to 10 params -#define AZ_FUNCTION_CALL_1(_1) _1() -#define AZ_FUNCTION_CALL_2(_1, _2) _1(_2) -#define AZ_FUNCTION_CALL_3(_1, _2, _3) _1(_2, _3) -#define AZ_FUNCTION_CALL_4(_1, _2, _3, _4) _1(_2, _3, _4) -#define AZ_FUNCTION_CALL_5(_1, _2, _3, _4, _5) _1(_2, _3, _4, _5) -#define AZ_FUNCTION_CALL_6(_1, _2, _3, _4, _5, _6) _1(_2, _3, _4, _5, _6) -#define AZ_FUNCTION_CALL_7(_1, _2, _3, _4, _5, _6, _7) _1(_2, _3, _4, _5, _6, _7) -#define AZ_FUNCTION_CALL_8(_1, _2, _3, _4, _5, _6, _7, _8) _1(_2, _3, _4, _5, _6, _7, _8) -#define AZ_FUNCTION_CALL_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) _1(_2, _3, _4, _5, _6, _7, _8, _9) +#define AZ_FUNCTION_CALL_1(_1) _1() +#define AZ_FUNCTION_CALL_2(_1, _2) _1(_2) +#define AZ_FUNCTION_CALL_3(_1, _2, _3) _1(_2, _3) +#define AZ_FUNCTION_CALL_4(_1, _2, _3, _4) _1(_2, _3, _4) +#define AZ_FUNCTION_CALL_5(_1, _2, _3, _4, _5) _1(_2, _3, _4, _5) +#define AZ_FUNCTION_CALL_6(_1, _2, _3, _4, _5, _6) _1(_2, _3, _4, _5, _6) +#define AZ_FUNCTION_CALL_7(_1, _2, _3, _4, _5, _6, _7) _1(_2, _3, _4, _5, _6, _7) +#define AZ_FUNCTION_CALL_8(_1, _2, _3, _4, _5, _6, _7, _8) _1(_2, _3, _4, _5, _6, _7, _8) +#define AZ_FUNCTION_CALL_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) _1(_2, _3, _4, _5, _6, _7, _8, _9) #define AZ_FUNCTION_CALL_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) _1(_2, _3, _4, _5, _6, _7, _8, _9, _10) // We require at least 1 param FunctionName @@ -293,7 +296,20 @@ namespace AZ #define AZ_DEFAULT_COPY_MOVE(_Class) AZ_DEFAULT_COPY(_Class) AZ_DEFAULT_MOVE(_Class) // Macro that can be used to avoid unreferenced variable warnings -#define AZ_UNUSED(x) (void)x +#define AZ_UNUSED_1(x) (void)(x); +#define AZ_UNUSED_2(x1, x2) AZ_UNUSED_1(x1) AZ_UNUSED_1(x2) +#define AZ_UNUSED_3(x1, x2, x3) AZ_UNUSED_1(x1) AZ_UNUSED_2(x2, x3) +#define AZ_UNUSED_4(x1, x2, x3, x4) AZ_UNUSED_2(x1, x2) AZ_UNUSED_2(x3, x4) +#define AZ_UNUSED_5(x1, x2, x3, x4, x5) AZ_UNUSED_2(x1, x2) AZ_UNUSED_3(x3, x4, x5) +#define AZ_UNUSED_6(x1, x2, x3, x4, x5, x6) AZ_UNUSED_3(x1, x2, x3) AZ_UNUSED_3(x4, x5, x6) +#define AZ_UNUSED_7(x1, x2, x3, x4, x5, x6, x7) AZ_UNUSED_3(x1, x2, x3) AZ_UNUSED_4(x4, x5, x6, x7) +#define AZ_UNUSED_8(x1, x2, x3, x4, x5, x6, x7, x8) AZ_UNUSED_4(x1, x2, x3, x4) AZ_UNUSED_4(x5, x6, x7, x8) +#define AZ_UNUSED_9(x1, x2, x3, x4, x5, x6, x7, x8, x9) AZ_UNUSED_4(x1, x2, x3, x4) AZ_UNUSED_5(x5, x6, x7, x8, x9) +#define AZ_UNUSED_10(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) AZ_UNUSED_5(x1, x2, x3, x4, x5) AZ_UNUSED_5(x6, x7, x8, x9, x10) +#define AZ_UNUSED_11(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) AZ_UNUSED_5(x1, x2, x3, x4, x5) AZ_UNUSED_6(x6, x7, x8, x9, x10, x11) +#define AZ_UNUSED_12(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) AZ_UNUSED_6(x1, x2, x3, x4, x5, x6) AZ_UNUSED_6(x7, x8, x9, x10, x11, x12) + +#define AZ_UNUSED(...) AZ_MACRO_SPECIALIZE(AZ_UNUSED_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__)) #define AZ_DEFINE_ENUM_BITWISE_OPERATORS(EnumType) \ inline constexpr EnumType operator | (EnumType a, EnumType b) \ diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp index cc45b36c41..39cb9e8c10 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/Platform_Windows.cpp @@ -42,7 +42,7 @@ namespace AZ } else { - AZ_Error("System", false, "Failed to open HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography\\MachineGuid!") + AZ_Error("System", false, "Failed to open HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography\\MachineGuid!"); } wchar_t* hostname = machineInfo + wcslen(machineInfo); diff --git a/Code/Framework/AzCore/Tests/Patching.cpp b/Code/Framework/AzCore/Tests/Patching.cpp index ee887d66c2..29b25ebf28 100644 --- a/Code/Framework/AzCore/Tests/Patching.cpp +++ b/Code/Framework/AzCore/Tests/Patching.cpp @@ -2651,7 +2651,7 @@ namespace UnitTest if (!rootElement.GetChildData(AZ_CRC("InnerBaseStringField"), stringField)) { AZ_Error("PatchingTest", false, "Unable to retrieve 'InnerBaseStringField' data for %u version of the InnerObjectFieldConverterClass", - rootElement.GetVersion()) + rootElement.GetVersion()); return false; } diff --git a/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h b/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h index dbbf443656..1c5db0a82b 100644 --- a/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h +++ b/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h @@ -18,6 +18,7 @@ #include #include #include +#include #include diff --git a/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h b/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h index 0a4e1e01ae..49506364f4 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,8 @@ namespace AzFramework virtual AZ::u32 SetState(AZ::u32 state) { (void)state; return 0; } virtual void PushMatrix(const AZ::Transform& tm) { (void)tm; } virtual void PopMatrix() {} + virtual void PushPremultipliedMatrix(const AZ::Matrix3x4& matrix) { (void)matrix; } + virtual AZ::Matrix3x4 PopPremultipliedMatrix() { return AZ::Matrix3x4::CreateIdentity(); } protected: virtual ~DebugDisplayRequests() = default; diff --git a/Code/Framework/AzFramework/AzFramework/IO/RemoteStorageDrive.cpp b/Code/Framework/AzFramework/AzFramework/IO/RemoteStorageDrive.cpp index 8db0c27475..5cd36ca05a 100644 --- a/Code/Framework/AzFramework/AzFramework/IO/RemoteStorageDrive.cpp +++ b/Code/Framework/AzFramework/AzFramework/IO/RemoteStorageDrive.cpp @@ -281,7 +281,7 @@ namespace AzFramework AZ_PROFILE_FUNCTION(AzCore); auto data = AZStd::get_if(&request->GetCommand()); - AZ_Assert(data, "Request doing reading in the RemoteStorageDrive didn't contain read data.") + AZ_Assert(data, "Request doing reading in the RemoteStorageDrive didn't contain read data."); HandleType file = InvalidHandle; diff --git a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp index 33fafa2110..6bbb07ea74 100644 --- a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp @@ -83,7 +83,7 @@ namespace AzFramework::ProjectManager return ProjectPathCheckResult::ProjectManagerLaunchFailed; } - bool LaunchProjectManager(const AZStd::string& commandLineArgs) + bool LaunchProjectManager([[maybe_unused]]const AZStd::string& commandLineArgs) { bool launchSuccess = false; #if (AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER) diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index 89338a355f..18667ac153 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -588,6 +588,12 @@ namespace AzFramework // pass through the camera's position and look vector for use in the lookAt function if (const auto lookAt = lookAtFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY())) { + // default to internal look at behavior if the look at point matches the camera translation + if (targetCamera.m_lookAt.IsClose(*lookAt)) + { + return false; + } + auto transform = AZ::Transform::CreateLookAt(targetCamera.m_lookAt, *lookAt); nextCamera.m_lookDist = -lookAt->GetDistance(targetCamera.m_lookAt); UpdateCameraFromTransform(nextCamera, transform); diff --git a/Code/Framework/AzFramework/AzFramework/Visibility/BoundsBus.h b/Code/Framework/AzFramework/AzFramework/Visibility/BoundsBus.h index ebd9484c55..7a60d5fdc5 100644 --- a/Code/Framework/AzFramework/AzFramework/Visibility/BoundsBus.h +++ b/Code/Framework/AzFramework/AzFramework/Visibility/BoundsBus.h @@ -45,6 +45,7 @@ namespace AzFramework protected: ~BoundsRequests() = default; }; + using BoundsRequestBus = AZ::EBus; //! Returns a union of all local Aabbs provided by components implementing the BoundsRequestBus. diff --git a/Code/Framework/AzFramework/Platform/Android/AzFramework/Windowing/NativeWindow_Android.cpp b/Code/Framework/AzFramework/Platform/Android/AzFramework/Windowing/NativeWindow_Android.cpp index e655435011..5910111ab7 100644 --- a/Code/Framework/AzFramework/Platform/Android/AzFramework/Windowing/NativeWindow_Android.cpp +++ b/Code/Framework/AzFramework/Platform/Android/AzFramework/Windowing/NativeWindow_Android.cpp @@ -57,6 +57,7 @@ namespace AzFramework uint32_t NativeWindowImpl_Android::GetDisplayRefreshRate() const { + // [GFX TODO][GHI - 2678] // Using 60 for now until proper support is added return 60; } diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h b/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h index 9b57d1d49e..833f4019f8 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h @@ -55,6 +55,29 @@ namespace AzFramework using LinuxXcbConnectionManagerBus = AZ::EBus; using LinuxXcbConnectionManagerInterface = AZ::Interface; + + class LinuxXcbEventHandler + { + public: + AZ_RTTI(LinuxXcbEventHandler, "{3F756E14-8D74-42FD-843C-4863307710DB}"); + + virtual ~LinuxXcbEventHandler() = default; + + virtual void HandleXcbEvent(xcb_generic_event_t* event) = 0; + }; + + class LinuxXcbEventHandlerBusTraits + : public AZ::EBusTraits + { + public: + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; + static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + ////////////////////////////////////////////////////////////////////////// + }; + + using LinuxXcbEventHandlerBus = AZ::EBus; #endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp index 407e256052..5cc147b038 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp @@ -6,101 +6,28 @@ * */ -#include #include +#include "Application_Linux_xcb.h" + //////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework { -#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - class LinuxXcbConnectionManagerImpl - : public LinuxXcbConnectionManagerBus::Handler - { - public: - LinuxXcbConnectionManagerImpl() - { - m_xcbConnection = xcb_connect(nullptr, nullptr); - AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server."); - LinuxXcbConnectionManagerBus::Handler::BusConnect(); - } - - ~LinuxXcbConnectionManagerImpl() override - { - LinuxXcbConnectionManagerBus::Handler::BusDisconnect(); - xcb_disconnect(m_xcbConnection); - } - xcb_connection_t* GetXcbConnection() const override - { - return m_xcbConnection; - } - private: - xcb_connection_t* m_xcbConnection = nullptr; - }; -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - - //////////////////////////////////////////////////////////////////////////////////////////////// - class ApplicationLinux - : public Application::Implementation - , public LinuxLifecycleEvents::Bus::Handler - { - public: - //////////////////////////////////////////////////////////////////////////////////////////// - AZ_CLASS_ALLOCATOR(ApplicationLinux, AZ::SystemAllocator, 0); - ApplicationLinux(); - ~ApplicationLinux() override; - - //////////////////////////////////////////////////////////////////////////////////////////// - // Application::Implementation - void PumpSystemEventLoopOnce() override; - void PumpSystemEventLoopUntilEmpty() override; - private: - -#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - AZStd::unique_ptr m_xcbConnectionManager; -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - - }; - //////////////////////////////////////////////////////////////////////////////////////////////// Application::Implementation* Application::Implementation::Create() { - return aznew ApplicationLinux(); - } - - //////////////////////////////////////////////////////////////////////////////////////////////// - ApplicationLinux::ApplicationLinux() - { - LinuxLifecycleEvents::Bus::Handler::BusConnect(); - #if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - m_xcbConnectionManager = AZStd::make_unique(); - if (LinuxXcbConnectionManagerInterface::Get() == nullptr) - { - LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get()); - } + return aznew ApplicationLinux_xcb(); +#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND + #error "Linux Window Manager Wayland not supported." + return nullptr; +#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB + #error "Linux Window Manager XLIB not supported." + return nullptr; +#else + #error "Linux Window Manager not recognized." + return nullptr; #endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } - //////////////////////////////////////////////////////////////////////////////////////////////// - ApplicationLinux::~ApplicationLinux() - { -#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get()) - { - LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get()); - } - m_xcbConnectionManager.reset(); -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - LinuxLifecycleEvents::Bus::Handler::BusDisconnect(); - } - - //////////////////////////////////////////////////////////////////////////////////////////////// - void ApplicationLinux::PumpSystemEventLoopOnce() - { - } - - //////////////////////////////////////////////////////////////////////////////////////////////// - void ApplicationLinux::PumpSystemEventLoopUntilEmpty() - { - } } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux_xcb.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux_xcb.cpp new file mode 100644 index 0000000000..aaab67b2a1 --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux_xcb.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include "Application_Linux_xcb.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +namespace AzFramework +{ +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + //////////////////////////////////////////////////////////////////////////////////////////////// + class LinuxXcbConnectionManagerImpl + : public LinuxXcbConnectionManagerBus::Handler + { + public: + LinuxXcbConnectionManagerImpl() + { + m_xcbConnection = xcb_connect(nullptr, nullptr); + AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server."); + LinuxXcbConnectionManagerBus::Handler::BusConnect(); + } + + ~LinuxXcbConnectionManagerImpl() + { + LinuxXcbConnectionManagerBus::Handler::BusDisconnect(); + xcb_disconnect(m_xcbConnection); + } + + xcb_connection_t* GetXcbConnection() const override + { + return m_xcbConnection; + } + + private: + xcb_connection_t* m_xcbConnection = nullptr; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////// + ApplicationLinux_xcb::ApplicationLinux_xcb() + { + LinuxLifecycleEvents::Bus::Handler::BusConnect(); + m_xcbConnectionManager = AZStd::make_unique(); + if (LinuxXcbConnectionManagerInterface::Get() == nullptr) + { + LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get()); + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + ApplicationLinux_xcb::~ApplicationLinux_xcb() + { + if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get()) + { + LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get()); + } + m_xcbConnectionManager.reset(); + LinuxLifecycleEvents::Bus::Handler::BusDisconnect(); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void ApplicationLinux_xcb::PumpSystemEventLoopOnce() + { + if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection()) + { + if (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection)) + { + LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event); + free(event); + } + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void ApplicationLinux_xcb::PumpSystemEventLoopUntilEmpty() + { + if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection()) + { + while (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection)) + { + LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event); + free(event); + } + } + } + +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux_xcb.h b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux_xcb.h new file mode 100644 index 0000000000..55daedb4dd --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux_xcb.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +namespace AzFramework +{ + +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + + //////////////////////////////////////////////////////////////////////////////////////////////// + class ApplicationLinux_xcb + : public Application::Implementation + , public LinuxLifecycleEvents::Bus::Handler + { + public: + //////////////////////////////////////////////////////////////////////////////////////////// + AZ_CLASS_ALLOCATOR(ApplicationLinux_xcb, AZ::SystemAllocator, 0); + ApplicationLinux_xcb(); + ~ApplicationLinux_xcb() override; + + //////////////////////////////////////////////////////////////////////////////////////////// + // Application::Implementation + void PumpSystemEventLoopOnce() override; + void PumpSystemEventLoopUntilEmpty() override; + + private: + AZStd::unique_ptr m_xcbConnectionManager; + }; + +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp index 0ab1281eda..436be28ee6 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp @@ -6,48 +6,24 @@ * */ -#include +#include "NativeWindow_Linux_xcb.h" namespace AzFramework { - class NativeWindowImpl_Linux final - : public NativeWindow::Implementation - { - public: - AZ_CLASS_ALLOCATOR(NativeWindowImpl_Linux, AZ::SystemAllocator, 0); - NativeWindowImpl_Linux() = default; - ~NativeWindowImpl_Linux() override = default; - - // NativeWindow::Implementation overrides... - void InitWindow(const AZStd::string& title, - const WindowGeometry& geometry, - const WindowStyleMasks& styleMasks) override; - NativeWindowHandle GetWindowHandle() const override; - uint32_t GetDisplayRefreshRate() const override; - }; - NativeWindow::Implementation* NativeWindow::Implementation::Create() { - return aznew NativeWindowImpl_Linux(); - } - - void NativeWindowImpl_Linux::InitWindow([[maybe_unused]]const AZStd::string& title, - const WindowGeometry& geometry, - [[maybe_unused]]const WindowStyleMasks& styleMasks) - { - m_width = geometry.m_width; - m_height = geometry.m_height; - } - - NativeWindowHandle NativeWindowImpl_Linux::GetWindowHandle() const - { - AZ_Assert(false, "NativeWindow not implemented for Linux"); +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + return aznew NativeWindowImpl_Linux_xcb(); +#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND + #error "Linux Window Manager Wayland not supported." return nullptr; +#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB + #error "Linux Window Manager XLIB not supported." + return nullptr; +#else + #error "Linux Window Manager not recognized." + return nullptr; +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } - uint32_t NativeWindowImpl_Linux::GetDisplayRefreshRate() const - { - //Using 60 for now until proper support is added - return 60; - } } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux_xcb.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux_xcb.cpp new file mode 100644 index 0000000000..005c1858a3 --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux_xcb.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include + +#include "NativeWindow_Linux_xcb.h" + +namespace AzFramework +{ +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + + [[maybe_unused]] const char LinuxXcbErrorWindow[] = "NativeWindow_Linux_xcb"; + static constexpr uint8_t s_XcbFormatDataSize = 32; // Format indicator for xcb for client messages + static constexpr uint16_t s_DefaultXcbWindowBorderWidth = 4; // The default border with in pixels if a border was specified + static constexpr uint8_t s_XcbResponseTypeMask = 0x7f; // Mask to extract the specific event type from an xcb event + + //////////////////////////////////////////////////////////////////////////////////////////////// + NativeWindowImpl_Linux_xcb::NativeWindowImpl_Linux_xcb() + : NativeWindow::Implementation() + { + if (auto xcbConnectionManager = AzFramework::LinuxXcbConnectionManagerInterface::Get(); + xcbConnectionManager != nullptr) + { + m_xcbConnection = xcbConnectionManager->GetXcbConnection(); + } + AZ_Error(LinuxXcbErrorWindow, m_xcbConnection != nullptr, "Unable to get XCB Connection"); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + NativeWindowImpl_Linux_xcb::~NativeWindowImpl_Linux_xcb() + { + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void NativeWindowImpl_Linux_xcb::InitWindow(const AZStd::string& title, + const WindowGeometry& geometry, + const WindowStyleMasks& styleMasks) + { + // Get the parent window + const xcb_setup_t* xcbSetup = xcb_get_setup(m_xcbConnection); + xcb_screen_t* xcbRootScreen = xcb_setup_roots_iterator(xcbSetup).data; + xcb_window_t xcbParentWindow = xcbRootScreen->root; + + // Create an XCB window from the connection + m_xcbWindow = xcb_generate_id(m_xcbConnection); + + uint16_t borderWidth = 0; + const uint32_t mask = styleMasks.m_platformAgnosticStyleMask; + if ((mask & WindowStyleMasks::WINDOW_STYLE_BORDERED) || + (mask & WindowStyleMasks::WINDOW_STYLE_RESIZEABLE)) + { + borderWidth = s_DefaultXcbWindowBorderWidth; + } + + uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + + uint32_t valueList[] = { xcbRootScreen->black_pixel, + XCB_EVENT_MASK_STRUCTURE_NOTIFY }; + + xcb_void_cookie_t xcbCheckResult; + + xcbCheckResult = xcb_create_window_checked(m_xcbConnection, + XCB_COPY_FROM_PARENT, + m_xcbWindow, + xcbParentWindow, + aznumeric_cast(geometry.m_posX), + aznumeric_cast(geometry.m_posY), + aznumeric_cast(geometry.m_width), + aznumeric_cast(geometry.m_height), + borderWidth, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + xcbRootScreen->root_visual, + eventMask, + valueList); + + AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to create xcb window."); + + SetWindowTitle(title); + + // Setup the window close event + const static char* wmProtocolString = "WM_PROTOCOLS"; + + xcb_intern_atom_cookie_t cookieProtocol = xcb_intern_atom(m_xcbConnection, 1, strlen(wmProtocolString), wmProtocolString); + xcb_intern_atom_reply_t* replyProtocol = xcb_intern_atom_reply(m_xcbConnection, cookieProtocol, nullptr); + AZ_Error(LinuxXcbErrorWindow, replyProtocol != nullptr, "Unable to query xcb '%s' atom", wmProtocolString); + m_xcbAtomProtocols = replyProtocol->atom; + + const static char* wmDeleteWindowString = "WM_DELETE_WINDOW"; + xcb_intern_atom_cookie_t cookieDeleteWindow = xcb_intern_atom(m_xcbConnection, 0, strlen(wmDeleteWindowString), wmDeleteWindowString); + xcb_intern_atom_reply_t* replyDeleteWindow = xcb_intern_atom_reply(m_xcbConnection, cookieDeleteWindow, nullptr); + AZ_Error(LinuxXcbErrorWindow, replyDeleteWindow != nullptr, "Unable to query xcb '%s' atom", wmDeleteWindowString); + m_xcbAtomDeleteWindow = replyDeleteWindow->atom; + + xcbCheckResult = xcb_change_property_checked(m_xcbConnection, + XCB_PROP_MODE_REPLACE, + m_xcbWindow, + m_xcbAtomProtocols, + XCB_ATOM_ATOM, + s_XcbFormatDataSize, + 1, + &m_xcbAtomDeleteWindow); + + AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to change the xcb atom property for WM_CLOSE event"); + + m_width = geometry.m_width; + m_height = geometry.m_height; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void NativeWindowImpl_Linux_xcb::Activate() + { + LinuxXcbEventHandlerBus::Handler::BusConnect(); + + if (!m_activated) // nothing to do if window was already activated + { + m_activated = true; + + xcb_map_window(m_xcbConnection, m_xcbWindow); + xcb_flush(m_xcbConnection); + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void NativeWindowImpl_Linux_xcb::Deactivate() + { + if (m_activated) // nothing to do if window was already deactivated + { + m_activated = false; + + WindowNotificationBus::Event(reinterpret_cast(m_xcbWindow), &WindowNotificationBus::Events::OnWindowClosed); + + xcb_unmap_window(m_xcbConnection, m_xcbWindow); + xcb_flush(m_xcbConnection); + } + LinuxXcbEventHandlerBus::Handler::BusDisconnect(); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + NativeWindowHandle NativeWindowImpl_Linux_xcb::GetWindowHandle() const + { + return reinterpret_cast(m_xcbWindow); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void NativeWindowImpl_Linux_xcb::SetWindowTitle(const AZStd::string& title) + { + xcb_void_cookie_t xcbCheckResult; + xcbCheckResult = xcb_change_property(m_xcbConnection, + XCB_PROP_MODE_REPLACE, + m_xcbWindow, + XCB_ATOM_WM_NAME, + XCB_ATOM_STRING, + 8, + static_cast(title.size()), + title.c_str()); + AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to set window title."); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void NativeWindowImpl_Linux_xcb::ResizeClientArea(WindowSize clientAreaSize) + { + const uint32_t values[] = { clientAreaSize.m_width, clientAreaSize.m_height }; + + xcb_configure_window(m_xcbConnection, m_xcbWindow, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); + + m_width = clientAreaSize.m_width; + m_height = clientAreaSize.m_height; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + uint32_t NativeWindowImpl_Linux_xcb::GetDisplayRefreshRate() const + { + // [GFX TODO][GHI - 2678] + // Using 60 for now until proper support is added + return 60; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + bool NativeWindowImpl_Linux_xcb::ValidateXcbResult(xcb_void_cookie_t cookie) + { + bool result = true; + if (xcb_generic_error_t* error = xcb_request_check(m_xcbConnection, cookie)) + { + AZ_TracePrintf("Error","Error code %d", error->error_code); + result = false; + } + return result; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void NativeWindowImpl_Linux_xcb::HandleXcbEvent(xcb_generic_event_t* event) + { + switch (event->response_type & s_XcbResponseTypeMask) + { + case XCB_CONFIGURE_NOTIFY: + { + xcb_configure_notify_event_t* cne = reinterpret_cast(event); + WindowSizeChanged(aznumeric_cast(cne->width), + aznumeric_cast(cne->height)); + + break; + } + case XCB_CLIENT_MESSAGE: + { + xcb_client_message_event_t* cme = reinterpret_cast(event); + if ((cme->type == m_xcbAtomProtocols) && + (cme->format == s_XcbFormatDataSize) && + (cme->data.data32[0] == m_xcbAtomDeleteWindow)) + { + Deactivate(); + + ApplicationRequests::Bus::Broadcast(&ApplicationRequests::ExitMainLoop); + } + break; + } + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void NativeWindowImpl_Linux_xcb::WindowSizeChanged(const uint32_t width, const uint32_t height) + { + if (m_width != width || m_height != height) + { + m_width = width; + m_height = height; + + if (m_activated) + { + WindowNotificationBus::Event(reinterpret_cast(m_xcbWindow), &WindowNotificationBus::Events::OnWindowResized, width, height); + } + } + } + +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux_xcb.h b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux_xcb.h new file mode 100644 index 0000000000..73e255bab0 --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux_xcb.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include + +namespace AzFramework +{ +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + class NativeWindowImpl_Linux_xcb final + : public NativeWindow::Implementation + , public LinuxXcbEventHandlerBus::Handler + { + public: + AZ_CLASS_ALLOCATOR(NativeWindowImpl_Linux_xcb, AZ::SystemAllocator, 0); + NativeWindowImpl_Linux_xcb(); + ~NativeWindowImpl_Linux_xcb() override; + + //////////////////////////////////////////////////////////////////////////////////////////// + // NativeWindow::Implementation + void InitWindow(const AZStd::string& title, + const WindowGeometry& geometry, + const WindowStyleMasks& styleMasks) override; + void Activate() override; + void Deactivate() override; + NativeWindowHandle GetWindowHandle() const override; + void SetWindowTitle(const AZStd::string& title) override; + void ResizeClientArea(WindowSize clientAreaSize) override; + uint32_t GetDisplayRefreshRate() const override; + + //////////////////////////////////////////////////////////////////////////////////////////// + // LinuxXcbEventHandlerBus::Handler + void HandleXcbEvent(xcb_generic_event_t* event) override; + + private: + bool ValidateXcbResult(xcb_void_cookie_t cookie); + void WindowSizeChanged(const uint32_t width, const uint32_t height); + + xcb_connection_t* m_xcbConnection = nullptr; + xcb_window_t m_xcbWindow = 0; + xcb_atom_t m_xcbAtomProtocols; + xcb_atom_t m_xcbAtomDeleteWindow; + }; +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake b/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake index 21201d954d..4330675fc7 100644 --- a/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake +++ b/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake @@ -12,6 +12,8 @@ set(FILES AzFramework/API/ApplicationAPI_Platform.h AzFramework/API/ApplicationAPI_Linux.h AzFramework/Application/Application_Linux.cpp + AzFramework/Application/Application_Linux_xcb.h + AzFramework/Application/Application_Linux_xcb.cpp AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp AzFramework/Process/ProcessWatcher_Linux.cpp AzFramework/Process/ProcessCommon.h @@ -20,6 +22,8 @@ set(FILES ../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp ../Common/Default/AzFramework/TargetManagement/TargetManagementComponent_Default.cpp AzFramework/Windowing/NativeWindow_Linux.cpp + AzFramework/Windowing/NativeWindow_Linux_xcb.h + AzFramework/Windowing/NativeWindow_Linux_xcb.cpp ../Common/Unimplemented/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad_Unimplemented.cpp ../Common/Unimplemented/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Unimplemented.cpp ../Common/Unimplemented/AzFramework/Input/Devices/Motion/InputDeviceMotion_Unimplemented.cpp diff --git a/Code/Framework/AzFramework/Tests/CameraInputTests.cpp b/Code/Framework/AzFramework/Tests/CameraInputTests.cpp index 486cca2af0..df7d22f7ca 100644 --- a/Code/Framework/AzFramework/Tests/CameraInputTests.cpp +++ b/Code/Framework/AzFramework/Tests/CameraInputTests.cpp @@ -6,6 +6,7 @@ * */ +#include #include #include #include @@ -47,18 +48,17 @@ namespace UnitTest m_firstPersonTranslateCamera = AZStd::make_shared(AzFramework::LookTranslation, m_translateCameraInputChannelIds); - auto orbitCamera = - AZStd::make_shared(AzFramework::InputChannelId("keyboard_key_modifier_alt_l")); + m_orbitCamera = AZStd::make_shared(m_orbitChannelId); auto orbitRotateCamera = AZStd::make_shared(AzFramework::InputDeviceMouse::Button::Left); auto orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation, m_translateCameraInputChannelIds); - orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera); + m_orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera); + m_orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera); m_cameraSystem->m_cameras.AddCamera(m_firstPersonRotateCamera); m_cameraSystem->m_cameras.AddCamera(m_firstPersonTranslateCamera); - m_cameraSystem->m_cameras.AddCamera(orbitCamera); + m_cameraSystem->m_cameras.AddCamera(m_orbitCamera); // these tests rely on using motion delta, not cursor positions (default is true) AzFramework::ed_cameraSystemUseCursor = false; @@ -68,6 +68,7 @@ namespace UnitTest { AzFramework::ed_cameraSystemUseCursor = true; + m_orbitCamera.reset(); m_firstPersonRotateCamera.reset(); m_firstPersonTranslateCamera.reset(); @@ -77,12 +78,14 @@ namespace UnitTest AllocatorsTestFixture::TearDown(); } + AzFramework::InputChannelId m_orbitChannelId = AzFramework::InputChannelId("keyboard_key_modifier_alt_l"); AzFramework::TranslateCameraInputChannelIds m_translateCameraInputChannelIds; AZStd::shared_ptr m_firstPersonRotateCamera; AZStd::shared_ptr m_firstPersonTranslateCamera; + AZStd::shared_ptr m_orbitCamera; }; - TEST_F(CameraInputFixture, Begin_and_end_OrbitCameraInput_consumes_correct_events) + TEST_F(CameraInputFixture, BeginAndEndOrbitCameraInputConsumesCorrectEvents) { // begin orbit camera const bool consumed1 = HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceKeyboard::Key::ModifierAltL, @@ -102,7 +105,7 @@ namespace UnitTest EXPECT_THAT(allConsumed, ElementsAre(true, false, true, false)); } - TEST_F(CameraInputFixture, Begin_CameraInput_notifies_ActivationBeganFn_for_TranslateCameraInput) + TEST_F(CameraInputFixture, BeginCameraInputNotifiesActivationBeganFnForTranslateCameraInput) { bool activationBegan = false; m_firstPersonTranslateCamera->SetActivationBeganFn( @@ -111,13 +114,13 @@ namespace UnitTest activationBegan = true; }); - HandleEventAndUpdate( - AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began }); + HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, + AzFramework::InputChannel::State::Began }); EXPECT_TRUE(activationBegan); } - TEST_F(CameraInputFixture, Begin_CameraInput_notifies_ActivationBeganFn_after_delta_for_RotateCameraInput) + TEST_F(CameraInputFixture, BeginCameraInputNotifiesActivationBeganFnAfterDeltaForRotateCameraInput) { bool activationBegan = false; m_firstPersonRotateCamera->SetActivationBeganFn( @@ -133,7 +136,7 @@ namespace UnitTest EXPECT_TRUE(activationBegan); } - TEST_F(CameraInputFixture, Begin_CameraInput_does_not_notify_ActivationBeganFn_with_no_delta_for_RotateCameraInput) + TEST_F(CameraInputFixture, BeginCameraInputDoesNotNotifyActivationBeganFnWithNoDeltaForRotateCameraInput) { bool activationBegan = false; m_firstPersonRotateCamera->SetActivationBeganFn( @@ -148,7 +151,7 @@ namespace UnitTest EXPECT_FALSE(activationBegan); } - TEST_F(CameraInputFixture, End_CameraInput_notifies_ActivationEndFn_after_delta_for_RotateCameraInput) + TEST_F(CameraInputFixture, EndCameraInputNotifiesActivationEndFnAfterDeltaForRotateCameraInput) { bool activationEnded = false; m_firstPersonRotateCamera->SetActivationEndedFn( @@ -166,7 +169,7 @@ namespace UnitTest EXPECT_TRUE(activationEnded); } - TEST_F(CameraInputFixture, End_CameraInput_does_not_notify_ActivationBeganFn_or_ActivationBeganFn_with_no_delta_for_RotateCameraInput) + TEST_F(CameraInputFixture, EndCameraInputDoesNotNotifyActivationBeganFnOrActivationBeganFnWithNoDeltaForRotateCameraInput) { bool activationBegan = false; m_firstPersonRotateCamera->SetActivationBeganFn( @@ -191,7 +194,7 @@ namespace UnitTest EXPECT_FALSE(activationEnded); } - TEST_F(CameraInputFixture, End_CameraInput_notifies_ActivationBeganFn_or_ActivationEndFn_with_TranslateCamera) + TEST_F(CameraInputFixture, End_CameraInputNotifiesActivationBeganFnOrActivationEndFnWithTranslateCamera) { bool activationBegan = false; m_firstPersonTranslateCamera->SetActivationBeganFn( @@ -207,16 +210,16 @@ namespace UnitTest activationEnded = true; }); - HandleEventAndUpdate( - AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began }); - HandleEventAndUpdate( - AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Ended }); + HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, + AzFramework::InputChannel::State::Began }); + HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, + AzFramework::InputChannel::State::Ended }); EXPECT_TRUE(activationBegan); EXPECT_TRUE(activationEnded); } - TEST_F(CameraInputFixture, End_activation_called_for_CameraInput_if_active_when_cameras_are_cleared) + TEST_F(CameraInputFixture, EndActivationCalledForCameraInputIfActiveWhenCamerasAreCleared) { bool activationEnded = false; m_firstPersonTranslateCamera->SetActivationEndedFn( @@ -225,11 +228,37 @@ namespace UnitTest activationEnded = true; }); - HandleEventAndUpdate( - AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began }); + HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, + AzFramework::InputChannel::State::Began }); m_cameraSystem->m_cameras.Clear(); EXPECT_TRUE(activationEnded); } + + TEST_F(CameraInputFixture, OrbitCameraInputHandlesLookAtPointAndSelfAtSamePositionWhenOrbiting) + { + // create pathological lookAtFn that just returns the same position as the camera + m_orbitCamera->SetLookAtFn( + [](const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction) + { + return position; + }); + + AzFramework::UpdateCameraFromTransform( + m_targetCamera, + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 10.0f, 10.0f))); + + m_camera = m_targetCamera; + + HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began }); + + // verify the camera yaw has not changed and the look at point + // does not match that of the camera translation + using ::testing::Eq; + using ::testing::Not; + EXPECT_THAT(m_camera.m_yaw, Eq(AZ::DegToRad(90.0f))); + EXPECT_THAT(m_camera.m_lookAt, Not(IsClose(m_camera.Translation()))); + } } // namespace UnitTest diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h index 5e907ae680..7f838b0073 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h @@ -45,6 +45,9 @@ namespace AzManipulatorTestFramework virtual void SetAngularStep(float step) = 0; //! Get the viewport id. virtual int GetViewportId() const = 0; + //! Updates the visibility state. + //! Updates which entities are currently visible given the current camera state. + virtual void UpdateVisibility() = 0; }; //! This interface is used to simulate the manipulator manager while the manipulators are under test. diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h index 9b253c718b..f87f83c1b2 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include #include namespace UnitTest @@ -21,20 +21,18 @@ namespace UnitTest //! Fixture to provide the indirect call viewport interaction that is dependent on AzToolsFramework::ToolsApplication. //! \tparam ToolsApplicationFixtureT The fixture that provides the AzToolsFramework::ToolsApplication functionality. template - class IndirectCallManipulatorViewportInteractionFixtureMixin - : public ToolsApplicationFixtureT + class IndirectCallManipulatorViewportInteractionFixtureMixin : public ToolsApplicationFixtureT { - using IndirectCallManipulatorViewportInteraction = - AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction; + using IndirectCallManipulatorViewportInteraction = AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction; using ImmediateModeActionDispatcher = AzManipulatorTestFramework::ImmediateModeActionDispatcher; - + void SetUpEditorFixtureImpl() override { ToolsApplicationFixtureT::SetUpEditorFixtureImpl(); m_viewportManipulatorInteraction = AZStd::make_unique(); m_actionDispatcher = AZStd::make_unique(*m_viewportManipulatorInteraction); - m_cameraState = AzFramework::CreateIdentityDefaultCamera( - AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize); + m_cameraState = + AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize); } void TearDownEditorFixtureImpl() override diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h index dabcf567db..a7b1be2c7d 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h @@ -9,8 +9,8 @@ #pragma once #include -#include #include +#include namespace AzManipulatorTestFramework { @@ -18,13 +18,12 @@ namespace AzManipulatorTestFramework class IndirectCallManipulatorManager; //! Implementation of manipulator viewport interaction that manipulates the manager indirectly via bus calls. - class IndirectCallManipulatorViewportInteraction - : public ManipulatorViewportInteraction + class IndirectCallManipulatorViewportInteraction : public ManipulatorViewportInteraction { public: IndirectCallManipulatorViewportInteraction(); ~IndirectCallManipulatorViewportInteraction(); - + // ManipulatorViewportInteractionInterface ... const ViewportInteractionInterface& GetViewportInteraction() const override; const ManipulatorManagerInterface& GetManipulatorManager() const override; diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h index b6944e0355..8b6ea5c59b 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h @@ -8,6 +8,7 @@ #pragma once +#include #include namespace AzManipulatorTestFramework @@ -19,6 +20,7 @@ namespace AzManipulatorTestFramework : public ViewportInteractionInterface , public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler , public AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler + , private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler { public: ViewportInteraction(); @@ -34,6 +36,7 @@ namespace AzManipulatorTestFramework void SetGridSize(float size) override; void SetAngularStep(float step) override; int GetViewportId() const override; + void UpdateVisibility() override; // ViewportInteractionRequestBus overrides ... AzFramework::CameraState GetCameraState() override; @@ -52,7 +55,11 @@ namespace AzManipulatorTestFramework float ManipulatorLineBoundWidth() const override; float ManipulatorCircleBoundWidth() const override; + // EditorEntityViewportInteractionRequestBus overrides ... + void FindVisibleEntities(AZStd::vector& visibleEntities) override; + private: + AzFramework::EntityVisibilityQuery m_entityVisibilityQuery; AZStd::unique_ptr m_nullDebugDisplayRequests; const int m_viewportId = 1234; // Arbitrary viewport id for manipulator tests AzFramework::CameraState m_cameraState; diff --git a/Code/Framework/AzManipulatorTestFramework/Source/AzManipulatorTestFrameworkUtils.cpp b/Code/Framework/AzManipulatorTestFramework/Source/AzManipulatorTestFrameworkUtils.cpp index 1b68a3d0cd..4f1e108a14 100644 --- a/Code/Framework/AzManipulatorTestFramework/Source/AzManipulatorTestFrameworkUtils.cpp +++ b/Code/Framework/AzManipulatorTestFramework/Source/AzManipulatorTestFrameworkUtils.cpp @@ -91,12 +91,12 @@ namespace AzManipulatorTestFramework AzToolsFramework::ViewportInteraction::MousePick BuildMousePick( const AzFramework::ScreenPoint& screenPoint, const AzFramework::CameraState& cameraState) { - const auto screenToWorld = AzFramework::ScreenToWorld(screenPoint, cameraState); + const auto nearPlaneWorldPosition = AzFramework::ScreenToWorld(screenPoint, cameraState); AzToolsFramework::ViewportInteraction::MousePick mousePick; mousePick.m_screenCoordinates = screenPoint; - mousePick.m_rayOrigin = screenToWorld; - mousePick.m_rayDirection = (screenToWorld - cameraState.m_position).GetNormalized(); + mousePick.m_rayOrigin = cameraState.m_position; + mousePick.m_rayDirection = (nearPlaneWorldPosition - cameraState.m_position).GetNormalized(); return mousePick; } diff --git a/Code/Framework/AzManipulatorTestFramework/Source/IndirectManipulatorViewportInteraction.cpp b/Code/Framework/AzManipulatorTestFramework/Source/IndirectManipulatorViewportInteraction.cpp index ff5e3981ef..730c106301 100644 --- a/Code/Framework/AzManipulatorTestFramework/Source/IndirectManipulatorViewportInteraction.cpp +++ b/Code/Framework/AzManipulatorTestFramework/Source/IndirectManipulatorViewportInteraction.cpp @@ -16,8 +16,7 @@ namespace AzManipulatorTestFramework using MouseInteractionEvent = AzToolsFramework::ViewportInteraction::MouseInteractionEvent; //! Implementation of the manipulator interface using bus calls to access to the manipulator manager. - class IndirectCallManipulatorManager - : public ManipulatorManagerInterface + class IndirectCallManipulatorManager : public ManipulatorManagerInterface { public: IndirectCallManipulatorManager(ViewportInteractionInterface& viewportInteraction); @@ -39,11 +38,18 @@ namespace AzManipulatorTestFramework void IndirectCallManipulatorManager::ConsumeMouseInteractionEvent(const MouseInteractionEvent& event) { + m_viewportInteraction.UpdateVisibility(); + + // ensure we call display viewport 2d to simulate this update step (some state may be + // updated here, e.g. box select) + AzFramework::ViewportDebugDisplayEventBus::Event( + AzToolsFramework::GetEntityContextId(), &AzFramework::ViewportDebugDisplayEvents::DisplayViewport2d, + AzFramework::ViewportInfo{ m_viewportInteraction.GetViewportId() }, m_viewportInteraction.GetDebugDisplay()); + DrawManipulators(); AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event( AzToolsFramework::GetEntityContextId(), - &AzToolsFramework::ViewportInteraction::InternalMouseViewportRequests::InternalHandleAllMouseInteractions, - event); + &AzToolsFramework::ViewportInteraction::InternalMouseViewportRequests::InternalHandleAllMouseInteractions, event); DrawManipulators(); } diff --git a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp index 0817df3849..4dae4fc00d 100644 --- a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp +++ b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp @@ -26,10 +26,12 @@ namespace AzManipulatorTestFramework { AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(m_viewportId); AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusConnect(m_viewportId); + AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(m_viewportId); } ViewportInteraction::~ViewportInteraction() { + AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusDisconnect(); } @@ -74,6 +76,16 @@ namespace AzManipulatorTestFramework return 0.1f; } + void ViewportInteraction::FindVisibleEntities(AZStd::vector& visibleEntitiesOut) + { + visibleEntitiesOut.assign(m_entityVisibilityQuery.Begin(), m_entityVisibilityQuery.End()); + } + + void ViewportInteraction::UpdateVisibility() + { + m_entityVisibilityQuery.UpdateVisibility(m_cameraState); + } + AzFramework::ScreenPoint ViewportInteraction::ViewportWorldToScreen(const AZ::Vector3& worldPosition) { return AzFramework::WorldToScreen(worldPosition, m_cameraState); diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Card.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Card.cpp index 40c0a1d55a..f72f89ca79 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Card.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Card.cpp @@ -342,7 +342,7 @@ namespace AzQtComponents config.toolTipPaddingInPixels = 5; config.headerIconSizeInPixels = CardHeader::defaultIconSize(); config.rootLayoutSpacing = 0; - config.warningIcon = QStringLiteral(":/Cards/img/UI20/Cards/warning.svg"); + config.warningIcon = QStringLiteral(":/Notifications/warning.svg"); config.warningIconSize = {24, 24}; config.disabledIconAlpha = 0.25; diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/VectorInput.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/VectorInput.cpp index 7acc7ad0d0..7b879e89b1 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/VectorInput.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/VectorInput.cpp @@ -303,7 +303,7 @@ VectorInput::~VectorInput() void VectorInput::setLabel(int index, const QString& label) { AZ_Warning("PropertyGrid", index < m_elementCount, - "This control handles only %i controls", m_elementCount) + "This control handles only %i controls", m_elementCount); if (index < m_elementCount) { m_elements[index]->setLabel(label); @@ -313,7 +313,7 @@ void VectorInput::setLabel(int index, const QString& label) void VectorInput::setLabelStyle(int index, const QString& qss) { AZ_Warning("PropertyGrid", index < m_elementCount, - "This control handles only %i controls", m_elementCount) + "This control handles only %i controls", m_elementCount); if (index < m_elementCount) { m_elements[index]->getLabelWidget()->setStyleSheet(qss); @@ -323,7 +323,7 @@ void VectorInput::setLabelStyle(int index, const QString& qss) void VectorInput::setValuebyIndex(double value, int elementIndex) { AZ_Warning("PropertyGrid", elementIndex < m_elementCount, - "This control handles only %i controls", m_elementCount) + "This control handles only %i controls", m_elementCount); if (elementIndex < m_elementCount) { m_elements[elementIndex]->setValue(value); diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc b/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc index 909510d63b..7321128b57 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc @@ -424,7 +424,6 @@ img/UI20/Cards/menu_ico.png img/UI20/Cards/error_icon.png img/UI20/Cards/warning.png - img/UI20/Cards/warning.svg img/UI20/Cards/search.png img/UI20/Cards/close.png img/UI20/Cards/error-conclict-state.svg diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/Cards/warning.svg b/Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/warning.svg similarity index 100% rename from Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/Cards/warning.svg rename to Code/Framework/AzQtComponents/AzQtComponents/Images/Notifications/warning.svg diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc index c72687359b..0c8fedc79d 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc +++ b/Code/Framework/AzQtComponents/AzQtComponents/Images/resources.qrc @@ -30,6 +30,7 @@ Notifications/checkmark.svg Notifications/download.svg Notifications/link.svg + Notifications/warning.svg Outliner/sort_a_to_z.svg diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentEntitySelectionBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentEntitySelectionBus.h index 64cae9ca3d..dd5af35649 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentEntitySelectionBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentEntitySelectionBus.h @@ -96,7 +96,7 @@ namespace AzToolsFramework { AZ::EBusReduceResult aabbResult(AZ::Aabb::CreateNull()); EditorComponentSelectionRequestsBus::EventResult( - aabbResult, entityId, &EditorComponentSelectionRequests::GetEditorSelectionBoundsViewport, viewportInfo); + aabbResult, entityId, &EditorComponentSelectionRequestsBus::Events::GetEditorSelectionBoundsViewport, viewportInfo); return aabbResult.value; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetBundler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetBundler.cpp index 99d53f6c62..92334f404c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetBundler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetBundler.cpp @@ -44,7 +44,7 @@ namespace AzToolsFramework const char AssetBundleSettingsFileExtension[] = "bundlesettings"; const char BundleFileExtension[] = "pak"; const char ComparisonRulesFileExtension[] = "rules"; - const char ErrorWindowName[] = "AssetBundler"; + [[maybe_unused]] const char ErrorWindowName[] = "AssetBundler"; const char* AssetFileInfoListComparison::ComparisonTypeNames[] = { "delta", "union", "intersection", "complement", "filepattern", "intersectioncount" }; const char* AssetFileInfoListComparison::FilePatternTypeNames[] = { "wildcard", "regex" }; const char DefaultTypeName[] = "default"; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h index 1cd36e8055..feb2fc12bf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h @@ -43,6 +43,8 @@ namespace AzToolsFramework virtual Prefab::InstanceOptionalReference GetRootPrefabInstance() = 0; + virtual Prefab::TemplateId GetRootPrefabTemplateId() = 0; + //! Get all Assets generated by Prefab processing when entering Play-In Editor mode (Ctrl+G) //! /return The vector of Assets generated by Prefab processing virtual const AZStd::vector>& GetPlayInEditorAssetData() = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 7df1e1b5c1..114f45d501 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -359,6 +359,12 @@ namespace AzToolsFramework return AZStd::nullopt; } + Prefab::TemplateId PrefabEditorEntityOwnershipService::GetRootPrefabTemplateId() + { + AZ_Assert(m_rootInstance, "A valid root prefab instance couldn't be found in PrefabEditorEntityOwnershipService."); + return m_rootInstance ? m_rootInstance->GetTemplateId() : Prefab::InvalidTemplateId; + } + const AZStd::vector>& PrefabEditorEntityOwnershipService::GetPlayInEditorAssetData() { return m_playInEditorData.m_assets; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h index bf1199d6dd..a98fce8059 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h @@ -193,6 +193,7 @@ namespace AzToolsFramework AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) override; Prefab::InstanceOptionalReference GetRootPrefabInstance() override; + Prefab::TemplateId GetRootPrefabTemplateId() override; const AZStd::vector>& GetPlayInEditorAssetData() override; ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp index 85b89b93dc..09439724cd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp @@ -26,6 +26,19 @@ namespace AzToolsFramework { namespace Prefab { + static constexpr const char s_saveAllPrefabsKey[] = "/O3DE/Preferences/Prefabs/SaveAllPrefabs"; + + void PrefabLoader::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Enum() + ->Value("Ask every time", SaveAllPrefabsPreference::AskEveryTime) + ->Value("Save all", SaveAllPrefabsPreference::SaveAll) + ->Value("Save none", SaveAllPrefabsPreference::SaveNone); + } + } + void PrefabLoader::RegisterPrefabLoaderInterface() { m_prefabSystemComponentInterface = AZ::Interface::Get(); @@ -657,6 +670,24 @@ namespace AzToolsFramework return finalPath; } + SaveAllPrefabsPreference PrefabLoader::GetSaveAllPrefabsPreference() const + { + SaveAllPrefabsPreference saveAllPrefabsPreference = SaveAllPrefabsPreference::AskEveryTime; + if (auto* registry = AZ::SettingsRegistry::Get()) + { + registry->GetObject(saveAllPrefabsPreference, s_saveAllPrefabsKey); + } + return saveAllPrefabsPreference; + } + + void PrefabLoader::SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference) + { + if (auto* registry = AZ::SettingsRegistry::Get()) + { + registry->SetObject(s_saveAllPrefabsKey, saveAllPrefabsPreference); + } + } + AZ::IO::Path PrefabLoaderInterface::GeneratePath() { return AZStd::string::format("Prefab_%s", AZ::Entity::MakeId().ToString().c_str()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h index 007933c021..15f201e027 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h @@ -39,6 +39,8 @@ namespace AzToolsFramework AZ_CLASS_ALLOCATOR(PrefabLoader, AZ::SystemAllocator, 0); AZ_RTTI(PrefabLoader, "{A302B072-4DC4-4B7E-9188-226F56A3429C8}", PrefabLoaderInterface); + static void Reflect(AZ::ReflectContext* context); + ////////////////////////////////////////////////////////////////////////// // PrefabLoaderInterface interface implementation @@ -108,6 +110,9 @@ namespace AzToolsFramework //! Returns if the path is a valid path for a prefab static bool IsValidPrefabPath(AZ::IO::PathView path); + SaveAllPrefabsPreference GetSaveAllPrefabsPreference() const override; + void SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference) override; + private: /** * Copies the template dom provided and manipulates it into the proper format to be saved to disk. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h index 3c60bea18c..a428f8a7b9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h @@ -17,6 +17,13 @@ namespace AzToolsFramework { namespace Prefab { + enum class SaveAllPrefabsPreference + { + AskEveryTime, + SaveAll, + SaveNone + }; + /*! * PrefabLoaderInterface * Interface for saving/loading Prefab files. @@ -84,6 +91,9 @@ namespace AzToolsFramework //! The path will always use the '/' separator. virtual AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) = 0; + virtual SaveAllPrefabsPreference GetSaveAllPrefabsPreference() const = 0; + virtual void SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference) = 0; + protected: // Generates a new path @@ -93,3 +103,8 @@ namespace AzToolsFramework } // namespace Prefab } // namespace AzToolsFramework +namespace AZ +{ + AZ_TYPE_INFO_SPECIALIZE(AzToolsFramework::Prefab::SaveAllPrefabsPreference, "{7E61EA82-4DE4-4A3F-945F-C8FEDC1114B5}"); +} + diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 2d3d1722ca..e88e999878 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -57,6 +57,7 @@ namespace AzToolsFramework AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor::Reflect(context); AzToolsFramework::Prefab::PrefabConversionUtils::EditorInfoRemover::Reflect(context); PrefabPublicRequestHandler::Reflect(context); + PrefabLoader::Reflect(context); AZ::SerializeContext* serialize = azrtti_cast(context); if (serialize) @@ -369,9 +370,11 @@ namespace AzToolsFramework PrefabDom& PrefabSystemComponent::FindTemplateDom(TemplateId templateId) { AZStd::optional> findTemplateResult = FindTemplate(templateId); - AZ_Assert(findTemplateResult.has_value(), + AZ_Assert( + findTemplateResult.has_value(), "PrefabSystemComponent::FindTemplateDom - Unable to retrieve Prefab template with id: '%llu'. " - "Template could not be found", templateId); + "Template could not be found", + templateId); AZ_Assert(findTemplateResult->get().IsValid(), "PrefabSystemComponent::FindTemplateDom - Unable to retrieve Prefab template with id: '%llu'. " @@ -526,12 +529,10 @@ namespace AzToolsFramework Template& targetTemplate = targetTemplateReference->get(); -#if defined(AZ_ENABLE_TRACING) Template& sourceTemplate = sourceTemplateReference->get(); AZStd::string_view instanceName(instanceIterator->name.GetString(), instanceIterator->name.GetStringLength()); const AZStd::string& targetTemplateFilePath = targetTemplate.GetFilePath().Native(); const AZStd::string& sourceTemplateFilePath = sourceTemplate.GetFilePath().Native(); -#endif LinkId newLinkId = CreateUniqueLinkId(); Link newLink(newLinkId); @@ -753,6 +754,89 @@ namespace AzToolsFramework } } + bool PrefabSystemComponent::AreDirtyTemplatesPresent(TemplateId rootTemplateId) + { + TemplateReference prefabTemplate = FindTemplate(rootTemplateId); + + if (!prefabTemplate.has_value()) + { + AZ_Assert(false, "Template with id %llu is not found", rootTemplateId); + return false; + } + + if (IsTemplateDirty(rootTemplateId)) + { + return true; + } + + const Template::Links& linkIds = prefabTemplate->get().GetLinks(); + + for (LinkId linkId : linkIds) + { + auto linkIterator = m_linkIdMap.find(linkId); + if (linkIterator != m_linkIdMap.end()) + { + return AreDirtyTemplatesPresent(linkIterator->second.GetSourceTemplateId()); + } + } + return false; + } + + void PrefabSystemComponent::SaveAllDirtyTemplates(TemplateId rootTemplateId) + { + AZStd::set dirtyTemplatePaths = GetDirtyTemplatePaths(rootTemplateId); + + for (AZ::IO::PathView dirtyTemplatePath : dirtyTemplatePaths) + { + auto dirtyTemplateIterator = m_templateFilePathToIdMap.find(dirtyTemplatePath); + if (dirtyTemplateIterator == m_templateFilePathToIdMap.end()) + { + AZ_Assert(false, "Template id for template with path '%s' is not found.", dirtyTemplatePath); + } + else + { + m_prefabLoader.SaveTemplate(dirtyTemplateIterator->second); + } + } + } + + AZStd::set PrefabSystemComponent::GetDirtyTemplatePaths(TemplateId rootTemplateId) + { + AZStd::vector dirtyTemplatePathVector; + GetDirtyTemplatePathsHelper(rootTemplateId, dirtyTemplatePathVector); + AZStd::set dirtyTemplatePaths; + dirtyTemplatePaths.insert(dirtyTemplatePathVector.begin(), dirtyTemplatePathVector.end()); + return AZStd::move(dirtyTemplatePaths); + } + + void PrefabSystemComponent::GetDirtyTemplatePathsHelper( + TemplateId rootTemplateId, AZStd::vector& dirtyTemplatePaths) + { + TemplateReference prefabTemplate = FindTemplate(rootTemplateId); + + if (!prefabTemplate.has_value()) + { + AZ_Assert(false, "Template with id %llu is not found", rootTemplateId); + return; + } + + if (IsTemplateDirty(rootTemplateId)) + { + dirtyTemplatePaths.emplace_back(prefabTemplate->get().GetFilePath()); + } + + const Template::Links& linkIds = prefabTemplate->get().GetLinks(); + + for (LinkId linkId : linkIds) + { + auto linkIterator = m_linkIdMap.find(linkId); + if (linkIterator != m_linkIdMap.end()) + { + GetDirtyTemplatePathsHelper(linkIterator->second.GetSourceTemplateId(), dirtyTemplatePaths); + } + } + } + bool PrefabSystemComponent::ConnectTemplates( Link& link, TemplateId sourceTemplateId, @@ -770,10 +854,8 @@ namespace AzToolsFramework return false; } -#if defined(AZ_ENABLE_TRACING) Template& sourceTemplate = sourceTemplateReference->get(); Template& targetTemplate = targetTemplateReference->get(); -#endif AZStd::string_view instanceName(instanceIterator->name.GetString(), instanceIterator->name.GetStringLength()); @@ -783,10 +865,9 @@ namespace AzToolsFramework PrefabDomValue& instance = instanceIterator->value; AZ_Assert(instance.IsObject(), "Nested instance DOM provided is not a valid JSON object."); - [[maybe_unused]] PrefabDomValueReference sourceTemplateName = PrefabDomUtils::FindPrefabDomValue(instance, PrefabDomUtils::SourceName); + PrefabDomValueReference sourceTemplateName = PrefabDomUtils::FindPrefabDomValue(instance, PrefabDomUtils::SourceName); AZ_Assert(sourceTemplateName, "Couldn't find source template name in the DOM of the nested instance while creating a link."); - AZ_Assert( - sourceTemplateName->get() == sourceTemplate.GetFilePath().c_str(), + AZ_Assert(sourceTemplateName->get() == sourceTemplate.GetFilePath().c_str(), "The name of the source template in the nested instance DOM does not match the name of the source template already loaded"); PrefabDomValueReference patchesReference = PrefabDomUtils::FindPrefabDomValue(instance, PrefabDomUtils::PatchesName); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index b07ccbada6..04bcee2961 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -183,6 +183,12 @@ namespace AzToolsFramework */ void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) override; + bool AreDirtyTemplatesPresent(TemplateId rootTemplateId) override; + + void SaveAllDirtyTemplates(TemplateId rootTemplateId) override; + + AZStd::set GetDirtyTemplatePaths(TemplateId rootTemplateId) override; + ////////////////////////////////////////////////////////////////////////// /** @@ -335,6 +341,9 @@ namespace AzToolsFramework */ bool RemoveLinkFromTargetTemplate(const LinkId& linkId, const Link& link); + // Helper function for GetDirtyTemplatePaths(). It uses vector to speed up iteration times. + void GetDirtyTemplatePathsHelper(TemplateId rootTemplateId, AZStd::vector& dirtyTemplatePaths); + // A container for mapping Templates to the Links they may propagate changes to. AZStd::unordered_map> m_templateToLinkIdsMap; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index 0c758a21af..ae66700728 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -9,11 +9,12 @@ #pragma once #include +#include +#include #include #include #include #include -#include namespace AzToolsFramework { @@ -50,6 +51,19 @@ namespace AzToolsFramework virtual bool IsTemplateDirty(const TemplateId& templateId) = 0; virtual void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) = 0; + //! Recursive function to check if the template is dirty or if any dirty templates are presents in the links of the template. + //! @param rootTemplateId The id of the template provided as the beginning template to check the outgoing links. + virtual bool AreDirtyTemplatesPresent(TemplateId rootTemplateId) = 0; + + //! Recursive function to save if the template is dirty and save all the dirty templates in the links of the template. + //! @param rootTemplateId The id of the template provided as the beginning template to check the outgoing links. + virtual void SaveAllDirtyTemplates(TemplateId rootTemplateId) = 0; + + //! Recursive function that fetches the set of dirty templates given a starting template to check for outgoing links. + //! @param rootTemplateId The id of the template provided as the beginning template to check the outgoing links. + //! @return The set of dirty template paths populated. + virtual AZStd::set GetDirtyTemplatePaths(TemplateId rootTemplateId) = 0; + virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; virtual void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h index 0befe55822..e92f08f9ff 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace AzToolsFramework { @@ -28,6 +29,15 @@ namespace AzToolsFramework * @return The id of the newly created entity. */ virtual AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) = 0; + + //! Constructs and executes the close dialog on a prefab template corresponding to templateId. + //! @param templateId The id of the template the user chose to close. + virtual int ExecuteClosePrefabDialog(TemplateId templateId) = 0; + + //! Constructs and executes the save dialog on a prefab template corresponding to templateId. + //! @param templateId The id of the template the user chose to save. + //! @param useSaveAllPrefabsPreference A flag indicating whether SaveAllPrefabsPreference should be used for saving templates. + virtual void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference = false) = 0; }; } // namespace Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index d7fdb604fe..0c61ccb501 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -27,12 +28,28 @@ #include #include +#include +#include +#include +#include + + #include +#include +#include +#include #include #include +#include +#include +#include #include #include #include +#include +#include +#include + namespace AzToolsFramework { @@ -43,8 +60,19 @@ namespace AzToolsFramework PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr; PrefabEditInterface* PrefabIntegrationManager::s_prefabEditInterface = nullptr; PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr; + PrefabSystemComponentInterface* PrefabIntegrationManager::s_prefabSystemComponentInterface = nullptr; const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab"; + + static const char* const ClosePrefabDialog = "ClosePrefabDialog"; + static const char* const FooterSeparatorLine = "FooterSeparatorLine"; + static const char* const PrefabSavedMessageFrame = "PrefabSavedMessageFrame"; + static const char* const PrefabSavePreferenceHint = "PrefabSavePreferenceHint"; + static const char* const PrefabSaveWarningFrame = "PrefabSaveWarningFrame"; + static const char* const SaveDependentPrefabsCard = "SaveDependentPrefabsCard"; + static const char* const SavePrefabDialog = "SavePrefabDialog"; + static const char* const UnsavedPrefabFileName = "UnsavedPrefabFileName"; + void PrefabUserSettings::Reflect(AZ::ReflectContext* context) { @@ -88,6 +116,13 @@ namespace AzToolsFramework return; } + s_prefabSystemComponentInterface = AZ::Interface::Get(); + if (s_prefabSystemComponentInterface == nullptr) + { + AZ_Assert(false, "Prefab - could not get PrefabSystemComponentInterface on PrefabIntegrationManager construction."); + return; + } + EditorContextMenuBus::Handler::BusConnect(); PrefabInstanceContainerNotificationBus::Handler::BusConnect(); AZ::Interface::Register(this); @@ -1050,5 +1085,239 @@ namespace AzToolsFramework return AZ::EntityId(); } } + + int PrefabIntegrationManager::ExecuteClosePrefabDialog(TemplateId templateId) + { + if (s_prefabSystemComponentInterface->AreDirtyTemplatesPresent(templateId)) + { + auto prefabSaveSelectionDialog = ConstructClosePrefabDialog(templateId); + + int prefabSaveSelection = prefabSaveSelectionDialog->exec(); + + if (prefabSaveSelection == QDialog::Accepted) + { + SavePrefabsInDialog(prefabSaveSelectionDialog.get()); + } + + return prefabSaveSelection; + } + + return QDialogButtonBox::DestructiveRole; + } + + void PrefabIntegrationManager::ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) + { + auto prefabTemplate = s_prefabSystemComponentInterface->FindTemplate(templateId); + AZ::IO::Path prefabTemplatePath = prefabTemplate->get().GetFilePath(); + + if (s_prefabSystemComponentInterface->IsTemplateDirty(templateId)) + { + if (s_prefabLoaderInterface->SaveTemplate(templateId) == false) + { + AZ_Error("Prefab", false, "Template '%s' could not be saved successfully.", prefabTemplatePath.c_str()); + return; + } + } + + if (s_prefabSystemComponentInterface->AreDirtyTemplatesPresent(templateId)) + { + if (useSaveAllPrefabsPreference) + { + SaveAllPrefabsPreference saveAllPrefabsPreference = s_prefabLoaderInterface->GetSaveAllPrefabsPreference(); + + if (saveAllPrefabsPreference == SaveAllPrefabsPreference::SaveAll) + { + s_prefabSystemComponentInterface->SaveAllDirtyTemplates(templateId); + return; + } + else if (saveAllPrefabsPreference == SaveAllPrefabsPreference::SaveNone) + { + return; + } + } + + AZStd::unique_ptr savePrefabDialog = ConstructSavePrefabDialog(templateId, useSaveAllPrefabsPreference); + if (savePrefabDialog) + { + int prefabSaveSelection = savePrefabDialog->exec(); + + if (prefabSaveSelection == QDialog::Accepted) + { + SavePrefabsInDialog(savePrefabDialog.get()); + } + } + } + } + + void PrefabIntegrationManager::SavePrefabsInDialog(QDialog* unsavedPrefabsDialog) + { + QList unsavedPrefabFileLabels = unsavedPrefabsDialog->findChildren(UnsavedPrefabFileName); + if (unsavedPrefabFileLabels.size() > 0) + { + for (const QLabel* unsavedPrefabFileLabel : unsavedPrefabFileLabels) + { + AZStd::string unsavedPrefabFileName = unsavedPrefabFileLabel->property("FilePath").toString().toUtf8().data(); + AzToolsFramework::Prefab::TemplateId unsavedPrefabTemplateId = + s_prefabSystemComponentInterface->GetTemplateIdFromFilePath(unsavedPrefabFileName.data()); + bool isTemplateSavedSuccessfully = s_prefabLoaderInterface->SaveTemplate(unsavedPrefabTemplateId); + AZ_Error("Prefab", isTemplateSavedSuccessfully, "Prefab '%s' could not be saved successfully.", unsavedPrefabFileName.c_str()); + } + } + } + + AZStd::unique_ptr PrefabIntegrationManager::ConstructSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) + { + AZStd::unique_ptr savePrefabDialog = AZStd::make_unique(AzToolsFramework::GetActiveWindow()); + + savePrefabDialog->setWindowTitle("Unsaved files detected"); + + // Main Content section begins. + savePrefabDialog->setObjectName(SavePrefabDialog); + QBoxLayout* contentLayout = new QVBoxLayout(savePrefabDialog.get()); + + QFrame* prefabSavedMessageFrame = new QFrame(savePrefabDialog.get()); + QHBoxLayout* prefabSavedMessageLayout = new QHBoxLayout(savePrefabDialog.get()); + prefabSavedMessageFrame->setObjectName(PrefabSavedMessageFrame); + prefabSavedMessageFrame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); + + // Add a checkMark icon next to the level entities saved message. + QPixmap checkMarkIcon(QString(":/Notifications/checkmark.svg")); + QLabel* prefabSavedSuccessfullyIconContainer = new QLabel(savePrefabDialog.get()); + prefabSavedSuccessfullyIconContainer->setPixmap(checkMarkIcon); + prefabSavedSuccessfullyIconContainer->setFixedWidth(checkMarkIcon.width()); + + // Add a message that level entities are saved successfully. + + auto prefabTemplate = s_prefabSystemComponentInterface->FindTemplate(templateId); + AZ::IO::Path prefabTemplatePath = prefabTemplate->get().GetFilePath(); + QLabel* prefabSavedSuccessfullyLabel = new QLabel( + QString("Prefab '%1' has been saved. Do you want to save the below dependent prefabs too?").arg(prefabTemplatePath.c_str()), + savePrefabDialog.get()); + prefabSavedMessageLayout->addWidget(prefabSavedSuccessfullyIconContainer); + prefabSavedMessageLayout->addWidget(prefabSavedSuccessfullyLabel); + prefabSavedMessageFrame->setLayout(prefabSavedMessageLayout); + contentLayout->addWidget(prefabSavedMessageFrame); + + AZStd::unique_ptr unsavedPrefabsContainer = ConstructUnsavedPrefabsCard(templateId); + contentLayout->addWidget(unsavedPrefabsContainer.release()); + + contentLayout->addStretch(); + + // Footer section begins. + QHBoxLayout* footerLayout = new QHBoxLayout(savePrefabDialog.get()); + + if (useSaveAllPrefabsPreference) + { + QFrame* footerSeparatorLine = new QFrame(savePrefabDialog.get()); + footerSeparatorLine->setObjectName(FooterSeparatorLine); + footerSeparatorLine->setFrameShape(QFrame::HLine); + contentLayout->addWidget(footerSeparatorLine); + + QLabel* prefabSavePreferenceHint = new QLabel( + "You can prevent this window from showing in the future by updating your global save preferences.", + savePrefabDialog.get()); + prefabSavePreferenceHint->setToolTip( + "Go to 'Edit > Editor Settings > Global Preferences... > Global save preferences' to update your preference"); + prefabSavePreferenceHint->setObjectName(PrefabSavePreferenceHint); + footerLayout->addWidget(prefabSavePreferenceHint); + } + + QDialogButtonBox* prefabSaveConfirmationButtons = + new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::No, savePrefabDialog.get()); + footerLayout->addWidget(prefabSaveConfirmationButtons); + contentLayout->addLayout(footerLayout); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, savePrefabDialog.get(), &QDialog::accept); + connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, savePrefabDialog.get(), &QDialog::reject); + AzQtComponents::StyleManager::setStyleSheet(savePrefabDialog->parentWidget(), QStringLiteral("style:Editor.qss")); + + savePrefabDialog->setLayout(contentLayout); + return AZStd::move(savePrefabDialog); + } + + AZStd::shared_ptr PrefabIntegrationManager::ConstructClosePrefabDialog(TemplateId templateId) + { + AZStd::shared_ptr closePrefabDialog = AZStd::make_shared(AzToolsFramework::GetActiveWindow()); + closePrefabDialog->setWindowTitle("Unsaved files detected"); + AZStd::weak_ptr closePrefabDialogWeakPtr(closePrefabDialog); + closePrefabDialog->setObjectName(ClosePrefabDialog); + + // Main Content section begins. + QVBoxLayout* contentLayout = new QVBoxLayout(closePrefabDialog.get()); + QFrame* prefabSaveWarningFrame = new QFrame(closePrefabDialog.get()); + QHBoxLayout* levelEntitiesSaveQuestionLayout = new QHBoxLayout(closePrefabDialog.get()); + prefabSaveWarningFrame->setObjectName(PrefabSaveWarningFrame); + + // Add a warning icon next to save prefab warning. + prefabSaveWarningFrame->setLayout(levelEntitiesSaveQuestionLayout); + QPixmap warningIcon(QString(":/Notifications/warning.svg")); + QLabel* warningIconContainer = new QLabel(closePrefabDialog.get()); + warningIconContainer->setPixmap(warningIcon); + warningIconContainer->setFixedWidth(warningIcon.width()); + levelEntitiesSaveQuestionLayout->addWidget(warningIconContainer); + + // Ask user if they want to save entities in level. + QLabel* prefabSaveQuestionLabel = new QLabel("Do you want to save the below unsaved prefabs?", closePrefabDialog.get()); + levelEntitiesSaveQuestionLayout->addWidget(prefabSaveQuestionLabel); + contentLayout->addWidget(prefabSaveWarningFrame); + + auto templateToSave = s_prefabSystemComponentInterface->FindTemplate(templateId); + AZ::IO::Path templateToSaveFilePath = templateToSave->get().GetFilePath(); + AZStd::unique_ptr unsavedPrefabsCard = ConstructUnsavedPrefabsCard(templateId); + contentLayout->addWidget(unsavedPrefabsCard.release()); + + contentLayout->addStretch(); + + QHBoxLayout* footerLayout = new QHBoxLayout(closePrefabDialog.get()); + + QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox( + QDialogButtonBox::Save | QDialogButtonBox::Discard | QDialogButtonBox::Cancel, closePrefabDialog.get()); + footerLayout->addWidget(prefabSaveConfirmationButtons); + contentLayout->addLayout(footerLayout); + QObject::connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, closePrefabDialog.get(), &QDialog::accept); + QObject::connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, closePrefabDialog.get(), &QDialog::reject); + QObject::connect( + prefabSaveConfirmationButtons, &QDialogButtonBox::clicked, closePrefabDialog.get(), + [closePrefabDialogWeakPtr, prefabSaveConfirmationButtons](QAbstractButton* button) + { + int prefabSaveSelection = prefabSaveConfirmationButtons->buttonRole(button); + closePrefabDialogWeakPtr.lock()->done(prefabSaveSelection); + }); + AzQtComponents::StyleManager::setStyleSheet(closePrefabDialog.get(), QStringLiteral("style:Editor.qss")); + closePrefabDialog->setLayout(contentLayout); + return closePrefabDialog; + } + + AZStd::unique_ptr PrefabIntegrationManager::ConstructUnsavedPrefabsCard(TemplateId templateId) + { + FlowLayout* unsavedPrefabsLayout = new FlowLayout(AzToolsFramework::GetActiveWindow()); + + AZStd::set dirtyTemplatePaths = s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId); + + for (AZ::IO::PathView dirtyTemplatePath : dirtyTemplatePaths) + { + QLabel* prefabNameLabel = + new QLabel(QString("%1").arg(dirtyTemplatePath.Filename().Native().data()), AzToolsFramework::GetActiveWindow()); + prefabNameLabel->setObjectName(UnsavedPrefabFileName); + prefabNameLabel->setWordWrap(true); + prefabNameLabel->setToolTip(dirtyTemplatePath.Native().data()); + prefabNameLabel->setProperty("FilePath", dirtyTemplatePath.Native().data()); + unsavedPrefabsLayout->addWidget(prefabNameLabel); + } + + AZStd::unique_ptr unsavedPrefabsContainer = AZStd::make_unique(AzToolsFramework::GetActiveWindow()); + unsavedPrefabsContainer->setObjectName(SaveDependentPrefabsCard); + unsavedPrefabsContainer->setTitle("Unsaved Prefabs"); + unsavedPrefabsContainer->header()->setHasContextMenu(false); + unsavedPrefabsContainer->header()->setIcon(QIcon(QStringLiteral(":/Entity/prefab_edit.svg"))); + + QFrame* unsavedPrefabsFrame = new QFrame(unsavedPrefabsContainer.get()); + unsavedPrefabsFrame->setLayout(unsavedPrefabsLayout); + QScrollArea* unsavedPrefabsScrollArea = new QScrollArea(unsavedPrefabsContainer.get()); + unsavedPrefabsScrollArea->setWidget(unsavedPrefabsFrame); + unsavedPrefabsScrollArea->setWidgetResizable(true); + unsavedPrefabsContainer->setContentWidget(unsavedPrefabsScrollArea); + + return AZStd::move(unsavedPrefabsContainer); + } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h index b40f0169c9..3e66350932 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h @@ -15,12 +15,15 @@ #include #include #include +#include #include #include #include #include #include +#include + namespace AzToolsFramework { namespace Prefab @@ -49,6 +52,7 @@ namespace AzToolsFramework , public AssetBrowser::AssetBrowserSourceDropBus::Handler , public PrefabInstanceContainerNotificationBus::Handler , public PrefabIntegrationInterface + , public QObject { public: AZ_CLASS_ALLOCATOR(PrefabIntegrationManager, AZ::SystemAllocator, 0); @@ -72,6 +76,8 @@ namespace AzToolsFramework // PrefabIntegrationInterface... AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) override; + int ExecuteClosePrefabDialog(TemplateId templateId) override; + void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) override; private: // Manages the Edit Mode UI for prefabs @@ -124,12 +130,19 @@ namespace AzToolsFramework static AZ::u32 GetSliceFlags(const AZ::Edit::ElementData* editData, const AZ::Edit::ClassData* classData); + AZStd::shared_ptr ConstructClosePrefabDialog(TemplateId templateId); + AZStd::unique_ptr ConstructUnsavedPrefabsCard(TemplateId templateId); + AZStd::unique_ptr ConstructSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference); + void SavePrefabsInDialog(QDialog* unsavedPrefabsDialog); + + static const AZStd::string s_prefabFileExtension; static EditorEntityUiInterface* s_editorEntityUiInterface; static PrefabPublicInterface* s_prefabPublicInterface; static PrefabEditInterface* s_prefabEditInterface; static PrefabLoaderInterface* s_prefabLoaderInterface; + static PrefabSystemComponentInterface* s_prefabSystemComponentInterface; }; } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp index 955ee61525..e3b45aca2b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp @@ -10,6 +10,25 @@ namespace AzToolsFramework { + AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction( + const ViewportInteraction::MouseInteractionEvent& mouseInteraction) + { + if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left()) + { + if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down) + { + return AzFramework::ClickDetector::ClickEvent::Down; + } + + if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up) + { + return AzFramework::ClickDetector::ClickEvent::Up; + } + } + + return AzFramework::ClickDetector::ClickEvent::Nil; + } + float ManipulatorLineBoundWidth(const AzFramework::ViewportId viewportId /*= AzFramework::InvalidViewportId*/) { float lineBoundWidth = 0.0f; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index 147c71c8e8..942fee1a49 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -250,8 +250,6 @@ namespace AzToolsFramework virtual AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) = 0; //! Return the terrain height given a world position in 2d (xy plane). virtual float TerrainHeight(const AZ::Vector2& position) = 0; - //! Given the current view frustum (viewport) return all visible entities. - virtual void FindVisibleEntities(AZStd::vector& visibleEntities) = 0; //! Is the user holding a modifier key to move the manipulator space from local to world. virtual bool ShowingWorldSpace() = 0; //! Return the widget to use as the parent for the viewport context menu. @@ -269,7 +267,20 @@ namespace AzToolsFramework //! Type to inherit to implement MainEditorViewportInteractionRequests. using MainEditorViewportInteractionRequestBus = AZ::EBus; - //! Viewport requests for managing the viewport's cursor state. + //! Editor entity requests to be made about the viewport. + class EditorEntityViewportInteractionRequests + { + public: + //! Given the current view frustum (viewport) return all visible entities. + virtual void FindVisibleEntities(AZStd::vector& visibleEntities) = 0; + + protected: + ~EditorEntityViewportInteractionRequests() = default; + }; + + using EditorEntityViewportInteractionRequestBus = AZ::EBus; + + //! Viewport requests for managing the viewport cursor state. class ViewportMouseCursorRequests { public: @@ -321,23 +332,8 @@ namespace AzToolsFramework //! Maps a mouse interaction event to a ClickDetector event. //! @note Function only cares about up or down events, all other events are mapped to Nil (ignored). - inline AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction( - const ViewportInteraction::MouseInteractionEvent& mouseInteraction) - { - if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left()) - { - if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down) - { - return AzFramework::ClickDetector::ClickEvent::Down; - } - - if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up) - { - return AzFramework::ClickDetector::ClickEvent::Up; - } - } - return AzFramework::ClickDetector::ClickEvent::Nil; - } + AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction( + const ViewportInteraction::MouseInteractionEvent& mouseInteraction); //! Wrap EBus call to retrieve manipulator line bound width. //! @note It is possible to pass AzFramework::InvalidViewportId (the default) to perform a Broadcast as opposed to a targeted Event. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp index c39b2c0ebc..eafd37f199 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp @@ -9,8 +9,8 @@ #include "EditorBoxSelect.h" #include -#include #include +#include #include @@ -19,11 +19,15 @@ namespace AzToolsFramework static const AZ::Color s_boxSelectColor = AZ::Color(1.0f, 1.0f, 1.0f, 0.4f); static const float s_boxSelectLineWidth = 2.0f; - void EditorBoxSelect::HandleMouseInteraction( - const ViewportInteraction::MouseInteractionEvent& mouseInteraction) + void EditorBoxSelect::HandleMouseInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) { AZ_PROFILE_FUNCTION(AzToolsFramework); + if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down) + { + m_cursorPositionAtDownEvent = mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates; + } + m_cursorState.SetCurrentPosition(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates); const auto selectClickEvent = ClickDetectorEventFromViewportInteraction(mouseInteraction); @@ -35,12 +39,7 @@ namespace AzToolsFramework m_leftMouseDown(mouseInteraction); } - m_boxSelectRegion = QRect - { - ViewportInteraction::QPointFromScreenPoint( - mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates), - QSize { 0, 0 } - }; + m_boxSelectRegion = QRect{ ViewportInteraction::QPointFromScreenPoint(m_cursorPositionAtDownEvent), QSize{ 0, 0 } }; } if (m_boxSelectRegion) @@ -87,11 +86,11 @@ namespace AzToolsFramework AZ::Vector2 viewportSize = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId).m_viewportSize; debugDisplay.DrawWireQuad2d( - AZ::Vector2( - aznumeric_cast(m_boxSelectRegion->x()), aznumeric_cast(m_boxSelectRegion->y())) / viewportSize, + AZ::Vector2(aznumeric_cast(m_boxSelectRegion->x()), aznumeric_cast(m_boxSelectRegion->y())) / viewportSize, AZ::Vector2( aznumeric_cast(m_boxSelectRegion->x()) + aznumeric_cast(m_boxSelectRegion->width()), - aznumeric_cast(m_boxSelectRegion->y()) + aznumeric_cast(m_boxSelectRegion->height())) / viewportSize, + aznumeric_cast(m_boxSelectRegion->y()) + aznumeric_cast(m_boxSelectRegion->height())) / + viewportSize, 0.f); debugDisplay.DepthTestOn(); @@ -101,8 +100,7 @@ namespace AzToolsFramework } } - void EditorBoxSelect::DisplayScene( - const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) + void EditorBoxSelect::DisplayScene(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) { if (m_displayScene) { @@ -122,15 +120,14 @@ namespace AzToolsFramework m_mouseMove = mouseMove; } - void EditorBoxSelect::InstallLeftMouseUp( - const AZStd::function& leftMouseUp) + void EditorBoxSelect::InstallLeftMouseUp(const AZStd::function& leftMouseUp) { m_leftMouseUp = leftMouseUp; } void EditorBoxSelect::InstallDisplayScene( - const AZStd::function& displayScene) + const AZStd::function& + displayScene) { m_displayScene = displayScene; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h index 8b36ec0a32..f1c59f9fd8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h @@ -81,5 +81,6 @@ namespace AzToolsFramework ViewportInteraction::KeyboardModifiers m_previousModifiers; //!< Modifier keys active on the previous frame. AzFramework::ClickDetector m_clickDetector; //!< Utility type to detect if a mouse click or move has occurred. AzFramework::CursorState m_cursorState; //!< Utility type to track the current cursor position (and movement/delta). + AzFramework::ScreenPoint m_cursorPositionAtDownEvent; //!< The position of the cursor when first potentially starting a box select. }; } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp index 7cb0e718a8..f4b68b5970 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp @@ -19,7 +19,7 @@ namespace AzToolsFramework { // default ray length for picking in the viewport - static const float s_pickRayLength = 1000.0f; + static const float EditorPickRayLength = 1000.0f; AZ::Vector3 CalculateCenterOffset(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot) { @@ -60,16 +60,27 @@ namespace AzToolsFramework return screenPosition; } - bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb) + bool AabbIntersectRay(const AZ::Vector3& origin, const AZ::Vector3& direction, const AZ::Aabb& aabb, float& distance) { AZ_PROFILE_FUNCTION(AzToolsFramework); - const AZ::Vector3 rayScaledDir = mouseInteraction.m_mousePick.m_rayDirection * s_pickRayLength; + const AZ::Vector3 rayScaledDir = direction * EditorPickRayLength; - AZ::Vector3 startNormal; float t, end; - return AZ::Intersect::IntersectRayAABB( - mouseInteraction.m_mousePick.m_rayOrigin, rayScaledDir, rayScaledDir.GetReciprocal(), aabb, t, end, startNormal) > 0; + AZ::Vector3 startNormal; + if (AZ::Intersect::IntersectRayAABB(origin, rayScaledDir, rayScaledDir.GetReciprocal(), aabb, t, end, startNormal) > 0) + { + distance = t * EditorPickRayLength; + return true; + } + + return false; + } + + bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb) + { + float unused; + return AabbIntersectRay(mouseInteraction.m_mousePick.m_rayOrigin, mouseInteraction.m_mousePick.m_rayDirection, aabb, unused); } bool PickEntity( @@ -117,8 +128,7 @@ namespace AzToolsFramework { float scaling = 1.0f; ViewportInteraction::ViewportInteractionRequestBus::EventResult( - scaling, viewportId, - &ViewportInteraction::ViewportInteractionRequestBus::Events::DeviceScalingFactor); + scaling, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::DeviceScalingFactor); return scaling; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h index aa1b3ae5ce..ec9bde9f9c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h @@ -46,6 +46,10 @@ namespace AzToolsFramework //! in screen space intersected an aabb in world space. bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb); + //! Wrapper to perform an intersection between a ray and an aabb. + //! Note: direction should be normalized (it is scaled internally by the editor pick distance). + bool AabbIntersectRay(const AZ::Vector3& origin, const AZ::Vector3& direction, const AZ::Aabb& aabb, float& distance); + //! Return if a mouse interaction (pick ray) did intersect the tested EntityId. bool PickEntity( AZ::EntityId entityId, const ViewportInteraction::MouseInteraction& mouseInteraction, float& closestDistance, int viewportId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 101d7094db..afcade944a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -44,39 +44,46 @@ namespace AzToolsFramework AZ_CVAR( float, - cl_viewportGizmoAxisLineWidth, + ed_viewportGizmoAxisLineWidth, 4.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "The width of the line for the viewport axis gizmo"); AZ_CVAR( float, - cl_viewportGizmoAxisLineLength, + ed_viewportGizmoAxisLineLength, 0.7f, nullptr, AZ::ConsoleFunctorFlags::Null, "The length of the line for the viewport axis gizmo"); AZ_CVAR( float, - cl_viewportGizmoAxisLabelOffset, + ed_viewportGizmoAxisLabelOffset, 1.15f, nullptr, AZ::ConsoleFunctorFlags::Null, "The offset of the label for the viewport axis gizmo"); AZ_CVAR( float, - cl_viewportGizmoAxisLabelSize, + ed_viewportGizmoAxisLabelSize, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "The size of each label for the viewport axis gizmo"); AZ_CVAR( AZ::Vector2, - cl_viewportGizmoAxisScreenPosition, + ed_viewportGizmoAxisScreenPosition, AZ::Vector2(0.045f, 0.9f), nullptr, AZ::ConsoleFunctorFlags::Null, "The screen position of the gizmo in normalized (0-1) ndc space"); + AZ_CVAR( + bool, + ed_viewportStickySelect, + true, + nullptr, + AZ::ConsoleFunctorFlags::Null, + "Sticky select implies a single click will not change selection with an entity already selected"); // strings related to new viewport interaction model (EditorTransformComponentSelection) static const char* const s_togglePivotTitleRightClick = "Toggle pivot"; @@ -991,14 +998,19 @@ namespace AzToolsFramework // ask the visible entity data cache if the entity is selectable in the viewport // (useful in the context of drawing when we only care about entities we can see) - static bool SelectableInVisibleViewportCache(const EditorVisibleEntityDataCache& entityDataCache, const AZ::EntityId entityId) + // note: return the index if it is selectable, nullopt otherwise + static AZStd::optional SelectableInVisibleViewportCache( + const EditorVisibleEntityDataCache& entityDataCache, const AZ::EntityId entityId) { if (auto entityIndex = entityDataCache.GetVisibleEntityIndexFromId(entityId)) { - return entityDataCache.IsVisibleEntitySelectableInViewport(*entityIndex); + if (entityDataCache.IsVisibleEntitySelectableInViewport(*entityIndex)) + { + return *entityIndex; + } } - return false; + return AZStd::nullopt; } static AZ::ComponentId GetTransformComponentId(const AZ::EntityId entityId) @@ -1709,17 +1721,17 @@ namespace AzToolsFramework m_pivotOverrideFrame.Reset(); } - bool EditorTransformComponentSelection::SelectDeselect(const AZ::EntityId entityIdUnderCursor) + bool EditorTransformComponentSelection::SelectDeselect(const AZ::EntityId entityId) { AZ_PROFILE_FUNCTION(AzToolsFramework); - if (entityIdUnderCursor.IsValid()) + if (entityId.IsValid()) { - if (IsEntitySelectedInternal(entityIdUnderCursor, m_selectedEntityIds)) + if (IsEntitySelectedInternal(entityId, m_selectedEntityIds)) { if (!UndoRedoOperationInProgress()) { - RemoveEntityFromSelection(entityIdUnderCursor); + RemoveEntityFromSelection(entityId); const auto nextEntityIds = EntityIdVectorFromContainer(m_selectedEntityIds); @@ -1742,7 +1754,7 @@ namespace AzToolsFramework { if (!UndoRedoOperationInProgress()) { - AddEntityToSelection(entityIdUnderCursor); + AddEntityToSelection(entityId); const auto nextEntityIds = EntityIdVectorFromContainer(m_selectedEntityIds); @@ -1783,25 +1795,21 @@ namespace AzToolsFramework // for entities selected with no bounds of their own (just TransformComponent) // check selection against the selection indicator aabb - for (AZ::EntityId entityId : m_selectedEntityIds) + for (const AZ::EntityId& entityId : m_selectedEntityIds) { - if (!SelectableInVisibleViewportCache(*m_entityDataCache, entityId)) + if (const auto entityIndex = SelectableInVisibleViewportCache(*m_entityDataCache, entityId); entityIndex.has_value()) { - continue; - } + const AZ::Transform& worldFromLocal = m_entityDataCache->GetVisibleEntityTransform(*entityIndex); + const AZ::Vector3 boxPosition = worldFromLocal.TransformPoint(CalculateCenterOffset(entityId, m_pivotMode)); + const AZ::Vector3 scaledSize = + AZ::Vector3(s_pivotSize) * CalculateScreenToWorldMultiplier(worldFromLocal.GetTranslation(), cameraState); - AZ::Transform worldFromLocal; - AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM); - - const AZ::Vector3 boxPosition = worldFromLocal.TransformPoint(CalculateCenterOffset(entityId, m_pivotMode)); - - const AZ::Vector3 scaledSize = - AZ::Vector3(s_pivotSize) * CalculateScreenToWorldMultiplier(worldFromLocal.GetTranslation(), cameraState); - - if (AabbIntersectMouseRay( - mouseInteraction.m_mouseInteraction, AZ::Aabb::CreateFromMinMax(boxPosition - scaledSize, boxPosition + scaledSize))) - { - m_cachedEntityIdUnderCursor = entityId; + if (AabbIntersectMouseRay( + mouseInteraction.m_mouseInteraction, + AZ::Aabb::CreateFromMinMax(boxPosition - scaledSize, boxPosition + scaledSize))) + { + m_cachedEntityIdUnderCursor = entityId; + } } } @@ -3490,7 +3498,7 @@ namespace AzToolsFramework const auto cameraProjection = AzFramework::CameraProjection(gizmoCameraState); // screen space offset to move the 2d gizmo around - const AZ::Vector2 screenOffset = AZ::Vector2(cl_viewportGizmoAxisScreenPosition) - AZ::Vector2(0.5f, 0.5f); + const AZ::Vector2 screenOffset = AZ::Vector2(ed_viewportGizmoAxisScreenPosition) - AZ::Vector2(0.5f, 0.5f); // map from a position in world space (relative to the the gizmo camera near the origin) to a position in // screen space @@ -3502,7 +3510,7 @@ namespace AzToolsFramework }; // get all important axis positions in screen space - const float lineLength = cl_viewportGizmoAxisLineLength; + const float lineLength = ed_viewportGizmoAxisLineLength; const auto gizmoStart = calculateGizmoAxis(AZ::Vector3::CreateZero()); const auto gizmoEndAxisX = calculateGizmoAxis(-AZ::Vector3::CreateAxisX() * lineLength); const auto gizmoEndAxisY = calculateGizmoAxis(-AZ::Vector3::CreateAxisY() * lineLength); @@ -3513,7 +3521,7 @@ namespace AzToolsFramework const AZ::Vector2 gizmoAxisZ = gizmoEndAxisZ - gizmoStart; // draw the axes of the gizmo - debugDisplay.SetLineWidth(cl_viewportGizmoAxisLineWidth); + debugDisplay.SetLineWidth(ed_viewportGizmoAxisLineWidth); debugDisplay.SetColor(AZ::Colors::Red); debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisX, 1.0f); debugDisplay.SetColor(AZ::Colors::Lime); @@ -3522,14 +3530,14 @@ namespace AzToolsFramework debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisZ, 1.0f); debugDisplay.SetLineWidth(1.0f); - const float labelOffset = cl_viewportGizmoAxisLabelOffset; + const float labelOffset = ed_viewportGizmoAxisLabelOffset; const float screenScale = GetScreenDisplayScaling(viewportId); const auto labelXScreenPosition = (gizmoStart + (gizmoAxisX * labelOffset)) * editorCameraState.m_viewportSize * screenScale; const auto labelYScreenPosition = (gizmoStart + (gizmoAxisY * labelOffset)) * editorCameraState.m_viewportSize * screenScale; const auto labelZScreenPosition = (gizmoStart + (gizmoAxisZ * labelOffset)) * editorCameraState.m_viewportSize * screenScale; // draw the label of of each axis for the gizmo - const float labelSize = cl_viewportGizmoAxisLabelSize; + const float labelSize = ed_viewportGizmoAxisLabelSize; debugDisplay.SetColor(AZ::Colors::White); debugDisplay.Draw2dTextLabel(labelXScreenPosition.GetX(), labelXScreenPosition.GetY(), labelSize, "X", true); debugDisplay.Draw2dTextLabel(labelYScreenPosition.GetX(), labelYScreenPosition.GetY(), labelSize, "Y", true); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h index 42ec423b03..f528a11688 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include #include @@ -32,6 +33,8 @@ namespace AzToolsFramework { + AZ_CVAR_EXTERNED(bool, ed_viewportStickySelect); + class EditorVisibleEntityDataCache; using EntityIdSet = AZStd::unordered_set; //!< Alias for unordered_set of EntityIds. @@ -170,14 +173,11 @@ namespace AzToolsFramework //! ViewportInteraction::ViewportSelectionRequests //! Intercept all viewport mouse events and respond to inputs. - bool HandleMouseInteraction( - const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override; + bool HandleMouseInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override; void DisplayViewportSelection( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; + const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; void DisplayViewportSelection2d( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; + const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; //! Add an entity to the current selection void AddEntityToSelection(AZ::EntityId entityId); @@ -206,7 +206,7 @@ namespace AzToolsFramework bool IsEntitySelected(AZ::EntityId entityId) const; void SetSelectedEntities(const EntityIdList& entityIds); void DeselectEntities(); - bool SelectDeselect(AZ::EntityId entityIdUnderCursor); + bool SelectDeselect(AZ::EntityId entityId); void RefreshSelectedEntityIds(); void RefreshSelectedEntityIds(const EntityIdList& selectedEntityIds); @@ -253,11 +253,10 @@ namespace AzToolsFramework void SnapSelectedEntitiesToWorldGrid(float gridSize) override; // EditorManipulatorCommandUndoRedoRequestBus ... - void UndoRedoEntityManipulatorCommand( - AZ::u8 pivotOverride, const AZ::Transform& transform, AZ::EntityId entityId) override; + void UndoRedoEntityManipulatorCommand(AZ::u8 pivotOverride, const AZ::Transform& transform, AZ::EntityId entityId) override; // EditorContextMenuBus... - void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2 & point, int flags) override; + void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override; int GetMenuPosition() const override; AZStd::string GetMenuIdentifier() const override; @@ -266,8 +265,7 @@ namespace AzToolsFramework // ToolsApplicationNotificationBus ... void BeforeEntitySelectionChanged() override; - void AfterEntitySelectionChanged( - const EntityIdList& newlySelectedEntities, const EntityIdList& newlyDeselectedEntities) override; + void AfterEntitySelectionChanged(const EntityIdList& newlySelectedEntities, const EntityIdList& newlyDeselectedEntities) override; // TransformNotificationBus ... void OnTransformChanged(const AZ::Transform& localTM, const AZ::Transform& worldTM) override; @@ -318,7 +316,8 @@ namespace AzToolsFramework EntityIdManipulators m_entityIdManipulators; //!< Mapping from a Manipulator to potentially many EntityIds. EditorBoxSelect m_boxSelect; //!< Type responsible for handling box select. - AZStd::unique_ptr m_manipulatorMoveCommand; //!< Track adjustments to manipulator translation and orientation (during mouse press/move). + //! Track adjustments to manipulator translation and orientation (during mouse press/move). + AZStd::unique_ptr m_manipulatorMoveCommand; AZStd::vector> m_actions; //!< What actions are tied to this handler. ViewportInteraction::KeyboardModifiers m_previousModifiers; //!< What modifiers were held last frame. EditorContextMenu m_contextMenu; //!< Viewport right click context menu. @@ -328,8 +327,10 @@ namespace AzToolsFramework ReferenceFrame m_referenceFrame = ReferenceFrame::Parent; //!< What reference frame is the Manipulator currently operating in. Frame m_axisPreview; //!< Axes of entity at the time of mouse down to indicate delta of translation. bool m_triedToRefresh = false; //!< Did a refresh event occur to recalculate the current Manipulator transform. - bool m_didSetSelectedEntities = false; //!< Was EditorTransformComponentSelection responsible for the most recent entity selection change. - bool m_selectedEntityIdsAndManipulatorsDirty = false; //!< Do the active manipulators need to recalculated after a modification (lock/visibility etc). + //! Was EditorTransformComponentSelection responsible for the most recent entity selection change. + bool m_didSetSelectedEntities = false; + //! Do the active manipulators need to recalculated after a modification (lock/visibility etc). + bool m_selectedEntityIdsAndManipulatorsDirty = false; bool m_transformChangedInternally = false; //!< Was an OnTransformChanged event triggered internally or not. ViewportUi::ClusterId m_transformModeClusterId; //!< Id of the Viewport UI cluster for changing transform mode. ViewportUi::ButtonId m_translateButtonId; //!< Id of the Viewport UI button for translate mode. @@ -363,15 +364,13 @@ namespace AzToolsFramework //! Calculate the orientation for a group of entities based on the incoming reference frame. template - PivotOrientationResult CalculatePivotOrientationForEntityIds( - const EntityIdMap& entityIdMap, const ReferenceFrame referenceFrame); + PivotOrientationResult CalculatePivotOrientationForEntityIds(const EntityIdMap& entityIdMap, const ReferenceFrame referenceFrame); //! Calculate the orientation for a group of entities based on the incoming //! reference frame with possible pivot override. template PivotOrientationResult CalculateSelectionPivotOrientation( - const EntityIdMap& entityIdMap, const OptionalFrame& pivotOverrideFrame, - const ReferenceFrame referenceFrame); + const EntityIdMap& entityIdMap, const OptionalFrame& pivotOverrideFrame, const ReferenceFrame referenceFrame); void SetEntityWorldTranslation(AZ::EntityId entityId, const AZ::Vector3& worldTranslation, bool& internal); void SetEntityLocalTranslation(AZ::EntityId entityId, const AZ::Vector3& localTranslation, bool& internal); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp index c65f494b72..5da827244f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp @@ -161,8 +161,8 @@ namespace AzToolsFramework // request list of visible entities from authoritative system EntityIdList nextVisibleEntityIds; - ViewportInteraction::MainEditorViewportInteractionRequestBus::Event( - viewportInfo.m_viewportId, &ViewportInteraction::MainEditorViewportInteractionRequestBus::Events::FindVisibleEntities, + ViewportInteraction::EditorEntityViewportInteractionRequestBus::Event( + viewportInfo.m_viewportId, &ViewportInteraction::EditorEntityViewportInteractionRequestBus::Events::FindVisibleEntities, nextVisibleEntityIds); // only bother resorting if we know the lists have changed diff --git a/Code/Framework/AzToolsFramework/Platform/Linux/AzToolsFramework/Archive/ArchiveComponent_Linux.cpp b/Code/Framework/AzToolsFramework/Platform/Linux/AzToolsFramework/Archive/ArchiveComponent_Linux.cpp index 4a834bdedb..cc8b9492e8 100644 --- a/Code/Framework/AzToolsFramework/Platform/Linux/AzToolsFramework/Archive/ArchiveComponent_Linux.cpp +++ b/Code/Framework/AzToolsFramework/Platform/Linux/AzToolsFramework/Archive/ArchiveComponent_Linux.cpp @@ -15,7 +15,7 @@ namespace AzToolsFramework { namespace Platform { - static const char ErrorChannel[] = "ArchiveComponent_Linux"; + [[maybe_unused]] static const char ErrorChannel[] = "ArchiveComponent_Linux"; static const char ZipExePath[] = R"(/usr/bin/zip)"; static const char UnzipExePath[] = R"(/usr/bin/unzip)"; diff --git a/Code/Framework/AzToolsFramework/Tests/ComponentModeTestFixture.cpp b/Code/Framework/AzToolsFramework/Tests/ComponentModeTestFixture.cpp index cfdd2d082c..672a0d6705 100644 --- a/Code/Framework/AzToolsFramework/Tests/ComponentModeTestFixture.cpp +++ b/Code/Framework/AzToolsFramework/Tests/ComponentModeTestFixture.cpp @@ -6,8 +6,8 @@ * */ -#include "ComponentModeTestDoubles.h" #include "ComponentModeTestFixture.h" +#include "ComponentModeTestDoubles.h" #include @@ -15,17 +15,15 @@ namespace UnitTest { void ComponentModeTestFixture::SetUpEditorFixtureImpl() { - using namespace AzToolsFramework; - using namespace AzToolsFramework::ComponentModeFramework; + namespace AztfCmf = AzToolsFramework::ComponentModeFramework; auto* app = GetApplication(); - ASSERT_TRUE(app); - app->RegisterComponentDescriptor(PlaceholderEditorComponent::CreateDescriptor()); - app->RegisterComponentDescriptor(AnotherPlaceholderEditorComponent::CreateDescriptor()); - app->RegisterComponentDescriptor(DependentPlaceholderEditorComponent::CreateDescriptor()); + app->RegisterComponentDescriptor(AztfCmf::PlaceholderEditorComponent::CreateDescriptor()); + app->RegisterComponentDescriptor(AztfCmf::AnotherPlaceholderEditorComponent::CreateDescriptor()); + app->RegisterComponentDescriptor(AztfCmf::DependentPlaceholderEditorComponent::CreateDescriptor()); app->RegisterComponentDescriptor( - TestComponentModeComponent::CreateDescriptor()); - app->RegisterComponentDescriptor(IncompatiblePlaceholderEditorComponent::CreateDescriptor()); + AztfCmf::TestComponentModeComponent::CreateDescriptor()); + app->RegisterComponentDescriptor(AztfCmf::IncompatiblePlaceholderEditorComponent::CreateDescriptor()); } } // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp index c1c158d0f9..dc6e38ecd5 100644 --- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp @@ -6,12 +6,14 @@ * */ +#include #include #include #include #include #include #include +#include #include #include #include @@ -20,10 +22,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -32,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +51,14 @@ namespace AZ namespace UnitTest { + AzToolsFramework::EntityIdList SelectedEntities() + { + AzToolsFramework::EntityIdList selectedEntitiesBefore; + AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult( + selectedEntitiesBefore, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetSelectedEntities); + return selectedEntitiesBefore; + } + class EditorEntityVisibilityCacheFixture : public ToolsApplicationFixture { public: @@ -110,6 +123,80 @@ namespace UnitTest EXPECT_FALSE(m_cache.IsVisibleEntityVisible(m_cache.GetVisibleEntityIndexFromId(m_entityIds[2]).value())); } + //! Basic component that implements BoundsRequestBus and EditorComponentSelectionRequestsBus to be compatible + //! with the Editor visibility system. + //! Note: Used for simulating selection (picking) in the viewport. + class BoundsTestComponent + : public AzToolsFramework::Components::EditorComponentBase + , public AzFramework::BoundsRequestBus::Handler + , public AzToolsFramework::EditorComponentSelectionRequestsBus::Handler + { + public: + AZ_EDITOR_COMPONENT( + BoundsTestComponent, "{E6312E9D-8489-4677-9980-C93C328BC92C}", AzToolsFramework::Components::EditorComponentBase); + + static void Reflect(AZ::ReflectContext* context); + + // AZ::Component overrides ... + void Activate() override; + void Deactivate() override; + + // EditorComponentSelectionRequestsBus overrides ... + AZ::Aabb GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& viewportInfo) override; + bool EditorSelectionIntersectRayViewport( + const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) override; + bool SupportsEditorRayIntersect() override; + + // BoundsRequestBus overrides ... + AZ::Aabb GetWorldBounds() override; + AZ::Aabb GetLocalBounds() override; + }; + + AZ::Aabb BoundsTestComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo) + { + return GetWorldBounds(); + } + + bool BoundsTestComponent::EditorSelectionIntersectRayViewport( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) + { + return AzToolsFramework::AabbIntersectRay(src, dir, GetWorldBounds(), distance); + } + + bool BoundsTestComponent::SupportsEditorRayIntersect() + { + return true; + } + + void BoundsTestComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context) + { + // noop + } + + void BoundsTestComponent::Activate() + { + AzFramework::BoundsRequestBus::Handler::BusConnect(GetEntityId()); + AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId()); + } + + void BoundsTestComponent::Deactivate() + { + AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(); + AzFramework::BoundsRequestBus::Handler::BusDisconnect(); + } + + AZ::Aabb BoundsTestComponent::GetWorldBounds() + { + AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); + AZ::TransformBus::EventResult(worldFromLocal, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); + return GetLocalBounds().GetTransformedAabb(worldFromLocal); + } + + AZ::Aabb BoundsTestComponent::GetLocalBounds() + { + return AZ::Aabb::CreateFromMinMax(AZ::Vector3(-0.5f), AZ::Vector3(0.5f)); + } + // Fixture to support testing EditorTransformComponentSelection functionality on an Entity selection. class EditorTransformComponentSelectionFixture : public ToolsApplicationFixture { @@ -120,27 +207,52 @@ namespace UnitTest m_entityIds.push_back(m_entityId1); } - void ArrangeIndividualRotatedEntitySelection(const AZ::Quaternion& orientation); - AZStd::optional GetManipulatorTransform() const; - void RefreshManipulators(AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::RefreshType refreshType); - void SetTransformMode(AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::Mode transformMode); - void OverrideManipulatorOrientation(const AZ::Quaternion& orientation); - void OverrideManipulatorTranslation(const AZ::Vector3& translation); - public: AZ::EntityId m_entityId1; AzToolsFramework::EntityIdList m_entityIds; }; - void EditorTransformComponentSelectionFixture::ArrangeIndividualRotatedEntitySelection(const AZ::Quaternion& orientation) + class EditorTransformComponentSelectionViewportPickingFixture : public ToolsApplicationFixture { - for (auto entityId : m_entityIds) + public: + void SetUpEditorFixtureImpl() override + { + auto* app = GetApplication(); + // register a simple component implementing BoundsRequestBus and EditorComponentSelectionRequestsBus + app->RegisterComponentDescriptor(BoundsTestComponent::CreateDescriptor()); + + auto createEntityWithBoundsFn = [](const char* entityName) + { + AZ::Entity* entity = nullptr; + AZ::EntityId entityId = CreateDefaultEditorEntity(entityName, &entity); + + entity->Deactivate(); + entity->CreateComponent(); + entity->Activate(); + + return entityId; + }; + + m_entityId1 = createEntityWithBoundsFn("Entity1"); + m_entityId2 = createEntityWithBoundsFn("Entity2"); + m_entityId3 = createEntityWithBoundsFn("Entity3"); + } + + public: + AZ::EntityId m_entityId1; + AZ::EntityId m_entityId2; + AZ::EntityId m_entityId3; + }; + + void ArrangeIndividualRotatedEntitySelection(const AzToolsFramework::EntityIdList& entityIds, const AZ::Quaternion& orientation) + { + for (auto entityId : entityIds) { AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, orientation); } } - AZStd::optional EditorTransformComponentSelectionFixture::GetManipulatorTransform() const + AZStd::optional GetManipulatorTransform() { using AzToolsFramework::EditorTransformComponentSelectionRequestBus; @@ -151,8 +263,7 @@ namespace UnitTest return manipulatorTransform; } - void EditorTransformComponentSelectionFixture::RefreshManipulators( - AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::RefreshType refreshType) + void RefreshManipulators(const AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::RefreshType refreshType) { using AzToolsFramework::EditorTransformComponentSelectionRequestBus; @@ -160,8 +271,7 @@ namespace UnitTest AzToolsFramework::GetEntityContextId(), &EditorTransformComponentSelectionRequestBus::Events::RefreshManipulators, refreshType); } - void EditorTransformComponentSelectionFixture::SetTransformMode( - AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::Mode transformMode) + void SetTransformMode(const AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::Mode transformMode) { using AzToolsFramework::EditorTransformComponentSelectionRequestBus; @@ -169,7 +279,7 @@ namespace UnitTest AzToolsFramework::GetEntityContextId(), &EditorTransformComponentSelectionRequestBus::Events::SetTransformMode, transformMode); } - void EditorTransformComponentSelectionFixture::OverrideManipulatorOrientation(const AZ::Quaternion& orientation) + void OverrideManipulatorOrientation(const AZ::Quaternion& orientation) { using AzToolsFramework::EditorTransformComponentSelectionRequestBus; @@ -178,7 +288,7 @@ namespace UnitTest orientation); } - void EditorTransformComponentSelectionFixture::OverrideManipulatorTranslation(const AZ::Vector3& translation) + void OverrideManipulatorTranslation(const AZ::Vector3& translation) { using AzToolsFramework::EditorTransformComponentSelectionRequestBus; @@ -190,7 +300,7 @@ namespace UnitTest /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // EditorTransformComponentSelection Tests - TEST_F(EditorTransformComponentSelectionFixture, Focus_is_not_changed_while_switching_viewport_interaction_request_instance) + TEST_F(EditorTransformComponentSelectionFixture, FocusIsNotChangedWhileSwitchingViewportInteractionRequestInstance) { // setup a dummy widget and make it the active window to ensure focus in/out events are fired auto dummyWidget = AZStd::make_unique(); @@ -239,7 +349,7 @@ namespace UnitTest // Given AzToolsFramework::SelectEntity(m_entityId1); - ArrangeIndividualRotatedEntitySelection(AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f))); + ArrangeIndividualRotatedEntitySelection(m_entityIds, AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f))); RefreshManipulators(EditorTransformComponentSelectionRequestBus::Events::RefreshType::All); SetTransformMode(EditorTransformComponentSelectionRequestBus::Events::Mode::Rotation); @@ -286,7 +396,7 @@ namespace UnitTest AzToolsFramework::SelectEntity(m_entityId1); const AZ::Quaternion initialEntityOrientation = AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f)); - ArrangeIndividualRotatedEntitySelection(initialEntityOrientation); + ArrangeIndividualRotatedEntitySelection(m_entityIds, initialEntityOrientation); // assign new orientation to manipulator which does not match entity orientation OverrideManipulatorOrientation(AZ::Quaternion::CreateRotationZ(AZ::DegToRad(90.0f))); @@ -478,6 +588,227 @@ namespace UnitTest /////////////////////////////////////////////////////////////////////////////////////////////////////////////// } + // fixture for use with the indirect manipulator test framework + using EditorTransformComponentSelectionViewportPickingManipulatorTestFixture = + IndirectCallManipulatorViewportInteractionFixtureMixin; + + TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, SingleClickWithNoSelectionWillSelectEntity) + { + AzToolsFramework::ed_viewportStickySelect = true; + + // the initial starting position of the entity + const auto initialTransformWorld = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)); + AZ::TransformBus::Event(m_entityId1, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorld); + + // initial camera position (looking down the negative x-axis) + AzFramework::SetCameraTransform( + m_cameraState, + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + + using ::testing::Eq; + auto selectedEntitiesBefore = SelectedEntities(); + EXPECT_TRUE(selectedEntitiesBefore.empty()); + + // calculate the position in screen space of the initial entity position + const auto initialPositionScreen = AzFramework::WorldToScreen(initialTransformWorld.GetTranslation(), m_cameraState); + + // click the entity in the viewport + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(initialPositionScreen)->MouseLButtonDown()->MouseLButtonUp(); + + // entity is selected + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1)); + EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1)); + } + + TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, SingleClickOffEntityWithSelectionWillNotDeselectEntity) + { + AzToolsFramework::ed_viewportStickySelect = true; + + // the initial starting position of the entity + AZ::TransformBus::Event( + m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f))); + + // position in space above the entity + const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f); + + // initial camera position (looking down the negative x-axis) + AzFramework::SetCameraTransform( + m_cameraState, + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + + AzToolsFramework::SelectEntity(m_entityId1); + + // calculate the position in screen space of the initial position of the entity + const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState); + + // click the empty space in the viewport + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(clickOffPositionScreen)->MouseLButtonDown()->MouseLButtonUp(); + + // entity was not deselected + using ::testing::Eq; + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1)); + EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1)); + } + + TEST_F( + EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, + SingleClickOnNewEntityWithSelectionWillNotChangeSelectedEntity) + { + AzToolsFramework::ed_viewportStickySelect = true; + + // the initial starting position of the entity + AZ::TransformBus::Event( + m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f))); + + const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f)); + AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity); + + // initial camera position (looking down the negative x-axis) + AzFramework::SetCameraTransform( + m_cameraState, + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + + AzToolsFramework::SelectEntity(m_entityId1); + + // calculate the position in screen space of the second entity + const auto initialPositionScreenSecondEntity = + AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState); + + // click the entity in the viewport + m_actionDispatcher->CameraState(m_cameraState) + ->MousePosition(initialPositionScreenSecondEntity) + ->MouseLButtonDown() + ->MouseLButtonUp(); + + // entity selection was not changed + using ::testing::Eq; + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1)); + EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1)); + } + + TEST_F( + EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, + CtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection) + { + AzToolsFramework::ed_viewportStickySelect = true; + + // the initial starting position of the entity + AZ::TransformBus::Event( + m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f))); + + const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f)); + AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity); + + // initial camera position (looking down the negative x-axis) + AzFramework::SetCameraTransform( + m_cameraState, + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + + AzToolsFramework::SelectEntity(m_entityId1); + + // calculate the position in screen space of the second entity + const auto initialPositionScreenSecondEntity = + AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState); + + // click the entity in the viewport + m_actionDispatcher->CameraState(m_cameraState) + ->MousePosition(initialPositionScreenSecondEntity) + ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) + ->MouseLButtonDown() + ->MouseLButtonUp(); + + // entity selection was changed (one entity selected to two) + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2)); + } + + TEST_F( + EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, + CtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection) + { + AzToolsFramework::ed_viewportStickySelect = true; + + // the initial starting position of the entity + AZ::TransformBus::Event( + m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f))); + + const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f)); + AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity); + + // initial camera position (looking down the negative x-axis) + AzFramework::SetCameraTransform( + m_cameraState, + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + + AzToolsFramework::SelectEntities({ m_entityId1, m_entityId2 }); + + // calculate the position in screen space of the second entity + const auto initialPositionScreenSecondEntity = + AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState); + + // click the entity in the viewport + m_actionDispatcher->CameraState(m_cameraState) + ->MousePosition(initialPositionScreenSecondEntity) + ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) + ->MouseLButtonDown() + ->MouseLButtonUp(); + + // entity selection was changed (entity2 was deselected) + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1)); + } + + TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, DISABLED_BoxSelectWithNoInitialSelectionAddsEntitiesToSelection) + { + AzToolsFramework::ed_viewportStickySelect = true; + + // the initial starting position of the entities + AZ::TransformBus::Event( + m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f))); + AZ::TransformBus::Event( + m_entityId2, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 14.0f, 10.0f))); + AZ::TransformBus::Event( + m_entityId3, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 16.0f, 10.0f))); + + // initial camera position (looking down the negative x-axis) + AzFramework::SetCameraTransform( + m_cameraState, + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + + using ::testing::Eq; + auto selectedEntitiesBefore = SelectedEntities(); + EXPECT_THAT(selectedEntitiesBefore.size(), Eq(0)); + + // calculate the position in screen space of where to begin and end the box select action + const auto beginningPositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 13.5f, 10.5f), m_cameraState); + const auto middlePositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 15.0f, 10.0f), m_cameraState); + const auto endingPositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState); + + // perform a box select in the viewport + m_actionDispatcher->CameraState(m_cameraState) + ->MousePosition(beginningPositionWorldBoxSelectStart) + ->MouseLButtonDown() + ->MousePosition(middlePositionWorldBoxSelectStart) + ->MousePosition(endingPositionWorldBoxSelectStart) + ->MouseLButtonUp(); + + // entities are selected + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3)); + } + using EditorTransformComponentSelectionManipulatorTestFixture = IndirectCallManipulatorViewportInteractionFixtureMixin; diff --git a/Code/Framework/GFxFramework/GFxFramework/MaterialIO/Material.cpp b/Code/Framework/GFxFramework/GFxFramework/MaterialIO/Material.cpp index de035ed9b6..22843fa230 100644 --- a/Code/Framework/GFxFramework/GFxFramework/MaterialIO/Material.cpp +++ b/Code/Framework/GFxFramework/GFxFramework/MaterialIO/Material.cpp @@ -236,7 +236,7 @@ namespace AZ case TextureMapType::Bump: return m_normalMap; default: - AZ_Assert(false, "Invalid Texture map requested.") + AZ_Assert(false, "Invalid Texture map requested."); return m_empty; } } @@ -255,7 +255,7 @@ namespace AZ m_normalMap = texture; break; default: - AZ_Assert(false, "Invalid Texture map requested.") + AZ_Assert(false, "Invalid Texture map requested."); break; } } @@ -599,7 +599,7 @@ namespace AZ if (!materialNode) { - AZ_Assert(false, "Attempted to add material to invalid xml document.") + AZ_Assert(false, "Attempted to add material to invalid xml document."); return false; } diff --git a/Code/Framework/GridMate/GridMate/Replica/ReplicaChunk.cpp b/Code/Framework/GridMate/GridMate/Replica/ReplicaChunk.cpp index ee42ff2ad0..d3db481ccd 100644 --- a/Code/Framework/GridMate/GridMate/Replica/ReplicaChunk.cpp +++ b/Code/Framework/GridMate/GridMate/Replica/ReplicaChunk.cpp @@ -351,7 +351,7 @@ namespace GridMate DataSetBase* dataset = descriptor->GetDataSet(this, i); if (!dataset) { - AZ_Assert(false, "How can we have a dirty dataset that doesn't exist?") + AZ_Assert(false, "How can we have a dirty dataset that doesn't exist?"); continue; } diff --git a/Code/Framework/GridMate/GridMate/Replica/ReplicaTarget.h b/Code/Framework/GridMate/GridMate/Replica/ReplicaTarget.h index 03f813ac6c..be1a86b627 100644 --- a/Code/Framework/GridMate/GridMate/Replica/ReplicaTarget.h +++ b/Code/Framework/GridMate/GridMate/Replica/ReplicaTarget.h @@ -64,7 +64,7 @@ namespace GridMate // Create Callback AZStd::weak_ptr CreateCallback(AZ::u64 revision) { - AZ_Assert(IsAckEnabled(), "ACK disabled.") //Shouldn't happen + AZ_Assert(IsAckEnabled(), "ACK disabled."); //Shouldn't happen AZ_Assert(m_replicaRevision <= revision, "Cannot decrease replica revision"); if(!m_callback || m_callback->m_revision != revision) diff --git a/Code/Framework/GridMate/GridMate/Session/Session.cpp b/Code/Framework/GridMate/GridMate/Session/Session.cpp index b731d82b71..3dcb16b08d 100644 --- a/Code/Framework/GridMate/GridMate/Session/Session.cpp +++ b/Code/Framework/GridMate/GridMate/Session/Session.cpp @@ -1583,7 +1583,7 @@ GridSession::OnStateCreate(HSM& sm, const HSM::Event& e) // Bind member replica bool isAdded = AddMember(m_myMember); - AZ_Error("GridMate", isAdded, "Failed to add my replica, check the number of open slots!") + AZ_Error("GridMate", isAdded, "Failed to add my replica, check the number of open slots!"); if (!isAdded) { sm.Transition(SS_DELETE); diff --git a/Code/Framework/GridMate/GridMate/Session/Session.h b/Code/Framework/GridMate/GridMate/Session/Session.h index 5080570373..e075a0aa48 100644 --- a/Code/Framework/GridMate/GridMate/Session/Session.h +++ b/Code/Framework/GridMate/GridMate/Session/Session.h @@ -698,7 +698,7 @@ namespace GridMate static void* UserDataCopier(const void* sourceData, unsigned int sourceDataSize) { (void)sourceDataSize; - AZ_Assert(sizeof(T) == sourceDataSize, "Data size %d doesn't match the type size %d", sourceDataSize, sizeof(T)) + AZ_Assert(sizeof(T) == sourceDataSize, "Data size %d doesn't match the type size %d", sourceDataSize, sizeof(T)); return azcreate(T, (*static_cast(sourceData)), GridMateAllocatorMP, "UserDataCopier"); } template diff --git a/Code/LauncherUnified/Launcher.cpp b/Code/LauncherUnified/Launcher.cpp index f5da40ccad..de4c496b2a 100644 --- a/Code/LauncherUnified/Launcher.cpp +++ b/Code/LauncherUnified/Launcher.cpp @@ -626,11 +626,8 @@ namespace O3DELauncher AZ_TracePrintf("Launcher", "Application is configured for VFS"); AZ_TracePrintf("Launcher", "Log and cache files will be written to the Cache directory on your host PC"); -#if defined(AZ_ENABLE_TRACING) - const char* message = "If your game does not run, check any of the following:\n" - "\t- Verify the remote_ip address is correct in bootstrap.cfg"; -#endif - + constexpr const char* message = "If your game does not run, check any of the following:\n" + "\t- Verify the remote_ip address is correct in bootstrap.cfg"; if (mainInfo.m_additionalVfsResolution) { AZ_TracePrintf("Launcher", "%s\n%s", message, mainInfo.m_additionalVfsResolution) diff --git a/Code/Legacy/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp index 71bec78f69..9f7cdfd609 100644 --- a/Code/Legacy/CryCommon/WinBase.cpp +++ b/Code/Legacy/CryCommon/WinBase.cpp @@ -6,9 +6,10 @@ * */ +#include // Description : Linux/Mac port support for Win32API calls -#if !defined(WIN32) +#if AZ_TRAIT_LEGACY_CRYCOMMON_USE_WINDOWS_STUBS #include "platform.h" // Note: This should be first to get consistent debugging definitions @@ -1391,4 +1392,4 @@ __finddata64_t::~__finddata64_t() } #endif //defined(APPLE) || defined(LINUX) -#endif // !defined(WIN32) +#endif // AZ_TRAIT_LEGACY_CRYCOMMON_USE_WINDOWS_STUBS diff --git a/Code/Legacy/CrySystem/System.cpp b/Code/Legacy/CrySystem/System.cpp index 71775dbb6c..4a9d9ece5f 100644 --- a/Code/Legacy/CrySystem/System.cpp +++ b/Code/Legacy/CrySystem/System.cpp @@ -131,7 +131,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) #include "SystemEventDispatcher.h" #include "HMDBus.h" -#include "zlib.h" #include "RemoteConsole/RemoteConsole.h" #include diff --git a/Code/Legacy/CrySystem/SystemCFG.cpp b/Code/Legacy/CrySystem/SystemCFG.cpp index 52e377db7f..802e577386 100644 --- a/Code/Legacy/CrySystem/SystemCFG.cpp +++ b/Code/Legacy/CrySystem/SystemCFG.cpp @@ -178,7 +178,7 @@ void CSystem::LogVersion() strftime(s, 128, "%d %b %y (%H %M %S)", today); #endif - const SFileVersion& ver = GetFileVersion(); + [[maybe_unused]] const SFileVersion& ver = GetFileVersion(); CryLogAlways("BackupNameAttachment=\" Build(%d) %s\" -- used by backup system\n", ver.v[0], s); // read by CreateBackupFile() @@ -249,7 +249,7 @@ void CSystem::LogVersion() ////////////////////////////////////////////////////////////////////////// void CSystem::LogBuildInfo() { - auto projectName = AZ::Utils::GetProjectName(); + [[maybe_unused]] auto projectName = AZ::Utils::GetProjectName(); CryLogAlways("GameName: %s", projectName.c_str()); CryLogAlways("BuildTime: " __DATE__ " " __TIME__); } diff --git a/Code/Legacy/CrySystem/SystemWin32.cpp b/Code/Legacy/CrySystem/SystemWin32.cpp index 20f4d7ef65..4f0a154afe 100644 --- a/Code/Legacy/CrySystem/SystemWin32.cpp +++ b/Code/Legacy/CrySystem/SystemWin32.cpp @@ -273,11 +273,7 @@ static const char* GetLastSystemErrorMessage() return szBuffer; } -#else - return 0; - #endif //WIN32 - return 0; } diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp index fb3f7e0270..84d731832e 100644 --- a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp @@ -441,7 +441,7 @@ namespace O3DE::ProjectManager return true; } - bool ReplaceFile(const QString& origFile, const QString& newFile, QWidget* parent, bool interactive) + bool ReplaceProjectFile(const QString& origFile, const QString& newFile, QWidget* parent, bool interactive) { QFileInfo original(origFile); if (original.exists()) diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.h b/Code/Tools/ProjectManager/Source/ProjectUtils.h index d06b8c2c8b..f1050531d4 100644 --- a/Code/Tools/ProjectManager/Source/ProjectUtils.h +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.h @@ -25,7 +25,7 @@ namespace O3DE::ProjectManager bool DeleteProjectFiles(const QString& path, bool force = false); bool MoveProject(QString origPath, QString newPath, QWidget* parent, bool skipRegister = false); - bool ReplaceFile(const QString& origFile, const QString& newFile, QWidget* parent = nullptr, bool interactive = true); + bool ReplaceProjectFile(const QString& origFile, const QString& newFile, QWidget* parent = nullptr, bool interactive = true); bool FindSupportedCompiler(QWidget* parent = nullptr); AZ::Outcome FindSupportedCompilerForPlatform(); diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index e1b6d740e2..08ad7f24d9 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -242,7 +242,7 @@ namespace O3DE::ProjectManager if (!newProjectSettings.m_newPreviewImagePath.isEmpty()) { - if (!ProjectUtils::ReplaceFile( + if (!ProjectUtils::ReplaceProjectFile( QDir(newProjectSettings.m_path).filePath(newProjectSettings.m_iconPath), newProjectSettings.m_newPreviewImagePath)) { QMessageBox::critical(this, tr("File replace failed"), tr("Failed to replace project preview image.")); diff --git a/Code/Tools/ProjectManager/tests/UtilsTests.cpp b/Code/Tools/ProjectManager/tests/UtilsTests.cpp index bfe26ba760..760b599ad8 100644 --- a/Code/Tools/ProjectManager/tests/UtilsTests.cpp +++ b/Code/Tools/ProjectManager/tests/UtilsTests.cpp @@ -202,7 +202,7 @@ namespace O3DE::ProjectManager TEST_F(ProjectManagerUtilsTests, ReplaceFile_Succeeds) #endif // !AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS { - EXPECT_TRUE(ReplaceFile(m_projectAOrigFilePath, m_projectAReplaceFilePath, nullptr, false)); + EXPECT_TRUE(ReplaceProjectFile(m_projectAOrigFilePath, m_projectAReplaceFilePath, nullptr, false)); QFile origFile(m_projectAOrigFilePath); EXPECT_TRUE(origFile.open(QIODevice::ReadOnly)); diff --git a/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.cpp b/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.cpp index ffbc5a445c..c88ea59bdb 100644 --- a/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.cpp +++ b/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.cpp @@ -60,8 +60,8 @@ void initSharedResources() namespace { - const char* LUAEditorDebugName = "LUA Debug"; - const char* LUAEditorInfoName = "LUA Editor"; + [[maybe_unused]] const char* LUAEditorDebugName = "LUA Debug"; + [[maybe_unused]] const char* LUAEditorInfoName = "LUA Editor"; } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp index 1618f376b4..9b41645280 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp @@ -63,7 +63,7 @@ namespace ImageProcessingAtom StepAll }; - const char ProcessStepNames[StepAll][64] = + [[maybe_unused]] const char ProcessStepNames[StepAll][64] = { "ValidateInput", "GenerateColorChart", diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp index d2bcf4b985..e20d9ecf6c 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AtomShaderConfig.cpp @@ -21,7 +21,7 @@ namespace AZ { namespace AtomShaderConfig { - static constexpr char AtomShaderConfigName[] = "AtomShaderConfig"; + [[maybe_unused]] static constexpr char AtomShaderConfigName[] = "AtomShaderConfig"; bool MutateToFirstAbsoluteFolderThatExists(AZStd::string& relativeFolder, AZStd::vector& watchFolders) { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp index 154bfdd607..a82c731d7b 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -1149,7 +1150,7 @@ namespace AZ return BuildResult::CompilationFailed; } - auto readJsonResult = JsonSerializationUtils::ReadJsonFile(outputFile); + auto readJsonResult = JsonSerializationUtils::ReadJsonFile(outputFile, AZ::RPI::JsonUtils::AtomMaxFileSize); if (readJsonResult.IsSuccess()) { @@ -1170,7 +1171,7 @@ namespace AZ AZStd::string outputFile = m_inputFilePath; AzFramework::StringFunc::Path::ReplaceExtension(outputFile, outputExtension); - auto readJsonResult = JsonSerializationUtils::ReadJsonFile(outputFile); + auto readJsonResult = JsonSerializationUtils::ReadJsonFile(outputFile, AZ::RPI::JsonUtils::AtomMaxFileSize); if (readJsonResult.IsSuccess()) { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/CommonTypes.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/CommonTypes.cpp index 35c1e48d37..d960b25c10 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/CommonTypes.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/CommonFiles/CommonTypes.cpp @@ -16,7 +16,7 @@ namespace AZ { namespace ShaderBuilder { - static const char* s_azslShaderCompilerName = "AZSL Compiler"; + [[maybe_unused]] static const char* s_azslShaderCompilerName = "AZSL Compiler"; AZ::RHI::Format StringToFormat(const char* format) { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp index 21eda31ca2..2abee4d297 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/PrecompiledShaderBuilder.cpp @@ -26,7 +26,7 @@ namespace AZ { namespace { - static const char* PrecompiledShaderBuilderName = "PrecompiledShaderBuilder"; + [[maybe_unused]] static const char* PrecompiledShaderBuilderName = "PrecompiledShaderBuilder"; static const char* PrecompiledShaderBuilderJobKey = "PrecompiledShader Asset Builder"; static const char* ShaderAssetExtension = "azshader"; } diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index 9ee4ff2161..6b673759cf 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -555,7 +556,7 @@ namespace AZ shaderAssetCreator.SetRenderStates(renderStates); } - Outcome hlslSourceCodeOutcome = Utils::ReadFile(hlslFullPath); + Outcome hlslSourceCodeOutcome = Utils::ReadFile(hlslFullPath, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!hlslSourceCodeOutcome.IsSuccess()) { AZ_Error( diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp index 88abf92e54..9c616569bd 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -45,13 +46,13 @@ namespace AZ { namespace ShaderBuilderUtility { - static constexpr char ShaderBuilderUtilityName[] = "ShaderBuilderUtility"; + [[maybe_unused]] static constexpr char ShaderBuilderUtilityName[] = "ShaderBuilderUtility"; Outcome LoadShaderDataJson(const AZStd::string& fullPathToJsonFile) { RPI::ShaderSourceData shaderSourceData; - auto document = JsonSerializationUtils::ReadJsonFile(fullPathToJsonFile); + auto document = JsonSerializationUtils::ReadJsonFile(fullPathToJsonFile, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!document.IsSuccess()) { @@ -127,7 +128,7 @@ namespace AZ AZStd::unordered_map> outcomes; for (int i : indicesOfInterest) { - outcomes[i] = JsonSerializationUtils::ReadJsonFile(pathOfJsonFiles[i]); + outcomes[i] = JsonSerializationUtils::ReadJsonFile(pathOfJsonFiles[i], AZ::RPI::JsonUtils::AtomMaxFileSize); if (!outcomes[i].IsSuccess()) { AZ_Error(builderName, false, "%s", outcomes[i].GetError().c_str()); @@ -622,7 +623,7 @@ namespace AZ StructData inputStruct; inputStruct.m_id = ""; - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(pathToIaJson); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(pathToIaJson, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderBuilderUtilityName, false, "%s", jsonOutcome.GetError().c_str()); @@ -715,7 +716,7 @@ namespace AZ StructData outputStruct; outputStruct.m_id = ""; - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(pathToOmJson); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(pathToOmJson, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderBuilderUtilityName, false, "%s", jsonOutcome.GetError().c_str()); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 12e5382b63..5a552a2702 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -478,7 +478,7 @@ namespace AZ RPI::Ptr shaderOptionGroupLayout = RPI::ShaderOptionGroupLayout::Create(); // The shader options define what options are available, what are the allowed values/range // for each option and what is its default value. - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(optionsGroupJsonPath); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(optionsGroupJsonPath, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str()); @@ -509,7 +509,7 @@ namespace AZ } auto functionsJsonPath = functionsJsonPathOutcome.TakeValue(); - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(functionsJsonPath); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(functionsJsonPath, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str()); @@ -541,7 +541,7 @@ namespace AZ } auto srgJsonPath = srgJsonPathOutcome.TakeValue(); - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(srgJsonPath); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(srgJsonPath, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str()); @@ -598,7 +598,7 @@ namespace AZ } auto bindingsJsonPath = bindingsJsonPathOutcome.TakeValue(); - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(bindingsJsonPath); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(bindingsJsonPath, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str()); @@ -630,7 +630,7 @@ namespace AZ } hlslSourcePath = hlslSourcePathOutcome.TakeValue(); - Outcome hlslSourceOutcome = Utils::ReadFile(hlslSourcePath); + Outcome hlslSourceOutcome = Utils::ReadFile(hlslSourcePath, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!hlslSourceOutcome.IsSuccess()) { AZ_Error( diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli index 6225bb3434..9d785e2086 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ReceiverPlaneDepthBias.azsli @@ -35,4 +35,4 @@ float ApplyReceiverPlaneDepthBias(const float2 receiverPlaneDepthBias, const flo // Clamping this will remove this effect fragmentDepthBias = min(fragmentDepthBias, 0.0); return fragmentDepthBias; -} \ No newline at end of file +} diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp index 4e84187165..af17e3a1da 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp @@ -115,10 +115,13 @@ namespace AZ AZ_Assert(m_shaderResourceGroup, "RayTracingPass [%s]: Failed to create RayTracingGlobalSrg", GetPathName().GetCStr()); RPI::PassUtils::BindDataMappingsToSrg(m_passDescriptor, m_shaderResourceGroup.get()); - // check to see if the shader requires the View and RayTracingMaterial Srgs + // check to see if the shader requires the View, Scene, or RayTracingMaterial Srgs const auto& viewSrgLayout = m_rayGenerationShader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::View); m_requiresViewSrg = (viewSrgLayout != nullptr); + const auto& sceneSrgLayout = m_rayGenerationShader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Scene); + m_requiresSceneSrg = (sceneSrgLayout != nullptr); + const auto& rayTracingMaterialSrgLayout = m_rayGenerationShader->FindShaderResourceGroupLayout(RayTracingMaterialSrgBindingSlot); m_requiresRayTracingMaterialSrg = (rayTracingMaterialSrgLayout != nullptr); @@ -324,6 +327,11 @@ namespace AZ } } + if (m_requiresSceneSrg) + { + shaderResourceGroups.push_back(scene->GetShaderResourceGroup()->GetRHIShaderResourceGroup()); + } + if (m_requiresRayTracingMaterialSrg) { shaderResourceGroups.push_back(rayTracingFeatureProcessor->GetRayTracingMaterialSrg()->GetRHIShaderResourceGroup()); diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h index 5eafa5b2f4..6ef97e0f10 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h @@ -72,6 +72,7 @@ namespace AZ RHI::ConstPtr m_globalPipelineState; RHI::Ptr m_rayTracingShaderTable; bool m_requiresViewSrg = false; + bool m_requiresSceneSrg = false; bool m_requiresRayTracingMaterialSrg = false; }; } // namespace RPI diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h index c1fd4453d4..42ba2d2e25 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h @@ -83,11 +83,11 @@ namespace AZ #if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) // On Linux platforms that uses XCB, a resize may occur in the swap chain but the command queue may still - // reference the original surface. This flag is a temporary fix to make sure that all the swap chains - // have finished their resize events before presenting the command queue. + // reference the original surface. This flag is a temporary fix to make sure the swap chain is ready to present + // We need to remove this work around with // [GFX TODO][GHI - 2678] - AZStd::atomic_bool m_resized{ false }; + AZStd::atomic_bool m_readyToPresent { false }; #endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB protected: diff --git a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp index d5b626917b..b4c68b3f75 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Edit/Utils.cpp @@ -30,7 +30,7 @@ namespace AZ namespace RHI { static AZStd::mutex s_profilingMutex; - static constexpr char ShaderPlatformInterfaceName[] = "ShaderPlatformInterface"; + [[maybe_unused]] static constexpr char ShaderPlatformInterfaceName[] = "ShaderPlatformInterface"; void ShaderCompilerProfiling::Entry::Reflect(ReflectContext* context) { diff --git a/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp index 5fbb83fccf..92d7a125d8 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp @@ -165,7 +165,9 @@ namespace AZ } #if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) - m_resized.store(true); + // If we are presenting through the editor, the resize is triggered through the editor's window, which + // won't happen until after the surface is ready to present + m_readyToPresent.store(true); #endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB return resultCode; diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/Device_Windows.cpp b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/Device_Windows.cpp index 7cf83e28bc..51272f3488 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/Device_Windows.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/Device_Windows.cpp @@ -258,6 +258,14 @@ namespace AZ return RHI::ResultCode::Success; } + RHI::ResultCode Device::CreateSwapChain( + [[maybe_unused]] const DXGI_SWAP_CHAIN_DESCX& swapChainDesc, + [[maybe_unused]] AZStd::array, RHI::Limits::Device::FrameCountMax>& outSwapChainResources) + { + AZ_Assert(false, "Wrong Device::CreateSwapChain function called on Windows."); + return RHI::ResultCode::Fail; + } + AZStd::vector Device::GetValidSwapChainImageFormats(const RHI::WindowHandle& windowHandle) const { AZStd::vector formatsList; diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/SwapChain_Platform.h b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/SwapChain_Platform.h new file mode 100644 index 0000000000..f611027497 --- /dev/null +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/SwapChain_Platform.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/SwapChain_Windows.cpp b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/SwapChain_Windows.cpp index 9a6d7e44d1..ab14f9b5d3 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/SwapChain_Windows.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/SwapChain_Windows.cpp @@ -5,15 +5,28 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#include + +#include + #include #include +#include #include namespace AZ { namespace DX12 { + RHI::Ptr SwapChain::Create() + { + return aznew SwapChain(); + } + + Device& SwapChain::GetDevice() const + { + return static_cast(RHI::SwapChain::GetDevice()); + } + RHI::ResultCode SwapChain::InitInternal(RHI::Device& deviceBase, const RHI::SwapChainDescriptor& descriptor, RHI::SwapChainDimensions* nativeDimensions) { // Check whether tearing support is available for full screen borderless windowed mode. @@ -165,6 +178,47 @@ namespace AZ return GetCurrentImageIndex(); } + RHI::ResultCode SwapChain::InitImageInternal(const InitImageRequest& request) + { + Device& device = GetDevice(); + + Microsoft::WRL::ComPtr resource; + DX12::AssertSuccess(m_swapChain->GetBuffer(request.m_imageIndex, IID_GRAPHICS_PPV_ARGS(resource.GetAddressOf()))); + + D3D12_RESOURCE_ALLOCATION_INFO allocationInfo; + device.GetImageAllocationInfo(request.m_descriptor, allocationInfo); + + Name name(AZStd::string::format("SwapChainImage_%d", request.m_imageIndex)); + + Image& image = static_cast(*request.m_image); + image.m_memoryView = MemoryView(resource.Get(), 0, allocationInfo.SizeInBytes, allocationInfo.Alignment, MemoryViewType::Image); + image.SetName(name); + image.GenerateSubresourceLayouts(); + // Overwrite m_initialAttachmentState because Swapchain images are created with D3D12_RESOURCE_STATE_COMMON state + image.SetAttachmentState(D3D12_RESOURCE_STATE_COMMON); + + RHI::HeapMemoryUsage& memoryUsage = m_memoryUsage.GetHeapMemoryUsage(RHI::HeapMemoryLevel::Device); + memoryUsage.m_reservedInBytes += allocationInfo.SizeInBytes; + memoryUsage.m_residentInBytes += allocationInfo.SizeInBytes; + + return RHI::ResultCode::Success; + } + + void SwapChain::ShutdownResourceInternal(RHI::Resource& resourceBase) + { + Image& image = static_cast(resourceBase); + + const size_t sizeInBytes = image.GetMemoryView().GetSize(); + + RHI::HeapMemoryUsage& memoryUsage = m_memoryUsage.GetHeapMemoryUsage(RHI::HeapMemoryLevel::Device); + memoryUsage.m_reservedInBytes -= sizeInBytes; + memoryUsage.m_residentInBytes -= sizeInBytes; + + GetDevice().QueueForRelease(image.m_memoryView); + + image.m_memoryView = {}; + } + RHI::ResultCode SwapChain::ResizeInternal(const RHI::SwapChainDimensions& dimensions, RHI::SwapChainDimensions* nativeDimensions) { GetDevice().WaitForIdle(); diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/SwapChain_Windows.h b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/SwapChain_Windows.h new file mode 100644 index 0000000000..2e45371c48 --- /dev/null +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/SwapChain_Windows.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include + +namespace AZ +{ + namespace DX12 + { + class Device; + + class SwapChain + : public RHI::SwapChain + { + public: + AZ_RTTI(SwapChain, "{974AC6A9-5009-47BE-BD7E-61348BF623F0}", RHI::SwapChain); + AZ_CLASS_ALLOCATOR(SwapChain, AZ::SystemAllocator, 0); + + static RHI::Ptr Create(); + + Device& GetDevice() const; + + private: + SwapChain() = default; + friend class SwapChainFactory; + + ////////////////////////////////////////////////////////////////////////// + // RHI::SwapChain + RHI::ResultCode InitInternal(RHI::Device& deviceBase, const RHI::SwapChainDescriptor& descriptor, RHI::SwapChainDimensions* nativeDimensions) override; + void ShutdownInternal() override; + uint32_t PresentInternal() override; + RHI::ResultCode InitImageInternal(const InitImageRequest& request) override; + void ShutdownResourceInternal(RHI::Resource& resourceBase) override; + RHI::ResultCode ResizeInternal(const RHI::SwapChainDimensions& dimensions, RHI::SwapChainDimensions* nativeDimensions) override; + bool IsExclusiveFullScreenPreferred() const override; + bool GetExclusiveFullScreenState() const override; + bool SetExclusiveFullScreenState(bool fullScreenState) override; + ////////////////////////////////////////////////////////////////////////// + + void ConfigureDisplayMode(const RHI::SwapChainDimensions& dimensions); + void EnsureColorSpace(const DXGI_COLOR_SPACE_TYPE& colorSpace); + void DisableHdr(); + void SetHDRMetaData(float maxOutputNits, float minOutputNits, float maxContentLightLevel, float maxFrameAverageLightLevel); + + static const uint32_t InvalidColorSpace = 0xFFFFFFFE; + DXGI_COLOR_SPACE_TYPE m_colorSpace = static_cast(InvalidColorSpace); + + RHI::Ptr m_swapChain; + bool m_isInFullScreenExclusiveState = false; //!< Was SetFullscreenState used to enter full screen exclusive state? + bool m_isTearingSupported = false; //!< Is tearing support available for full screen borderless windowed mode? + }; + } +} diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/platform_private_windows_files.cmake b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/platform_private_windows_files.cmake index e3a60c937c..5333b89336 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/platform_private_windows_files.cmake +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/platform_private_windows_files.cmake @@ -22,7 +22,9 @@ set(FILES RHI/DX12_Windows.cpp RHI/DX12_Windows.h RHI/SystemComponent_Windows.cpp + RHI/SwapChain_Platform.h RHI/SwapChain_Windows.cpp + RHI/SwapChain_Windows.h RHI/NsightAftermathGpuCrashTracker_Windows.cpp RHI/NsightAftermathGpuCrashTracker_Windows.h RHI/NsightAftermath_Windows.cpp diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h index 4d1f2c4ac9..7004900ec5 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h @@ -57,6 +57,10 @@ namespace AZ const DXGI_SWAP_CHAIN_DESCX& swapChainDesc, RHI::Ptr& swapChain); + RHI::ResultCode CreateSwapChain( + const DXGI_SWAP_CHAIN_DESCX& swapChainDesc, + AZStd::array, RHI::Limits::Device::FrameCountMax>& outSwapChainResources); + void GetImageAllocationInfo( const RHI::ImageDescriptor& descriptor, D3D12_RESOURCE_ALLOCATION_INFO& info); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingPipelineState.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingPipelineState.cpp index be0c084d95..37f4e6b49a 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingPipelineState.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingPipelineState.cpp @@ -28,11 +28,11 @@ namespace AZ } #endif - RHI::ResultCode RayTracingPipelineState::InitInternal(RHI::Device& deviceBase, [[maybe_unused]]const RHI::RayTracingPipelineStateDescriptor* descriptor) + RHI::ResultCode RayTracingPipelineState::InitInternal([[maybe_unused]]RHI::Device& deviceBase, [[maybe_unused]]const RHI::RayTracingPipelineStateDescriptor* descriptor) { +#ifdef AZ_DX12_DXR_SUPPORT Device& device = static_cast(deviceBase); -#ifdef AZ_DX12_DXR_SUPPORT size_t dxilLibraryCount = descriptor->GetShaderLibraries().size(); size_t hitGroupCount = descriptor->GetHitGroups().size(); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/SwapChain.cpp deleted file mode 100644 index bb5acc878a..0000000000 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/SwapChain.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - -namespace AZ -{ - namespace DX12 - { - RHI::Ptr SwapChain::Create() - { - return aznew SwapChain(); - } - - Device& SwapChain::GetDevice() const - { - return static_cast(Base::GetDevice()); - } - - RHI::ResultCode SwapChain::InitImageInternal(const InitImageRequest& request) - { - - Device& device = GetDevice(); - - Microsoft::WRL::ComPtr resource; - DX12::AssertSuccess(m_swapChain->GetBuffer(request.m_imageIndex, IID_GRAPHICS_PPV_ARGS(resource.GetAddressOf()))); - - D3D12_RESOURCE_ALLOCATION_INFO allocationInfo; - device.GetImageAllocationInfo(request.m_descriptor, allocationInfo); - - Name name(AZStd::string::format("SwapChainImage_%d", request.m_imageIndex)); - - Image& image = static_cast(*request.m_image); - image.m_memoryView = MemoryView(resource.Get(), 0, allocationInfo.SizeInBytes, allocationInfo.Alignment, MemoryViewType::Image); - image.SetName(name); - image.GenerateSubresourceLayouts(); - // Overwrite m_initialAttachmentState because Swapchain images are created with D3D12_RESOURCE_STATE_COMMON state - image.SetAttachmentState(D3D12_RESOURCE_STATE_COMMON); - - RHI::HeapMemoryUsage& memoryUsage = m_memoryUsage.GetHeapMemoryUsage(RHI::HeapMemoryLevel::Device); - memoryUsage.m_reservedInBytes += allocationInfo.SizeInBytes; - memoryUsage.m_residentInBytes += allocationInfo.SizeInBytes; - - return RHI::ResultCode::Success; - } - - void SwapChain::ShutdownResourceInternal(RHI::Resource& resourceBase) - { - Image& image = static_cast(resourceBase); - - const size_t sizeInBytes = image.GetMemoryView().GetSize(); - - RHI::HeapMemoryUsage& memoryUsage = m_memoryUsage.GetHeapMemoryUsage(RHI::HeapMemoryLevel::Device); - memoryUsage.m_reservedInBytes -= sizeInBytes; - memoryUsage.m_residentInBytes -= sizeInBytes; - - GetDevice().QueueForRelease(image.m_memoryView); - - image.m_memoryView = {}; - } - } -} diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/SwapChain.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/SwapChain.h index 8035ae1e38..bd12b1f316 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/SwapChain.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/SwapChain.h @@ -7,56 +7,4 @@ */ #pragma once -#include -#include - -namespace AZ -{ - namespace DX12 - { - class Device; - class Image; - class CommandQueue; - - class SwapChain - : public RHI::SwapChain - { - using Base = RHI::SwapChain; - public: - AZ_RTTI(SwapChain, "{974AC6A9-5009-47BE-BD7E-61348BF623F0}", Base); - AZ_CLASS_ALLOCATOR(SwapChain, AZ::SystemAllocator, 0); - - static RHI::Ptr Create(); - - Device& GetDevice() const; - - private: - SwapChain() = default; - - ////////////////////////////////////////////////////////////////////////// - // RHI::SwapChain - RHI::ResultCode InitInternal(RHI::Device& deviceBase, const RHI::SwapChainDescriptor& descriptor, RHI::SwapChainDimensions* nativeDimensions) override; - void ShutdownInternal() override; - uint32_t PresentInternal() override; - RHI::ResultCode InitImageInternal(const InitImageRequest& request) override; - void ShutdownResourceInternal(RHI::Resource& resourceBase) override; - RHI::ResultCode ResizeInternal(const RHI::SwapChainDimensions& dimensions, RHI::SwapChainDimensions* nativeDimensions) override; - bool IsExclusiveFullScreenPreferred() const override; - bool GetExclusiveFullScreenState() const override; - bool SetExclusiveFullScreenState(bool fullScreenState) override; - ////////////////////////////////////////////////////////////////////////// - - void ConfigureDisplayMode(const RHI::SwapChainDimensions& dimensions); - void EnsureColorSpace(const DXGI_COLOR_SPACE_TYPE& colorSpace); - void DisableHdr(); - void SetHDRMetaData(float maxOutputNits, float minOutputNits, float maxContentLightLevel, float maxFrameAverageLightLevel); - - static const uint32_t InvalidColorSpace = 0xFFFFFFFE; - DXGI_COLOR_SPACE_TYPE m_colorSpace = static_cast(InvalidColorSpace); - - RHI::Ptr m_swapChain; - bool m_isInFullScreenExclusiveState = false; //!< Was SetFullscreenState used to enter full screen exclusive state? - bool m_isTearingSupported = false; //!< Is tearing support available for full screen borderless windowed mode? - }; - } -} +#include diff --git a/Gems/Atom/RHI/DX12/Code/atom_rhi_dx12_private_common_files.cmake b/Gems/Atom/RHI/DX12/Code/atom_rhi_dx12_private_common_files.cmake index 3ad79398b4..807a637b0f 100644 --- a/Gems/Atom/RHI/DX12/Code/atom_rhi_dx12_private_common_files.cmake +++ b/Gems/Atom/RHI/DX12/Code/atom_rhi_dx12_private_common_files.cmake @@ -95,7 +95,6 @@ set(FILES Source/RHI/ShaderResourceGroup.h Source/RHI/ShaderResourceGroupPool.cpp Source/RHI/ShaderResourceGroupPool.h - Source/RHI/SwapChain.cpp Source/RHI/SwapChain.h Source/RHI/DX12.cpp Source/RHI/DX12.h diff --git a/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt b/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt index f4148b435e..5c74852f57 100644 --- a/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt @@ -19,9 +19,12 @@ if(NOT PAL_TRAIT_ATOM_RHI_VULKAN_SUPPORTED) NAMESPACE Gem FILES_CMAKE atom_rhi_vulkan_stub_module.cmake + atom_rhi_vulkan_reflect_common_files.cmake INCLUDE_DIRECTORIES PRIVATE + Include Source + ${pal_include_dir} Include/Atom/RHI.Loader/Glad BUILD_DEPENDENCIES PRIVATE diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Common/Unimplemented/ModuleStub_Unimplemented.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Common/Unimplemented/ModuleStub_Unimplemented.cpp index 8c06700404..44a8a26968 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Common/Unimplemented/ModuleStub_Unimplemented.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Common/Unimplemented/ModuleStub_Unimplemented.cpp @@ -5,6 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + +#include #include namespace AZ @@ -17,7 +19,12 @@ namespace AZ public: AZ_RTTI(PlatformModule, "{958CB096-796C-42C7-9B29-17C6FE792C30}", Module); - PlatformModule() = default; + PlatformModule() + { + m_descriptors.insert(m_descriptors.end(), { + ReflectSystemComponent::CreateDescriptor() + }); + } ~PlatformModule() override = default; AZ::ComponentTypeList GetRequiredSystemComponents() const override diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp index db6a454cea..8b99b7b510 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp @@ -23,7 +23,7 @@ namespace AZ { namespace Vulkan { - static const char* VulkanShaderPlatformName = "VulkanShaderPlatform"; + [[maybe_unused]] static const char* VulkanShaderPlatformName = "VulkanShaderPlatform"; static const char* WindowsPlatformShaderHeader = "Builders/ShaderHeaders/Platform/Windows/Vulkan/PlatformHeader.hlsli"; static const char* AndroidPlatformShaderHeader = "Builders/ShaderHeaders/Platform/Android/Vulkan/PlatformHeader.hlsli"; static const char* WindowsAzslShaderHeader = "Builders/ShaderHeaders/Platform/Windows/Vulkan/AzslcHeader.azsli"; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp index dc52e530e0..e4d8212228 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp @@ -45,7 +45,7 @@ namespace AZ #if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) for (RHI::SwapChain* swapChain : rhiRequest.m_swapChainsToPresent) { - if (!swapChain->m_resized) + if (!swapChain->m_readyToPresent) { return; } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp index 0ae3ae1114..e1d3e8c060 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -127,6 +128,17 @@ namespace AZ nativeDimensions->m_imageFormat = ConvertFormat(m_surfaceFormat.format); } +#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) + // When launching in game mode, the surface will be ready at this point, meaning that after + // intialization, this swap chain is ready to present + AZ::ApplicationTypeQuery appType; + ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType); + if (appType.IsGame()) + { + m_readyToPresent.store(true); + } +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + SetName(GetName()); return result; } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h index 1a62e1753c..913a9702b1 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h @@ -20,6 +20,10 @@ namespace AZ { namespace JsonUtils { + //! Protects from allocating too much memory. The choice of a 1MB threshold is arbitrary. + //! If you need to work with larger files, please use AZ::IO directly instead of these utility functions. + inline constexpr size_t AtomMaxFileSize = 1024 * 1024; + // Declarations... //! Loads serialized object data from a json file at the specified path @@ -39,7 +43,7 @@ namespace AZ { objectData = ObjectType(); - auto loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(path); + auto loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(path, AtomMaxFileSize); if (!loadOutcome.IsSuccess()) { AZ_Error("AZ::RPI::JsonUtils", false, "%s", loadOutcome.GetError().c_str()); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h index 378a8743d8..abdbe9cdce 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h @@ -153,7 +153,9 @@ namespace AZ void AssetCreator::ReportError([[maybe_unused]] const char* format, [[maybe_unused]] Args... args) { ++m_errorCount; +#if defined(AZ_ENABLE_TRACING) // disabling since it requires argument expansion in this context AZ_Error(m_assetClassName, false, format, args...); +#endif } template @@ -161,7 +163,9 @@ namespace AZ void AssetCreator::ReportWarning([[maybe_unused]] const char* format, [[maybe_unused]] Args... args) { ++m_warningCount; +#if defined(AZ_ENABLE_TRACING) // disabling since it requires argument expansion in this context AZ_Warning(m_assetClassName, false, format, args...); +#endif } template diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp index c9c477048f..4d060b97b1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp @@ -30,7 +30,7 @@ namespace AZ { namespace { - const char* AnyAssetBuilderName = "AnyAssetBuilder"; + [[maybe_unused]] const char* AnyAssetBuilderName = "AnyAssetBuilder"; const char* AnyAssetBuilderJobKey = "Any Asset Builder"; const char* AnyAssetBuilderDefaultExtension = "azasset"; const char* AnyAssetSourceExtensions[] = diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 09f6610150..62e078c628 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -36,7 +37,7 @@ namespace AZ { namespace { - static constexpr char const MaterialBuilderName[] = "MaterialBuilder"; + [[maybe_unused]] static constexpr char const MaterialBuilderName[] = "MaterialBuilder"; } const char* MaterialBuilder::JobKey = "Atom Material Builder"; @@ -151,7 +152,7 @@ namespace AZ AZStd::string fullSourcePath; AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), fullSourcePath, true); - auto loadOutcome = JsonSerializationUtils::ReadJsonFile(fullSourcePath); + auto loadOutcome = JsonSerializationUtils::ReadJsonFile(fullSourcePath, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!loadOutcome.IsSuccess()) { AZ_Error(MaterialBuilderName, false, "%s", loadOutcome.GetError().c_str()); @@ -298,7 +299,7 @@ namespace AZ AZStd::string fullSourcePath; AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), fullSourcePath, true); - auto loadOutcome = JsonSerializationUtils::ReadJsonFile(fullSourcePath); + auto loadOutcome = JsonSerializationUtils::ReadJsonFile(fullSourcePath, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!loadOutcome.IsSuccess()) { AZ_Error(MaterialBuilderName, false, "Failed to load material file: %s", loadOutcome.GetError().c_str()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index 0ac5b61662..cf7e53c596 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -37,7 +37,7 @@ namespace AZ { namespace RPI { - static const char* MaterialExporterName = "Scene Material Builder"; + [[maybe_unused]] static const char* MaterialExporterName = "Scene Material Builder"; void MaterialAssetDependenciesComponent::Reflect(ReflectContext* context) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp index 9fc99e3ea4..1da16b44b6 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelAssetBuilderComponent.cpp @@ -1078,9 +1078,7 @@ namespace AZ template void ModelAssetBuilderComponent::ValidateStreamSize([[maybe_unused]] size_t expectedVertexCount, [[maybe_unused]] const AZStd::vector& bufferData, [[maybe_unused]] AZ::RHI::Format format, [[maybe_unused]] const char* streamName) const { -#if defined(AZ_ENABLE_TRACING) size_t actualVertexCount = (bufferData.size() * sizeof(T)) / RHI::GetFormatSize(format); -#endif AZ_Error(s_builderName, expectedVertexCount == actualVertexCount, "VertexStream '%s' does not match the expected vertex count. This typically means multiple sub-meshes have mis-matched vertex stream layouts (such as one having more uv sets than the other) but are assigned the same material in the dcc tool so they were merged.", streamName); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelExporterComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelExporterComponent.cpp index f7e672ab32..4539f4b432 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelExporterComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/ModelExporterComponent.cpp @@ -37,7 +37,7 @@ namespace AZ { namespace RPI { - static const char* s_exporterName = "Atom Model Builder"; + [[maybe_unused]] static const char* s_exporterName = "Atom Model Builder"; ModelExporterComponent::ModelExporterComponent() { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp index 44141f3ae3..f5812aae8b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MorphTargetExporter.cpp @@ -70,11 +70,9 @@ namespace AZ::RPI { const Containers::SceneGraph& sceneGraph = scene.GetGraph(); -#if defined(AZ_ENABLE_TRACING) const auto baseMeshIt = AZStd::find(sceneGraph.GetContentStorage().cbegin(), sceneGraph.GetContentStorage().cend(), sourceMesh.m_meshData); const Containers::SceneGraph::NodeIndex baseMeshIndex = sceneGraph.ConvertToNodeIndex(baseMeshIt); const AZStd::string_view baseMeshName{sceneGraph.GetNodeName(baseMeshIndex).GetName(), sceneGraph.GetNodeName(baseMeshIndex).GetNameLength()}; -#endif // Get the blend shapes for the given mesh AZStd::unordered_map blendShapeInfos = GetBlendShapeInfos(scene, sourceMesh.m_meshData.get()); @@ -90,10 +88,8 @@ namespace AZ::RPI AZ_Assert(blendShapeData, "Node is expected to be a blend shape."); if (blendShapeData) { -#if defined(AZ_ENABLE_TRACING) const Containers::SceneGraph::NodeIndex morphMeshParentIndex = sceneGraph.GetNodeParent(sceneNodeIndex); const AZStd::string_view sourceMeshName{sceneGraph.GetNodeName(morphMeshParentIndex).GetName(), sceneGraph.GetNodeName(morphMeshParentIndex).GetNameLength()}; -#endif AZ_Assert(AZ::StringFunc::Equal(baseMeshName, sourceMeshName, /*bCaseSensitive=*/true), "Scene graph mesh node (%.*s) has a different name than the product mesh (%.*s).", diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp index b67f1643df..d5e243c687 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp @@ -28,7 +28,7 @@ namespace AZ { namespace { - static const char* PassBuilderName = "PassBuilder"; + [[maybe_unused]] static const char* PassBuilderName = "PassBuilder"; static const char* PassBuilderJobKey = "Pass Asset Builder"; static const char* PassAssetExtension = "pass"; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp index 307d2bb80f..6f68115ccb 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -67,7 +68,7 @@ namespace AZ { AZStd::string materialTypePath = AssetUtils::ResolvePathReference(jsonFileLoadContext->GetFilePath(), materialSourceData->m_materialType); - auto materialTypeJson = JsonSerializationUtils::ReadJsonFile(materialTypePath); + auto materialTypeJson = JsonSerializationUtils::ReadJsonFile(materialTypePath, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!materialTypeJson.IsSuccess()) { AZStd::string failureMessage; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 0c2e9dca1f..80b292ea9b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -64,7 +65,7 @@ namespace AZ AZ::Outcome loadOutcome; if (document == nullptr) { - loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(filePath); + loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(filePath, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!loadOutcome.IsSuccess()) { AZ_Error("AZ::RPI::JsonUtils", false, "%s", loadOutcome.GetError().c_str()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp index 3945560eb3..d08fa3e58e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp @@ -419,9 +419,7 @@ namespace AZ { if (!materialPropertyDependencies.test(index.GetIndex())) { -#if defined(AZ_ENABLE_TRACING) const MaterialPropertyDescriptor* propertyDescriptor = materialPropertiesLayout.GetPropertyDescriptor(index); -#endif AZ_Error("MaterialFunctor", false, "Material functor accessing an unregistered material property '%s'.", propertyDescriptor ? propertyDescriptor->GetName().GetCStr() : ""); } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp index 0fc55e2363..4419e0c49f 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp @@ -73,6 +73,7 @@ namespace AtomToolsFramework return AZ::Transform::CreateIdentity(); } + void ModularCameraViewportContextImpl::SetCameraTransform(const AZ::Transform& transform) { if (auto viewportContext = RetrieveViewportContext(m_viewportId)) @@ -80,6 +81,7 @@ namespace AtomToolsFramework viewportContext->SetCameraTransform(transform); } } + void ModularCameraViewportContextImpl::ConnectViewMatrixChangedHandler(AZ::RPI::ViewportContext::MatrixChangedEvent::Handler& handler) { if (auto viewportContext = RetrieveViewportContext(m_viewportId)) diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index d720463ce2..b45fbe05f6 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -1552,6 +1552,26 @@ namespace AZ::AtomBridge } } + void AtomDebugDisplayViewportInterface::PushPremultipliedMatrix(const AZ::Matrix3x4& matrix) + { + AZ_Assert(m_rendState.m_currentTransform < RenderState::TransformStackSize, "Exceeded AtomDebugDisplayViewportInterface matrix stack size"); + if (m_rendState.m_currentTransform < RenderState::TransformStackSize) + { + m_rendState.m_currentTransform++; + m_rendState.m_transformStack[m_rendState.m_currentTransform] = matrix; + } + } + + AZ::Matrix3x4 AtomDebugDisplayViewportInterface::PopPremultipliedMatrix() + { + AZ_Assert(m_rendState.m_currentTransform > 0, "Underflowed AtomDebugDisplayViewportInterface matrix stack"); + if (m_rendState.m_currentTransform > 0) + { + m_rendState.m_currentTransform--; + } + return m_rendState.m_transformStack[m_rendState.m_currentTransform + 1]; + } + const AZ::Matrix3x4& AtomDebugDisplayViewportInterface::GetCurrentTransform() const { return m_rendState.m_transformStack[m_rendState.m_currentTransform]; diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h index 22fb8875a4..07f4efdf50 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h @@ -193,6 +193,8 @@ namespace AZ::AtomBridge AZ::u32 SetState(AZ::u32 state) override; void PushMatrix(const AZ::Transform& tm) override; void PopMatrix() override; + void PushPremultipliedMatrix(const AZ::Matrix3x4& matrix) override; + AZ::Matrix3x4 PopPremultipliedMatrix() override; private: diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp index 2a72641050..8270901b6b 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp @@ -16,6 +16,7 @@ #include // Included so we can deduce the asset type from asset paths. +#include #include #include #include @@ -24,7 +25,7 @@ namespace AZ { namespace AtomBridge { - static constexpr char AssetCollectionAsyncLoaderTestComponentName[] = " AssetCollectionAsyncLoaderTestComponent"; + [[maybe_unused]] static constexpr char AssetCollectionAsyncLoaderTestComponentName[] = " AssetCollectionAsyncLoaderTestComponent"; void AssetCollectionAsyncLoaderTestComponent::Reflect(AZ::ReflectContext* context) { @@ -114,7 +115,7 @@ namespace AZ { rapidjson::Document jsonDoc; - auto readJsonResult = JsonSerializationUtils::ReadJsonFile(pathToAssetListJson); + auto readJsonResult = JsonSerializationUtils::ReadJsonFile(pathToAssetListJson, AZ::RPI::JsonUtils::AtomMaxFileSize); if (!readJsonResult.IsSuccess()) { diff --git a/Gems/AudioEngineWwise/Code/Source/Engine/Config_wwise.cpp b/Gems/AudioEngineWwise/Code/Source/Engine/Config_wwise.cpp index 9bd376b641..437c1d156a 100644 --- a/Gems/AudioEngineWwise/Code/Source/Engine/Config_wwise.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Engine/Config_wwise.cpp @@ -11,8 +11,8 @@ #include #include #include +#include #include -#include // For AZ_Printf statements... #define WWISE_CONFIG_WINDOW "WwiseConfig" @@ -56,7 +56,7 @@ namespace Audio::Wwise bool ConfigurationSettings::Load(const AZStd::string& filePath) { AZ::IO::Path fileIoPath(filePath); - auto outcome = AzFramework::FileFunc::ReadJsonFile(fileIoPath); + auto outcome = AZ::JsonSerializationUtils::ReadJsonFile(fileIoPath.Native()); if (!outcome) { AZ_Printf(WWISE_CONFIG_WINDOW, "ERROR: %s\n", outcome.GetError().c_str()); @@ -92,7 +92,7 @@ namespace Audio::Wwise return false; } - auto outcome = AzFramework::FileFunc::WriteJsonFile(jsonDoc, filePath); + auto outcome = AZ::JsonSerializationUtils::WriteJsonFile(jsonDoc, filePath); if (!outcome) { AZ_Printf(WWISE_CONFIG_WINDOW, "ERROR: %s\n", outcome.GetError().c_str()); diff --git a/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp b/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp index 07113e09d3..cf042dc4ac 100644 --- a/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp +++ b/Gems/AudioEngineWwise/Code/Source/Engine/FileIOHandler_wwise.cpp @@ -19,9 +19,7 @@ #include #include -#define MAX_NUMBER_STRING_SIZE (10) // 4G -#define ID_TO_STRING_FORMAT_BANK AKTEXT("%u.bnk") -#define ID_TO_STRING_FORMAT_WEM AKTEXT("%u.wem") +#define MAX_NUMBER_STRING_SIZE (10) // max digits in u32 base-10 number #define MAX_EXTENSION_SIZE (4) // .xxx #define MAX_FILETITLE_SIZE (MAX_NUMBER_STRING_SIZE + MAX_EXTENSION_SIZE + 1) // null-terminated @@ -442,11 +440,16 @@ namespace Audio } } - AkOSChar fileName[MAX_FILETITLE_SIZE] = { '\0' }; + AkOSChar fileName[MAX_FILETITLE_SIZE] = { 0 }; - const AkOSChar* const filenameFormat = (flags->uCodecID == AKCODECID_BANK ? ID_TO_STRING_FORMAT_BANK : ID_TO_STRING_FORMAT_WEM); - - AK_OSPRINTF(fileName, MAX_FILETITLE_SIZE, filenameFormat, static_cast(fileID)); + if (flags->uCodecID == AKCODECID_BANK) + { + AK_OSPRINTF(fileName, MAX_FILETITLE_SIZE, AKTEXT("%u.bnk"), static_cast(fileID)); + } + else + { + AK_OSPRINTF(fileName, MAX_FILETITLE_SIZE, AKTEXT("%u.wem"), static_cast(fileID)); + } AKPLATFORM::SafeStrCat(finalFilePath, fileName, AK_MAX_PATH); diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp index 171100592d..cb5c525cec 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.cpp @@ -50,26 +50,21 @@ namespace EMotionFX return newPlugin; } - bool RagdollNodeInspectorPlugin::PhysXGemAvailable() const + bool RagdollNodeInspectorPlugin::IsPhysXGemAvailable() const { AZ::SerializeContext* serializeContext = nullptr; AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); - if (serializeContext) - { - // TypeId of D6JointLimitConfiguration - const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(AZ::TypeId::CreateString("{90C5C23D-16C0-4F23-AD50-A190E402388E}")); - if (classData && ColliderHelpers::AreCollidersReflected()) - { - return true; - } - } - return false; + // TypeId of PhysX::SystemComponent + const char* typeIDPhysXSystem = "{85F90819-4D9A-4A77-AB89-68035201F34B}"; + + return serializeContext + && serializeContext->FindClassData(AZ::TypeId::CreateString(typeIDPhysXSystem)); } bool RagdollNodeInspectorPlugin::Init() { - if (PhysXGemAvailable()) + if (IsPhysXGemAvailable() && ColliderHelpers::AreCollidersReflected()) { m_nodeWidget = new RagdollNodeWidget(); m_nodeWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.h b/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.h index 2df0fc2d95..36a33c1cd3 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.h +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeInspectorPlugin.h @@ -80,7 +80,7 @@ namespace EMotionFX void OnPasteJointLimits(); private: - bool PhysXGemAvailable() const; + bool IsPhysXGemAvailable() const; RagdollNodeWidget* m_nodeWidget; diff --git a/Gems/EMotionFX/Code/Tests/D6JointLimitConfiguration.h b/Gems/EMotionFX/Code/Tests/D6JointLimitConfiguration.h index c35ed4fefe..edb7b57017 100644 --- a/Gems/EMotionFX/Code/Tests/D6JointLimitConfiguration.h +++ b/Gems/EMotionFX/Code/Tests/D6JointLimitConfiguration.h @@ -14,14 +14,13 @@ namespace EMotionFX { // Add so that RagdollNodeInspectorPlugin::PhysXCharactersGemAvailable() will return the correct value // We duplicated the D6JointLimitConfiguration because it doesn't exist in the test environment. - class D6JointLimitConfiguration + struct D6JointLimitConfiguration : public AzPhysics::JointConfiguration { public: AZ_CLASS_ALLOCATOR(D6JointLimitConfiguration, AZ::SystemAllocator, 0); // This uses the same uuid as the production D6JointLimitConfiguration. - // The Ragdoll UI uses this UUID to see if physx is available. - AZ_RTTI(D6JointLimitConfiguration, "{90C5C23D-16C0-4F23-AD50-A190E402388E}", AzPhysics::JointConfiguration); + AZ_RTTI(D6JointLimitConfiguration, "{88E067B4-21E8-4FFA-9142-6C52605B704C}", AzPhysics::JointConfiguration); static void Reflect(AZ::ReflectContext* context); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h b/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h index a78fe52aa1..882d198092 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h @@ -8,6 +8,8 @@ #pragma once +#include +#include #include #include #include @@ -20,6 +22,20 @@ namespace Physics , AZ::Interface::Registrar { public: + // This uses the same uuid as the production PhysX::SystemComponent. + // The Ragdoll UI uses this UUID to see if physx is available. + AZ_RTTI(MockPhysicsSystem, "{85F90819-4D9A-4A77-AB89-68035201F34B}"); + + static void Reflect(AZ::ReflectContext* context) + { + if (auto serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(0) + ; + } + } + MockPhysicsSystem() { BusConnect(); diff --git a/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteColliders.cpp b/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteColliders.cpp index a30750071e..4f43e7dae5 100644 --- a/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteColliders.cpp +++ b/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteColliders.cpp @@ -39,7 +39,10 @@ namespace EMotionFX UIFixture::SetUp(); - D6JointLimitConfiguration::Reflect(GetSerializeContext()); + AZ::SerializeContext* serializeContext = GetSerializeContext(); + + Physics::MockPhysicsSystem::Reflect(serializeContext); // Required by Ragdoll plugin to fake PhysX Gem is available + D6JointLimitConfiguration::Reflect(serializeContext); EXPECT_CALL(m_jointHelpers, GetSupportedJointTypeIds) .WillRepeatedly(testing::Return(AZStd::vector{ azrtti_typeid() })); diff --git a/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteJointLimits.cpp b/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteJointLimits.cpp index 7fd0ec61e1..8e4fba0dd6 100644 --- a/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteJointLimits.cpp +++ b/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteJointLimits.cpp @@ -41,7 +41,10 @@ namespace EMotionFX { using testing::_; - D6JointLimitConfiguration::Reflect(GetSerializeContext()); + AZ::SerializeContext* serializeContext = GetSerializeContext(); + + Physics::MockPhysicsSystem::Reflect(serializeContext); // Required by Ragdoll plugin to fake PhysX Gem is available + D6JointLimitConfiguration::Reflect(serializeContext); EMStudio::GetMainWindow()->ApplicationModeChanged("Physics"); diff --git a/Gems/EMotionFX/Code/Tests/UI/CanAddToSimulatedObject.cpp b/Gems/EMotionFX/Code/Tests/UI/CanAddToSimulatedObject.cpp index ae1752cddd..e27d558664 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanAddToSimulatedObject.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanAddToSimulatedObject.cpp @@ -41,6 +41,7 @@ namespace EMotionFX AZ::SerializeContext* serializeContext = nullptr; AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + Physics::MockPhysicsSystem::Reflect(serializeContext); // Required by Ragdoll plugin to fake PhysX Gem is available D6JointLimitConfiguration::Reflect(serializeContext); SetupPluginWindows(); diff --git a/Gems/EMotionFX/Code/Tests/UI/RagdollEditTests.cpp b/Gems/EMotionFX/Code/Tests/UI/RagdollEditTests.cpp index b700a39472..1c39cde5b6 100644 --- a/Gems/EMotionFX/Code/Tests/UI/RagdollEditTests.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/RagdollEditTests.cpp @@ -40,6 +40,7 @@ namespace EMotionFX AZ::SerializeContext* serializeContext = nullptr; AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + Physics::MockPhysicsSystem::Reflect(serializeContext); // Required by Ragdoll plugin to fake PhysX Gem is available D6JointLimitConfiguration::Reflect(serializeContext); EXPECT_CALL(m_jointHelpers, GetSupportedJointTypeIds) diff --git a/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp b/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp index 561daa269e..38b29bcdf2 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp @@ -206,10 +206,7 @@ namespace EditorPythonBindings if (eventName == e.m_name) { AZStd::string eventNameValue{ eventName }; -#if defined(AZ_ENABLE_TRACING) - const auto& callbackIt = m_callbackMap.find(eventNameValue); -#endif - AZ_Warning("python", m_callbackMap.end() == callbackIt, "Replacing callback for eventName:%s", eventNameValue.c_str()); + AZ_Warning("python", m_callbackMap.end() == m_callbackMap.find(eventNameValue), "Replacing callback for eventName:%s", eventNameValue.c_str()); m_callbackMap[eventNameValue] = callback; return true; } @@ -293,7 +290,7 @@ namespace EditorPythonBindings handler->m_ebus->m_name.c_str(), eventName); } - void OnEventGenericHook(const char* eventName, pybind11::function callback, [[maybe_unused]] int eventIndex, AZ::BehaviorValueParameter* result, int numParameters, AZ::BehaviorValueParameter* parameters) + void OnEventGenericHook([[maybe_unused]] const char* eventName, pybind11::function callback, [[maybe_unused]] int eventIndex, AZ::BehaviorValueParameter* result, int numParameters, AZ::BehaviorValueParameter* parameters) { // build the parameters to send to callback Convert::StackVariableAllocator stackVariableAllocator; diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerClickOrTap.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerClickOrTap.inl index 77f6044642..b14ef18994 100644 --- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerClickOrTap.inl +++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerClickOrTap.inl @@ -73,12 +73,12 @@ inline Gestures::RecognizerClickOrTap::~RecognizerClickOrTap() //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerClickOrTap::OnPressedEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex != m_config.pointerIndex) + if (pointerIndex != m_config.pointerIndex) { return false; } - const CTimeValue currentTime = gEnv->pTimer->GetFrameStartTime(); + const CTimeValue currentTime = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime() : CTimeValue(); switch (m_currentState) { case State::Idle: @@ -120,7 +120,7 @@ inline bool Gestures::RecognizerClickOrTap::OnPressedEvent(const AZ::Vector2& sc //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerClickOrTap::OnDownEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex != m_config.pointerIndex) + if (pointerIndex != m_config.pointerIndex) { return false; } @@ -129,7 +129,7 @@ inline bool Gestures::RecognizerClickOrTap::OnDownEvent(const AZ::Vector2& scree { case State::Pressed: { - const CTimeValue currentTime = gEnv->pTimer->GetFrameStartTime(); + const CTimeValue currentTime = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime() : CTimeValue(); if ((currentTime.GetDifferenceInSeconds(m_timeOfLastEvent) > m_config.maxSecondsHeld) || (screenPosition.GetDistance(m_positionOfLastEvent) > m_config.maxPixelsMoved)) { @@ -159,7 +159,7 @@ inline bool Gestures::RecognizerClickOrTap::OnDownEvent(const AZ::Vector2& scree //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerClickOrTap::OnReleasedEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex != m_config.pointerIndex) + if (pointerIndex != m_config.pointerIndex) { return false; } @@ -168,7 +168,7 @@ inline bool Gestures::RecognizerClickOrTap::OnReleasedEvent(const AZ::Vector2& s { case State::Pressed: { - const CTimeValue currentTime = gEnv->pTimer->GetFrameStartTime(); + const CTimeValue currentTime = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime() : CTimeValue(); if ((currentTime.GetDifferenceInSeconds(m_timeOfLastEvent) > m_config.maxSecondsHeld) || (screenPosition.GetDistance(m_positionOfLastEvent) > m_config.maxPixelsMoved)) { diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerDrag.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerDrag.inl index c473293765..0c83893c9d 100644 --- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerDrag.inl +++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerDrag.inl @@ -59,7 +59,7 @@ inline Gestures::RecognizerDrag::~RecognizerDrag() //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerDrag::OnPressedEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex != m_config.pointerIndex) + if (pointerIndex != m_config.pointerIndex) { return false; } @@ -68,7 +68,7 @@ inline bool Gestures::RecognizerDrag::OnPressedEvent(const AZ::Vector2& screenPo { case State::Idle: { - m_startTime = gEnv->pTimer->GetFrameStartTime().GetValue(); + m_startTime = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime().GetValue() : 0; m_startPosition = screenPosition; m_currentPosition = screenPosition; m_currentState = State::Pressed; @@ -90,7 +90,7 @@ inline bool Gestures::RecognizerDrag::OnPressedEvent(const AZ::Vector2& screenPo //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerDrag::OnDownEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex != m_config.pointerIndex) + if (pointerIndex != m_config.pointerIndex) { return false; } @@ -101,7 +101,7 @@ inline bool Gestures::RecognizerDrag::OnDownEvent(const AZ::Vector2& screenPosit { case State::Pressed: { - const CTimeValue currentTime = gEnv->pTimer->GetFrameStartTime(); + const CTimeValue currentTime = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime() : CTimeValue(); if ((currentTime.GetDifferenceInSeconds(m_startTime) >= m_config.minSecondsHeld) && (GetDistance() >= m_config.minPixelsMoved)) { diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.inl index 99a3f7042c..6af8a10890 100644 --- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.inl +++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerHold.inl @@ -59,7 +59,7 @@ inline Gestures::RecognizerHold::~RecognizerHold() //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerHold::OnPressedEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex != m_config.pointerIndex) + if (pointerIndex != m_config.pointerIndex) { return false; } @@ -68,7 +68,7 @@ inline bool Gestures::RecognizerHold::OnPressedEvent(const AZ::Vector2& screenPo { case State::Idle: { - m_startTime = gEnv->pTimer->GetFrameStartTime().GetValue(); + m_startTime = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime().GetValue() : 0; m_startPosition = screenPosition; m_currentPosition = screenPosition; m_currentState = State::Pressed; @@ -90,7 +90,7 @@ inline bool Gestures::RecognizerHold::OnPressedEvent(const AZ::Vector2& screenPo //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerHold::OnDownEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex != m_config.pointerIndex) + if (pointerIndex != m_config.pointerIndex) { return false; } @@ -101,7 +101,7 @@ inline bool Gestures::RecognizerHold::OnDownEvent(const AZ::Vector2& screenPosit { case State::Pressed: { - const CTimeValue currentTime = gEnv->pTimer->GetFrameStartTime(); + const CTimeValue currentTime = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime() : CTimeValue(); if (screenPosition.GetDistance(m_startPosition) > m_config.maxPixelsMoved) { // Hold recognition failed. diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerPinch.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerPinch.inl index c64e310c36..642d781c35 100644 --- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerPinch.inl +++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerPinch.inl @@ -106,13 +106,13 @@ inline float AngleInDegreesBetweenVectors(const AZ::Vector2& vec0, const AZ::Vec //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerPinch::OnDownEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex > s_maxPinchPointerIndex) + if (pointerIndex > s_maxPinchPointerIndex) { return false; } m_currentPositions[pointerIndex] = screenPosition; - m_lastUpdateTimes[pointerIndex] = gEnv->pTimer->GetFrameStartTime().GetValue(); + m_lastUpdateTimes[pointerIndex] = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime().GetValue() : 0; if (m_lastUpdateTimes[0] != m_lastUpdateTimes[1]) { // We need to wait until both touches have been updated this frame. diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerRotate.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerRotate.inl index da6f84afca..2ae504e309 100644 --- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerRotate.inl +++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerRotate.inl @@ -95,13 +95,13 @@ inline bool Gestures::RecognizerRotate::OnPressedEvent(const AZ::Vector2& screen //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerRotate::OnDownEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex > s_maxRotatePointerIndex) + if (pointerIndex > s_maxRotatePointerIndex) { return false; } m_currentPositions[pointerIndex] = screenPosition; - m_lastUpdateTimes[pointerIndex] = gEnv->pTimer->GetFrameStartTime().GetValue(); + m_lastUpdateTimes[pointerIndex] = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime().GetValue() : 0; if (m_lastUpdateTimes[0] != m_lastUpdateTimes[1]) { // We need to wait until both touches have been updated this frame. diff --git a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerSwipe.inl b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerSwipe.inl index f84e85df52..5f879ce423 100644 --- a/Gems/Gestures/Code/Include/Gestures/GestureRecognizerSwipe.inl +++ b/Gems/Gestures/Code/Include/Gestures/GestureRecognizerSwipe.inl @@ -59,7 +59,7 @@ inline Gestures::RecognizerSwipe::~RecognizerSwipe() //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerSwipe::OnPressedEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex != m_config.pointerIndex) + if (pointerIndex != m_config.pointerIndex) { return false; } @@ -68,7 +68,7 @@ inline bool Gestures::RecognizerSwipe::OnPressedEvent(const AZ::Vector2& screenP { case State::Idle: { - m_startTime = gEnv->pTimer->GetFrameStartTime().GetValue(); + m_startTime = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime().GetValue() : 0; m_startPosition = screenPosition; m_endPosition = screenPosition; m_currentState = State::Pressed; @@ -89,7 +89,7 @@ inline bool Gestures::RecognizerSwipe::OnPressedEvent(const AZ::Vector2& screenP //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerSwipe::OnDownEvent([[maybe_unused]] const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex != m_config.pointerIndex) + if (pointerIndex != m_config.pointerIndex) { return false; } @@ -98,7 +98,7 @@ inline bool Gestures::RecognizerSwipe::OnDownEvent([[maybe_unused]] const AZ::Ve { case State::Pressed: { - const CTimeValue currentTime = gEnv->pTimer->GetFrameStartTime(); + const CTimeValue currentTime = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime() : CTimeValue(); if (currentTime.GetDifferenceInSeconds(m_startTime) > m_config.maxSecondsHeld) { // Swipe recognition failed because we took too long. @@ -125,7 +125,7 @@ inline bool Gestures::RecognizerSwipe::OnDownEvent([[maybe_unused]] const AZ::Ve //////////////////////////////////////////////////////////////////////////////////////////////////// inline bool Gestures::RecognizerSwipe::OnReleasedEvent(const AZ::Vector2& screenPosition, uint32_t pointerIndex) { - if (!gEnv || !gEnv->pTimer || pointerIndex != m_config.pointerIndex) + if (pointerIndex != m_config.pointerIndex) { return false; } @@ -134,7 +134,7 @@ inline bool Gestures::RecognizerSwipe::OnReleasedEvent(const AZ::Vector2& screen { case State::Pressed: { - const CTimeValue currentTime = gEnv->pTimer->GetFrameStartTime(); + const CTimeValue currentTime = (gEnv && gEnv->pTimer) ? gEnv->pTimer->GetFrameStartTime() : CTimeValue(); if ((currentTime.GetDifferenceInSeconds(m_startTime) <= m_config.maxSecondsHeld) && (screenPosition.GetDistance(m_startPosition) >= m_config.minPixelsMoved)) { diff --git a/Gems/LmbrCentral/Code/Source/Builders/BenchmarkAssetBuilder/BenchmarkAssetBuilderWorker.cpp b/Gems/LmbrCentral/Code/Source/Builders/BenchmarkAssetBuilder/BenchmarkAssetBuilderWorker.cpp index da7181ae04..22be22265a 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/BenchmarkAssetBuilder/BenchmarkAssetBuilderWorker.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/BenchmarkAssetBuilder/BenchmarkAssetBuilderWorker.cpp @@ -253,12 +253,10 @@ namespace BenchmarkAssetBuilder // and 2 bytes of storage for text-based formats. // This is just an approximate total size because there's a bit of additional overhead // for asset headers and the other fields in the generated asset. -#if defined(AZ_ENABLE_TRACING) uint64_t approximateTotalStorageBytes = (settingsPtr->m_assetStorageType == AZ::DataStream::StreamType::ST_BINARY) ? UINT64_C(1) * totalGeneratedBytes : UINT64_C(2) * totalGeneratedBytes; -#endif AZ_TracePrintf(AssetBuilderSDK::InfoWindow, "Benchmark asset generation will generate %" PRIu64 " assets " diff --git a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp b/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp index b5dce54f85..c06b21337b 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/MaterialBuilder/MaterialBuilderComponent.cpp @@ -19,7 +19,7 @@ namespace MaterialBuilder { - const char s_materialBuilder[] = "MaterialBuilder"; + [[maybe_unused]] const char s_materialBuilder[] = "MaterialBuilder"; namespace Internal { diff --git a/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp b/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp index 14096f73d2..79cf3ac282 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp @@ -49,7 +49,7 @@ namespace SliceBuilder } } // namespace anonymous - static const char* const s_sliceBuilder = "SliceBuilder"; + [[maybe_unused]] static const char* const s_sliceBuilder = "SliceBuilder"; static const char* const s_sliceBuilderSettingsFilename = "SliceBuilderSettings.json"; SliceBuilderWorker::SliceBuilderWorker() diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp index 78742028f9..31cf68e9a0 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp +++ b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp @@ -72,6 +72,7 @@ // Shape components #include "Shape/SphereShapeComponent.h" #include "Shape/DiskShapeComponent.h" +#include "Shape/AxisAlignedBoxShapeComponent.h" #include "Shape/BoxShapeComponent.h" #include "Shape/QuadShapeComponent.h" #include "Shape/CylinderShapeComponent.h" @@ -202,6 +203,7 @@ namespace LmbrCentral SphereShapeComponent::CreateDescriptor(), DiskShapeComponent::CreateDescriptor(), BoxShapeComponent::CreateDescriptor(), + AxisAlignedBoxShapeComponent::CreateDescriptor(), QuadShapeComponent::CreateDescriptor(), CylinderShapeComponent::CreateDescriptor(), CapsuleShapeComponent::CreateDescriptor(), @@ -215,6 +217,7 @@ namespace LmbrCentral SphereShapeDebugDisplayComponent::CreateDescriptor(), DiskShapeDebugDisplayComponent::CreateDescriptor(), BoxShapeDebugDisplayComponent::CreateDescriptor(), + AxisAlignedBoxShapeDebugDisplayComponent::CreateDescriptor(), QuadShapeDebugDisplayComponent::CreateDescriptor(), CapsuleShapeDebugDisplayComponent::CreateDescriptor(), CylinderShapeDebugDisplayComponent::CreateDescriptor(), diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp index b15a31f8b3..511bf98582 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp +++ b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp @@ -24,6 +24,7 @@ #include "Scripting/EditorSpawnerComponent.h" #include "Scripting/EditorTagComponent.h" +#include "Shape/EditorAxisAlignedBoxShapeComponent.h" #include "Shape/EditorBoxShapeComponent.h" #include "Shape/EditorQuadShapeComponent.h" #include "Shape/EditorSphereShapeComponent.h" @@ -67,6 +68,7 @@ namespace LmbrCentral EditorDiskShapeComponent::CreateDescriptor(), EditorTubeShapeComponent::CreateDescriptor(), EditorBoxShapeComponent::CreateDescriptor(), + EditorAxisAlignedBoxShapeComponent::CreateDescriptor(), EditorQuadShapeComponent::CreateDescriptor(), EditorLookAtComponent::CreateDescriptor(), EditorCylinderShapeComponent::CreateDescriptor(), diff --git a/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShape.cpp b/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShape.cpp new file mode 100644 index 0000000000..2553f8ab3e --- /dev/null +++ b/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShape.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include "AxisAlignedBoxShape.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace LmbrCentral +{ + AxisAlignedBoxShape::AxisAlignedBoxShape() + : BoxShape() + { + } + + void AxisAlignedBoxShape::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ; + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class("Axis Aligned Box Shape", "Axis Aligned Box shape configuration parameters") + ; + } + } + } + + void AxisAlignedBoxShape::Activate(AZ::EntityId entityId) + { + BoxShape::Activate(entityId); + m_currentTransform.SetRotation(AZ::Quaternion::CreateIdentity()); + } + + void AxisAlignedBoxShape::OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) + { + AZ::Transform worldNoRotation(world.GetTranslation(), AZ::Quaternion::CreateIdentity(), world.GetUniformScale()); + BoxShape::OnTransformChanged(local, worldNoRotation); + } +} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShape.h b/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShape.h new file mode 100644 index 0000000000..724092b608 --- /dev/null +++ b/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShape.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include "BoxShape.h" + +namespace AzFramework +{ + class DebugDisplayRequests; +} + +namespace LmbrCentral +{ + struct ShapeDrawParams; + + class AxisAlignedBoxShape + : public BoxShape + { + public: + AZ_CLASS_ALLOCATOR(AxisAlignedBoxShape, AZ::SystemAllocator, 0) + AZ_RTTI(AxisAlignedBoxShape, "{CFDC96C5-287A-4033-8D7D-BA9331C13F25}", BoxShape) + + AxisAlignedBoxShape(); + + static void Reflect(AZ::ReflectContext* context); + + void Activate(AZ::EntityId entityId) override; + + // AZ::TransformNotificationBus::Handler + void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; + }; +} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShapeComponent.cpp new file mode 100644 index 0000000000..7f919bc097 --- /dev/null +++ b/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShapeComponent.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + + +#include "AxisAlignedBoxShapeComponent.h" +#include +#include +#include +#include +#include + +namespace LmbrCentral +{ + void AxisAlignedBoxShapeComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("ShapeService")); + provided.push_back(AZ_CRC_CE("BoxShapeService")); + provided.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService")); + } + + void AxisAlignedBoxShapeComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("ShapeService")); + incompatible.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService")); + } + + void AxisAlignedBoxShapeComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC_CE("TransformService")); + } + + void AxisAlignedBoxShapeComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) + { + dependent.push_back(AZ_CRC_CE("NonUniformScaleService")); + } + + void AxisAlignedBoxShapeDebugDisplayComponent::Reflect(AZ::ReflectContext* context) + { + if (auto serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1)->Field( + "Configuration", &AxisAlignedBoxShapeDebugDisplayComponent::m_boxShapeConfig) + ; + } + } + + void AxisAlignedBoxShapeDebugDisplayComponent::Activate() + { + EntityDebugDisplayComponent::Activate(); + ShapeComponentNotificationsBus::Handler::BusConnect(GetEntityId()); + m_nonUniformScale = AZ::Vector3::CreateOne(); + AZ::NonUniformScaleRequestBus::EventResult(m_nonUniformScale, GetEntityId(), &AZ::NonUniformScaleRequests::GetScale); + } + + void AxisAlignedBoxShapeDebugDisplayComponent::Deactivate() + { + ShapeComponentNotificationsBus::Handler::BusDisconnect(); + EntityDebugDisplayComponent::Deactivate(); + } + + void AxisAlignedBoxShapeDebugDisplayComponent::Draw(AzFramework::DebugDisplayRequests& debugDisplay) + { + AZ::Matrix3x4 saveMatrix; + ShapeDrawParams drawParams = g_defaultShapeDrawParams; + drawParams.m_shapeColor = m_boxShapeConfig.GetDrawColor(); + drawParams.m_filled = m_boxShapeConfig.IsFilled(); + AZ::Transform transform = GetCurrentTransform(); + transform.SetRotation(AZ::Quaternion::CreateIdentity()); + saveMatrix = debugDisplay.PopPremultipliedMatrix(); + debugDisplay.PushMatrix(transform); + DrawBoxShape(drawParams, m_boxShapeConfig, debugDisplay, m_nonUniformScale); + debugDisplay.PopMatrix(); + debugDisplay.PushPremultipliedMatrix(saveMatrix); + } + + bool AxisAlignedBoxShapeDebugDisplayComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig) + { + if (const auto config = azrtti_cast(baseConfig)) + { + m_boxShapeConfig = *config; + return true; + } + return false; + } + + bool AxisAlignedBoxShapeDebugDisplayComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const + { + if (auto outConfig = azrtti_cast(outBaseConfig)) + { + *outConfig = m_boxShapeConfig; + return true; + } + return false; + } + + void AxisAlignedBoxShapeDebugDisplayComponent::OnShapeChanged(ShapeChangeReasons changeReason) + { + if (changeReason == ShapeChangeReasons::ShapeChanged) + { + BoxShapeComponentRequestsBus::EventResult(m_boxShapeConfig, GetEntityId(), &BoxShapeComponentRequests::GetBoxConfiguration); + AZ::NonUniformScaleRequestBus::EventResult(m_nonUniformScale, GetEntityId(), &AZ::NonUniformScaleRequests::GetScale); + } + } + + void AxisAlignedBoxShapeComponent::Reflect(AZ::ReflectContext* context) + { + AxisAlignedBoxShape::Reflect(context); + + if (auto serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ->Field("AxisAlignedBoxShape", &AxisAlignedBoxShapeComponent::m_aaboxShape) + ; + } + + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->Constant("AxisAlignedBoxShapeComponentTypeId", BehaviorConstant(AxisAlignedBoxShapeComponentTypeId)); + } + } + + void AxisAlignedBoxShapeComponent::Activate() + { + m_aaboxShape.Activate(GetEntityId()); + } + + void AxisAlignedBoxShapeComponent::Deactivate() + { + m_aaboxShape.Deactivate(); + } + + bool AxisAlignedBoxShapeComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig) + { + if (const auto config = azrtti_cast(baseConfig)) + { + m_aaboxShape.SetBoxConfiguration(*config); + return true; + } + return false; + } + + bool AxisAlignedBoxShapeComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const + { + if (auto config = azrtti_cast(outBaseConfig)) + { + *config = m_aaboxShape.GetBoxConfiguration(); + return true; + } + return false; + } + +} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShapeComponent.h b/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShapeComponent.h new file mode 100644 index 0000000000..094f9591d1 --- /dev/null +++ b/Gems/LmbrCentral/Code/Source/Shape/AxisAlignedBoxShapeComponent.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +#include "Rendering/EntityDebugDisplayComponent.h" +#include "AxisAlignedBoxShape.h" + +namespace LmbrCentral +{ + /// Type ID for the AxisAlignedBoxShapeComponent + static const AZ::Uuid AxisAlignedBoxShapeComponentTypeId = "{641D817E-1BC6-406A-BBB2-218541808E45}"; + + /// Type ID for the EditorAxisAlignedBoxShapeComponent + static const AZ::Uuid EditorAxisAlignedBoxShapeComponentTypeId = "{8C027DF6-E157-4159-9BF8-F1B925466F1F}"; + + /// Provide a Component interface for AxisAlignedBoxShape functionality. + class AxisAlignedBoxShapeComponent + : public AZ::Component + { + public: + AZ_COMPONENT(AxisAlignedBoxShapeComponent, AxisAlignedBoxShapeComponentTypeId) + static void Reflect(AZ::ReflectContext* context); + + // AZ::Component + void Activate() override; + void Deactivate() override; + bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override; + bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override; + + private: + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); + + AxisAlignedBoxShape m_aaboxShape; ///< Stores underlying box type for this component. + }; + + /// Concrete EntityDebugDisplay implementation for BoxShape. + class AxisAlignedBoxShapeDebugDisplayComponent + : public EntityDebugDisplayComponent + , public ShapeComponentNotificationsBus::Handler + { + public: + AZ_COMPONENT(AxisAlignedBoxShapeDebugDisplayComponent, "{BA93F933-1DC9-4E0E-B930-A7E3968D5DD1}", EntityDebugDisplayComponent) + static void Reflect(AZ::ReflectContext* context); + + AxisAlignedBoxShapeDebugDisplayComponent() = default; + + // AZ::Component + void Activate() override; + void Deactivate() override; + bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override; + bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override; + + // EntityDebugDisplayComponent + void Draw(AzFramework::DebugDisplayRequests& debugDisplay) override; + + private: + AZ_DISABLE_COPY_MOVE(AxisAlignedBoxShapeDebugDisplayComponent) + + // ShapeComponentNotificationsBus + void OnShapeChanged(ShapeChangeReasons changeReason) override; + + BoxShapeConfig m_boxShapeConfig; ///< Stores configuration data for box shape. + AZ::Vector3 m_nonUniformScale = AZ::Vector3::CreateOne(); ///< Caches non-uniform scale for this entity. + }; +} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Shape/BoxShape.h b/Gems/LmbrCentral/Code/Source/Shape/BoxShape.h index a3831fbee6..a9dfd5c35f 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/BoxShape.h +++ b/Gems/LmbrCentral/Code/Source/Shape/BoxShape.h @@ -37,7 +37,7 @@ namespace LmbrCentral static void Reflect(AZ::ReflectContext* context); - void Activate(AZ::EntityId entityId); + virtual void Activate(AZ::EntityId entityId); void Deactivate(); void InvalidateCache(InvalidateShapeCacheReason reason); @@ -67,12 +67,9 @@ namespace LmbrCentral void SetDrawColor(const AZ::Color& color) { m_boxShapeConfig.SetDrawColor(color); } - protected: - - friend class EditorBoxShapeComponent; BoxShapeConfig& ModifyConfiguration() { return m_boxShapeConfig; } - private: + protected: /// Runtime data - cache potentially expensive operations. class BoxIntersectionDataCache : public IntersectionTestDataCache @@ -82,6 +79,7 @@ namespace LmbrCentral const AZ::Vector3& currentNonUniformScale = AZ::Vector3::CreateOne()) override; friend BoxShape; + friend class AxisAlignedBoxShape; AZ::Aabb m_aabb; ///< Aabb representing this Box (including the effects of scale). AZ::Obb m_obb; ///< Obb representing this Box (including the effects of scale). @@ -90,12 +88,12 @@ namespace LmbrCentral bool m_axisAligned = true; ///< Indicates whether the box is axis or object aligned. }; - BoxShapeConfig m_boxShapeConfig; ///< Underlying box configuration. BoxIntersectionDataCache m_intersectionDataCache; ///< Caches transient intersection data. AZ::Transform m_currentTransform; ///< Caches the current transform for the entity on which this component lives. AZ::EntityId m_entityId; ///< Id of the entity the box shape is attached to. AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler; ///< Responds to changes in non-uniform scale. AZ::Vector3 m_currentNonUniformScale = AZ::Vector3::CreateOne(); ///< Caches the current non-uniform scale. + BoxShapeConfig m_boxShapeConfig; ///< Underlying box configuration. }; void DrawBoxShape( diff --git a/Gems/LmbrCentral/Code/Source/Shape/BoxShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/BoxShapeComponent.cpp index 40d5dce3cc..ce4a934e91 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/BoxShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/BoxShapeComponent.cpp @@ -101,23 +101,15 @@ namespace LmbrCentral } } - namespace ClassConverters - { - static bool DeprecateBoxColliderConfiguration(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); - static bool DeprecateBoxColliderComponent(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); - } - void BoxShapeConfig::Reflect(AZ::ReflectContext* context) { + // Don't reflect again if we're already reflected to the passed in context + if (context->IsTypeReflected(BoxShapeConfigTypeId)) + { + return; + } if (auto serializeContext = azrtti_cast(context)) { - // Deprecate: BoxColliderConfiguration -> BoxShapeConfig - serializeContext->ClassDeprecate( - "BoxColliderConfiguration", - "{282E47CB-9F6D-47AE-A210-4CE879527EFD}", - &ClassConverters::DeprecateBoxColliderConfiguration) - ; - serializeContext->Class() ->Version(2) ->Field("Dimensions", &BoxShapeConfig::m_dimensions) @@ -151,13 +143,6 @@ namespace LmbrCentral if (auto serializeContext = azrtti_cast(context)) { - // Deprecate: BoxColliderComponent -> BoxShapeComponent - serializeContext->ClassDeprecate( - "BoxColliderComponent", - "{C215EB2A-1803-4EDC-B032-F7C92C142337}", - &ClassConverters::DeprecateBoxColliderComponent) - ; - serializeContext->Class() ->Version(2, &ClassConverters::UpgradeBoxShapeComponent) ->Field("BoxShape", &BoxShapeComponent::m_boxShape) @@ -205,85 +190,4 @@ namespace LmbrCentral } return false; } - - namespace ClassConverters - { - static bool DeprecateBoxColliderConfiguration(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) - { - /* - Old: - - - - - New: - - - - */ - - // Cache the Dimensions - AZ::Vector3 oldDimensions; - const int oldIndex = classElement.FindElement(AZ_CRC("Size", 0xf7c0246a)); - if (oldIndex != -1) - { - classElement.GetSubElement(oldIndex).GetData(oldDimensions); - } - - // Convert to BoxShapeConfig - const bool result = classElement.Convert(context, "{F034FBA2-AC2F-4E66-8152-14DFB90D6283}"); - if (result) - { - const int newIndex = classElement.AddElement(context, "Dimensions"); - if (newIndex != -1) - { - classElement.GetSubElement(newIndex).SetData(context, oldDimensions); - return true; - } - } - return false; - } - - static bool DeprecateBoxColliderComponent(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) - { - /* - Old: - - - - - - - New: - - - - - - */ - - // Cache the Configuration - BoxShapeConfig configuration; - int configIndex = classElement.FindElement(AZ_CRC("Configuration", 0xa5e2a5d7)); - if (configIndex != -1) - { - classElement.GetSubElement(configIndex).GetData(configuration); - } - - // Convert to BoxShapeComponent - const bool result = classElement.Convert(context, BoxShapeComponentTypeId); - if (result) - { - configIndex = classElement.AddElement(context, "Configuration"); - if (configIndex != -1) - { - classElement.GetSubElement(configIndex).SetData(context, configuration); - } - return true; - } - return false; - } - - } // namespace ClassConverters - } // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Shape/EditorAxisAlignedBoxShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/EditorAxisAlignedBoxShapeComponent.cpp new file mode 100644 index 0000000000..c833677b1d --- /dev/null +++ b/Gems/LmbrCentral/Code/Source/Shape/EditorAxisAlignedBoxShapeComponent.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + + +#include +#include +#include +#include +#include + +#include "AxisAlignedBoxShapeComponent.h" +#include "EditorAxisAlignedBoxShapeComponent.h" +#include "EditorShapeComponentConverters.h" +#include "ShapeDisplay.h" + +namespace LmbrCentral +{ + void EditorAxisAlignedBoxShapeComponent::Reflect(AZ::ReflectContext* context) + { + if (auto serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1) + ->Field("AxisAlignedBoxShape", &EditorAxisAlignedBoxShapeComponent::m_aaboxShape) + ->Field("ComponentMode", &EditorAxisAlignedBoxShapeComponent::m_componentModeDelegate) + ; + + if (auto editContext = serializeContext->GetEditContext()) + { + editContext->Class( + "Axis Aligned Box Shape", "The Axis Aligned Box Shape component creates a box around the associated entity") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Category, "Shape") + ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Box_Shape.svg") + ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Box_Shape.svg") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/shape/axis-aligned-box-shape/") + ->DataElement(AZ::Edit::UIHandlers::Default, &EditorAxisAlignedBoxShapeComponent::m_aaboxShape, "Axis Aligned Box Shape", "Axis Aligned Box Shape Configuration") + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAxisAlignedBoxShapeComponent::ConfigurationChanged) + ->DataElement(AZ::Edit::UIHandlers::Default, &EditorAxisAlignedBoxShapeComponent::m_componentModeDelegate, "Component Mode", "Axis Aligned Box Shape Component Mode") + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ; + } + } + } + + void EditorAxisAlignedBoxShapeComponent::Init() + { + EditorBaseShapeComponent::Init(); + + SetShapeComponentConfig(&m_aaboxShape.ModifyConfiguration()); + } + + void EditorAxisAlignedBoxShapeComponent::Activate() + { + EditorBaseShapeComponent::Activate(); + m_aaboxShape.Activate(GetEntityId()); + AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); + AzToolsFramework::BoxManipulatorRequestBus::Handler::BusConnect( + AZ::EntityComponentIdPair(GetEntityId(), GetId())); + + // ComponentMode + m_componentModeDelegate.ConnectWithSingleComponentMode< + EditorAxisAlignedBoxShapeComponent, AzToolsFramework::BoxComponentMode>( + AZ::EntityComponentIdPair(GetEntityId(), GetId()), this); + } + + void EditorAxisAlignedBoxShapeComponent::Deactivate() + { + m_componentModeDelegate.Disconnect(); + + AzToolsFramework::BoxManipulatorRequestBus::Handler::BusDisconnect(); + AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); + m_aaboxShape.Deactivate(); + EditorBaseShapeComponent::Deactivate(); + } + + void EditorAxisAlignedBoxShapeComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + EditorBaseShapeComponent::GetProvidedServices(provided); + provided.push_back(AZ_CRC_CE("BoxShapeService")); + provided.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService")); + } + + void EditorAxisAlignedBoxShapeComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) + { + dependent.push_back(AZ_CRC_CE("NonUniformScaleService")); + } + + void EditorAxisAlignedBoxShapeComponent::DisplayEntityViewport( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, + AzFramework::DebugDisplayRequests& debugDisplay) + { + DisplayShape( + debugDisplay, [this]() { return CanDraw(); }, + [this](AzFramework::DebugDisplayRequests& debugDisplay) + { + DrawBoxShape( + { m_aaboxShape.GetBoxConfiguration().GetDrawColor(), m_shapeWireColor, m_aaboxShape.GetBoxConfiguration().IsFilled() }, + m_aaboxShape.GetBoxConfiguration(), debugDisplay, m_aaboxShape.GetCurrentNonUniformScale()); + }, + m_aaboxShape.GetCurrentTransform()); + } + + void EditorAxisAlignedBoxShapeComponent::ConfigurationChanged() + { + m_aaboxShape.InvalidateCache(InvalidateShapeCacheReason::ShapeChange); + + ShapeComponentNotificationsBus::Event(GetEntityId(), + &ShapeComponentNotificationsBus::Events::OnShapeChanged, + ShapeComponentNotifications::ShapeChangeReasons::ShapeChanged); + + AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast( + &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::Refresh, + AZ::EntityComponentIdPair(GetEntityId(), GetId())); + } + + void EditorAxisAlignedBoxShapeComponent::BuildGameEntity(AZ::Entity* gameEntity) + { + if (AxisAlignedBoxShapeComponent* boxShapeComponent = gameEntity->CreateComponent()) + { + boxShapeComponent->SetConfiguration(m_aaboxShape.GetBoxConfiguration()); + } + + if (m_visibleInGameView) + { + if (auto component = gameEntity->CreateComponent()) + { + component->SetConfiguration(m_aaboxShape.GetBoxConfiguration()); + } + } + } + + void EditorAxisAlignedBoxShapeComponent::OnTransformChanged( + const AZ::Transform& /*local*/, const AZ::Transform& /*world*/) + { + AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast( + &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::Refresh, + AZ::EntityComponentIdPair(GetEntityId(), GetId())); + } + + AZ::Vector3 EditorAxisAlignedBoxShapeComponent::GetDimensions() + { + return m_aaboxShape.GetBoxDimensions(); + } + + void EditorAxisAlignedBoxShapeComponent::SetDimensions(const AZ::Vector3& dimensions) + { + return m_aaboxShape.SetBoxDimensions(dimensions); + } + + AZ::Transform EditorAxisAlignedBoxShapeComponent::GetCurrentTransform() + { + return AzToolsFramework::TransformNormalizedScale(m_aaboxShape.GetCurrentTransform()); + } + + AZ::Vector3 EditorAxisAlignedBoxShapeComponent::GetBoxScale() + { + return AZ::Vector3(m_aaboxShape.GetCurrentTransform().GetUniformScale() * m_aaboxShape.GetCurrentNonUniformScale()); + } +} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Shape/EditorAxisAlignedBoxShapeComponent.h b/Gems/LmbrCentral/Code/Source/Shape/EditorAxisAlignedBoxShapeComponent.h new file mode 100644 index 0000000000..8bff4ea7e1 --- /dev/null +++ b/Gems/LmbrCentral/Code/Source/Shape/EditorAxisAlignedBoxShapeComponent.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include "AxisAlignedBoxShape.h" +#include "AxisAlignedBoxShapeComponent.h" +#include "EditorBaseShapeComponent.h" + +#include +#include +#include + + +namespace LmbrCentral +{ + /// Editor representation of Box Shape Component. + class EditorAxisAlignedBoxShapeComponent + : public EditorBaseShapeComponent + , private AzFramework::EntityDebugDisplayEventBus::Handler + , private AzToolsFramework::BoxManipulatorRequestBus::Handler + { + public: + AZ_EDITOR_COMPONENT(EditorAxisAlignedBoxShapeComponent, EditorAxisAlignedBoxShapeComponentTypeId, EditorBaseShapeComponent); + static void Reflect(AZ::ReflectContext* context); + + EditorAxisAlignedBoxShapeComponent() = default; + + // AZ::Component + void Init() override; + void Activate() override; + void Deactivate() override; + + protected: + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); + + // EditorComponentBase + void BuildGameEntity(AZ::Entity* gameEntity) override; + + // AZ::TransformNotificationBus::Handler + void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; + + private: + AZ_DISABLE_COPY_MOVE(EditorAxisAlignedBoxShapeComponent) + + // AzFramework::EntityDebugDisplayEventBus + void DisplayEntityViewport( + const AzFramework::ViewportInfo& viewportInfo, + AzFramework::DebugDisplayRequests& debugDisplay) override; + + // AzToolsFramework::BoxManipulatorRequestBus + AZ::Vector3 GetDimensions() override; + void SetDimensions(const AZ::Vector3& dimensions) override; + AZ::Transform GetCurrentTransform() override; + AZ::Vector3 GetBoxScale() override; + + void ConfigurationChanged(); + + AxisAlignedBoxShape m_aaboxShape; ///< Stores underlying box representation for this component. + + using ComponentModeDelegate = AzToolsFramework::ComponentModeFramework::ComponentModeDelegate; + ComponentModeDelegate m_componentModeDelegate; /**< Responsible for detecting ComponentMode activation + * and creating a concrete ComponentMode.*/ + }; +} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Shape/EditorBoxShapeComponent.cpp b/Gems/LmbrCentral/Code/Source/Shape/EditorBoxShapeComponent.cpp index f645c54610..2983ca7753 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/EditorBoxShapeComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/EditorBoxShapeComponent.cpp @@ -49,7 +49,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/shape/box-shape/") ->DataElement(AZ::Edit::UIHandlers::Default, &EditorBoxShapeComponent::m_boxShape, "Box Shape", "Box Shape Configuration") - // ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) // disabled - prevents ChangeNotify attribute firing correctly + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorBoxShapeComponent::ConfigurationChanged) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorBoxShapeComponent::m_componentModeDelegate, "Component Mode", "Box Shape Component Mode") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) diff --git a/Gems/LmbrCentral/Code/Tests/AxisAlignedBoxShapeTest.cpp b/Gems/LmbrCentral/Code/Tests/AxisAlignedBoxShapeTest.cpp new file mode 100644 index 0000000000..c3e8d06791 --- /dev/null +++ b/Gems/LmbrCentral/Code/Tests/AxisAlignedBoxShapeTest.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace UnitTest +{ + class AxisAlignedBoxShapeTest : public AllocatorsFixture + { + AZStd::unique_ptr m_serializeContext; + AZStd::unique_ptr m_transformComponentDescriptor; + AZStd::unique_ptr m_axisAlignedBoxShapeComponentDescriptor; + AZStd::unique_ptr m_axisAlignedBoxShapeDebugDisplayComponentDescriptor; + AZStd::unique_ptr m_nonUniformScaleComponentDescriptor; + + public: + void SetUp() override + { + AllocatorsFixture::SetUp(); + m_serializeContext = AZStd::make_unique(); + + m_transformComponentDescriptor = + AZStd::unique_ptr(AzFramework::TransformComponent::CreateDescriptor()); + m_transformComponentDescriptor->Reflect(&(*m_serializeContext)); + m_axisAlignedBoxShapeComponentDescriptor = + AZStd::unique_ptr(LmbrCentral::AxisAlignedBoxShapeComponent::CreateDescriptor()); + m_axisAlignedBoxShapeComponentDescriptor->Reflect(&(*m_serializeContext)); + m_axisAlignedBoxShapeDebugDisplayComponentDescriptor = + AZStd::unique_ptr(LmbrCentral::AxisAlignedBoxShapeDebugDisplayComponent::CreateDescriptor()); + m_axisAlignedBoxShapeDebugDisplayComponentDescriptor->Reflect(&(*m_serializeContext)); + m_nonUniformScaleComponentDescriptor = + AZStd::unique_ptr(AzFramework::NonUniformScaleComponent::CreateDescriptor()); + m_nonUniformScaleComponentDescriptor->Reflect(&(*m_serializeContext)); + } + + void TearDown() override + { + m_transformComponentDescriptor.reset(); + m_axisAlignedBoxShapeComponentDescriptor.reset(); + m_axisAlignedBoxShapeDebugDisplayComponentDescriptor.reset(); + m_nonUniformScaleComponentDescriptor.reset(); + m_serializeContext.reset(); + AllocatorsFixture::TearDown(); + } + }; + + void CreateAxisAlignedBox(const AZ::Transform& transform, const AZ::Vector3& dimensions, AZ::Entity& entity) + { + entity.CreateComponent(); + entity.CreateComponent(); + entity.CreateComponent(); + + entity.Init(); + entity.Activate(); + + AZ::TransformBus::Event(entity.GetId(), &AZ::TransformBus::Events::SetWorldTM, transform); + LmbrCentral::BoxShapeComponentRequestsBus::Event( + entity.GetId(), &LmbrCentral::BoxShapeComponentRequestsBus::Events::SetBoxDimensions, dimensions); + } + + void CreateAxisAlignedBoxWithNonUniformScale( + const AZ::Transform& transform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& dimensions, AZ::Entity& entity) + { + entity.CreateComponent(); + entity.CreateComponent(); + entity.CreateComponent(); + entity.CreateComponent(); + + entity.Init(); + entity.Activate(); + + AZ::TransformBus::Event(entity.GetId(), &AZ::TransformBus::Events::SetWorldTM, transform); + LmbrCentral::BoxShapeComponentRequestsBus::Event( + entity.GetId(), &LmbrCentral::BoxShapeComponentRequestsBus::Events::SetBoxDimensions, dimensions); + AZ::NonUniformScaleRequestBus::Event(entity.GetId(), &AZ::NonUniformScaleRequests::SetScale, nonUniformScale); + } + + void CreateDefaultAxisAlignedBox(const AZ::Transform& transform, AZ::Entity& entity) + { + CreateAxisAlignedBox(transform, AZ::Vector3(10.0f, 10.0f, 10.0f), entity); + } + + TEST_F(AxisAlignedBoxShapeTest, EntityTransformIsCorrect) + { + AZ::Entity entity; + CreateAxisAlignedBox( + AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, 0.0f, 0.0f)) * AZ::Transform::CreateRotationZ(AZ::Constants::QuarterPi), + AZ::Vector3(1.0f), entity); + + AZ::Transform transform; + AZ::TransformBus::EventResult(transform, entity.GetId(), &AZ::TransformBus::Events::GetWorldTM); + + EXPECT_EQ(transform, AZ::Transform::CreateRotationZ(AZ::Constants::QuarterPi)); + } + + TEST_F(AxisAlignedBoxShapeTest, BoxWithZRotationHasCorrectRayIntersection) + { + AZ::Entity entity; + CreateAxisAlignedBox( + AZ::Transform::CreateRotationZ(AZ::Constants::QuarterPi), + AZ::Vector3(1.0f), entity); + + bool rayHit = false; + float distance; + LmbrCentral::ShapeComponentRequestsBus::EventResult( + rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(5.0f, 0.0f, 0.0f), + AZ::Vector3(-1.0f, 0.0f, 0.0f), distance); + + // This test creates a unit box centered on (0, 0, 0) and rotated by 45 degrees. The distance to the box should + // be 4.5 if it isn't rotated but less if there is any rotation. + EXPECT_TRUE(rayHit); + EXPECT_NEAR(distance, 4.5f, 1e-2f); + } + + TEST_F(AxisAlignedBoxShapeTest, BoxWithTranslationAndRotationsHasCorrectRayIntersection) + { + AZ::Entity entity; + CreateAxisAlignedBox( + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::HalfPi) * + AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), AZ::Constants::QuarterPi), + AZ::Vector3(-10.0f, -10.0f, -10.0f)), + AZ::Vector3(4.0f, 4.0f, 2.0f), entity); + + bool rayHit = false; + float distance; + LmbrCentral::ShapeComponentRequestsBus::EventResult( + rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(-10.0f, -10.0f, 0.0f), + AZ::Vector3(0.0f, 0.0f, -1.0f), distance); + + // This test creates a box of dimensions (4.0, 4.0, 2.0) centered on (-10, -10, 0) and rotated in X and Z. The distance to the box should + // be 9.0 if it isn't rotated but less if there is any rotation. + EXPECT_TRUE(rayHit); + EXPECT_NEAR(distance, 9.00f, 1e-2f); + } + + TEST_F(AxisAlignedBoxShapeTest, BoxWithTranslationHasCorrectRayIntersection) + { + AZ::Entity entity; + CreateAxisAlignedBox( + AZ::Transform::CreateTranslation(AZ::Vector3(100.0f, 100.0f, 0.0f)), + AZ::Vector3(5.0f, 5.0f, 5.0f), entity); + + bool rayHit = false; + float distance; + LmbrCentral::ShapeComponentRequestsBus::EventResult( + rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(100.0f, 100.0f, -100.0f), + AZ::Vector3(0.0f, 0.0f, 1.0f), distance); + + // This test creates a box of dimensions (5.0, 5.0, 5.0) centered on (100, 100, 0) and not rotated. The distance to the box + // should be 97.5. + EXPECT_TRUE(rayHit); + EXPECT_NEAR(distance, 97.5f, 1e-2f); + } + + TEST_F(AxisAlignedBoxShapeTest, BoxWithTranslationRotationAndScaleHasCorrectRayIntersection) + { + AZ::Entity entity; + CreateAxisAlignedBox( + AZ::Transform( + AZ::Vector3(0.0f, 0.0f, 5.0f), AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisY(), AZ::Constants::QuarterPi), 3.0f), + AZ::Vector3(2.0f, 4.0f, 1.0f), entity); + + bool rayHit = false; + float distance; + LmbrCentral::ShapeComponentRequestsBus::EventResult( + rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(1.0f, -10.0f, 4.0f), + AZ::Vector3(0.0f, 1.0f, 0.0f), distance); + + // This test creates a box of dimensions (2.0, 4.0, 1.0) centered on (0, 0, 5) and rotated about the Y axis by 45 degrees. + // The distance to the box should be 4.0 if not rotated but scaled and less if it is. + EXPECT_TRUE(rayHit); + EXPECT_NEAR(distance, 4.0f, 1e-2f); + } + + TEST_F(AxisAlignedBoxShapeTest, RayIntersectWithBoxRotatedNonUniformScale) + { + AZ::Entity entity; + CreateAxisAlignedBoxWithNonUniformScale( + AZ::Transform( + AZ::Vector3(2.0f, -5.0f, 3.0f), AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisY(), AZ::Constants::QuarterPi), + 0.5f), + AZ::Vector3(2.2f, 1.8f, 0.4f), AZ::Vector3(0.2f, 2.6f, 1.2f), entity); + + // This test creates a box of dimensions (2.2, 1.8, 0.4) centered on (2.0, -5, 3) and rotated about the Y axis by 45 degrees. + // The box is tested for axis-alignment by firing various rays and ensuring they either hit or miss the box. Any failure here + // would show the box has been rotated. + + // Ray should just miss the box + bool rayHit = false; + float distance = AZ::Constants::FloatMax; + LmbrCentral::ShapeComponentRequestsBus::EventResult( + rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(1.8f, -6.2f, 3.0f), + AZ::Vector3(1.0f, 0.0f, 0.0f), distance); + EXPECT_FALSE(rayHit); + + // Ray should just hit the box + rayHit = false; + distance = AZ::Constants::FloatMax; + LmbrCentral::ShapeComponentRequestsBus::EventResult( + rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(1.8f, -6.1f, 3.0f), + AZ::Vector3(1.0f, 0.0f, 0.0f), distance); + EXPECT_TRUE(rayHit); + EXPECT_NEAR(distance, 0.09f, 1e-3f); + + // Ray should just miss the box + rayHit = false; + distance = AZ::Constants::FloatMax; + LmbrCentral::ShapeComponentRequestsBus::EventResult( + rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(2.2f, -6.2f, 3.0f), + AZ::Vector3(0.0f, 1.0f, 0.0f), distance); + EXPECT_FALSE(rayHit); + + // Ray should just hit the box + rayHit = false; + distance = AZ::Constants::FloatMax; + LmbrCentral::ShapeComponentRequestsBus::EventResult( + rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(2.1f, -6.2f, 3.0f), + AZ::Vector3(0.0f, 1.0f, 0.0f), distance); + EXPECT_TRUE(rayHit); + EXPECT_NEAR(distance, 0.03f, 1e-3f); + } +} // namespace UnitTest diff --git a/Gems/LmbrCentral/Code/Tests/DiskShapeTest.cpp b/Gems/LmbrCentral/Code/Tests/DiskShapeTest.cpp index e9c19585cc..65693a2a2e 100644 --- a/Gems/LmbrCentral/Code/Tests/DiskShapeTest.cpp +++ b/Gems/LmbrCentral/Code/Tests/DiskShapeTest.cpp @@ -34,10 +34,10 @@ namespace 0.5f, 1.0f, 2.0f, 4.0f, 8.0f, }; - const uint32_t RayCount = 5; + const uint32_t RayCountDisk = 5; // Various normalized offset directions from center of disk along disk's surface. - const AZStd::array OffsetsFromCenter = + const AZStd::array OffsetsFromCenterDisk = { AZ::Vector3(0.18f, -0.50f, 0.0f).GetNormalized(), AZ::Vector3(-0.08f, 0.59f, 0.0f).GetNormalized(), @@ -47,7 +47,7 @@ namespace }; // Various directions away from a point on the disk's surface - const AZStd::array OffsetsFromSurface = + const AZStd::array OffsetsFromSurfaceDisk = { AZ::Vector3(0.69f, 0.38f, 0.09f).GetNormalized(), AZ::Vector3(-0.98f, -0.68f, -0.28f).GetNormalized(), @@ -57,7 +57,7 @@ namespace }; // Various distance away from the surface for the rays - const AZStd::array RayDistances = + const AZStd::array RayDistancesDisk = { 0.5f, 1.0f, 2.0f, 4.0f, 8.0f }; @@ -185,7 +185,7 @@ namespace UnitTest } // Offsets from center scaled down from the disk edge so that all the rays should hit - const AZStd::array offsetFromCenterScale = + const AZStd::array offsetFromCenterScale = { 0.8f, 0.2f, @@ -197,20 +197,20 @@ namespace UnitTest // Construct rays and test against the different disks for (uint32_t diskIndex = 0; diskIndex < DiskCount; ++diskIndex) { - for (uint32_t rayIndex = 0; rayIndex < RayCount; ++rayIndex) + for (uint32_t rayIndex = 0; rayIndex < RayCountDisk; ++rayIndex) { - AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenter[rayIndex] * DiskRadii[diskIndex] * offsetFromCenterScale[rayIndex]; + AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenterDisk[rayIndex] * DiskRadii[diskIndex] * offsetFromCenterScale[rayIndex]; AZ::Vector3 positionOnDiskSurface = DiskTransforms[diskIndex].TransformPoint(scaledOffsetFromCenter); - AZ::Vector3 rayOrigin = positionOnDiskSurface + OffsetsFromSurface[rayIndex] * RayDistances[rayIndex]; + AZ::Vector3 rayOrigin = positionOnDiskSurface + OffsetsFromSurfaceDisk[rayIndex] * RayDistancesDisk[rayIndex]; bool rayHit2 = false; float distance2; LmbrCentral::ShapeComponentRequestsBus::EventResult( rayHit2, diskEntities[diskIndex].GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, - rayOrigin, -OffsetsFromSurface[rayIndex], distance2); + rayOrigin, -OffsetsFromSurfaceDisk[rayIndex], distance2); EXPECT_TRUE(rayHit2); - EXPECT_NEAR(distance2, RayDistances[rayIndex], 1e-4f); + EXPECT_NEAR(distance2, RayDistancesDisk[rayIndex], 1e-4f); } } @@ -241,7 +241,7 @@ namespace UnitTest } // Offsets from center scaled up from the disk edge so that all the rays should miss - const AZStd::array offsetFromCenterScale = + const AZStd::array offsetFromCenterScale = { 1.8f, 1.2f, @@ -253,17 +253,17 @@ namespace UnitTest // Construct rays and test against the different disks for (uint32_t diskIndex = 0; diskIndex < DiskCount; ++diskIndex) { - for (uint32_t rayIndex = 0; rayIndex < RayCount; ++rayIndex) + for (uint32_t rayIndex = 0; rayIndex < RayCountDisk; ++rayIndex) { - AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenter[rayIndex] * DiskRadii[diskIndex] * offsetFromCenterScale[rayIndex]; + AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenterDisk[rayIndex] * DiskRadii[diskIndex] * offsetFromCenterScale[rayIndex]; AZ::Vector3 positionOnDiskSurface = DiskTransforms[diskIndex].TransformPoint(scaledOffsetFromCenter); - AZ::Vector3 rayOrigin = positionOnDiskSurface + OffsetsFromSurface[rayIndex] * RayDistances[rayIndex]; + AZ::Vector3 rayOrigin = positionOnDiskSurface + OffsetsFromSurfaceDisk[rayIndex] * RayDistancesDisk[rayIndex]; bool rayHit2 = false; float distance2; LmbrCentral::ShapeComponentRequestsBus::EventResult( rayHit2, diskEntities[diskIndex].GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, - rayOrigin, -OffsetsFromSurface[rayIndex], distance2); + rayOrigin, -OffsetsFromSurfaceDisk[rayIndex], distance2); EXPECT_FALSE(rayHit2); } diff --git a/Gems/LmbrCentral/Code/Tests/QuadShapeTest.cpp b/Gems/LmbrCentral/Code/Tests/QuadShapeTest.cpp index a28916bb24..c02cf18aca 100644 --- a/Gems/LmbrCentral/Code/Tests/QuadShapeTest.cpp +++ b/Gems/LmbrCentral/Code/Tests/QuadShapeTest.cpp @@ -41,10 +41,10 @@ namespace LmbrCentral::QuadShapeConfig(1.0f, 0.5f), }; - const uint32_t RayCount = 5; + const uint32_t RayCountQuad = 5; // Various normalized offset directions from center of quad along quad's surface. - const AZStd::array OffsetsFromCenter = + const AZStd::array OffsetsFromCenterQuad = { AZ::Vector3( 0.18f, -0.50f, 0.0f).GetNormalized(), AZ::Vector3(-0.08f, 0.59f, 0.0f).GetNormalized(), @@ -54,7 +54,7 @@ namespace }; // Various directions away from a point on the quad's surface - const AZStd::array OffsetsFromSurface = + const AZStd::array OffsetsFromSurfaceQuad = { AZ::Vector3( 0.69f, 0.38f, 0.09f).GetNormalized(), AZ::Vector3(-0.98f, -0.68f, -0.28f).GetNormalized(), @@ -64,7 +64,7 @@ namespace }; // Various distance away from the surface for the rays - const AZStd::array RayDistances = + const AZStd::array RayDistancesQuad = { 0.5f, 1.0f, 2.0f, 4.0f, 8.0f }; @@ -248,23 +248,23 @@ namespace UnitTest // Construct rays and test against the different quads for (uint32_t quadIndex = 0; quadIndex < QuadCount; ++quadIndex) { - for (uint32_t rayIndex = 0; rayIndex < RayCount; ++rayIndex) + for (uint32_t rayIndex = 0; rayIndex < RayCountQuad; ++rayIndex) { - // OffsetsFromCenter are all less than 1, so scale by the dimensions of the quad. + // OffsetsFromCenterQuad are all less than 1, so scale by the dimensions of the quad. AZ::Vector3 scaledWidthHeight = AZ::Vector3(QuadDims[quadIndex].m_width, QuadDims[quadIndex].m_height, 0.0f); // Scale the offset and multiply by 0.5 because distance from center is half the width/height - AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenter[rayIndex] * scaledWidthHeight * 0.5f; + AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenterQuad[rayIndex] * scaledWidthHeight * 0.5f; AZ::Vector3 positionOnQuadSurface = QuadTransforms[quadIndex].TransformPoint(scaledOffsetFromCenter); - AZ::Vector3 rayOrigin = positionOnQuadSurface + OffsetsFromSurface[rayIndex] * RayDistances[rayIndex]; + AZ::Vector3 rayOrigin = positionOnQuadSurface + OffsetsFromSurfaceQuad[rayIndex] * RayDistancesQuad[rayIndex]; bool rayHit2 = false; float distance2; LmbrCentral::ShapeComponentRequestsBus::EventResult( rayHit2, quadEntities[quadIndex].GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, - rayOrigin, -OffsetsFromSurface[rayIndex], distance2); + rayOrigin, -OffsetsFromSurfaceQuad[rayIndex], distance2); EXPECT_TRUE(rayHit2); - EXPECT_NEAR(distance2, RayDistances[rayIndex], 1e-4f); + EXPECT_NEAR(distance2, RayDistancesQuad[rayIndex], 1e-4f); } } @@ -297,20 +297,20 @@ namespace UnitTest // Construct rays and test against the different quads for (uint32_t quadIndex = 0; quadIndex < QuadCount; ++quadIndex) { - for (uint32_t rayIndex = 0; rayIndex < RayCount; ++rayIndex) + for (uint32_t rayIndex = 0; rayIndex < RayCountQuad; ++rayIndex) { - // OffsetsFromCenter are all less than 1, so scale by the dimensions of the quad. + // OffsetsFromCenterQuad are all less than 1, so scale by the dimensions of the quad. AZ::Vector3 scaledWidthHeight = AZ::Vector3(QuadDims[quadIndex].m_width, QuadDims[quadIndex].m_height, 0.0f); - // Scale the offset and add 1.0 to OffsetsFromCenter to ensure the point is outside the quad. - AZ::Vector3 scaledOffsetFromCenter = (AZ::Vector3::CreateOne() + OffsetsFromCenter[rayIndex]) * scaledWidthHeight; + // Scale the offset and add 1.0 to OffsetsFromCenterQuad to ensure the point is outside the quad. + AZ::Vector3 scaledOffsetFromCenter = (AZ::Vector3::CreateOne() + OffsetsFromCenterQuad[rayIndex]) * scaledWidthHeight; AZ::Vector3 positionOnQuadSurface = QuadTransforms[quadIndex].TransformPoint(scaledOffsetFromCenter); - AZ::Vector3 rayOrigin = positionOnQuadSurface + OffsetsFromSurface[rayIndex] * RayDistances[rayIndex]; + AZ::Vector3 rayOrigin = positionOnQuadSurface + OffsetsFromSurfaceQuad[rayIndex] * RayDistancesQuad[rayIndex]; bool rayHit2 = false; float distance2; LmbrCentral::ShapeComponentRequestsBus::EventResult( rayHit2, quadEntities[quadIndex].GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, - rayOrigin, -OffsetsFromSurface[rayIndex], distance2); + rayOrigin, -OffsetsFromSurfaceQuad[rayIndex], distance2); EXPECT_FALSE(rayHit2); } diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Shape/BoxShapeComponentBus.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Shape/BoxShapeComponentBus.h index a84b0e2a4f..488e8b5617 100644 --- a/Gems/LmbrCentral/Code/include/LmbrCentral/Shape/BoxShapeComponentBus.h +++ b/Gems/LmbrCentral/Code/include/LmbrCentral/Shape/BoxShapeComponentBus.h @@ -21,13 +21,16 @@ namespace LmbrCentral /// Type ID for the EditorBoxShapeComponent static const AZ::Uuid EditorBoxShapeComponentTypeId = "{2ADD9043-48E8-4263-859A-72E0024372BF}"; + /// Type ID for the BoxShapeConfig + static const AZ::Uuid BoxShapeConfigTypeId = "{F034FBA2-AC2F-4E66-8152-14DFB90D6283}"; + /// Configuration data for BoxShapeComponent class BoxShapeConfig : public ShapeComponentConfig { public: AZ_CLASS_ALLOCATOR(BoxShapeConfig, AZ::SystemAllocator, 0) - AZ_RTTI(BoxShapeConfig, "{F034FBA2-AC2F-4E66-8152-14DFB90D6283}", ShapeComponentConfig) + AZ_RTTI(BoxShapeConfig, BoxShapeConfigTypeId, ShapeComponentConfig) static void Reflect(AZ::ReflectContext* context); diff --git a/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake index f96fd7a3b2..5c77888922 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake @@ -50,6 +50,8 @@ set(FILES Source/Shape/EditorDiskShapeComponent.cpp Source/Shape/EditorBoxShapeComponent.h Source/Shape/EditorBoxShapeComponent.cpp + Source/Shape/EditorAxisAlignedBoxShapeComponent.h + Source/Shape/EditorAxisAlignedBoxShapeComponent.cpp Source/Shape/EditorCylinderShapeComponent.h Source/Shape/EditorCylinderShapeComponent.cpp Source/Shape/EditorCapsuleShapeComponent.h diff --git a/Gems/LmbrCentral/Code/lmbrcentral_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_files.cmake index d663d2ec06..18412e2a38 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_files.cmake @@ -106,6 +106,10 @@ set(FILES Source/Shape/SphereShape.cpp Source/Shape/SphereShapeComponent.h Source/Shape/SphereShapeComponent.cpp + Source/Shape/AxisAlignedBoxShape.h + Source/Shape/AxisAlignedBoxShape.cpp + Source/Shape/AxisAlignedBoxShapeComponent.h + Source/Shape/AxisAlignedBoxShapeComponent.cpp Source/Shape/BoxShape.h Source/Shape/BoxShape.cpp Source/Shape/BoxShapeComponent.h diff --git a/Gems/LmbrCentral/Code/lmbrcentral_tests_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_tests_files.cmake index 5c4da3db73..c0f1ffd9ec 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_tests_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_tests_files.cmake @@ -8,6 +8,7 @@ set(FILES Tests/AudioComponentTests.cpp + Tests/AxisAlignedBoxShapeTest.cpp Tests/BoxShapeTest.cpp Tests/BundlingSystemComponentTests.cpp Tests/SphereShapeTest.cpp diff --git a/Gems/LyShine/Code/Pipeline/LyShineBuilder/UiCanvasBuilderWorker.cpp b/Gems/LyShine/Code/Pipeline/LyShineBuilder/UiCanvasBuilderWorker.cpp index 68ce1497f0..e0802fa4d1 100644 --- a/Gems/LyShine/Code/Pipeline/LyShineBuilder/UiCanvasBuilderWorker.cpp +++ b/Gems/LyShine/Code/Pipeline/LyShineBuilder/UiCanvasBuilderWorker.cpp @@ -31,7 +31,7 @@ namespace LyShine { - static const char* const s_uiSliceBuilder = "UiSliceBuilder"; + [[maybe_unused]] static const char* const s_uiSliceBuilder = "UiSliceBuilder"; void UiCanvasBuilderWorker::ShutDown() { diff --git a/Gems/PhysX/Code/physx_unsupported_files.cmake b/Gems/PhysX/Code/physx_unsupported_files.cmake new file mode 100644 index 0000000000..c2c5a11c4c --- /dev/null +++ b/Gems/PhysX/Code/physx_unsupported_files.cmake @@ -0,0 +1,10 @@ +# +# 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 +# +# + +set(FILES +) diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp index 536a678577..f474c10532 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorker.cpp @@ -6,7 +6,6 @@ * */ - #include #include #include @@ -16,20 +15,19 @@ #include #include #include - -#include +#include #include +#include #include #include #include #include +#include #include #include #include #include -#include - namespace ScriptCanvasBuilder { void Worker::Activate(const AssetHandlers& handlers) @@ -82,55 +80,18 @@ namespace ScriptCanvasBuilder m_processEditorAssetDependencies.clear(); - AZStd::unordered_multimap jobDependenciesByKey; - - auto assetFilter = [this, &jobDependenciesByKey](const AZ::Data::AssetFilterInfo& filterInfo) - { - // force load these before processing - if (filterInfo.m_assetType == azrtti_typeid() - || filterInfo.m_assetType == azrtti_typeid()) - { - this->m_processEditorAssetDependencies.push_back(filterInfo); - } - - // these trigger re-processing - if (filterInfo.m_assetType == azrtti_typeid()) - { - AZ_Error("ScriptCanvas", false, "ScriptAsset Reference in a graph detected"); - } - - if (filterInfo.m_assetType == azrtti_typeid()) - { - AssetBuilderSDK::SourceFileDependency dependency; - dependency.m_sourceFileDependencyUUID = filterInfo.m_assetId.m_guid; - jobDependenciesByKey.insert({ ScriptEvents::k_builderJobKey, dependency }); - } - - if (filterInfo.m_assetType == azrtti_typeid()) - { - AssetBuilderSDK::SourceFileDependency dependency; - dependency.m_sourceFileDependencyUUID = filterInfo.m_assetId.m_guid; - jobDependenciesByKey.insert({ s_scriptCanvasProcessJobKey, dependency }); - } - - // Asset filter always returns false to prevent parsing dependencies, but makes note of the script canvas dependencies - return false; - }; - AZ::Data::Asset asset; asset.Create(AZ::Data::AssetId(AZ::Uuid::CreateRandom())); - if (m_editorAssetHandler->LoadAssetDataFromStream(asset, assetDataStream, assetFilter) != AZ::Data::AssetHandler::LoadResult::LoadComplete) + if (m_editorAssetHandler->LoadAssetDataFromStream(asset, assetDataStream, {}) != AZ::Data::AssetHandler::LoadResult::LoadComplete) { AZ_Warning(s_scriptCanvasBuilder, false, "CreateJobs for \"%s\" failed because the asset data could not be loaded from the file", fullPath.data()); return; } - // Flush asset database events to ensure no asset references are held by closures queued on Ebuses. - AZ::Data::AssetManager::Instance().DispatchEvents(); - auto* scriptCanvasEntity = asset.Get()->GetScriptCanvasEntity(); auto* sourceGraph = AZ::EntityUtils::FindFirstDerivedComponent(scriptCanvasEntity); AZ_Assert(sourceGraph, "Graph component is missing from entity."); + AZ_Assert(sourceGraph->GetGraphData(), "GraphData is missing from entity"); struct EntityIdComparer { @@ -152,7 +113,58 @@ namespace ScriptCanvasBuilder } } - m_processEditorAssetDependencies.clear(); + AZ::SerializeContext* serializeContext{}; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + AZ_Assert(serializeContext, "SerializeContext is required to enumerate dependent assets in the ScriptCanvas file"); + + AZStd::unordered_multimap jobDependenciesByKey; + auto assetFilter = [this, &jobDependenciesByKey] + ( void* instancePointer + , const AZ::SerializeContext::ClassData* classData + , [[maybe_unused]] const AZ::SerializeContext::ClassElement* classElement) + { + auto azTypeId = classData->m_azRtti->GetTypeId(); + + if (azTypeId == azrtti_typeid>()) + { + const auto* subgraphAsset = reinterpret_cast*>(instancePointer); + if (subgraphAsset->GetId().IsValid()) + { + AssetBuilderSDK::SourceFileDependency dependency; + dependency.m_sourceFileDependencyUUID = subgraphAsset->GetId().m_guid; + jobDependenciesByKey.insert({ s_scriptCanvasProcessJobKey, dependency }); + this->m_processEditorAssetDependencies.push_back + ( { subgraphAsset->GetId(), azTypeId, AZ::Data::AssetLoadBehavior::PreLoad }); + } + } + else if (azTypeId == azrtti_typeid>()) + { + const auto* eventAsset = reinterpret_cast*>(instancePointer); + if (eventAsset->GetId().IsValid()) + { + AssetBuilderSDK::SourceFileDependency dependency; + dependency.m_sourceFileDependencyUUID = eventAsset->GetId().m_guid; + jobDependenciesByKey.insert({ ScriptEvents::k_builderJobKey, dependency }); + this->m_processEditorAssetDependencies.push_back + ( { eventAsset->GetId(), azTypeId, AZ::Data::AssetLoadBehavior::PreLoad }); + } + } + + // always continue, make note of the script canvas dependencies + return true; + }; + + AZ_Verify(serializeContext->EnumerateInstanceConst + ( sourceGraph->GetGraphData() + , azrtti_typeid() + , assetFilter + , {} + , AZ::SerializeContext::ENUM_ACCESS_FOR_READ + , nullptr + , nullptr), "Failed to gather dependencies from graph data"); + + // Flush asset database events to ensure no asset references are held by closures queued on Ebuses. + AZ::Data::AssetManager::Instance().DispatchEvents(); for (const AssetBuilderSDK::PlatformInfo& info : request.m_enabledPlatforms) { @@ -222,7 +234,7 @@ namespace ScriptCanvasBuilder bool pathFound = false; AZStd::string relativePath; AzToolsFramework::AssetSystemRequestBus::BroadcastResult - (pathFound + ( pathFound , &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath , request.m_fullPath.c_str(), relativePath); @@ -272,9 +284,6 @@ namespace ScriptCanvasBuilder assetDataStream->Open(AZStd::move(fileBuffer)); } - AZ::SerializeContext* context{}; - AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext); - AZ::Data::Asset asset; asset.Create(request.m_sourceFileUUID); if (m_editorAssetHandler->LoadAssetDataFromStream(asset, assetDataStream, nullptr) != AZ::Data::AssetHandler::LoadResult::LoadComplete) @@ -305,13 +314,6 @@ namespace ScriptCanvasBuilder } else { - // force load all dependencies into memory - for (auto& dependency : m_processEditorAssetDependencies) - { - auto depAsset = AZ::Data::AssetManager::Instance().GetAsset(dependency.m_assetId, dependency.m_assetType, AZ::Data::AssetLoadBehavior::PreLoad); - depAsset.BlockUntilLoadComplete(); - } - AZ::Entity* buildEntity = asset.Get()->GetScriptCanvasEntity(); ProcessTranslationJobInput input; @@ -375,6 +377,8 @@ namespace ScriptCanvasBuilder AZ_Error(s_scriptCanvasBuilder, false, translationOutcome.GetError().c_str()); } } + + m_processEditorAssetDependencies.clear(); } AZ_TracePrintf(s_scriptCanvasBuilder, "Finish Processing Job"); diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp index 6f86b93dda..dea63ab852 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetHandler.cpp @@ -93,6 +93,49 @@ namespace ScriptCanvasEditor } } + AZ::Outcome LoadScriptCanvasDataFromJson + ( ScriptCanvas::ScriptCanvasData& dataTarget + , AZStd::string_view source + , AZ::SerializeContext& serializeContext) + { + namespace JSRU = AZ::JsonSerializationUtils; + using namespace ScriptCanvas; + + AZ::JsonDeserializerSettings settings; + settings.m_serializeContext = &serializeContext; + settings.m_metadata.Create(); + + auto loadResult = JSRU::LoadObjectFromStringByType + ( &dataTarget + , azrtti_typeid() + , source + , &settings); + + if (!loadResult.IsSuccess()) + { + return loadResult; + } + + if (auto graphData = dataTarget.ModGraph()) + { + auto listeners = settings.m_metadata.Find(); + AZ_Assert(listeners, "Failed to find SerializationListeners"); + + ScriptCanvasAssetHandlerCpp::CollectNodes(graphData->GetGraphData()->m_nodes, *listeners); + + for (auto listener : *listeners) + { + listener->OnDeserialize(); + } + } + else + { + return AZ::Failure(AZStd::string("Failed to find graph data after loading source")); + } + + return AZ::Success(); + } + AZ::Data::AssetHandler::LoadResult ScriptCanvasAssetHandler::LoadAssetData ( const AZ::Data::Asset& assetTarget , AZStd::shared_ptr streamSource @@ -110,8 +153,9 @@ namespace ScriptCanvasEditor { streamSource->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); auto& scriptCanvasDataTarget = scriptCanvasAssetTarget->GetScriptCanvasData(); - AZStd::vector byteBuffer; + AZStd::vector byteBuffer; byteBuffer.resize_no_construct(streamSource->GetLength()); + // this duplicate stream is to allow for trying again if the JSON read fails AZ::IO::ByteContainerStream byteStreamSource(&byteBuffer); const size_t bytesRead = streamSource->Read(byteBuffer.size(), byteBuffer.data()); scriptCanvasDataTarget.m_scriptCanvasEntity.reset(nullptr); @@ -123,47 +167,45 @@ namespace ScriptCanvasEditor settings.m_serializeContext = m_serializeContext; settings.m_metadata.Create(); // attempt JSON deserialization... - if (JSRU::LoadObjectFromStreamByType - ( &scriptCanvasDataTarget - , azrtti_typeid() - , byteStreamSource - , &settings).IsSuccess()) + auto jsonResult = LoadScriptCanvasDataFromJson + ( scriptCanvasDataTarget + , AZStd::string_view{ byteBuffer.begin(), byteBuffer.size() } + , *m_serializeContext); + + if (jsonResult.IsSuccess()) { - if (auto graphData = scriptCanvasAssetTarget->GetScriptCanvasGraph() - ? scriptCanvasAssetTarget->GetScriptCanvasGraph()->GetGraphData() - : nullptr) - { - auto listeners = settings.m_metadata.Find(); - AZ_Assert(listeners, "Failed to create SerializationListeners"); - - ScriptCanvasAssetHandlerCpp::CollectNodes(graphData->m_nodes, *listeners); - - for (auto listener : *listeners) - { - listener->OnDeserialize(); - } - - return AZ::Data::AssetHandler::LoadResult::LoadComplete; - } - else - { - AZ_Warning("ScriptCanvas", false, "ScriptCanvasAssetHandler::LoadAssetData failed to load graph data from JOSON"); - } + return AZ::Data::AssetHandler::LoadResult::LoadComplete; } #if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)//// else - {// ...if there is a failure, check if it is saved in the old format + { + // ...if there is a failure, check if it is saved in the old format byteStreamSource.Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); // tolerate unknown classes in the editor. Let the asset processor warn about bad nodes... if (AZ::Utils::LoadObjectFromStreamInPlace - (byteStreamSource + ( byteStreamSource , scriptCanvasDataTarget , m_serializeContext , AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES))) { + AZ_Warning + ( "ScriptCanvas" + , false + , "ScriptCanvasAssetHandler::LoadAssetData failed to load graph data from JSON, %s, consider converting to JSON" + " by opening it and saving it, or running the graph update tool from the editor0" + , jsonResult.GetError().c_str()); return AZ::Data::AssetHandler::LoadResult::LoadComplete; } } +#else + else + { + AZ_Warning + ( "ScriptCanvas" + , false + , "ScriptCanvasAssetHandler::LoadAssetData failed to load graph data from JSON %s" + , jsonResult.GetError().c_str()"); + } #endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED) } } diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index 1899951638..f003618c03 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -3467,11 +3467,12 @@ namespace ScriptCanvasEditor m_focusHelper.SetActiveGraph(GetGraphCanvasGraphId()); } - bool Graph::UpgradeGraph(const AZ::Data::Asset& asset) + bool Graph::UpgradeGraph(const AZ::Data::Asset& asset, UpgradeRequest request, bool isVerbose) { m_upgradeSM.SetAsset(asset); + m_upgradeSM.SetVerbose(isVerbose); - if (!GetVersion().IsLatest()) + if (request == UpgradeRequest::Forced || !GetVersion().IsLatest()) { m_upgradeSM.Run(Start::StateID()); return true; diff --git a/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp b/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp index 9df6311a92..e87c82e186 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp @@ -79,7 +79,7 @@ namespace ScriptCanvasEditor { if (node->GetComponents().empty()) { - AZ_TracePrintf("Script Canvas", "Removing node due to missing components: %s\nVerify that all gems that this script relies on are enabled\n", node->GetName().c_str()); + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Removing node due to missing components: %s\nVerify that all gems that this script relies on are enabled\n", node->GetName().c_str()); nodesToRemove.push_back(node); } @@ -193,7 +193,7 @@ namespace ScriptCanvasEditor } else { - AZ_Warning("ScriptCanvas", false, "Could not find ScriptCanvas Node with id %llu", static_cast(scriptCanvasSourceEndpoint.GetNodeId())); + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Could not find ScriptCanvas Node with id %llu", static_cast(scriptCanvasSourceEndpoint.GetNodeId())); } AZ::EntityId graphCanvasSourceSlotId; @@ -213,7 +213,7 @@ namespace ScriptCanvasEditor if (!graphCanvasSourceSlotId.IsValid()) { - AZ_Warning("ScriptCanvas", sm->m_deletedNodes.count(scriptCanvasSourceEndpoint.GetNodeId()) > 0, "Could not create connection(%s) for Node(%s).", connectionId.ToString().c_str(), scriptCanvasSourceEndpoint.GetNodeId().ToString().c_str()); + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), sm->m_deletedNodes.count(scriptCanvasSourceEndpoint.GetNodeId()) > 0, "Could not create connection(%s) for Node(%s).", connectionId.ToString().c_str(), scriptCanvasSourceEndpoint.GetNodeId().ToString().c_str()); graph->DisconnectById(connectionId); continue; } @@ -229,7 +229,7 @@ namespace ScriptCanvasEditor } else { - AZ_Warning("ScriptCanvas", false, "Could not find ScriptCanvas Node with id %llu", static_cast(scriptCanvasSourceEndpoint.GetNodeId())); + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Could not find ScriptCanvas Node with id %llu", static_cast(scriptCanvasSourceEndpoint.GetNodeId())); } SlotMappingRequestBus::EventResult(graphCanvasTargetEndpoint.m_slotId, graphCanvasTargetEndpoint.GetNodeId(), &SlotMappingRequests::MapToGraphCanvasId, scriptCanvasTargetEndpoint.GetSlotId()); @@ -245,7 +245,7 @@ namespace ScriptCanvasEditor if (!graphCanvasTargetEndpoint.IsValid()) { - AZ_Warning("ScriptCanvas", sm->m_deletedNodes.count(scriptCanvasTargetEndpoint.GetNodeId()) > 0, "Could not create connection(%s) for Node(%s).", connectionId.ToString().c_str(), scriptCanvasTargetEndpoint.GetNodeId().ToString().c_str()); + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), sm->m_deletedNodes.count(scriptCanvasTargetEndpoint.GetNodeId()) > 0, "Could not create connection(%s) for Node(%s).", connectionId.ToString().c_str(), scriptCanvasTargetEndpoint.GetNodeId().ToString().c_str()); graph->DisconnectById(connectionId); continue; } @@ -422,7 +422,7 @@ namespace ScriptCanvasEditor if (!sm->m_updateReport.IsEmpty()) { // currently, it is expected that there are no deleted old slots, those need manual correction - AZ_Error("ScriptCanvas", sm->m_updateReport.m_deletedOldSlots.empty(), "Graph upgrade path: If old slots are deleted, manual upgrading is required"); + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), sm->m_updateReport.m_deletedOldSlots.empty(), "Graph upgrade path: If old slots are deleted, manual upgrading is required"); UpdateConnectionStatus(*graph, sm->m_updateReport); } } @@ -511,17 +511,19 @@ namespace ScriptCanvasEditor bool saveRawTranslationOuputToFile = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile; ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + + // save parsing status before after, just because it didn't parse after doesn't mean it didn't before graph->Parse(validationResults); ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = saveRawTranslationOuputToFile; - if (validationResults.HasResults()) + if (validationResults.HasErrors()) { + AZ::Interface::Get()->GraphNeedsManualUpgrade(sm->m_asset.GetId()); + for (auto& err : validationResults.GetEvents()) { // Register this graph as needing manual updates - AZ::Interface::Get()->GraphNeedsManualUpgrade(sm->m_asset.GetId()); - Log("%s: %s\n", err->GetIdentifier().c_str(), err->GetDescription().data()); } } @@ -678,6 +680,7 @@ namespace ScriptCanvasEditor if (m_asset != asset) { m_asset = asset; + SetDebugPrefix(asset.GetHint()); } } @@ -690,6 +693,10 @@ namespace ScriptCanvasEditor ////////////////////////////////////////////////////////////////////// // State Machine Internals + bool StateMachine::GetVerbose() const + { + return m_isVerbose; + } void StateMachine::OnSystemTick() { @@ -743,7 +750,22 @@ namespace ScriptCanvasEditor AZ::SystemTickBus::Handler::BusConnect(); } - } + void StateMachine::SetVerbose(bool isVerbose) + { + m_isVerbose = isVerbose; + } + + const AZStd::string& StateMachine::GetDebugPrefix() const + { + return m_debugPrefix; + } + + void StateMachine::SetDebugPrefix(AZStd::string_view prefix) + { + m_debugPrefix = prefix; + } + + } diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasAssetHandler.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasAssetHandler.h index c0af2d59ac..f29d5aa9cb 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasAssetHandler.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasAssetHandler.h @@ -20,6 +20,11 @@ namespace AZ namespace ScriptCanvasEditor { + AZ::Outcome LoadScriptCanvasDataFromJson + ( ScriptCanvas::ScriptCanvasData& dataTarget + , AZStd::string_view source + , AZ::SerializeContext& serializeContext); + /** * Manages editor Script Canvas graph assets. */ @@ -49,7 +54,7 @@ namespace ScriptCanvasEditor // Called by the asset database to perform actual asset save. Returns true if successful otherwise false (default - as we don't require support save). bool SaveAssetData(const AZ::Data::Asset& asset, AZ::IO::GenericStream* stream) override; bool SaveAssetData(const ScriptCanvasAsset* assetData, AZ::IO::GenericStream* stream); - bool SaveAssetData(const ScriptCanvasAsset* assetData, AZ::IO::GenericStream* stream , AZ::DataStream::StreamType streamType); + bool SaveAssetData(const ScriptCanvasAsset* assetData, AZ::IO::GenericStream* stream, AZ::DataStream::StreamType streamType); // Called by the asset database when an asset should be deleted. void DestroyAsset(AZ::Data::AssetPtr ptr) override; diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.cpp b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.cpp new file mode 100644 index 0000000000..6da134ed6a --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +namespace ScriptCanvas +{ + Graph* ScriptCanvasData::ModGraph() + { + return AZ::EntityUtils::FindFirstDerivedComponent(m_scriptCanvasEntity.get()); + } + + const Graph* ScriptCanvasData::GetGraph() const + { + return AZ::EntityUtils::FindFirstDerivedComponent(m_scriptCanvasEntity.get()); + } +} diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h index d36b773e83..f4b02b56b6 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h @@ -28,6 +28,10 @@ namespace ScriptCanvas AZ::Entity* GetScriptCanvasEntity() const { return m_scriptCanvasEntity.get(); } + Graph* ModGraph(); + + const Graph* GetGraph() const; + AZStd::unique_ptr m_scriptCanvasEntity; private: ScriptCanvasData(const ScriptCanvasData&) = delete; diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h index 1f036e22bb..4497968ffc 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Bus/EditorScriptCanvasBus.h @@ -223,9 +223,9 @@ namespace ScriptCanvasEditor using AssetList = AZStd::list; virtual AssetList& GetAssetsToUpgrade() = 0; + virtual void ClearGraphsThatNeedUpgrade() = 0; virtual void GraphNeedsManualUpgrade(const AZ::Data::AssetId&) = 0; - virtual AZStd::vector& GetGraphsThatNeedManualUpgrade() = 0; - + virtual const AZStd::vector& GetGraphsThatNeedManualUpgrade() const = 0; virtual bool IsUpgrading() = 0; virtual void SetIsUpgrading(bool isUpgrading) = 0; }; diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h index bf654a4440..cb6689091b 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h @@ -230,7 +230,12 @@ namespace ScriptCanvasEditor ///// EditorGraphUpgradeMachine m_upgradeSM; - bool UpgradeGraph(const AZ::Data::Asset& asset); + enum UpgradeRequest + { + IfOutOfDate, + Forced + }; + bool UpgradeGraph(const AZ::Data::Asset& asset, UpgradeRequest request, bool isVerbose = true); void ConnectGraphCanvasBuses(); void DisconnectGraphCanvasBuses(); /////// diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h index df7fa0535f..89ee0f3b55 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h @@ -131,8 +131,20 @@ namespace ScriptCanvasEditor void OnSystemTick() override; + bool GetVerbose() const; + + void SetVerbose(bool isVerbose); + + const AZStd::string& GetDebugPrefix() const; + + void SetDebugPrefix(AZStd::string_view); + AZStd::shared_ptr m_currentState = nullptr; AZStd::vector> m_states; + + private: + bool m_isVerbose = true; + AZStd::string m_debugPrefix; }; //! This state machine will collect and share a variety of data from the EditorGraph @@ -342,19 +354,22 @@ namespace ScriptCanvasEditor int EvaluateTransition() override; }; + template void ScriptCanvasEditor::State::Log(const char* format, ...) { if (m_verbose) { - char sBuffer[1024]; + char sBuffer[2048]; va_list ArgList; va_start(ArgList, format); azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); sBuffer[sizeof(sBuffer) - 1] = '\0'; va_end(ArgList); - - AZ_TracePrintf("Script Canvas", "%s\n", sBuffer); + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data() + , "%s-%s\n" + , m_stateMachine->GetDebugPrefix().c_str() + , sBuffer); } } } diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.h b/Gems/ScriptCanvas/Code/Editor/SystemComponent.h index 37515944c7..ba850401d6 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.h @@ -1,3 +1,4 @@ + /* * 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. @@ -109,6 +110,11 @@ namespace ScriptCanvasEditor //////////////////////////////////////////////////////////////////////// // IUpgradeRequests... + void ClearGraphsThatNeedUpgrade() + { + m_assetsThatNeedManualUpgrade.clear(); + } + IUpgradeRequests::AssetList& GetAssetsToUpgrade() override { return m_assetsToConvert; @@ -122,7 +128,7 @@ namespace ScriptCanvasEditor } } - AZStd::vector& GetGraphsThatNeedManualUpgrade() override + const AZStd::vector& GetGraphsThatNeedManualUpgrade() const override { return m_assetsThatNeedManualUpgrade; } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.cpp index da0e9c6045..704f67e034 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.cpp @@ -154,9 +154,7 @@ namespace ScriptCanvasEditor const ScriptEvents::ScriptEvent& definition = data->m_definition; -#if defined(AZ_ENABLE_TRACING) bool recategorize = previousDefinition ? definition.GetCategory().compare(previousDefinition->GetCategory()) != 0 : false; -#endif AZ_Warning("ScriptCanvas", !recategorize, "Unable to recategorize ScriptEvents events while open. Please close and re-open the Script Canvas Editor to see the new categorization"); if (definition.GetName().empty()) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.cpp index 3d42fdad42..5e6858c993 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.cpp @@ -92,7 +92,7 @@ namespace ScriptCanvasEditor void UpgradeTool::closeEvent(QCloseEvent* event) { - m_keepEditorAlive.reset(); + // m_keepEditorAlive.reset(); DisconnectBuses(); @@ -110,7 +110,7 @@ namespace ScriptCanvasEditor { setWindowFlag(Qt::WindowCloseButtonHint, false); - m_keepEditorAlive = AZStd::make_unique(); + // m_keepEditorAlive = AZStd::make_unique(); UpdateSettings(); @@ -581,74 +581,6 @@ namespace ScriptCanvasEditor accept(); } - template - AZ::Entity* UpgradeGraph(AZ::Data::Asset& asset, UpgradeTool* upgradeTool) - { - AssetType* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "Unable to get the asset of type: %s", azrtti_typeid().template ToString().c_str()); - - if (!scriptCanvasAsset) - { - return nullptr; - } - - AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); - if (!scriptCanvasEntity) - { - return nullptr; - } - - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - bool isLatest = graphComponent->GetVersion().IsLatest(); - if (isLatest) - { - ++upgradeTool->SkippedGraphCount(); - - // No need to upgrade - return nullptr; - } - - - 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(); - } - - if (graphComponent) - { - if (!graphComponent->UpgradeGraph(asset)) - { - ++upgradeTool->SkippedGraphCount(); - } - else - { - ++upgradeTool->UpgradedGraphCount(); - } - } - - return scriptCanvasEntity; - } - void UpgradeTool::SaveLog() { AZStd::string outputFileName = AZStd::string::format("@devroot@/ScriptCanvasUpgradeReport.html"); @@ -688,29 +620,9 @@ namespace ScriptCanvasEditor outputFile.Close(); } - AZ::Entity* UpgradeTool::AssetUpgradeJob(AZ::Data::Asset& asset) + AZ::Entity* UpgradeTool::AssetUpgradeJob(AZ::Data::Asset&) { - using namespace ScriptCanvasEditor; - - AZ_Assert(asset.IsReady(), "The asset must be ready by now"); - - AZStd::lock_guard myLocker(m_mutex); - - AZ::Entity* scriptCanvasEntity = nullptr; - if (asset.GetType() == azrtti_typeid()) - { - scriptCanvasEntity = UpgradeGraph(asset, this); - } - - if (!scriptCanvasEntity) - { - // This may happen if the graph failed or did not need to upgrade - AZ_TracePrintf("Script Canvas", "%s .. up to date!\n", asset.GetHint().c_str()); - return nullptr; - } - - // The rest will happen when we get notified that the graph is done. - return scriptCanvasEntity; + return nullptr; } void UpgradeTool::RetryMove(AZ::Data::Asset& asset, const AZStd::string& source, const AZStd::string& target) @@ -780,28 +692,6 @@ namespace ScriptCanvasEditor return false; } - ScriptCanvasEditor::EditorKeepAlive::EditorKeepAlive() - { - ISystem* system = nullptr; - CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); - - m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); - - if (m_edKeepEditorActive) - { - m_keepEditorActive = m_edKeepEditorActive->GetIVal(); - m_edKeepEditorActive->Set(1); - } - } - - ScriptCanvasEditor::EditorKeepAlive::~EditorKeepAlive() - { - if (m_edKeepEditorActive) - { - m_edKeepEditorActive->Set(m_keepEditorActive); - } - } - #include } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h index d771de4dd1..be00198457 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h @@ -38,18 +38,7 @@ namespace Ui namespace ScriptCanvasEditor { - //! Scoped utility to set and restore the "ed_KeepEditorActive" CVar in order to allow - //! the upgrade tool to work even if the editor is not in the foreground - class EditorKeepAlive - { - public: - EditorKeepAlive(); - ~EditorKeepAlive(); - - private: - int m_keepEditorActive; - ICVar* m_edKeepEditorActive; - }; + class KeepEditorAlive; //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog class UpgradeTool @@ -140,7 +129,7 @@ namespace ScriptCanvasEditor AZStd::unique_ptr m_ui; AZStd::recursive_mutex m_mutex; - AZStd::unique_ptr m_keepEditorAlive; + // AZStd::unique_ptr m_keepEditorAlive; AZStd::vector m_logs; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.cpp index 738cfd8d22..eb182ed291 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.cpp @@ -6,40 +6,89 @@ * */ + +#include +#include #include #include -#include #include -#include #include -#include "VersionExplorer.h" - #include #include #include +#include #include #include - #include #include - +#include +#include #include #include #include - -#include - #include #include #include - +#include #include #include -#include + +namespace VersionExplorerCpp +{ + class FileEventHandler + : public AZ::IO::FileIOEventBus::Handler + { + public: + int m_errorCode = 0; + AZStd::string m_fileName; + + FileEventHandler() + { + BusConnect(); + } + + ~FileEventHandler() + { + BusDisconnect(); + } + + void OnError(const AZ::IO::SystemFile* /*file*/, const char* fileName, int errorCode) override + { + m_errorCode = errorCode; + + if (fileName) + { + m_fileName = fileName; + } + } + }; +} namespace ScriptCanvasEditor { + EditorKeepAlive::EditorKeepAlive() + { + ISystem* system = nullptr; + CrySystemRequestBus::BroadcastResult(system, &CrySystemRequestBus::Events::GetCrySystem); + + m_edKeepEditorActive = system->GetIConsole()->GetCVar("ed_KeepEditorActive"); + + if (m_edKeepEditorActive) + { + m_keepEditorActive = m_edKeepEditorActive->GetIVal(); + m_edKeepEditorActive->Set(1); + } + } + + EditorKeepAlive::~EditorKeepAlive() + { + if (m_edKeepEditorActive) + { + m_edKeepEditorActive->Set(m_keepEditorActive); + } + } + VersionExplorer::VersionExplorer(QWidget* parent /*= nullptr*/) : AzQtComponents::StyledDialog(parent) , m_ui(new Ui::VersionExplorer()) @@ -62,7 +111,6 @@ namespace ScriptCanvasEditor m_ui->progressBar->setVisible(false); m_keepEditorAlive = AZStd::make_unique(); - m_inspectingAsset = m_assetsToInspect.end(); } @@ -80,14 +128,14 @@ namespace ScriptCanvasEditor { if (m_ui->verbose->isChecked()) { - char sBuffer[1024]; + char sBuffer[2048]; va_list ArgList; va_start(ArgList, format); azvsnprintf(sBuffer, sizeof(sBuffer), format, ArgList); sBuffer[sizeof(sBuffer) - 1] = '\0'; va_end(ArgList); - AZ_TracePrintf("Script Canvas", "%s\n", sBuffer); + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "%s\n", sBuffer); } } @@ -122,13 +170,13 @@ namespace ScriptCanvasEditor } else { - m_ui->tableWidget->insertRow(static_cast(m_inspectedAssets)); + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); QTableWidgetItem* rowName = new QTableWidgetItem ( tr(AZStd::string::format("Error: %s", assetToUpgrade.m_relativePath.c_str()).c_str())); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); + ++m_currentAssetRowIndex; - m_ui->tableWidget->setItem(static_cast(m_inspectedAssets), static_cast(ColumnAsset), rowName); Log("SystemTick::ProcessState::Scan: %s post-blocking load, problem loading asset", assetToUpgrade.m_relativePath.c_str()); - ++m_currentAssetIndex; ++m_failedAssets; ScanComplete(m_currentAsset); } @@ -136,13 +184,62 @@ namespace ScriptCanvasEditor break; case ProcessState::Upgrade: - - if (!IsUpgrading()) + { + AZStd::lock_guard lock(m_mutex); + if (m_upgradeComplete) { - OperationResult result = BackupGraph(*m_inProgressAsset); - // Make the backup - if (result == OperationResult::BackupSuccess) + ++m_upgradeAssetIndex; + m_inProgress = false; + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + + if (m_scriptCanvasEntity) { + m_scriptCanvasEntity->Deactivate(); + m_scriptCanvasEntity = nullptr; + } + + GraphUpgradeCompleteUIUpdate(m_upgradeAsset, m_upgradeResult, m_upgradeMessage); + + if (!m_isUpgradingSingleGraph) + { + if (m_inProgressAsset != m_assetsToUpgrade.end()) + { + m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); + } + + if (m_inProgressAsset == m_assetsToUpgrade.end()) + { + FinalizeUpgrade(); + } + } + else + { + m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); + m_inProgress = false; + m_state = ProcessState::Inactive; + m_settingsCache.reset(); + AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + + m_isUpgradingSingleGraph = false; + + if (m_assetsToUpgrade.empty()) + { + m_ui->upgradeAllButton->setEnabled(false); + } + + m_upgradeComplete = false; + } + + if (!IsUpgrading() && m_state == ProcessState::Upgrade) + { + AZStd::string errorMessage = BackupGraph(*m_inProgressAsset); + // Make the backup + if (errorMessage.empty()) + { + Log("SystemTick::ProcessState::Upgrade: Backup Success %s ", m_inProgressAsset->GetHint().c_str()); QList items = m_ui->tableWidget->findItems(m_inProgressAsset->GetHint().c_str(), Qt::MatchFlag::MatchExactly); if (!items.isEmpty()) { @@ -159,12 +256,13 @@ namespace ScriptCanvasEditor } else { - GraphUpgradeComplete(*m_inProgressAsset, result); + Log("SystemTick::ProcessState::Upgrade: Backup Failed %s ", m_inProgressAsset->GetHint().c_str()); + GraphUpgradeComplete(*m_inProgressAsset, OperationResult::Failure, errorMessage); } } break; - + } default: break; } @@ -179,20 +277,28 @@ namespace ScriptCanvasEditor void VersionExplorer::OnUpgradeAll() { - AZ::Interface::Get()->SetIsUpgrading(true); - m_state = ProcessState::Upgrade; + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + AZ::Interface::Get()->SetIsUpgrading(true); + AZ::Interface::Get()->ClearGraphsThatNeedUpgrade(); m_inProgressAsset = m_assetsToUpgrade.begin(); - + AZ::Debug::TraceMessageBus::Handler::BusConnect(); AZ::SystemTickBus::Handler::BusConnect(); + m_ui->progressBar->setVisible(true); + m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToUpgrade.size())); + m_ui->progressBar->setValue(m_upgradeAssetIndex); + m_keepEditorAlive = AZStd::make_unique(); } - VersionExplorer::OperationResult VersionExplorer::BackupGraph(const AZ::Data::Asset& asset) + AZStd::string VersionExplorer::BackupGraph(const AZ::Data::Asset& asset) { - bool makeBackup = m_ui->makeBackupCheckbox->isChecked(); - if (!makeBackup) + if (!m_ui->makeBackupCheckbox->isChecked()) { - return OperationResult::SkipBackup; + // considered a success + return ""; } QDateTime theTime = QDateTime::currentDateTime(); @@ -207,8 +313,8 @@ namespace ScriptCanvasEditor { if (AZ::IO::FileIOBase::GetInstance()->CreatePath(backupPath.c_str()) != AZ::IO::ResultCode::Success) { - AZ_Error("Script Canvas", false, "Failed to create backup folder %s", backupPath.c_str()); - return OperationResult::BackupFail_CreateFolder; + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Failed to create backup folder %s", backupPath.c_str()); + return "Failed to create backup folder"; } } @@ -243,8 +349,8 @@ namespace ScriptCanvasEditor } else { - // The file no longer exists, we'll need to skip it. - return OperationResult::BackupFail_FileNotFound; + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorer::BackupGraph: Failed to find file: %s", asset.GetHint().c_str()); + return "Failed to find source file"; } devRoot = devRootCStr; @@ -257,289 +363,290 @@ namespace ScriptCanvasEditor relativePath = relativePath.substr(1, relativePath.size() - 1); } - AZStd::string targetFilePath; - AzFramework::StringFunc::Path::Join(backupPath.c_str(), relativePath.c_str(), targetFilePath); + AzFramework::StringFunc::Path::Normalize(relativePath); + AzFramework::StringFunc::Path::Normalize(backupPath); - if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Error) + AZStd::string targetFilePath = backupPath; + targetFilePath += relativePath; + + if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Success) { - AZ_TracePrintf("Script Canvas", "Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - } - else - { - AZ_TracePrintf("Script Canvas", "Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); - return OperationResult::BackupFail; + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "VersionExplorer::BackupGraph: Error creating backup: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return "Failed to copy source file to backup location"; } - return OperationResult::BackupSuccess; - } - - // Upgrade - - template - AZ::Entity* UpgradeGraphProcess(const AZ::Data::Asset& asset, VersionExplorer* /*versionExplorer*/) - { - AssetType* scriptCanvasAsset = asset.GetAs(); - AZ_Assert(scriptCanvasAsset, "Unable to get the asset of type: %s", azrtti_typeid().template ToString().c_str()); - - if (!scriptCanvasAsset) - { - return nullptr; - } - - AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); - AZ_Assert(scriptCanvasEntity, "The Script Canvas asset must have a valid entity"); - if (!scriptCanvasEntity) - { - return nullptr; - } - - - 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(); - } - - auto graphComponent = scriptCanvasEntity->FindComponent(); - AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); - - if (graphComponent) - { - graphComponent->UpgradeGraph(asset); - } - - return scriptCanvasEntity; + Log("VersionExplorer::BackupGraph: Backed up: %s ---> %s\n", sourceFilePath.c_str(), targetFilePath.c_str()); + return ""; } void VersionExplorer::UpgradeGraph(const AZ::Data::Asset& asset) { m_inProgress = true; - + m_upgradeComplete = false; + Log("UpgradeGraph %s ", m_inProgressAsset->GetHint().c_str()); m_ui->spinner->SetText(QObject::tr("Upgrading: %1").arg(asset.GetHint().c_str())); - - AZ::Debug::TraceMessageBus::Handler::BusConnect(); + m_scriptCanvasEntity = nullptr; UpgradeNotifications::Bus::Handler::BusConnect(); if (asset.GetType() == azrtti_typeid()) { - m_scriptCanvasEntity = UpgradeGraphProcess(asset, this); + ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs(); + AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s" + , azrtti_typeid().template ToString().c_str()); + + if (!scriptCanvasAsset) + { + return; + } + + AZ::Entity* scriptCanvasEntity = scriptCanvasAsset->GetScriptCanvasEntity(); + AZ_Assert(scriptCanvasEntity, "VersionExplorer::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(); + AZ_Assert(graphComponent, "The Script Canvas entity must have a Graph component"); + + if (graphComponent) + { + m_scriptCanvasEntity = scriptCanvasEntity; + + graphComponent->UpgradeGraph + ( asset + , m_ui->forceUpgrade->isChecked() ? Graph::UpgradeRequest::Forced : Graph::UpgradeRequest::IfOutOfDate + , m_ui->verbose->isChecked()); + } } - if (!m_scriptCanvasEntity) - { - AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); - return; - } + AZ_Assert(m_scriptCanvasEntity, "The ScriptCanvas asset should have an entity"); } void VersionExplorer::OnGraphUpgradeComplete(AZ::Data::Asset& asset, bool /*skipped*/ /*= false*/) { 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); + if (!fullPathFound) + { + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Full source path not found for %s", relativePath.c_str()); + } + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(fullPath); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + this->OnSourceFileReleased(asset); + }); + streamer->QueueRequest(flushRequest); + } + + void VersionExplorer::OnSourceFileReleased(AZ::Data::Asset asset) + { + 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_tmpFileName.clear(); AZStd::string tmpFileName; - bool tmpFilesaved = false; - // 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. - if (AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) + if (!AZ::IO::CreateTempFileName(fullPath.c_str(), tmpFileName)) { - AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); + GraphUpgradeComplete(asset, OperationResult::Failure, "Failure to create temporary file name"); + return; + } - if (fileStream.IsOpen()) + bool tempSavedSucceeded = false; + AZ::IO::FileIOStream fileStream(tmpFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeText); + if (fileStream.IsOpen()) + { + if (asset.GetType() == azrtti_typeid()) { - if (asset.GetType() == azrtti_typeid()) - { - tmpFilesaved = AZ::Utils::SaveObjectToStream(fileStream, AZ::DataStream::ST_XML, &asset.GetAs()->GetScriptCanvasData()); - } - - fileStream.Close(); + ScriptCanvasEditor::ScriptCanvasAssetHandler handler; + tempSavedSucceeded = handler.SaveAssetData(asset, &fileStream); } - using SCCommandBus = AzToolsFramework::SourceControlCommandBus; - SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, - [this, &asset, fullPath, tmpFileName, tmpFilesaved](bool /*success*/, const AzToolsFramework::SourceControlFileInfo& info) - { - if (!info.IsReadOnly()) - { - if (tmpFilesaved) - { - PerformMove(asset, tmpFileName, fullPath); - } - } - else - { - if (m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - - if (tmpFilesaved) - { - PerformMove(asset, tmpFileName, fullPath); - } - } - else - { - int result = QMessageBox::No; - if (!m_overwriteAll) - { - QMessageBox mb(QMessageBox::Warning, - QObject::tr("Failed to Save Upgraded File"), - QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), - QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); - - result = mb.exec(); - if (result == QMessageBox::YesToAll) - { - m_overwriteAll = true; - } - } - - if (result == QMessageBox::Yes || m_overwriteAll) - { - AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); - - if (tmpFilesaved) - { - PerformMove(asset, tmpFileName, fullPath); - } - } - - } - } - //if (!info.IsReadOnly()) - //{ - // if (tmpFilesaved) - // { - // auto normTarget = fullPath; - // AzFramework::StringFunc::Path::Normalize(normTarget); - - // auto moveResult = AZ::IO::SmartMove(tmpFileName.c_str(), normTarget.c_str()); - // if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - // { - // // Bump the slice asset up in the asset processor's queue. - // AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, fullPath.c_str()); - - // AZ::SystemTickBus::QueueFunction([this, asset]() { GraphUpgradeComplete(asset); }); - // } - // else - // { - // AZ::SystemTickBus::QueueFunction([this, asset, tmpFileName, fullPath]() { RetryMove(asset, tmpFileName, fullPath); }); - // } - - // } - //} - //else - //{ - // QWidget* mainWindow = nullptr; - // AzToolsFramework::EditorRequests::Bus::BroadcastResult(mainWindow, &AzToolsFramework::EditorRequests::GetMainWindow); - // QMessageBox::warning(mainWindow, QObject::tr("Unable to Modify Script Canvas asset"), - // QObject::tr("File is not writable."), QMessageBox::Ok, QMessageBox::Ok); - //} - }); + fileStream.Close(); } + + // attempt to remove temporary file no matter what + m_tmpFileName = tmpFileName; + if (!tempSavedSucceeded) + { + GraphUpgradeComplete(asset, OperationResult::Failure, "Save asset data to temporary file failed"); + return; + } + + using SCCommandBus = AzToolsFramework::SourceControlCommandBus; + SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullPath.c_str(), true, + [this, asset, fullPath, tmpFileName]([[maybe_unused]] bool success, const AzToolsFramework::SourceControlFileInfo& info) + { + constexpr const size_t k_maxAttemps = 10; + + if (!info.IsReadOnly()) + { + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + else + { + if (m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + else + { + int result = QMessageBox::No; + if (!m_overwriteAll) + { + QMessageBox mb(QMessageBox::Warning, + QObject::tr("Failed to Save Upgraded File"), + QObject::tr("The upgraded file could not be saved because the file is read only.\nDo you want to make it writeable and overwrite it?"), + QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No, this); + + result = mb.exec(); + if (result == QMessageBox::YesToAll) + { + m_overwriteAll = true; + } + } + + if (result == QMessageBox::Yes || m_overwriteAll) + { + AZ::IO::SystemFile::SetWritable(info.m_filePath.c_str(), true); + PerformMove(asset, tmpFileName, fullPath, k_maxAttemps); + } + } + } + }); } - void VersionExplorer::PerformMove(AZ::Data::Asset& asset, const AZStd::string& source, const AZStd::string& target) + void VersionExplorer::PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target + , size_t remainingAttempts) { - auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); - if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - { - // Bump the slice asset up in the asset processor's queue. - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); + VersionExplorerCpp::FileEventHandler fileEventHandler; - AZ::SystemTickBus::QueueFunction([this, asset]() { GraphUpgradeComplete(asset); }); + if (remainingAttempts == 0) + { + // all attempts failed, give up + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s. giving up", target.c_str()); + GraphUpgradeComplete(asset, OperationResult::Failure, "Failed to move updated file from backup to source destination"); + } + else if (remainingAttempts == 2) + { + // before the final attempt, flush all caches + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCaches(); + streamer->SetRequestCompleteCallback(flushRequest + , [this, asset, remainingAttempts, source, target]([[maybe_unused]] AZ::IO::FileRequestHandle request) + { + // Continue saving. + AZ::SystemTickBus::QueueFunction( + [this, asset, remainingAttempts, source, target](){ PerformMove(asset, source, target, remainingAttempts - 1); }); + }); + streamer->QueueRequest(flushRequest); } else { - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - streamer->SetRequestCompleteCallback(flushRequest, [this, &asset, &source, &target]([[maybe_unused]] AZ::IO::FileRequestHandle request) + // the actual move attempt + auto moveResult = AZ::IO::SmartMove(source.c_str(), target.c_str()); + if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) + { + m_tmpFileName.clear(); + auto streamer = AZ::Interface::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()); + AZ::SystemTickBus::QueueFunction([this, asset]() + { + GraphUpgradeComplete(asset, OperationResult::Success, ""); + }); + } + else + { + AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "moving converted file to source destination failed: %s, trying again", target.c_str()); + auto streamer = AZ::Interface::Get(); + AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); + streamer->SetRequestCompleteCallback(flushRequest, [this, asset, source, target, remainingAttempts]([[maybe_unused]] AZ::IO::FileRequestHandle request) { // Continue saving. - AZ::SystemTickBus::QueueFunction([this, asset, source, target]() { RetryMove(asset, source, target); }); + AZ::SystemTickBus::QueueFunction([this, asset, source, target, remainingAttempts]() { PerformMove(asset, source, target, remainingAttempts - 1); }); }); - streamer->QueueRequest(flushRequest); - - } + streamer->QueueRequest(flushRequest); + } + } } - void VersionExplorer::GraphUpgradeComplete(const AZ::Data::Asset& asset, OperationResult result /*= OperationResult::Success*/) + void VersionExplorer::GraphUpgradeComplete + ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) { - m_inProgress = false; + AZStd::lock_guard lock(m_mutex); + m_upgradeComplete = true; + m_upgradeResult = result; + m_upgradeMessage = message; + m_upgradeAsset = asset; - if (m_scriptCanvasEntity) + if (!m_tmpFileName.empty()) { - m_scriptCanvasEntity->Deactivate(); - m_scriptCanvasEntity = nullptr; - } + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIO, "GraphUpgradeComplete: No FileIO instance"); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - - GraphUpgradeCompleteUIUpdate(asset, result); - - if (!m_isUpgradingSingleGraph) - { - if (m_inProgressAsset != m_assetsToUpgrade.end()) + if (fileIO->Exists(m_tmpFileName.c_str()) && !fileIO->Remove(m_tmpFileName.c_str())) { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - } - - if (m_inProgressAsset == m_assetsToUpgrade.end()) - { - FinalizeUpgrade(); + AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Failed to remove temporary file: %s", m_tmpFileName.c_str()); } } - else - { - m_inProgressAsset = m_assetsToUpgrade.erase(m_inProgressAsset); - m_inProgress = false; - m_state = ProcessState::Inactive; - AZ::SystemTickBus::Handler::BusDisconnect(); + if (m_upgradeResult == OperationResult::Failure) + { + AZ::Interface::Get()->GraphNeedsManualUpgrade(asset.GetId()); } - m_isUpgradingSingleGraph = false; - - if (m_assetsToUpgrade.empty()) - { - m_ui->upgradeAllButton->setEnabled(false); - } + m_tmpFileName.clear(); } - void VersionExplorer::GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset& asset, OperationResult result /*= OperationResult::Success*/) + void VersionExplorer::GraphUpgradeCompleteUIUpdate + ( const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message) { QString text = asset.GetHint().c_str(); QList items = m_ui->tableWidget->findItems(text, Qt::MatchFlag::MatchExactly); + if (!items.isEmpty()) { for (auto* item : items) { int row = item->row(); - QTableWidgetItem* label = m_ui->tableWidget->item(row, ColumnAsset); - QString assetName = asset.GetHint().c_str(); + if (label->text().compare(assetName) == 0) { m_ui->tableWidget->removeCellWidget(row, ColumnAction); @@ -554,33 +661,24 @@ namespace ScriptCanvasEditor else { doneButton->setIcon(QIcon(":/stylesheet/img/UI20/titlebar-close.svg")); - if (result == OperationResult::BackupFail_FileNotFound) - { - doneButton->setToolTip("The file no longer exists"); - } - else if (result == OperationResult::BackupFail_CreateFolder) - { - doneButton->setToolTip("Failed to create the backup folder"); - } - + doneButton->setToolTip(message.data()); } m_ui->tableWidget->setCellWidget(row, ColumnStatus, doneButton); } - - } } } void VersionExplorer::FinalizeUpgrade() { + Log("FinalizeUpgrade!"); m_inProgress = false; m_assetsToUpgrade.clear(); - m_ui->upgradeAllButton->setEnabled(false); m_ui->onlyShowOutdated->setEnabled(true); - + m_keepEditorAlive.reset(); + m_ui->progressBar->setVisible(false); // Manual correction size_t assetsThatNeedManualInspection = AZ::Interface::Get()->GetGraphsThatNeedManualUpgrade().size(); @@ -588,12 +686,16 @@ namespace ScriptCanvasEditor { m_ui->spinner->SetText("Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog"); } + else + { + m_ui->spinner->SetText("Upgrade complete."); + } AZ::SystemTickBus::Handler::BusDisconnect(); AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); UpgradeNotifications::Bus::Handler::BusDisconnect(); - AZ::Interface::Get()->SetIsUpgrading(false); + m_settingsCache.reset(); } // Scanning @@ -604,6 +706,7 @@ namespace ScriptCanvasEditor m_assetsToInspect.clear(); m_ui->tableWidget->setRowCount(0); m_inspectedAssets = 0; + m_currentAssetRowIndex = 0; IUpgradeRequests* upgradeRequests = AZ::Interface::Get(); m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade(); DoScan(); @@ -611,9 +714,13 @@ namespace ScriptCanvasEditor void VersionExplorer::DoScan() { - AZ::SystemTickBus::Handler::BusConnect(); - m_state = ProcessState::Scan; + m_settingsCache = AZStd::make_unique(); + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + ScriptCanvas::Grammar::g_printAbstractCodeModel = false; + ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false; + + AZ::SystemTickBus::Handler::BusConnect(); AZ::Debug::TraceMessageBus::Handler::BusConnect(); if (!m_assetsToInspect.empty()) @@ -621,8 +728,9 @@ namespace ScriptCanvasEditor m_discoveredAssets = m_assetsToInspect.size(); m_failedAssets = 0; m_inspectedAssets = 0; - + m_currentAssetRowIndex = 0; m_ui->progressFrame->setVisible(true); + m_ui->progressBar->setVisible(true); m_ui->progressBar->setRange(0, aznumeric_cast(m_assetsToInspect.size())); m_ui->progressBar->setValue(0); @@ -634,21 +742,20 @@ namespace ScriptCanvasEditor m_ui->onlyShowOutdated->setEnabled(false); m_inspectingAsset = m_assetsToInspect.begin(); + m_keepEditorAlive = AZStd::make_unique(); } } void VersionExplorer::BackupComplete() { - m_currentAssetIndex = 0; + m_currentAssetRowIndex = 0; m_ui->progressBar->setValue(0); - DoScan(); } void VersionExplorer::InspectAsset(AZ::Data::Asset& asset, AZ::Data::AssetInfo& assetInfo) { Log("InspectAsset: %s", asset.GetHint().c_str()); - AZ::Entity* scriptCanvasEntity = nullptr; if (asset.GetType() == azrtti_typeid()) { @@ -668,18 +775,19 @@ namespace ScriptCanvasEditor bool onlyShowOutdatedGraphs = m_ui->onlyShowOutdated->isChecked(); bool forceUpgrade = m_ui->forceUpgrade->isChecked(); + ScriptCanvas::VersionData graphVersion = graphComponent->GetVersion(); - if (!forceUpgrade && onlyShowOutdatedGraphs && graphComponent->GetVersion().IsLatest()) + + if (!forceUpgrade && onlyShowOutdatedGraphs && graphVersion.IsLatest()) { - ++m_currentAssetIndex; ScanComplete(asset); Log("InspectAsset: %s, is at latest", asset.GetHint().c_str()); return; } - m_ui->tableWidget->insertRow(static_cast(m_inspectedAssets)); + m_ui->tableWidget->insertRow(static_cast(m_currentAssetRowIndex)); QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str())); - m_ui->tableWidget->setItem(static_cast(m_inspectedAssets), static_cast(ColumnAsset), rowName); + m_ui->tableWidget->setItem(static_cast(m_currentAssetRowIndex), static_cast(ColumnAsset), rowName); if (forceUpgrade || !graphComponent->GetVersion().IsLatest()) { @@ -703,14 +811,10 @@ namespace ScriptCanvasEditor }); - m_ui->tableWidget->setCellWidget(static_cast(m_inspectedAssets), static_cast(ColumnAction), rowGoToButton); - m_ui->tableWidget->setCellWidget(static_cast(m_inspectedAssets), static_cast(ColumnStatus), spinner); + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnAction), rowGoToButton); + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnStatus), spinner); } - QToolButton* browseButton = new QToolButton(this); - browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); - browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); - char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; AZStd::string path = AZStd::string::format("@devroot@/%s", asset.GetHint().c_str()); AZ::IO::FileIOBase::GetInstance()->ResolvePath(path.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); @@ -722,22 +826,22 @@ namespace ScriptCanvasEditor AZStd::string watchFolder; QByteArray assetNameUtf8 = asset.GetHint().c_str(); AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, assetNameUtf8, info, watchFolder); - if (!result) - { - AZ_Error("AssetProvider", false, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); - } + + AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), result, "Failed to locate asset info for '%s'.", assetNameUtf8.constData()); + + QToolButton* browseButton = new QToolButton(this); + browseButton->setToolTip(AzQtComponents::fileBrowserActionName()); + browseButton->setIcon(QIcon(":/stylesheet/img/UI20/browse-edit.svg")); QString absolutePath = QDir(watchFolder.c_str()).absoluteFilePath(info.m_relativePath.c_str()); - connect(browseButton, &QPushButton::clicked, [absolutePath] { AzQtComponents::ShowFileOnDesktop(absolutePath); }); - m_ui->tableWidget->setCellWidget(static_cast(m_inspectedAssets), static_cast(ColumnBrowse), browseButton); - - ++m_inspectedAssets; - ++m_currentAssetIndex; + m_ui->tableWidget->setCellWidget(static_cast(m_currentAssetRowIndex), static_cast(ColumnBrowse), browseButton); ScanComplete(asset); + ++m_inspectedAssets; + ++m_currentAssetRowIndex; } void VersionExplorer::UpgradeSingle @@ -752,7 +856,7 @@ namespace ScriptCanvasEditor { asset.BlockUntilLoadComplete(); - if (!asset.IsReady()) + if (asset.IsReady()) { AZ::Interface::Get()->SetIsUpgrading(true); m_isUpgradingSingleGraph = true; @@ -777,7 +881,7 @@ namespace ScriptCanvasEditor { Log("ScanComplete: %s", asset.GetHint().c_str()); m_inProgress = false; - m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetIndex)); + m_ui->progressBar->setValue(aznumeric_cast(m_currentAssetRowIndex)); m_ui->scanButton->setEnabled(true); m_inspectingAsset = m_assetsToInspect.erase(m_inspectingAsset); @@ -818,8 +922,8 @@ namespace ScriptCanvasEditor } else { - spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu" - , m_discoveredAssets, m_inspectedAssets, m_failedAssets)); + spinnerText.append(QString::asprintf(" - Discovered: %zu, Inspected: %zu, Failed: %zu, Upgradeable: %zu" + , m_discoveredAssets, m_inspectedAssets, m_failedAssets, m_assetsToUpgrade.size())); } @@ -836,6 +940,7 @@ namespace ScriptCanvasEditor UpgradeNotifications::Bus::Handler::BusDisconnect(); m_keepEditorAlive.reset(); + m_settingsCache.reset(); m_state = ProcessState::Inactive; } @@ -866,8 +971,13 @@ namespace ScriptCanvasEditor } - void VersionExplorer::CaptureLogFromTraceBus(const char* /*window*/, const char* message) + bool VersionExplorer::CaptureLogFromTraceBus(const char* window, const char* message) { + if (m_ui->updateReportingOnly->isChecked() && window != ScriptCanvas::k_VersionExplorerWindow) + { + return true; + } + AZStd::string msg = message; if (msg.ends_with("\n")) { @@ -875,64 +985,30 @@ namespace ScriptCanvasEditor } m_logs.push_back(msg); + return m_ui->updateReportingOnly->isChecked(); } bool VersionExplorer::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) { AZStd::string msg = AZStd::string::format("(Error): %s", message); - CaptureLogFromTraceBus(window, msg.c_str()); - - return false; + return CaptureLogFromTraceBus(window, msg.c_str()); } bool VersionExplorer::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) { AZStd::string msg = AZStd::string::format("(Warning): %s", message); - CaptureLogFromTraceBus(window, msg.c_str()); - - return false; + return CaptureLogFromTraceBus(window, msg.c_str()); } bool VersionExplorer::OnException(const char* message) { AZStd::string msg = AZStd::string::format("(Exception): %s", message); - CaptureLogFromTraceBus("Script Canvas", msg.c_str()); - - return false; + return CaptureLogFromTraceBus("Script Canvas", msg.c_str()); } bool VersionExplorer::OnPrintf(const char* window, const char* message) { - CaptureLogFromTraceBus(window, message); - return false; - } - - void VersionExplorer::RetryMove(const AZ::Data::Asset& asset, const AZStd::string& source, const AZStd::string& target) - { - auto normTarget = target; - AzFramework::StringFunc::Path::Normalize(normTarget); - auto moveResult = AZ::IO::SmartMove(source.c_str(), normTarget.c_str()); - if (moveResult.GetResultCode() == AZ::IO::ResultCode::Success) - { - // Bump the slice asset up in the asset processor's queue. - AzFramework::AssetSystemRequestBus::Broadcast(&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetBySearchTerm, target.c_str()); - - AZ::SystemTickBus::QueueFunction([this, asset]() { GraphUpgradeComplete(asset); }); - } - else - { - auto streamer = AZ::Interface::Get(); - AZ::IO::FileRequestPtr flushRequest = streamer->FlushCache(target.c_str()); - streamer->SetRequestCompleteCallback(flushRequest, [this, &asset, &source, &target]([[maybe_unused]] AZ::IO::FileRequestHandle request) - { - // Continue saving. - AZ::SystemTickBus::QueueFunction([this, asset, source, target]() { RetryMove(asset, source, target); }); - }); - streamer->QueueRequest(flushRequest); - - - //AZ::SystemTickBus::QueueFunction([this, asset, source, target]() { RetryMove(asset, source, target); }); - } + return CaptureLogFromTraceBus(window, message); } void VersionExplorer::closeEvent(QCloseEvent* event) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h index 266a42e2e6..acb28a7dba 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h @@ -20,11 +20,11 @@ AZ_POP_DISABLE_WARNING #include #include +#include #include #include #include -#include "UpgradeTool.h" #endif class QPushButton; @@ -41,6 +41,19 @@ namespace AzQtComponents namespace ScriptCanvasEditor { + //! Scoped utility to set and restore the "ed_KeepEditorActive" CVar in order to allow + //! the upgrade tool to work even if the editor is not in the foreground + class EditorKeepAlive + { + public: + EditorKeepAlive(); + ~EditorKeepAlive(); + + private: + int m_keepEditorActive; + ICVar* m_edKeepEditorActive; + }; + //! A tool that collects and upgrades all Script Canvas graphs in the asset catalog class VersionExplorer : public AzQtComponents::StyledDialog @@ -71,14 +84,10 @@ namespace ScriptCanvasEditor Inactive, Backup, Scan, - Upgrade + Upgrade, }; ProcessState m_state = ProcessState::Inactive; - bool DoBackup(); - void BackupAsset(const AZ::Data::AssetInfo& assetInfo); - void BackupComplete(); - void DoScan(); void ScanComplete(const AZ::Data::Asset&); @@ -97,24 +106,21 @@ namespace ScriptCanvasEditor bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; // - void CaptureLogFromTraceBus(const char* window, const char* message); + bool CaptureLogFromTraceBus(const char* window, const char* message); enum class OperationResult { Success, - SkipBackup, - BackupSuccess, - BackupFail, - BackupFail_CreateFolder, - BackupFail_FileNotFound + Failure, }; - void GraphUpgradeComplete(const AZ::Data::Asset&, OperationResult result = OperationResult::Success); + void GraphUpgradeComplete(const AZ::Data::Asset, OperationResult result, AZStd::string_view message); bool IsUpgrading() const; bool m_inProgress = false; - size_t m_currentAssetIndex = 0; + // scan fields + size_t m_currentAssetRowIndex = 0; size_t m_inspectedAssets = 0; size_t m_failedAssets = 0; size_t m_discoveredAssets = 0; @@ -129,7 +135,16 @@ namespace ScriptCanvasEditor AZStd::unique_ptr m_ui; + AZStd::unique_ptr m_settingsCache; + + // upgrade fields AZStd::recursive_mutex m_mutex; + bool m_upgradeComplete = false; + AZ::Data::Asset m_upgradeAsset; + int m_upgradeAssetIndex = 0; + OperationResult m_upgradeResult; + AZStd::string m_upgradeMessage; + AZStd::string m_tmpFileName; AZStd::unique_ptr m_keepEditorAlive; @@ -146,18 +161,19 @@ namespace ScriptCanvasEditor void FinalizeUpgrade(); void FinalizeScan(); - OperationResult BackupGraph(const AZ::Data::Asset&); + void BackupComplete(); + AZStd::string BackupGraph(const AZ::Data::Asset&); void UpgradeGraph(const AZ::Data::Asset&); - void RetryMove(const AZ::Data::Asset& asset, const AZStd::string& source, const AZStd::string& target); - - void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset& asset, OperationResult result = OperationResult::Success); + void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset asset, OperationResult result, AZStd::string_view message); void OnGraphUpgradeComplete(AZ::Data::Asset&, bool skipped = false) override; + void OnSourceFileReleased(AZ::Data::Asset asset); + void closeEvent(QCloseEvent* event) override; bool m_overwriteAll = false; - void PerformMove(AZ::Data::Asset& asset, const AZStd::string& source, const AZStd::string& target); + void PerformMove(AZ::Data::Asset asset, AZStd::string source, AZStd::string target, size_t remainingAttempts); void Log(const char* format, ...); }; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.ui b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.ui index 3e2604dd99..0cd67bcf22 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.ui +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.ui @@ -9,8 +9,8 @@ 0 0 - 747 - 687 + 1363 + 770 @@ -261,10 +261,10 @@ 0 - - Qt::ScrollBarAlwaysOn - - + + Qt::ScrollBarAlwaysOn + + true @@ -273,6 +273,16 @@ + + + + Backup before upgrade + + + true + + + @@ -311,36 +321,16 @@ - - + + - Only show outdated graphs + Verbose - true + false - - - - Force Upgrade - - - false - - - - - - - Verbose - - - false - - - @@ -354,16 +344,36 @@ - - + + - Backup before upgrade + Only show outdated graphs true + + + + Force Upgrade + + + false + + + + + + + Update Reporting Only + + + true + + + diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp index 1986eb653e..9b2d0e4982 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.cpp @@ -135,8 +135,19 @@ namespace ScriptCanvas if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) { serializeContext->Class() + ->Version(2, [](AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) + { + if (classElement.GetVersion() < 2) + { + FileVersion fileVersion = ScriptCanvas::FileVersion::Initial; + classElement.AddElementWithData(context, "_fileVersion", fileVersion); + } + + return true; + }) ->Field("_grammarVersion", &VersionData::grammarVersion) ->Field("_runtimeVersion", &VersionData::runtimeVersion) + ->Field("_fileVersion", &VersionData::fileVersion) ; } } @@ -152,6 +163,7 @@ namespace ScriptCanvas { grammarVersion = GrammarVersion::Current; runtimeVersion = RuntimeVersion::Current; + fileVersion = FileVersion::Current; } void ReflectEventTypeOnDemand(const AZ::TypeId& typeId, AZStd::string_view name, AZ::IRttiHelper* rttiHelper) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h index 170e4c5acb..0e64c19dcb 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Core.h @@ -57,6 +57,8 @@ namespace ScriptCanvas constexpr const char* k_OnVariableWriteEventName = "OnVariableValueChanged"; constexpr const char* k_OnVariableWriteEbusName = "VariableNotification"; + constexpr const AZStd::string_view k_VersionExplorerWindow = "VersionExplorerWindow"; + class Node; class Edge; @@ -69,6 +71,13 @@ namespace ScriptCanvas using NodePtrList = AZStd::vector; using NodePtrConstList = AZStd::vector; + enum class PropertyStatus : AZ::u8 + { + Getter, + None, + Setter, + }; + enum class GrammarVersion : int { Initial = -1, @@ -87,11 +96,13 @@ namespace ScriptCanvas Current, }; - enum class PropertyStatus : AZ::u8 + enum class FileVersion : int { - Getter, - None, - Setter, + Initial = -1, + JSON = 0, + + // add new entries above + Current, }; struct VersionData @@ -104,10 +115,13 @@ namespace ScriptCanvas GrammarVersion grammarVersion = GrammarVersion::Initial; RuntimeVersion runtimeVersion = RuntimeVersion::Initial; + FileVersion fileVersion = FileVersion::Initial; bool operator == (const VersionData& rhs) const { - return grammarVersion == rhs.grammarVersion && runtimeVersion == rhs.runtimeVersion; + return grammarVersion == rhs.grammarVersion + && runtimeVersion == rhs.runtimeVersion + && fileVersion == rhs.fileVersion; } bool IsLatest() const diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp index 5a88036a0f..d77789b6e3 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp @@ -33,7 +33,7 @@ namespace SubgraphInterfaceCpp Current }; - const size_t k_maxTabs = 20; + [[maybe_unused]] const size_t k_maxTabs = 20; AZ_INLINE const char* GetTabs(size_t tabs) { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp index e93fd1263d..8d324e95c0 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp @@ -45,7 +45,7 @@ namespace ExecutionInterpretedAPICpp 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, k_Bad,k_Bad,k_Bad,k_Bad,k_Bad,k_Bad,k_Bad, 10, 11, 12, 13, 14, 15 }; - constexpr unsigned char k_FastValuesIndexSentinel = 'G' - '0'; + [[maybe_unused]] constexpr unsigned char k_FastValuesIndexSentinel = 'G' - '0'; template T* GetAs(AZ::BehaviorValueParameter& argument) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp index c1b0d51ac8..5fe5c32a48 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp @@ -116,7 +116,7 @@ namespace ScriptCanvas return; } #else - AZ_Assert(m_runtimeAsset.Get(), "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); + AZ_Assert(m_runtimeOverrides.m_runtimeAsset.Get(), "RuntimeComponent::m_runtimeAsset AssetId: %s was valid, but the data was not pre-loaded, so this script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); #endif AZ_PROFILE_SCOPE(ScriptCanvas, "RuntimeComponent::InitializeExecution (%s)", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().c_str()); @@ -130,7 +130,7 @@ namespace ScriptCanvas return; } #else - AZ_Assert(m_executionState, "RuntimeComponent::m_runtimeAsset AssetId: %s failed to create an execution state, possibly due to missing dependent asset, script will not run", m_runtimeAsset.GetId().ToString().data()); + AZ_Assert(m_executionState, "RuntimeComponent::m_runtimeAsset AssetId: %s failed to create an execution state, possibly due to missing dependent asset, script will not run", m_runtimeOverrides.m_runtimeAsset.GetId().ToString().data()); #endif AZ::EntityBus::Handler::BusConnect(GetEntityId()); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.cpp index 4878dfdc6c..14f7a926b1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.cpp @@ -17,5 +17,23 @@ namespace ScriptCanvas AZ_CVAR(bool, g_printAbstractCodeModelAtPrefabTime, false, {}, AZ::ConsoleFunctorFlags::Null, "Print out the Abstract Code Model at the end of parsing (at prefab time) for debug purposes."); AZ_CVAR(bool, g_saveRawTranslationOuputToFile, true, {}, AZ::ConsoleFunctorFlags::Null, "Save out the raw result of translation for debug purposes."); AZ_CVAR(bool, g_saveRawTranslationOuputToFileAtPrefabTime, false, {}, AZ::ConsoleFunctorFlags::Null, "Save out the raw result of translation (at prefab time) for debug purposes."); + + SettingsCache::SettingsCache() + { + m_disableParseOnGraphValidation = g_disableParseOnGraphValidation; + m_printAbstractCodeModel = g_printAbstractCodeModel; + m_printAbstractCodeModelAtPrefabTime = g_printAbstractCodeModelAtPrefabTime; + m_saveRawTranslationOuputToFile = g_saveRawTranslationOuputToFile; + m_saveRawTranslationOuputToFileAtPrefabTime = g_saveRawTranslationOuputToFileAtPrefabTime; + } + + SettingsCache::~SettingsCache() + { + g_disableParseOnGraphValidation = m_disableParseOnGraphValidation; + g_printAbstractCodeModel = m_printAbstractCodeModel; + g_printAbstractCodeModelAtPrefabTime = m_printAbstractCodeModelAtPrefabTime; + g_saveRawTranslationOuputToFile = m_saveRawTranslationOuputToFile; + g_saveRawTranslationOuputToFileAtPrefabTime = m_saveRawTranslationOuputToFileAtPrefabTime; + } } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h index 16befe79b0..a6ce31d6e7 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h @@ -248,6 +248,22 @@ namespace ScriptCanvas AZ_CVAR_EXTERNED(bool, g_saveRawTranslationOuputToFile); AZ_CVAR_EXTERNED(bool, g_saveRawTranslationOuputToFileAtPrefabTime); + class SettingsCache + { + public: + AZ_CLASS_ALLOCATOR(SettingsCache, AZ::SystemAllocator, 0); + + SettingsCache(); + ~SettingsCache(); + + private: + bool m_disableParseOnGraphValidation; + bool m_printAbstractCodeModel; + bool m_printAbstractCodeModelAtPrefabTime; + bool m_saveRawTranslationOuputToFile; + bool m_saveRawTranslationOuputToFileAtPrefabTime; + }; + struct DependencyInfo { AZ::Data::AssetId assetId; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp index ef73bb967d..4e2d740656 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp @@ -78,6 +78,8 @@ namespace ScriptCanvas variableIds.insert(scopedVariableId->m_identifier); } } + + Node::CollectVariableReferences(variableIds); } bool EBusEventHandler::ContainsReferencesToVariables(const AZStd::unordered_set< ScriptCanvas::VariableId >& variableIds) const @@ -90,11 +92,14 @@ namespace ScriptCanvas if (scopedVariableId) { - return variableIds.find(scopedVariableId->m_identifier) != variableIds.end(); + if(variableIds.find(scopedVariableId->m_identifier) != variableIds.end()) + { + return true; + } } } - return false; + return Node::ContainsReferencesToVariables(variableIds); } size_t EBusEventHandler::GenerateFingerprint() const diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp index eb1ee501a9..793224fd86 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp @@ -681,6 +681,13 @@ namespace ScriptCanvas outType = eventType; return true; } + + AZ_Warning("Script Canvas" + , !m_warnOnMissingFunction + , "Could not find event: %s, in bus: %s, anywhere in BehaviorContext" + , methodName.c_str() + , m_className.c_str()); + return false; } break; @@ -693,6 +700,12 @@ namespace ScriptCanvas outType = EventType::Count; return true; } + + AZ_Warning("Script Canvas" + , !m_warnOnMissingFunction + , "Could not find free method: %s anywhere in BehaviorContext" + , methodName.c_str()); + return false; } break; @@ -709,15 +722,27 @@ namespace ScriptCanvas outType = EventType::Count; return true; } + + AZ_Warning("Script Canvas" + , !m_warnOnMissingFunction + , "Could not find method or property: %s in class %s: , anywhere in BehaviorContext" + , methodName.c_str() + , m_className.c_str()); + return false; } break; - default: - AZ_Warning("Script Canvas", !m_warnOnMissingFunction, "unsupported method type in method"); + default: break; } } + AZ_Warning("Script Canvas" + , !m_warnOnMissingFunction + , "Could not find overloaded method: %s, class or event name: %s, anywhere in BehaviorContext" + , methodName.c_str() + , m_className.c_str()); + return false; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp index b874077834..5a2eb80187 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp @@ -353,7 +353,7 @@ namespace ScriptCanvas AZStd::optional ReceiveScriptEvent::GetEventIndex(AZStd::string eventName) const { - return m_handler->GetFunctionIndex(eventName.c_str());; + return m_handler ? AZStd::optional(m_handler->GetFunctionIndex(eventName.c_str())) : AZStd::nullopt; } AZStd::vector ReceiveScriptEvent::GetEventSlotIds() const @@ -556,29 +556,6 @@ namespace ScriptCanvas return true; } - bool ReceiveScriptEvent::SetupHandler() - { - if (!m_handler) - { - if (!m_asset.IsReady() && m_scriptEventAssetId.IsValid()) - { - m_asset = AZ::Data::AssetManager::Instance().GetAsset(m_scriptEventAssetId, AZ::Data::AssetLoadBehavior::PreLoad); - m_asset.BlockUntilLoadComplete(); - CreateHandler(m_asset); - CreateEbus(); - } - - if (!m_handler) - { - AZStd::string error = AZStd::string::format("Script Event receiver node was not initialized (%s)!", m_definition.GetName().c_str()); - SCRIPTCANVAS_REPORT_ERROR((*this), error.c_str()); - return false; - } - } - - return true; - } - bool ReceiveScriptEvent::IsOutOfDate(const VersionData& graphVersion) const { AZ_UNUSED(graphVersion); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h index f2bdd98b2b..0f8d673629 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h @@ -88,7 +88,6 @@ namespace ScriptCanvas private: bool CreateEbus(); - bool SetupHandler(); AZ::BehaviorEBusHandler* m_handler = nullptr; AZ::BehaviorEBus* m_ebus = nullptr; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp index 37d6e2c35f..37fd3b14d6 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Serialization/DatumSerializer.cpp @@ -125,7 +125,7 @@ namespace AZ { listeners->push_back(outputDatum); } - + return context.Report(result, result.GetProcessing() != JSR::Processing::Halted ? "DatumSerializer Load finished loading Datum" : "DatumSerializer Load failed to load Datum"); @@ -145,13 +145,13 @@ namespace AZ auto inputScriptDataPtr = reinterpret_cast(inputValue); auto defaultScriptDataPtr = reinterpret_cast(defaultValue); - + if (defaultScriptDataPtr) { if (*inputScriptDataPtr == *defaultScriptDataPtr) { return context.Report - ( JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "DatumSerializer Store used defaults for Datum"); + (JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "DatumSerializer Store used defaults for Datum"); } } diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake index 1b9f07594a..52b1cc4772 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_editor_files.cmake @@ -21,6 +21,8 @@ set(FILES Editor/Assets/ScriptCanvasAssetHelpers.h Editor/Assets/ScriptCanvasAssetHelpers.cpp Editor/Assets/ScriptCanvasAssetTrackerDefinitions.h + Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.h + Editor/Include/ScriptCanvas/Assets/ScriptCanvasBaseAssetData.cpp Editor/Include/ScriptCanvas/Assets/ScriptCanvasAsset.h Editor/Assets/ScriptCanvasAsset.cpp Editor/Include/ScriptCanvas/Assets/ScriptCanvasAssetBus.h diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_SimultaneousDataInputError.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_SimultaneousDataInputError.scriptcanvas deleted file mode 100644 index b4f2ad14fa..0000000000 --- a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_SimultaneousDataInputError.scriptcanvas +++ /dev/null @@ -1,1396 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_SimultaneousDataInputErrorSource.scriptcanvas_fn b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_SimultaneousDataInputErrorSource.scriptcanvas_fn deleted file mode 100644 index 145019ed18..0000000000 --- a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_SimultaneousDataInputErrorSource.scriptcanvas_fn +++ /dev/null @@ -1,1331 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt index 29360912d8..499bb84c2d 100644 --- a/Gems/ScriptCanvasTesting/Code/CMakeLists.txt +++ b/Gems/ScriptCanvasTesting/Code/CMakeLists.txt @@ -77,6 +77,7 @@ ly_add_target( # By default, the above module is used only in tools: ly_create_alias(NAME ScriptCanvasTesting.Tools NAMESPACE Gem TARGETS Gem::ScriptCanvasTesting.Editor) +ly_create_alias(NAME ScriptCanvasTesting.Builders NAMESPACE Gem TARGETS Gem::ScriptCanvasTesting.Editor) ################################################################################ # Tests diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp index c2fa59b037..00705bfbaa 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp @@ -367,11 +367,6 @@ TEST_F(ScriptCanvasTestFixture, InterpretedMultipleOutDataFlowParseError) ExpectParseError("LY_SC_UnitTest_MultipleOutDataFlowParseError"); } -TEST_F(ScriptCanvasTestFixture, InterpretedSimultaneousDataInputError) -{ - ExpectParseError("LY_SC_UnitTest_SimultaneousDataInputError"); -} - TEST_F(ScriptCanvasTestFixture, InterpretedAnyAsTailNoOp) { RunUnitTestGraph("LY_SC_UnitTest_AnyAsTailNoOp"); diff --git a/Gems/ScriptEvents/Code/Builder/ScriptEventsBuilderWorker.cpp b/Gems/ScriptEvents/Code/Builder/ScriptEventsBuilderWorker.cpp index bc9ed886ea..caf3d3c42c 100644 --- a/Gems/ScriptEvents/Code/Builder/ScriptEventsBuilderWorker.cpp +++ b/Gems/ScriptEvents/Code/Builder/ScriptEventsBuilderWorker.cpp @@ -27,7 +27,7 @@ namespace ScriptEventsBuilder { - static const char* s_scriptEventsBuilder = "ScriptEventsBuilder"; + [[maybe_unused]] static const char* s_scriptEventsBuilder = "ScriptEventsBuilder"; Worker::Worker() { diff --git a/Gems/Terrain/Assets/Shaders/Terrain/Terrain.azsl b/Gems/Terrain/Assets/Shaders/Terrain/Terrain.azsl index 57d0909ae4..50d11ca610 100644 --- a/Gems/Terrain/Assets/Shaders/Terrain/Terrain.azsl +++ b/Gems/Terrain/Assets/Shaders/Terrain/Terrain.azsl @@ -6,120 +6,90 @@ */ #include +#include #include - - -struct VertexInput -{ - float2 Position : POSITION; - float2 UV : UV; -}; +#include "TerrainCommon.azsli" struct VertexOutput { - float4 Position : SV_Position; - float3 Normal : NORMAL; - float2 UV : UV; + linear centroid float4 m_position : SV_Position; + float3 m_normal : NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float m_height : UV; }; -ShaderResourceGroup ObjectSrg : SRG_PerObject +struct ForwardPassOutput { - Texture2D HeightmapImage; - - Sampler LinearSampler - { - MinFilter = Linear; - MagFilter = Linear; - MipFilter = Linear; - AddressU = Clamp; - AddressV = Clamp; - AddressW = Clamp; - }; - - row_major float3x4 m_modelToWorld; - float m_heightScale; - float2 m_uvMin; - float2 m_uvMax; - float2 m_uvStep; -} - -float4x4 GetObject_WorldMatrix() -{ - float4x4 modelToWorld = float4x4( - float4(1, 0, 0, 0), - float4(0, 1, 0, 0), - float4(0, 0, 1, 0), - float4(0, 0, 0, 1)); - - modelToWorld[0] = ObjectSrg::m_modelToWorld[0]; - modelToWorld[1] = ObjectSrg::m_modelToWorld[1]; - modelToWorld[2] = ObjectSrg::m_modelToWorld[2]; - return modelToWorld; -} - -float GetHeight(float2 origUv) -{ - float2 uv = clamp(origUv, 0.0f, 1.0f); - return ObjectSrg::m_heightScale * (ObjectSrg::HeightmapImage.SampleLevel(ObjectSrg::LinearSampler, uv, 0).r - 0.5f); -} - -VertexOutput MainVS(in VertexInput input) -{ - VertexOutput output; - - // Clamp the UVs *after* lerping to ensure that everything aligns properly right to the edge. - // We use out-of-bounds UV values to denote vertices that need to be removed. - float2 origUv = lerp(ObjectSrg::m_uvMin, ObjectSrg::m_uvMax, input.UV); - float2 uv = clamp(origUv, 0.0f, 1.0f); - - // Loop up the height and calculate our final position. - float height = GetHeight(uv); - float3 worldPosition = mul(GetObject_WorldMatrix(), float4(input.Position, height, 1.0f)).xyz; - output.Position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0f)); - - // Remove all vertices outside our bounds by turning them into NaN positions. - output.Position = output.Position / ((origUv.x >= 0.0f && origUv.x < 1.0f && origUv.y >= 0.0f && origUv.y < 1.0f) ? 1.0f : 0.0f); - - // Calculate normal - float2 gridSize = {1.0f, 1.0f}; - float up = GetHeight(uv + ObjectSrg::m_uvStep * float2(-1.0f, 0.0f)); - float right = GetHeight(uv + ObjectSrg::m_uvStep * float2( 0.0f, 1.0f)); - float down = GetHeight(uv + ObjectSrg::m_uvStep * float2( 1.0f, 0.0f)); - float left = GetHeight(uv + ObjectSrg::m_uvStep * float2( 0.0f, -1.0f)); - - float dydx = (right - left) * gridSize[0]; - float dydz = (down - up) * gridSize[1]; - - output.Normal = normalize(float3(dydx, 2.0f, dydz)); - - output.UV = uv; - return output; -} + float4 m_diffuseColor : SV_Target0; //!< RGB = Diffuse Lighting, A = Blend Alpha (for blended surfaces) OR A = special encoding of surfaceScatteringFactor, m_subsurfaceScatteringQuality, o_enableSubsurfaceScattering + float4 m_specularColor : SV_Target1; //!< RGB = Specular Lighting, A = Unused + float4 m_albedo : SV_Target2; //!< RGB = Surface albedo pre-multiplied by other factors that will be multiplied later by diffuse GI, A = specularOcclusion + float4 m_specularF0 : SV_Target3; //!< RGB = Specular F0, A = roughness + float4 m_normal : SV_Target4; //!< RGB10 = EncodeNormalSignedOctahedron(worldNormal), A2 = multiScatterCompensationEnabled +}; struct PixelOutput { float4 m_color : SV_Target0; }; - -PixelOutput MainPS(in VertexOutput input) + +VertexOutput MainVS(in VertexInput input) { - PixelOutput output; + VertexOutput output; + ObjectSrg::TerrainData terrainData = ObjectSrg::m_terrainData; - // Hard-coded fake light direction - float3 lightDirection = normalize(float3(1.0, -1.0, 1.0)); + float2 uv = input.m_uv; + float2 origUv = lerp(terrainData.m_uvMin, terrainData.m_uvMax, uv); + output.m_position = GetTerrainProjectedPosition(terrainData, input.m_position, origUv); + // Calculate normal + float up = GetHeight(origUv + terrainData.m_uvStep * float2( 0.0f, -1.0f)); + float right = GetHeight(origUv + terrainData.m_uvStep * float2( 1.0f, 0.0f)); + float down = GetHeight(origUv + terrainData.m_uvStep * float2( 0.0f, 1.0f)); + float left = GetHeight(origUv + terrainData.m_uvStep * float2(-1.0f, 0.0f)); + + output.m_bitangent = normalize(float3(0.0, terrainData.m_sampleSpacing * 2.0f, down - up)); + output.m_tangent = normalize(float3(terrainData.m_sampleSpacing * 2.0f, 0.0, right - left)); + output.m_normal = cross(output.m_tangent, output.m_bitangent); + + output.m_height = GetHeight(origUv); + return output; +} + +ForwardPassOutput MainPS(in VertexOutput input) +{ + ForwardPassOutput output; + + float3 lightDirection = normalize(float3(-1.0, 1.0, -1.0)); + float3 lightIntensity = float3(1.0, 1.0, 1.0); + if (SceneSrg::m_directionalLightCount > 0) + { + lightDirection = SceneSrg::m_directionalLights[0].m_direction; + lightIntensity = SceneSrg::m_directionalLights[0].m_rgbIntensityLux; + } + // Fake light intensity ranges from 1.0 for normals directly facing the light to zero for those // directly facing away. - float lightDot = dot(normalize(input.Normal), lightDirection); - float lightIntensity = lightDot * 0.5 + 0.5; + const float minLight = 0.01; + const float midLight = 0.1; + float lightDot = dot(normalize(input.m_normal), -lightDirection); + lightIntensity *= lightDot > 0.0 ? + lightDot * (1.0 - midLight) + midLight : // surface facing light + (lightDot + 1.0) * (midLight - minLight) + minLight; // surface facing away - // add a small amount of ambient and reduce direct light to keep in 0-1 range - lightIntensity = saturate(0.1 + lightIntensity * 0.9); + output.m_diffuseColor.rgb = 0.5 * lightIntensity; + output.m_diffuseColor.a = 0.0f; - // The lightIntensity should not affect alpha so only apply it to rgb. - //output.m_color.rgb = ((input.Normal + float3(1.0, 1.0, 1.0)) / 2.0); - output.m_color.rgb = float3(1.0, 1.0, 1.0) * lightIntensity; - output.m_color.a = 1.0f; + output.m_specularColor.rgb = 0.0; + + output.m_albedo.rgb = 0.25 + input.m_height * 0.5; + output.m_albedo.a = 0.0; + + output.m_specularF0.rgb = 0.04; + output.m_specularF0.a = 1.0; + + output.m_normal.rgb = input.m_normal; + output.m_normal.a = 0.0; return output; } diff --git a/Gems/Terrain/Assets/Shaders/Terrain/Terrain.shader b/Gems/Terrain/Assets/Shaders/Terrain/Terrain.shader index f20f4201ae..e844a54a21 100644 --- a/Gems/Terrain/Assets/Shaders/Terrain/Terrain.shader +++ b/Gems/Terrain/Assets/Shaders/Terrain/Terrain.shader @@ -1,21 +1,13 @@ { - - "Source" : "Terrain", + "Source" : "./Terrain.azsl", - - "RasterState" : { "CullMode" : "None" }, - - "DepthStencilState" : { - "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } - }, - - "BlendState" : { - "Enable" : true, - "BlendSource" : "One", - "BlendAlphaSource" : "One", - "BlendDest" : "AlphaSourceInverse", - "BlendAlphaDest" : "AlphaSourceInverse", - "BlendAlphaOp" : "Add" + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + } }, "DrawList" : "forward", @@ -33,5 +25,9 @@ "type": "Fragment" } ] + }, + + "BlendState" : { + "Enable" : false } } diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli b/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli new file mode 100644 index 0000000000..6e489796d7 --- /dev/null +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli @@ -0,0 +1,76 @@ +/* + * 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 + +ShaderResourceGroup ObjectSrg : SRG_PerObject +{ + Texture2D m_heightmapImage; + + Sampler LinearSampler + { + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; + + row_major float3x4 m_modelToWorld; + + struct TerrainData + { + float2 m_uvMin; + float2 m_uvMax; + float2 m_uvStep; + float m_sampleSpacing; + float m_heightScale; + }; + + TerrainData m_terrainData; +} + +struct VertexInput +{ + float2 m_position : POSITION; + float2 m_uv : UV; +}; + +float4x4 GetObject_WorldMatrix() +{ + float4x4 modelToWorld = float4x4( + float4(1, 0, 0, 0), + float4(0, 1, 0, 0), + float4(0, 0, 1, 0), + float4(0, 0, 0, 1)); + + modelToWorld[0] = ObjectSrg::m_modelToWorld[0]; + modelToWorld[1] = ObjectSrg::m_modelToWorld[1]; + modelToWorld[2] = ObjectSrg::m_modelToWorld[2]; + return modelToWorld; +} + +float GetHeight(float2 origUv) +{ + float2 uv = clamp(origUv, 0.0f, 1.0f); + return ObjectSrg::m_terrainData.m_heightScale * (ObjectSrg::m_heightmapImage.SampleLevel(ObjectSrg::LinearSampler, uv, 0).r - 0.5f); +} + +float4 GetTerrainProjectedPosition(ObjectSrg::TerrainData terrainData, float2 vertexPosition, float2 uv) +{ + // Remove all vertices outside our bounds by turning them into NaN positions. + if (any(uv > 1.0) || any (uv < 0.0)) + { + return asfloat(0x7fc00000); // NaN + } + + // Loop up the height and calculate our final position. + float height = GetHeight(uv); + float4 worldPosition = mul(GetObject_WorldMatrix(), float4(vertexPosition, height, 1.0f)); + return mul(ViewSrg::m_viewProjectionMatrix, worldPosition); +} diff --git a/Gems/Terrain/Assets/Shaders/Terrain/Terrain_DepthPass.azsl b/Gems/Terrain/Assets/Shaders/Terrain/Terrain_DepthPass.azsl new file mode 100644 index 0000000000..20c56323ac --- /dev/null +++ b/Gems/Terrain/Assets/Shaders/Terrain/Terrain_DepthPass.azsl @@ -0,0 +1,25 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include "TerrainCommon.azsli" + +struct VSDepthOutput +{ + float4 m_position : SV_Position; +}; + +VSDepthOutput MainVS(in VertexInput input) +{ + VSDepthOutput output; + ObjectSrg::TerrainData terrainData = ObjectSrg::m_terrainData; + + float2 origUv = lerp(terrainData.m_uvMin, terrainData.m_uvMax, input.m_uv); + output.m_position = GetTerrainProjectedPosition(terrainData, input.m_position, origUv); + return output; +} diff --git a/Gems/Terrain/Assets/Shaders/Terrain/Terrain_DepthPass.shader b/Gems/Terrain/Assets/Shaders/Terrain/Terrain_DepthPass.shader new file mode 100644 index 0000000000..f1bcdbc1d3 --- /dev/null +++ b/Gems/Terrain/Assets/Shaders/Terrain/Terrain_DepthPass.shader @@ -0,0 +1,26 @@ +{ + "Source" : "./Terrain_DepthPass.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + } + }, + + "DrawList" : "depth", + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + } + ] + } + +} diff --git a/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.cpp index 06372a3490..e17dbd0e93 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.cpp @@ -78,7 +78,7 @@ namespace Terrain void TerrainLayerSpawnerComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services) { - services.push_back(AZ_CRC("BoxShapeService")); + services.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService")); } void TerrainLayerSpawnerComponent::Reflect(AZ::ReflectContext* context) @@ -105,17 +105,19 @@ namespace Terrain AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId()); LmbrCentral::ShapeComponentNotificationsBus::Handler::BusConnect(GetEntityId()); TerrainAreaRequestBus::Handler::BusConnect(GetEntityId()); + TerrainSpawnerRequestBus::Handler::BusConnect(GetEntityId()); TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::RegisterArea, GetEntityId()); } void TerrainLayerSpawnerComponent::Deactivate() { - TerrainAreaRequestBus::Handler::BusDisconnect(); TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::UnregisterArea, GetEntityId()); - - AZ::TransformNotificationBus::Handler::BusDisconnect(); + TerrainSpawnerRequestBus::Handler::BusDisconnect(); + TerrainAreaRequestBus::Handler::BusDisconnect(); LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect(); + AZ::TransformNotificationBus::Handler::BusDisconnect(); + } bool TerrainLayerSpawnerComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig) @@ -147,6 +149,17 @@ namespace Terrain { RefreshArea(); } + + void TerrainLayerSpawnerComponent::GetPriority(AZ::u32& outLayer, AZ::u32& outPriority) + { + outLayer = m_configuration.m_layer; + outPriority = m_configuration.m_priority; + } + + bool TerrainLayerSpawnerComponent::GetUseGroundPlane() + { + return m_configuration.m_useGroundPlane; + } void TerrainLayerSpawnerComponent::RegisterArea() { diff --git a/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.h b/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.h index 1f1ae90227..3f8e72e1b8 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.h @@ -59,6 +59,7 @@ namespace Terrain , private AZ::TransformNotificationBus::Handler , private LmbrCentral::ShapeComponentNotificationsBus::Handler , private Terrain::TerrainAreaRequestBus::Handler + , private Terrain::TerrainSpawnerRequestBus::Handler { public: template @@ -80,7 +81,6 @@ namespace Terrain bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override; bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override; - ////////////////////////////////////////////////////////////////////////// // AZ::TransformNotificationBus::Handler void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; @@ -88,6 +88,10 @@ namespace Terrain // ShapeComponentNotificationsBus void OnShapeChanged(ShapeChangeReasons changeReason) override; + // TerrainSpawnerRequestBus + void GetPriority(AZ::u32& outLayer, AZ::u32& outPriority) override; + bool GetUseGroundPlane() override; + void RegisterArea() override; void RefreshArea() override; diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp index 2178151e3d..f0743cfb52 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp @@ -36,17 +36,14 @@ namespace Terrain namespace { const uint32_t DEFAULT_UploadBufferSize = 512 * 1024; // 512k - const char* TerrainFPName = "TerrainFeatureProcessor"; + [[maybe_unused]] const char* TerrainFPName = "TerrainFeatureProcessor"; } namespace ShaderInputs { - static const char* const HeightmapImage("HeightmapImage"); + static const char* const HeightmapImage("m_heightmapImage"); static const char* const ModelToWorld("m_modelToWorld"); - static const char* const HeightScale("m_heightScale"); - static const char* const UvMin("m_uvMin"); - static const char* const UvMax("m_uvMax"); - static const char* const UvStep("m_uvStep"); + static const char* const TerrainData("m_terrainData"); } @@ -68,76 +65,76 @@ namespace Terrain EnableSceneNotification(); } + void TerrainFeatureProcessor::ConfigurePipelineState(ShaderState& shaderState, bool assertOnFail) + { + bool success = GetParentScene()->ConfigurePipelineState(shaderState.m_shader->GetDrawListTag(), shaderState.m_pipelineStateDescriptor); + AZ_Assert(success || !assertOnFail, "Couldn't configure the pipeline state."); + if (success) + { + shaderState.m_pipelineState = shaderState.m_shader->AcquirePipelineState(shaderState.m_pipelineStateDescriptor); + AZ_Assert(shaderState.m_pipelineState, "Failed to acquire default pipeline state."); + } + } + void TerrainFeatureProcessor::InitializeAtomStuff() { m_rhiSystem = AZ::RHI::RHISystemInterface::Get(); - { - // Load the shader - constexpr const char* TerrainShaderFilePath = "Shaders/Terrain/Terrain.azshader"; - m_shader = AZ::RPI::LoadShader(TerrainShaderFilePath); - if (!m_shader) + { + auto LoadShader = [this](const char* filePath, ShaderState& shaderState) { - AZ_Error(TerrainFPName, false, "Failed to find or create a shader instance from shader asset '%s'", TerrainShaderFilePath); + shaderState.m_shader = AZ::RPI::LoadShader(filePath); + if (!shaderState.m_shader) + { + AZ_Error(TerrainFPName, false, "Failed to find or create a shader instance from shader asset '%s'", filePath); + return; + } + + // Create the data layout + shaderState.m_pipelineStateDescriptor = AZ::RHI::PipelineStateDescriptorForDraw{}; + { + AZ::RHI::InputStreamLayoutBuilder layoutBuilder; + + layoutBuilder.AddBuffer() + ->Channel("POSITION", AZ::RHI::Format::R32G32_FLOAT) + ->Channel("UV", AZ::RHI::Format::R32G32_FLOAT) + ; + shaderState.m_pipelineStateDescriptor.m_inputStreamLayout = layoutBuilder.End(); + } + + auto shaderVariant = shaderState.m_shader->GetVariant(AZ::RPI::ShaderAsset::RootShaderVariantStableId); + shaderVariant.ConfigurePipelineState(shaderState.m_pipelineStateDescriptor); + + // If this fails to run now, it's ok, we'll initialize it in OnRenderPipelineAdded later. + ConfigurePipelineState(shaderState, false); + }; + + LoadShader("Shaders/Terrain/Terrain.azshader", m_shaderStates[ShaderType::Forward]); + LoadShader("Shaders/Terrain/Terrain_DepthPass_WithPS.azshader", m_shaderStates[ShaderType::Depth]); + + // Forward and depth shader use same srg layout. + AZ::RHI::Ptr perObjectSrgLayout = + m_shaderStates[ShaderType::Forward].m_shader->FindShaderResourceGroupLayout(AZ::Name{"ObjectSrg"}); + + if (!perObjectSrgLayout) + { + AZ_Error(TerrainFPName, false, "Failed to get shader resource group layout"); + return; + } + else if (!perObjectSrgLayout->IsFinalized()) + { + AZ_Error(TerrainFPName, false, "Shader resource group layout is not loaded"); return; } - // Create the data layout - m_pipelineStateDescriptor = AZ::RHI::PipelineStateDescriptorForDraw{}; - { - AZ::RHI::InputStreamLayoutBuilder layoutBuilder; - - layoutBuilder.AddBuffer() - ->Channel("POSITION", AZ::RHI::Format::R32G32_FLOAT) - ->Channel("UV", AZ::RHI::Format::R32G32_FLOAT) - ; - m_pipelineStateDescriptor.m_inputStreamLayout = layoutBuilder.End(); - } - - auto shaderVariant = m_shader->GetVariant(AZ::RPI::ShaderAsset::RootShaderVariantStableId); - shaderVariant.ConfigurePipelineState(m_pipelineStateDescriptor); - - m_drawListTag = m_shader->GetDrawListTag(); - - m_perObjectSrgAsset = m_shader->FindShaderResourceGroupLayout(AZ::Name{"ObjectSrg"}); - if (!m_perObjectSrgAsset) - { - AZ_Error(TerrainFPName, false, "Failed to get shader resource group asset"); - return; - } - else if (!m_perObjectSrgAsset->IsFinalized()) - { - AZ_Error(TerrainFPName, false, "Shader resource group asset is not loaded"); - return; - } - - const AZ::RHI::ShaderResourceGroupLayout* shaderResourceGroupLayout = &(*m_perObjectSrgAsset); - - m_heightmapImageIndex = shaderResourceGroupLayout->FindShaderInputImageIndex(AZ::Name(ShaderInputs::HeightmapImage)); + m_heightmapImageIndex = perObjectSrgLayout->FindShaderInputImageIndex(AZ::Name(ShaderInputs::HeightmapImage)); AZ_Error(TerrainFPName, m_heightmapImageIndex.IsValid(), "Failed to find shader input image %s.", ShaderInputs::HeightmapImage); - m_modelToWorldIndex = shaderResourceGroupLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::ModelToWorld)); + m_modelToWorldIndex = perObjectSrgLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::ModelToWorld)); AZ_Error(TerrainFPName, m_modelToWorldIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::ModelToWorld); - m_heightScaleIndex = shaderResourceGroupLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::HeightScale)); - AZ_Error(TerrainFPName, m_heightScaleIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::HeightScale); - - m_uvMinIndex = shaderResourceGroupLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::UvMin)); - AZ_Error(TerrainFPName, m_uvMinIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::UvMin); - - m_uvMaxIndex = shaderResourceGroupLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::UvMax)); - AZ_Error(TerrainFPName, m_uvMaxIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::UvMax); - - m_uvStepIndex = shaderResourceGroupLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::UvStep)); - AZ_Error(TerrainFPName, m_uvStepIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::UvStep); - - // If this fails to run now, it's ok, we'll initialize it in OnRenderPipelineAdded later. - bool success = GetParentScene()->ConfigurePipelineState(m_shader->GetDrawListTag(), m_pipelineStateDescriptor); - if (success) - { - m_pipelineState = m_shader->AcquirePipelineState(m_pipelineStateDescriptor); - AZ_Assert(m_pipelineState, "Failed to acquire default pipeline state for shader '%s'", TerrainShaderFilePath); - } + m_terrainDataIndex = perObjectSrgLayout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::TerrainData)); + AZ_Error(TerrainFPName, m_terrainDataIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::TerrainData); } AZ::RHI::BufferPoolDescriptor dmaPoolDescriptor; @@ -165,12 +162,9 @@ namespace Terrain void TerrainFeatureProcessor::OnRenderPipelineAdded([[maybe_unused]] AZ::RPI::RenderPipelinePtr pipeline) { - bool success = GetParentScene()->ConfigurePipelineState(m_drawListTag, m_pipelineStateDescriptor); - AZ_Assert(success, "Couldn't configure the pipeline state."); - if (success) + for (ShaderState& shaderState: m_shaderStates) { - m_pipelineState = m_shader->AcquirePipelineState(m_pipelineStateDescriptor); - AZ_Assert(m_pipelineState, "Failed to acquire default pipeline state."); + ConfigurePipelineState(shaderState, true); } } @@ -206,7 +200,7 @@ namespace Terrain void TerrainFeatureProcessor::UpdateTerrainData( const AZ::Transform& transform, const AZ::Aabb& worldBounds, - [[maybe_unused]] float sampleSpacing, + float sampleSpacing, uint32_t width, uint32_t height, const AZStd::vector& heightData) { if (!worldBounds.IsValid()) @@ -219,6 +213,7 @@ namespace Terrain m_areaData.m_terrainBounds = worldBounds; m_areaData.m_heightmapImageHeight = height; m_areaData.m_heightmapImageWidth = width; + m_areaData.m_sampleSpacing = sampleSpacing; // Create heightmap image data { @@ -228,13 +223,22 @@ namespace Terrain imageSize.m_width = width; imageSize.m_height = height; + AZStd::vector uint16Heights; + uint16Heights.reserve(heightData.size()); + for (float sampleHeight : heightData) + { + float clampedSample = AZ::GetClamp(sampleHeight, 0.0f, 1.0f); + constexpr uint16_t MaxUint16 = 0xFFFF; + uint16Heights.push_back(aznumeric_cast(clampedSample * MaxUint16)); + } + AZ::Data::Instance streamingImagePool = AZ::RPI::ImageSystemInterface::Get()->GetSystemStreamingPool(); m_areaData.m_heightmapImage = AZ::RPI::StreamingImage::CreateFromCpuData(*streamingImagePool, AZ::RHI::ImageDimension::Image2D, imageSize, - AZ::RHI::Format::R32_FLOAT, - (uint8_t*)heightData.data(), - heightData.size() * sizeof(float)); + AZ::RHI::Format::R16_UNORM, + (uint8_t*)uint16Heights.data(), + heightData.size() * sizeof(uint16_t)); AZ_Error(TerrainFPName, m_areaData.m_heightmapImage, "Failed to initialize the heightmap image!"); } @@ -244,7 +248,8 @@ namespace Terrain { AZ_PROFILE_FUNCTION(AzRender); - if (m_drawListTag.IsNull()) + if (m_shaderStates[ShaderType::Forward].m_shader->GetDrawListTag().IsNull() || + m_shaderStates[ShaderType::Depth].m_shader->GetDrawListTag().IsNull()) { return; } @@ -256,6 +261,7 @@ namespace Terrain if (m_areaData.m_propertiesDirty) { + m_areaData.m_propertiesDirty = false; m_sectorData.clear(); AZ::RHI::DrawPacketBuilder drawPacketBuilder; @@ -281,17 +287,17 @@ namespace Terrain drawPacketBuilder.Begin(nullptr); drawPacketBuilder.SetDrawArguments(drawIndexed); drawPacketBuilder.SetIndexBufferView(m_indexBufferView); + auto& forwardShader = m_shaderStates[ShaderType::Forward].m_shader; - auto resourceGroup = AZ::RPI::ShaderResourceGroup::Create(m_shader->GetAsset(), m_shader->GetSupervariantIndex(), AZ::Name("ObjectSrg")); - //auto m_resourceGroup = AZ::RPI::ShaderResourceGroup::Create(m_shader->GetAsset(), AZ::Name("ObjectSrg")); + auto resourceGroup = AZ::RPI::ShaderResourceGroup::Create(forwardShader->GetAsset(), forwardShader->GetSupervariantIndex(), AZ::Name("ObjectSrg")); if (!resourceGroup) { AZ_Error(TerrainFPName, false, "Failed to create shader resource group"); return; } - float uvMin[2] = { 0.0f, 0.0f }; - float uvMax[2] = { 1.0f, 1.0f }; + AZStd::array uvMin = { 0.0f, 0.0f }; + AZStd::array uvMax = { 1.0f, 1.0f }; uvMin[0] = (float)((xPatch - m_areaData.m_terrainBounds.GetMin().GetX()) / m_areaData.m_terrainBounds.GetXExtent()); uvMin[1] = (float)((yPatch - m_areaData.m_terrainBounds.GetMin().GetY()) / m_areaData.m_terrainBounds.GetYExtent()); @@ -301,7 +307,7 @@ namespace Terrain uvMax[1] = (float)(((yPatch + m_gridMeters) - m_areaData.m_terrainBounds.GetMin().GetY()) / m_areaData.m_terrainBounds.GetYExtent()); - float uvStep[2] = + AZStd::array uvStep = { 1.0f / m_areaData.m_heightmapImageWidth, 1.0f / m_areaData.m_heightmapImageHeight, }; @@ -313,18 +319,32 @@ namespace Terrain resourceGroup->SetImage(m_heightmapImageIndex, m_areaData.m_heightmapImage); resourceGroup->SetConstant(m_modelToWorldIndex, matrix3x4); - resourceGroup->SetConstant(m_heightScaleIndex, m_areaData.m_heightScale); - resourceGroup->SetConstant(m_uvMinIndex, uvMin); - resourceGroup->SetConstant(m_uvMaxIndex, uvMax); - resourceGroup->SetConstant(m_uvStepIndex, uvStep); + + ShaderTerrainData terrainDataForSrg; + terrainDataForSrg.m_sampleSpacing = m_areaData.m_sampleSpacing; + terrainDataForSrg.m_heightScale = m_areaData.m_heightScale; + terrainDataForSrg.m_uvMin = uvMin; + terrainDataForSrg.m_uvMax = uvMax; + terrainDataForSrg.m_uvStep = uvStep; + resourceGroup->SetConstant(m_terrainDataIndex, terrainDataForSrg); + resourceGroup->Compile(); drawPacketBuilder.AddShaderResourceGroup(resourceGroup->GetRHIShaderResourceGroup()); - AZ::RHI::DrawPacketBuilder::DrawRequest drawRequest; - drawRequest.m_listTag = m_drawListTag; - drawRequest.m_pipelineState = m_pipelineState.get(); - drawRequest.m_streamBufferViews = AZStd::array_view(&m_vertexBufferView, 1); - drawPacketBuilder.AddDrawItem(drawRequest); + auto addDrawItem = [&](ShaderState& shaderState) + { + AZ::RHI::DrawPacketBuilder::DrawRequest drawRequest; + drawRequest.m_listTag = shaderState.m_shader->GetDrawListTag(); + drawRequest.m_pipelineState = shaderState.m_pipelineState.get(); + drawRequest.m_streamBufferViews = AZStd::array_view(&m_vertexBufferView, 1); + drawPacketBuilder.AddDrawItem(drawRequest); + }; + + for (ShaderState& shaderState : m_shaderStates) + { + addDrawItem(shaderState); + } + //addDrawItem(m_shaderStates[ShaderType::Forward]); m_sectorData.emplace_back( drawPacketBuilder.End(), @@ -368,16 +388,16 @@ namespace Terrain uint16_t startIndex = (uint16_t)(m_gridVertices.size()); m_gridVertices.emplace_back(x0, y0, x0 / m_gridMeters, y0 / m_gridMeters); - m_gridVertices.emplace_back(x0, y1, x0 / m_gridMeters, y1 / m_gridMeters); m_gridVertices.emplace_back(x1, y0, x1 / m_gridMeters, y0 / m_gridMeters); + m_gridVertices.emplace_back(x0, y1, x0 / m_gridMeters, y1 / m_gridMeters); m_gridVertices.emplace_back(x1, y1, x1 / m_gridMeters, y1 / m_gridMeters); m_gridIndices.emplace_back(startIndex); m_gridIndices.emplace_back(aznumeric_cast(startIndex + 1)); m_gridIndices.emplace_back(aznumeric_cast(startIndex + 2)); m_gridIndices.emplace_back(aznumeric_cast(startIndex + 1)); - m_gridIndices.emplace_back(aznumeric_cast(startIndex + 2)); m_gridIndices.emplace_back(aznumeric_cast(startIndex + 3)); + m_gridIndices.emplace_back(aznumeric_cast(startIndex + 2)); } } } @@ -441,8 +461,6 @@ namespace Terrain m_vertexBufferView = AZ::RHI::StreamBufferView( *buffer, 0, static_cast(elementSize), static_cast(sizeof(Vertex))); - - AZ::RHI::ValidateStreamBufferViews(m_pipelineStateDescriptor.m_inputStreamLayout, { { m_vertexBufferView } }); } m_hostPool->UnmapBuffer(*buffer); @@ -459,8 +477,9 @@ namespace Terrain m_indexBufferView = {}; m_vertexBufferView = {}; - m_pipelineStateDescriptor = AZ::RHI::PipelineStateDescriptorForDraw{}; - m_pipelineState = nullptr; + for (ShaderState& shaderState : m_shaderStates) + { + shaderState.Reset(); + } } - } diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.h b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.h index 7a7b63b634..382f473b25 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.h +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.h @@ -56,12 +56,45 @@ namespace Terrain } private: + + // System-level references to the shader, pipeline, and shader-related information + enum ShaderType + { + Depth, + Forward, + Count, + }; + + struct ShaderState + { + AZ::Data::Instance m_shader; + AZ::RHI::ConstPtr m_pipelineState; + AZ::RHI::PipelineStateDescriptorForDraw m_pipelineStateDescriptor; + + void Reset() + { + m_shader.reset(); + m_pipelineState.reset(); + m_pipelineStateDescriptor = {}; + } + }; + + struct ShaderTerrainData // Must align with struct in Object Srg + { + AZStd::array m_uvMin; + AZStd::array m_uvMax; + AZStd::array m_uvStep; + float m_sampleSpacing; + float m_heightScale; + }; + // RPI::SceneNotificationBus overrides ... void OnRenderPipelineAdded(AZ::RPI::RenderPipelinePtr pipeline) override; void OnRenderPipelineRemoved(AZ::RPI::RenderPipeline* pipeline) override; void OnRenderPipelinePassesChanged(AZ::RPI::RenderPipeline* renderPipeline) override; void InitializeAtomStuff(); + void ConfigurePipelineState(ShaderState& shaderState, bool assertOnFail); void InitializeTerrainPatch(); @@ -77,20 +110,11 @@ namespace Terrain // System-level cached reference to the Atom RHI AZ::RHI::RHISystemInterface* m_rhiSystem = nullptr; - // System-level references to the shader, pipeline, and shader-related information - AZ::Data::Instance m_shader{}; - AZ::RHI::PipelineStateDescriptorForDraw m_pipelineStateDescriptor; - AZ::RHI::ConstPtr m_pipelineState = nullptr; - AZ::RHI::DrawListTag m_drawListTag; - AZ::RHI::Ptr m_perObjectSrgAsset; + AZStd::array m_shaderStates; AZ::RHI::ShaderInputImageIndex m_heightmapImageIndex; AZ::RHI::ShaderInputConstantIndex m_modelToWorldIndex; - AZ::RHI::ShaderInputConstantIndex m_heightScaleIndex; - AZ::RHI::ShaderInputConstantIndex m_uvMinIndex; - AZ::RHI::ShaderInputConstantIndex m_uvMaxIndex; - AZ::RHI::ShaderInputConstantIndex m_uvStepIndex; - + AZ::RHI::ShaderInputConstantIndex m_terrainDataIndex; // Pos_float_2 + UV_float_2 struct Vertex @@ -125,11 +149,12 @@ namespace Terrain { AZ::Transform m_transform{ AZ::Transform::CreateIdentity() }; AZ::Aabb m_terrainBounds{ AZ::Aabb::CreateNull() }; - float m_heightScale; + float m_heightScale{ 0.0f }; AZ::Data::Instance m_heightmapImage; - uint32_t m_heightmapImageWidth; - uint32_t m_heightmapImageHeight; + uint32_t m_heightmapImageWidth{ 0 }; + uint32_t m_heightmapImageHeight{ 0 }; bool m_propertiesDirty{ true }; + float m_sampleSpacing{ 0.0f }; }; TerrainAreaData m_areaData; diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp index 90b74f08ba..a271d624f5 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp @@ -17,6 +17,33 @@ using namespace Terrain; +bool TerrainLayerPriorityComparator::operator()(const AZ::EntityId& layer1id, const AZ::EntityId& layer2id) const +{ + // Comparator for insertion/keylookup. + // Sorts into layer/priority order, highest priority first. + AZ::u32 priority1, layer1; + Terrain::TerrainSpawnerRequestBus::Event(layer1id, &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer1, priority1); + + AZ::u32 priority2, layer2; + Terrain::TerrainSpawnerRequestBus::Event(layer2id, &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer2, priority2); + + if (layer1 < layer2) + { + return false; + } + else if (layer1 > layer2) + { + return true; + } + + if (priority1 != priority2) + { + return priority1 > priority2; + } + + return layer1id > layer2id; +} + TerrainSystem::TerrainSystem() { Terrain::TerrainSystemServiceRequestBus::Handler::BusConnect(); @@ -78,17 +105,14 @@ float TerrainSystem::GetHeightSynchronous(float x, float y) const AZStd::shared_lock lock(m_areaMutex); - if (!m_registeredAreas.empty()) + for (auto& [areaId, areaBounds] : m_registeredAreas) { - for (auto& [areaId, areaBounds] : m_registeredAreas) + inPosition.SetZ(areaBounds.GetMin().GetZ()); + if (areaBounds.Contains(inPosition)) { - inPosition.SetZ(areaBounds.GetMin().GetZ()); - if (areaBounds.Contains(inPosition)) - { - Terrain::TerrainAreaHeightRequestBus::Event( - areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, - Terrain::TerrainAreaHeightRequestBus::Events::Sampler::DEFAULT); - } + Terrain::TerrainAreaHeightRequestBus::Event( + areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, + Terrain::TerrainAreaHeightRequestBus::Events::Sampler::DEFAULT); } } @@ -305,26 +329,34 @@ void TerrainSystem::SystemDeactivate() void TerrainSystem::RegisterArea(AZ::EntityId areaId) { - { - AZStd::unique_lock lock(m_areaMutex); - AZ::Aabb aabb = AZ::Aabb::CreateNull(); - LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb); - m_registeredAreas[areaId] = aabb; - } - - RefreshArea(areaId); + AZStd::unique_lock lock(m_areaMutex); + AZ::Aabb aabb = AZ::Aabb::CreateNull(); + LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb); + m_registeredAreas[areaId] = aabb; + m_dirtyRegion.AddAabb(aabb); + m_terrainHeightDirty = true; } void TerrainSystem::UnregisterArea(AZ::EntityId areaId) { - { - AZStd::unique_lock lock(m_areaMutex); - AZ::Aabb aabb = AZ::Aabb::CreateNull(); - LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb); - m_registeredAreas.erase(areaId); - } + AZStd::unique_lock lock(m_areaMutex); - RefreshArea(areaId); + // Remove the data for this entity from the registered areas. + // Erase_if is used as erase would use the comparator to lookup the entity id in the map. + // As the comparator will get the new layer/priority data for the entity, the id lookup will fail. + AZStd::erase_if( + m_registeredAreas, + [areaId, this](const auto& item) + { + auto const& [entityId, aabb] = item; + if (areaId == entityId) + { + m_dirtyRegion.AddAabb(aabb); + m_terrainHeightDirty = true; + return true; + } + return false; + }); } void TerrainSystem::RefreshArea(AZ::EntityId areaId) @@ -336,7 +368,6 @@ void TerrainSystem::RefreshArea(AZ::EntityId areaId) AZ::Aabb oldAabb = (areaAabb != m_registeredAreas.end()) ? areaAabb->second : AZ::Aabb::CreateNull(); AZ::Aabb newAabb = AZ::Aabb::CreateNull(); LmbrCentral::ShapeComponentRequestsBus::EventResult(newAabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb); - m_registeredAreas[areaId] = newAabb; AZ::Aabb expandedAabb = oldAabb; @@ -400,31 +431,37 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) const uint32_t pixelDataSize = width * height * sizeof(float); memset(pixels.data(), 0, pixelDataSize); - for (auto& [areaId, areaBounds] : m_registeredAreas) + for (uint32_t y = 0; y < height; y++) { - for (uint32_t y = 0; y < height; y++) + for (uint32_t x = 0; x < width; x++) { - for (uint32_t x = 0; x < width; x++) + // Find the first terrain layer that covers this position. This will be the highest priority, so others can be ignored. + for (auto& [areaId, areaBounds] : m_registeredAreas) { AZ::Vector3 inPosition( (x * m_currentSettings.m_heightQueryResolution.GetX()) + m_currentSettings.m_worldBounds.GetMin().GetX(), (y * m_currentSettings.m_heightQueryResolution.GetY()) + m_currentSettings.m_worldBounds.GetMin().GetY(), areaBounds.GetMin().GetZ()); - if (areaBounds.Contains(inPosition)) + + if (!areaBounds.Contains(inPosition)) { - AZ::Vector3 outPosition; - const Terrain::TerrainAreaHeightRequests::Sampler sampleFilter = - Terrain::TerrainAreaHeightRequests::Sampler::DEFAULT; - - Terrain::TerrainAreaHeightRequestBus::Event( - areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, sampleFilter); - - pixels[(y * width) + x] = (outPosition.GetZ() - m_currentSettings.m_worldBounds.GetMin().GetZ()) / - m_currentSettings.m_worldBounds.GetExtents().GetZ(); + continue; } + + AZ::Vector3 outPosition; + const Terrain::TerrainAreaHeightRequests::Sampler sampleFilter = Terrain::TerrainAreaHeightRequests::Sampler::DEFAULT; + + Terrain::TerrainAreaHeightRequestBus::Event( + areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, sampleFilter); + + pixels[(y * width) + x] = (outPosition.GetZ() - m_currentSettings.m_worldBounds.GetMin().GetZ()) / + m_currentSettings.m_worldBounds.GetExtents().GetZ(); + + break; } } } + const AZ::RPI::Scene* scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get(); auto terrainFeatureProcessor = scene->GetFeatureProcessor(); diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h index 2d2286a0c3..0239170640 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h @@ -25,6 +25,11 @@ namespace Terrain { + struct TerrainLayerPriorityComparator + { + bool operator()(const AZ::EntityId& layer1id, const AZ::EntityId& layer2id) const; + }; + class TerrainSystem : public AzFramework::Terrain::TerrainDataRequestBus::Handler , private Terrain::TerrainSystemServiceRequestBus::Handler @@ -112,6 +117,6 @@ namespace Terrain AZ::Aabb m_dirtyRegion; mutable AZStd::shared_mutex m_areaMutex; - AZStd::unordered_map m_registeredAreas; + AZStd::map m_registeredAreas; }; } // namespace Terrain diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h index e999cbf8be..cb41ba9957 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h @@ -112,5 +112,26 @@ namespace Terrain }; using TerrainAreaHeightRequestBus = AZ::EBus; + + /** + * A bus for the TerrainSystem to interrogate TerrainLayerSpawners. + */ + class TerrainSpawnerRequests + : public AZ::ComponentBus + { + public: + //////////////////////////////////////////////////////////////////////// + // EBusTraits + using MutexType = AZStd::recursive_mutex; + //////////////////////////////////////////////////////////////////////// + + virtual ~TerrainSpawnerRequests() = default; + + virtual void GetPriority(AZ::u32& outLayer, AZ::u32& outPriority) = 0; + virtual bool GetUseGroundPlane() = 0; + + }; + + using TerrainSpawnerRequestBus = AZ::EBus; } diff --git a/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp b/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp new file mode 100644 index 0000000000..91d6a26f75 --- /dev/null +++ b/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +#include + +#include +#include +#include + +#include + +class LayerSpawnerComponentTest + : public ::testing::Test +{ +protected: + AZ::ComponentApplication m_app; + + AZStd::unique_ptr m_entity; + Terrain::TerrainLayerSpawnerComponent* m_layerSpawnerComponent; + UnitTest::MockBoxShapeComponent* m_shapeComponent; + AZStd::unique_ptr m_terrainSystem; + + void SetUp() override + { + AZ::ComponentApplication::Descriptor appDesc; + appDesc.m_memoryBlocksByteSize = 20 * 1024 * 1024; + appDesc.m_recordingMode = AZ::Debug::AllocationRecords::RECORD_NO_RECORDS; + appDesc.m_stackRecordLevels = 20; + + m_app.Create(appDesc); + } + + void TearDown() override + { + if (m_terrainSystem) + { + m_terrainSystem->Deactivate(); + } + m_app.Destroy(); + } + + void CreateEntity() + { + m_entity = AZStd::make_unique(); + m_entity->Init(); + + ASSERT_TRUE(m_entity); + } + + void AddLayerSpawnerAndShapeComponentToEntity() + { + AddLayerSpawnerAndShapeComponentToEntity(Terrain::TerrainLayerSpawnerConfig()); + } + + void AddLayerSpawnerAndShapeComponentToEntity(const Terrain::TerrainLayerSpawnerConfig& config) + { + m_layerSpawnerComponent = m_entity->CreateComponent(config); + m_app.RegisterComponentDescriptor(m_layerSpawnerComponent->CreateDescriptor()); + + m_shapeComponent = m_entity->CreateComponent(); + m_app.RegisterComponentDescriptor(m_shapeComponent->CreateDescriptor()); + + ASSERT_TRUE(m_layerSpawnerComponent); + ASSERT_TRUE(m_shapeComponent); + } + + void ResetEntity() + { + m_entity->Deactivate(); + m_entity->Reset(); + } + + void CreateMockTerrainSystem() + { + m_terrainSystem = AZStd::make_unique(); + m_terrainSystem->Activate(); + } +}; + +TEST_F(LayerSpawnerComponentTest, ActivatEntityActivateSuccess) +{ + CreateEntity(); + AddLayerSpawnerAndShapeComponentToEntity(); + + m_entity->Activate(); + EXPECT_EQ(m_entity->GetState(), AZ::Entity::State::Active); + + ResetEntity(); +} + +TEST_F(LayerSpawnerComponentTest, LayerSpawnerDefaultValuesCorrect) +{ + CreateEntity(); + AddLayerSpawnerAndShapeComponentToEntity(); + + m_entity->Activate(); + + AZ::u32 priority = 999, layer = 999; + Terrain::TerrainSpawnerRequestBus::Event(m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority); + + EXPECT_EQ(0, priority); + EXPECT_EQ(1, layer); + + bool useGroundPlane = false; + + Terrain::TerrainSpawnerRequestBus::EventResult(useGroundPlane, m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); + + EXPECT_TRUE(useGroundPlane); + + ResetEntity(); +} + +TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect) +{ + CreateEntity(); + + constexpr static AZ::u32 testPriority = 15; + constexpr static AZ::u32 testLayer = 0; + + Terrain::TerrainLayerSpawnerConfig config; + config.m_layer = testLayer; + config.m_priority = testPriority; + config.m_useGroundPlane = false; + + AddLayerSpawnerAndShapeComponentToEntity(config); + + m_entity->Activate(); + + AZ::u32 priority = 999, layer = 999; + Terrain::TerrainSpawnerRequestBus::Event(m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority); + + EXPECT_EQ(testPriority, priority); + EXPECT_EQ(testLayer, layer); + + bool useGroundPlane = true; + + Terrain::TerrainSpawnerRequestBus::EventResult( + useGroundPlane, m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); + + EXPECT_FALSE(useGroundPlane); + + ResetEntity(); +} + +TEST_F(LayerSpawnerComponentTest, LayerSpawnerRegisterAreaUpdatesTerrainSystem) +{ + CreateEntity(); + + CreateMockTerrainSystem(); + + AddLayerSpawnerAndShapeComponentToEntity(); + + m_entity->Activate(); + + // The Activate call should have registered the area. + EXPECT_EQ(1, m_terrainSystem->m_registerAreaCalledCount); + + ResetEntity(); +} + +TEST_F(LayerSpawnerComponentTest, LayerSpawnerUnregisterAreaUpdatesTerrainSystem) +{ + CreateEntity(); + + CreateMockTerrainSystem(); + + AddLayerSpawnerAndShapeComponentToEntity(); + + m_entity->Activate(); + + m_layerSpawnerComponent->Deactivate(); + + // The Deactivate call should have unregistered the area. + EXPECT_EQ(1, m_terrainSystem->m_unregisterAreaCalledCount); + + ResetEntity(); +} + +TEST_F(LayerSpawnerComponentTest, LayerSpawnerTransformChangedUpdatesTerrainSystem) +{ + CreateEntity(); + + CreateMockTerrainSystem(); + + AddLayerSpawnerAndShapeComponentToEntity(); + + m_entity->Activate(); + + AZ::TransformNotificationBus::Event( + m_entity->GetId(), &AZ::TransformNotificationBus::Events::OnTransformChanged, AZ::Transform(), AZ::Transform()); + + EXPECT_EQ(1, m_terrainSystem->m_refreshAreaCalledCount); + + ResetEntity(); +} + +TEST_F(LayerSpawnerComponentTest, LayerSpawnerShapeChangedUpdatesTerrainSystem) +{ + CreateEntity(); + + CreateMockTerrainSystem(); + + AddLayerSpawnerAndShapeComponentToEntity(); + + m_entity->Activate(); + + LmbrCentral::ShapeComponentNotificationsBus::Event( + m_entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged, + LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::ShapeChanged); + + EXPECT_EQ(1, m_terrainSystem->m_refreshAreaCalledCount); + + ResetEntity(); +} diff --git a/Gems/Terrain/Code/Tests/TerrainMocks.h b/Gems/Terrain/Code/Tests/TerrainMocks.h new file mode 100644 index 0000000000..5f90cafd69 --- /dev/null +++ b/Gems/Terrain/Code/Tests/TerrainMocks.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include + +namespace UnitTest +{ + static const AZ::Uuid BoxShapeComponentTypeId = "{5EDF4B9E-0D3D-40B8-8C91-5142BCFC30A6}"; + + class MockBoxShapeComponent + : public AZ::Component + { + public: + AZ_COMPONENT(MockBoxShapeComponent, BoxShapeComponentTypeId) + static void Reflect([[maybe_unused]] AZ::ReflectContext* context) + { + } + + void Activate() override + { + } + + void Deactivate() override + { + } + + bool ReadInConfig([[maybe_unused]] const AZ::ComponentConfig* baseConfig) override + { + return true; + } + + bool WriteOutConfig([[maybe_unused]] AZ::ComponentConfig* outBaseConfig) const override + { + return true; + } + + private: + static void GetProvidedServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); + provided.push_back(AZ_CRC("BoxShapeService", 0x946a0032)); + } + + static void GetIncompatibleServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + } + + static void GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) + { + } + + static void GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent) + { + } + }; + + class MockTerrainSystem : private Terrain::TerrainSystemServiceRequestBus::Handler + { + public: + void Activate() override + { + Terrain::TerrainSystemServiceRequestBus::Handler::BusConnect(); + } + + void Deactivate() override + { + Terrain::TerrainSystemServiceRequestBus::Handler::BusDisconnect(); + } + + void SetWorldBounds(const AZ::Aabb& worldBounds) override + { + } + + void SetHeightQueryResolution([[maybe_unused]] AZ::Vector2 queryResolution) override + { + } + + void RegisterArea([[maybe_unused]] AZ::EntityId areaId) override + { + m_registerAreaCalledCount++; + } + + void UnregisterArea([[maybe_unused]] AZ::EntityId areaId) override + { + m_unregisterAreaCalledCount++; + } + + void RefreshArea([[maybe_unused]] AZ::EntityId areaId) override + { + m_refreshAreaCalledCount++; + } + + int m_registerAreaCalledCount = 0; + int m_refreshAreaCalledCount = 0; + int m_unregisterAreaCalledCount = 0; + }; +} diff --git a/Gems/Terrain/Code/terrain_tests_files.cmake b/Gems/Terrain/Code/terrain_tests_files.cmake index beed6bd83d..b44f143f3b 100644 --- a/Gems/Terrain/Code/terrain_tests_files.cmake +++ b/Gems/Terrain/Code/terrain_tests_files.cmake @@ -7,5 +7,7 @@ # set(FILES + Tests/TerrainMocks.h Tests/TerrainTest.cpp + Tests/LayerSpawnerTests.cpp ) diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/TangentSpaceHelper.cpp b/Gems/WhiteBox/Code/Source/Rendering/Atom/TangentSpaceHelper.cpp index 913778cc44..a43b48d3b9 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/TangentSpaceHelper.cpp +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/TangentSpaceHelper.cpp @@ -73,9 +73,7 @@ namespace WhiteBox for (AZ::u32 i = 0; i < triangleCount; ++i) { -#if defined(AZ_ENABLE_TRACING) const auto& trianglePositions = trianglesPositions[i]; -#endif const auto& triangleUVs = trianglesUVs[i]; const auto& triangleEdges = trianglesEdges[i]; diff --git a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake index fe03f2e7c9..f22de7e4c8 100644 --- a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake +++ b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake @@ -11,7 +11,6 @@ ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) -ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev1-android TARGETS lz4 PACKAGE_HASH da8ec7736640a3e9834f6db1c69e8a0ea61c054fe8b6324509f36928cfc21dc9) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee) @@ -28,3 +27,5 @@ ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-android TARGETS Goo ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-android TARGETS libsamplerate PACKAGE_HASH bf13662afe65d02bcfa16258a4caa9b875534978227d6f9f36c9cfa92b3fb12b) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev1-android TARGETS OpenSSL PACKAGE_HASH 4036d4019d722f0e1b7a1621bf60b5a17ca6a65c9c78fd8701cee1131eec8480) ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-android TARGETS zlib PACKAGE_HASH 85b730b97176772538cfcacd6b6aaf4655fc2d368d134d6dd55e02f28f183826) +ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-android TARGETS lz4 PACKAGE_HASH f5b22642d218dbbb442cae61e469e5b241c4740acd258c3e8678e60dec61ea93) + diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 1e0de4f2ed..c9315336b9 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -15,7 +15,6 @@ ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) -ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev1-linux TARGETS lz4 PACKAGE_HASH 2e2653ce04a036c38fe28f3971bc3bfb8a4e771335aa8d1b95b0feb3423f1b0a) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) ly_associate_package(PACKAGE_NAME SQLite-3.32.2-rev3-multiplatform TARGETS SQLite PACKAGE_HASH dd4d3de6cbb4ce3d15fc504ba0ae0587e515dc89a25228037035fc0aef4831f4) @@ -28,7 +27,7 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af) ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux TARGETS freetype PACKAGE_HASH 9ad246873067717962c6b780d28a5ce3cef3321b73c9aea746a039c798f52e93) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-linux TARGETS tiff PACKAGE_HASH ae92b4d3b189c42ef644abc5cac865d1fb2eb7cb5622ec17e35642b00d1a0a76) -ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev5-linux TARGETS AWSNativeSDK PACKAGE_HASH 0101a4052d9fce83a6f5515e00f366e97b308ecb8261ad23a6e4eb4365212ab6) +ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev6-linux TARGETS AWSNativeSDK PACKAGE_HASH 490291e4c8057975c3ab86feb971b8a38871c58bac5e5d86abdd1aeb7141eec4) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-linux TARGETS PhysX PACKAGE_HASH a110249cbef4f266b0002c4ee9a71f59f373040cefbe6b82f1e1510c811edde6) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-linux TARGETS etc2comp PACKAGE_HASH 9283aa5db5bb7fb90a0ddb7a9f3895317c8ebe8044943124bbb3673a41407430) @@ -46,5 +45,4 @@ ly_associate_package(PACKAGE_NAME azslc-1.7.23-rev2-linux ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-linux TARGETS zlib PACKAGE_HASH 16f3b9e11cda525efb62144f354c1cfc30a5def9eff020dbe49cb00ee7d8234f) ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-linux TARGETS squish-ccr PACKAGE_HASH 85fecafbddc6a41a27c5f59ed4a5dfb123a94cb4666782cf26e63c0a4724c530) ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-linux TARGETS ISPCTexComp PACKAGE_HASH 065fd12abe4247dde247330313763cf816c3375c221da030bdec35024947f259) - - +ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-linux TARGETS lz4 PACKAGE_HASH 5de3dbd3e2a3537c6555d759b3c5bb98e5456cf85c74ff6d046f809b7087290d) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 58c6849657..4d62f6a7bf 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -15,7 +15,6 @@ ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) -ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev1-mac TARGETS lz4 PACKAGE_HASH 3ce6866b43d024452c0412f385ae46aba0e1ae99eb64f7099d3fc539c8460881) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) ly_associate_package(PACKAGE_NAME SQLite-3.32.2-rev3-multiplatform TARGETS SQLite PACKAGE_HASH dd4d3de6cbb4ce3d15fc504ba0ae0587e515dc89a25228037035fc0aef4831f4) @@ -30,7 +29,7 @@ ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-ma ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-mac TARGETS SPIRVCross PACKAGE_HASH 78c6376ed2fd195b9b1f5fb2b56e5267a32c3aa21fb399e905308de470eb4515) ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) -ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-mac TARGETS AWSNativeSDK PACKAGE_HASH 89e1651cde6b4e6bd80cdb96ed6b624accad9f9688ff38bfca226777f4fcb678) +ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev5-mac TARGETS AWSNativeSDK PACKAGE_HASH ffb890bd9cf23afb429b9214ad9bac1bf04696f07a0ebb93c42058c482ab2f01) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev6-mac TARGETS Lua PACKAGE_HASH b9079fd35634774c9269028447562c6b712dbc83b9c64975c095fd423ff04c08) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-mac TARGETS PhysX PACKAGE_HASH 5e092a11d5c0a50c4dd99bb681a04b566a4f6f29aa08443d9bffc8dc12c27c8e) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-mac TARGETS etc2comp PACKAGE_HASH 1966ab101c89db7ecf30984917e0a48c0d02ee0e4d65b798743842b9469c0818) @@ -44,4 +43,5 @@ ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-mac ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-mac TARGETS zlib PACKAGE_HASH 21714e8a6de4f2523ee92a7f52d51fbee29c5f37ced334e00dc3c029115b472e) ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-mac TARGETS squish-ccr PACKAGE_HASH 155bfbfa17c19a9cd2ef025de14c5db598f4290045d5b0d83ab58cb345089a77) ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-mac TARGETS ISPCTexComp PACKAGE_HASH 8a4e93277b8face6ea2fd57c6d017bdb55643ed3d6387110bc5f6b3b884dd169) +ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-mac TARGETS lz4 PACKAGE_HASH 891ff630bf34f7ab1d8eaee2ea0a8f1fca89dbdc63fca41ee592703dd488a73b) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 17792675d3..64cbfa05dd 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -15,7 +15,6 @@ ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) -ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev1-windows TARGETS lz4 PACKAGE_HASH 02e6ba2ca1407483bac082fd97803c5e19f48bc576171bfc8cec62412efe639c) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) ly_associate_package(PACKAGE_NAME SQLite-3.32.2-rev3-multiplatform TARGETS SQLite PACKAGE_HASH dd4d3de6cbb4ce3d15fc504ba0ae0587e515dc89a25228037035fc0aef4831f4) @@ -31,7 +30,7 @@ ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-wi ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-windows TARGETS SPIRVCross PACKAGE_HASH 7d601ea9d625b1d509d38bd132a1f433d7e895b16adab76bac6103567a7a6817) ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows TARGETS freetype PACKAGE_HASH 88dedc86ccb8c92f14c2c033e51ee7d828fa08eafd6475c6aa963938a99f4bf3) ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-windows TARGETS tiff PACKAGE_HASH ab60d1398e4e1e375ec0f1a00cdb1d812a07c0096d827db575ce52dd6d714207) -ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-windows TARGETS AWSNativeSDK PACKAGE_HASH 929873d4252c464620a9d288e41bd5d47c0bd22750aeb3a1caa68a3da8247c48) +ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-windows TARGETS AWSNativeSDK PACKAGE_HASH a900e80f7259e43aed5c847afee2599ada37f29db70505481397675bcbb6c76c) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-windows TARGETS Lua PACKAGE_HASH 136faccf1f73891e3fa3b95f908523187792e56f5b92c63c6a6d7e72d1158d40) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-windows TARGETS PhysX PACKAGE_HASH 0c5ffbd9fa588e5cf7643721a7cfe74d0fe448bf82252d39b3a96d06dfca2298) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-windows TARGETS etc2comp PACKAGE_HASH fc9ae937b2ec0d42d5e7d0e9e8c80e5e4d257673fb33bc9b7d6db76002117123) @@ -51,3 +50,4 @@ ly_associate_package(PACKAGE_NAME Crashpad-0.8.0-rev1-windows ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-windows TARGETS zlib PACKAGE_HASH 9afab1d67641ed8bef2fb38fc53942da47f2ab339d9e77d3d20704a48af2da0b) ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-windows TARGETS squish-ccr PACKAGE_HASH 5c3d9fa491e488ccaf802304ad23b932268a2b2846e383f088779962af2bfa84) ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-windows TARGETS ISPCTexComp PACKAGE_HASH b6fa6ea28a2808a9a5524c72c37789c525925e435770f2d94eb2d387360fa2d0) +ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-windows TARGETS lz4 PACKAGE_HASH 4ea457b833cd8cfaf8e8e06ed6df601d3e6783b606bdbc44a677f77e19e0db16) diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index f98f2009f2..69576bb665 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -11,7 +11,6 @@ ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) -ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev1-ios TARGETS lz4 PACKAGE_HASH 7a9391daf53e47e529cf811dca3554c83769f62a2ee52488610ec73214961ae1) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee) @@ -29,3 +28,4 @@ ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-ios TARGETS GoogleB ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-ios TARGETS libsamplerate PACKAGE_HASH 7656b961697f490d4f9c35d2e61559f6fc38c32102e542a33c212cd618fc2119) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev1-ios TARGETS OpenSSL PACKAGE_HASH cd0dfce3086a7172777c63dadbaf0ac3695b676119ecb6d0614b5fb1da03462f) ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-ios TARGETS zlib PACKAGE_HASH a59fc0f83a02c616b679799310e9d86fde84514c6d2acefa12c6def0ae4a880c) +ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-ios TARGETS lz4 PACKAGE_HASH 588ea05739caa9231a9a17a1e8cf64c5b9a265e16528bc05420af7e2534e86c1) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 328e5f8df7..5bc4b919fb 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -415,6 +415,19 @@ def ExportTestResults(Map options, String platform, String type, String workspac } } +def ExportTestScreenshots(Map options, String workspace, String platformName, String jobName, Map params) { + catchError(message: "Error exporting test screenshots (this won't fail the build)", buildResult: 'SUCCESS', stageResult: 'FAILURE') { + def screenshotsFolder = '${workspace}/${ENGINE_REPOSITORY_NAME}/AutomatedTesting/user/PythonTests/Automated/Screenshots' + def s3Uploader = '${workspace}/${ENGINE_REPOSITORY_NAME}/scripts/build/tools/upload_to_s3.py' + def command = '${options.PYTHON_DIR}/python.cmd -u ${s3Uploader} --base_dir ${screenshotsFolder} ' + + '--file_regex "(.*zip$)" --bucket ${env.TEST_SCREENSHOT_BUCKET} ' + + '--search_subdirectories True --key_prefix ${branchName}_${env.BUILD_NUMBER}' + + '--extra-args {"ACL": "bucket-owner-full-control"}' + bat label: "Uploading test screenshots for ${jobName}", + script: command + } +} + def PostBuildCommonSteps(String workspace, boolean mount = true) { echo 'Starting post-build common steps...' @@ -470,6 +483,14 @@ def CreateExportTestResultsStage(Map pipelineConfig, String platformName, String } } +def CreateExportTestScreenshotsStage(Map pipelineConfig, String platformName, String jobName, Map environmentVars, Map params) { + return { + stage("${jobName}_screenshots") { + ExportTestScreenshots(pipelineConfig, platformName, jobName, environmentVars['WORKSPACE'], params) + } + } +} + def CreateTeardownStage(Map environmentVars) { return { stage('Teardown') { @@ -532,6 +553,9 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar if (params && params.containsKey('TEST_RESULTS') && params.TEST_RESULTS == 'True') { CreateExportTestResultsStage(pipelineConfig, platform.key, build_job_name, envVars, params).call() } + if (params && params.containsKey('TEST_SCREENSHOTS') && params.TEST_SCREENSHOTS == 'True' && currentResult == 'FAILURE') { + CreateExportTestScreenshotsStage(pipelineConfig, platform.key, build_job_name, envVars, params).call() + } CreateTeardownStage(envVars).call() } }