diff --git a/AutomatedTesting/Gem/PythonTests/Multiplayer/tests/Multiplayer_AutoComponent_RPC.py b/AutomatedTesting/Gem/PythonTests/Multiplayer/tests/Multiplayer_AutoComponent_RPC.py index 827826cbcc..62ec410d3b 100644 --- a/AutomatedTesting/Gem/PythonTests/Multiplayer/tests/Multiplayer_AutoComponent_RPC.py +++ b/AutomatedTesting/Gem/PythonTests/Multiplayer/tests/Multiplayer_AutoComponent_RPC.py @@ -62,15 +62,16 @@ def Multiplayer_AutoComponent_RPC(): Report.critical_result(TestSuccessFailTuples.find_network_player, player_id.IsValid()) # 4) Check the editor logs for expected and unexpected log output + # Authority->Autonomous RPC PLAYERID_RPC_WAIT_TIME_SECONDS = 1.0 # The player id is sent from the server as soon as the player script is spawned. 1 second should be more than enough time to send/receive that RPC. helper.succeed_if_log_line_found('EditorServer', 'Script: AutoComponent_RPC: Sending client PlayerNumber 1', section_tracer.prints, PLAYERID_RPC_WAIT_TIME_SECONDS) helper.succeed_if_log_line_found('Script', "AutoComponent_RPC: I'm Player #1", section_tracer.prints, PLAYERID_RPC_WAIT_TIME_SECONDS) - # Uncomment once editor game-play mode supports level entities with net-binding - #PLAYFX_RPC_WAIT_TIME_SECONDS = 1.1 # The server will send an RPC to play an fx on the client every second. - #helper.succeed_if_log_line_found('EditorServer', "Script: AutoComponent_RPC_NetLevelEntity Activated on entity: NetLevelEntity", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS) - #helper.succeed_if_log_line_found('EditorServer', "Script: AutoComponent_RPC_NetLevelEntity: Authority sending RPC to play some fx.", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS) - #helper.succeed_if_log_line_found('Script', "AutoComponent_RPC_NetLevelEntity: I'm a client playing some superficial fx.", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS) + # Authority->Client RPC + PLAYFX_RPC_WAIT_TIME_SECONDS = 1.1 # The server will send an RPC to play an fx on the client every second. + helper.succeed_if_log_line_found('EditorServer', "Script: AutoComponent_RPC_NetLevelEntity Activated on entity: NetLevelEntity", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS) + helper.succeed_if_log_line_found('EditorServer', "Script: AutoComponent_RPC_NetLevelEntity: Authority sending RPC to play some fx.", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS) + helper.succeed_if_log_line_found('Script', "AutoComponent_RPC_NetLevelEntity: I'm a client playing some fx.", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS) # Exit game mode diff --git a/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC.prefab b/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC.prefab index 758cb4fca8..35d5ef9527 100644 --- a/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC.prefab +++ b/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC.prefab @@ -568,22 +568,10 @@ "$type": "EditorScriptCanvasComponent", "Id": 14750978061505735417, "m_name": "GlobalGameData", - "m_assetHolder": { - "m_asset": { - "assetId": { - "guid": "{B16589A0-EA01-56BC-8141-91A3967FB95F}" - }, - "assetHint": "levels/multiplayer/autocomponent_rpc/globalgamedata.scriptcanvas" - } - }, "runtimeDataIsValid": true, - "runtimeDataOverrides": { - "source": { - "assetId": { - "guid": "{B16589A0-EA01-56BC-8141-91A3967FB95F}" - }, - "assetHint": "levels/multiplayer/autocomponent_rpc/globalgamedata.scriptcanvas" - } + "sourceHandle": { + "id": "{B16589A0-EA01-56BC-8141-91A3967FB95F}", + "path": "levels/multiplayer/autocomponent_rpc/globalgamedata.scriptcanvas" } }, "Component_[16436925042043744033]": { @@ -636,6 +624,13 @@ "$type": "SelectionComponent", "Id": 12302672911455629152 }, + "Component_[12517591696100736853]": { + "$type": "GenericComponentWrapper", + "Id": 12517591696100736853, + "m_template": { + "$type": "AutomatedTesting::NetworkTestLevelEntityComponent" + } + }, "Component_[14169903623243423134]": { "$type": "EditorVisibilityComponent", "Id": 14169903623243423134 @@ -644,13 +639,6 @@ "$type": "EditorInspectorComponent", "Id": 14607413934411389854 }, - "Component_[15396284312416541768]": { - "$type": "GenericComponentWrapper", - "Id": 15396284312416541768, - "m_template": { - "$type": "Multiplayer::LocalPredictionPlayerInputComponent" - } - }, "Component_[15494977028055234270]": { "$type": "EditorDisabledCompositionComponent", "Id": 15494977028055234270 @@ -682,22 +670,10 @@ "$type": "EditorScriptCanvasComponent", "Id": 7256163899440301540, "m_name": "AutoComponent_RPC_NetLevelEntity", - "m_assetHolder": { - "m_asset": { - "assetId": { - "guid": "{1D517006-AC01-5ECA-AE66-0E007871F0CD}" - }, - "assetHint": "levels/multiplayer/autocomponent_rpc/autocomponent_rpc_netlevelentity.scriptcanvas" - } - }, "runtimeDataIsValid": true, - "runtimeDataOverrides": { - "source": { - "assetId": { - "guid": "{1D517006-AC01-5ECA-AE66-0E007871F0CD}" - }, - "assetHint": "levels/multiplayer/autocomponent_rpc/autocomponent_rpc_netlevelentity.scriptcanvas" - } + "sourceHandle": { + "id": "{1D517006-AC01-5ECA-AE66-0E007871F0CD}", + "path": "levels/multiplayer/autocomponent_rpc/autocomponent_rpc_netlevelentity.scriptcanvas" } }, "Component_[731336627222243355]": { @@ -730,13 +706,6 @@ "$type": "NetBindComponent" } }, - "Component_[9816897251206708579]": { - "$type": "GenericComponentWrapper", - "Id": 9816897251206708579, - "m_template": { - "$type": "AutomatedTesting::NetworkTestPlayerComponent" - } - }, "Component_[9880860858035405475]": { "$type": "EditorOnlyEntityComponent", "Id": 9880860858035405475 diff --git a/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC.scriptcanvas b/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC.scriptcanvas index c1c77b14fe..7f3f8181ae 100644 --- a/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC.scriptcanvas +++ b/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC.scriptcanvas @@ -5,7 +5,7 @@ "ClassData": { "m_scriptCanvas": { "Id": { - "id": 2816238339133127497 + "id": 8397436129732444837 }, "Name": "AutoComponent_RPC", "Components": { @@ -37,7 +37,7 @@ } }, "Component_[9755768666831861951]": { - "$type": "{4D755CA9-AB92-462C-B24F-0B3376F19967} Graph", + "$type": "EditorGraph", "Id": 9755768666831861951, "m_graphData": { "m_nodes": [ @@ -1734,6 +1734,1542 @@ { "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, { "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" } @@ -3272,6 +4808,1542 @@ { "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, + { + "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" + }, { "m_id": "{82D3E2FD-ADFA-47F7-A889-D1172BF2EC49}" } @@ -4723,7 +7795,7 @@ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - 380.0, + 360.0, 620.0 ] }, @@ -4953,15 +8025,16 @@ }, { "Key": { - "id": 2816238339133127497 + "id": 8397436129732444837 }, "Value": { "ComponentData": { "{5F84B500-8C45-40D1-8EFC-A5306B241444}": { "$type": "SceneComponentSaveData", "ViewParams": { - "AnchorX": 260.0, - "AnchorY": 479.0 + "Scale": 0.8049999999999999, + "AnchorX": -166.45962524414063, + "AnchorY": -216.14906311035156 } } } diff --git a/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC_NetLevelEntity.scriptcanvas b/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC_NetLevelEntity.scriptcanvas index 5d61fea3e7..70730a4496 100644 --- a/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC_NetLevelEntity.scriptcanvas +++ b/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC_NetLevelEntity.scriptcanvas @@ -5,7 +5,7 @@ "ClassData": { "m_scriptCanvas": { "Id": { - "id": 7369225496155711251 + "id": 7558387155527535988 }, "Name": "AutoComponent_RPC_NetLevelEntity", "Components": { @@ -93,7 +93,6 @@ ], "Datums": [ { - "isOverloadedStorage": false, "scriptCanvasType": { "m_type": 1 }, @@ -108,6 +107,9 @@ "methodType": 2, "methodName": "GetAuthorityToClientNoParams_PlayFxEventByEntityId", "className": "NetworkTestLevelEntityComponent", + "resultSlotIDs": [ + {} + ], "inputSlots": [ { "m_id": "{AE2A0AA3-99DD-4DE4-AFEA-7560F078943C}" @@ -688,6 +690,199 @@ } } }, + { + "Id": { + "id": 11750998249450 + }, + "Name": "SC-Node(IsNetEntityRoleAuthority)", + "Components": { + "Component_[17217487756380135718]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 17217487756380135718, + "Slots": [ + { + "id": { + "m_id": "{C58EF254-1A51-443B-B35E-B26831323D27}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityId: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{98927A53-663A-452D-ABAF-01D31F7D5D53}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{89F646CA-FBC6-45D2-916B-0B47474EE693}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{3FFC81A6-5C31-4CBA-8253-5DF361F10610}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Is Role Authority", + "DisplayDataType": { + "m_type": 0 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "Entity Id" + } + ], + "methodType": 2, + "methodName": "IsNetEntityRoleAuthority", + "className": "NetBindComponent", + "inputSlots": [ + { + "m_id": "{C58EF254-1A51-443B-B35E-B26831323D27}" + } + ], + "prettyClassName": "NetBindComponent" + } + } + }, + { + "Id": { + "id": 13206992162794 + }, + "Name": "SC-Node(Gate)", + "Components": { + "Component_[18126119383071583133]": { + "$type": "Gate", + "Id": 18126119383071583133, + "Slots": [ + { + "id": { + "m_id": "{3896AA13-516C-410F-AB9C-2CAA5E71AEF6}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Condition", + "toolTip": "If true the node will signal the Output and proceed execution", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{F651B19A-FD1A-44EB-9C16-0CDB44CD85AA}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "Input signal", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{78807DC9-82B7-4893-ADA4-53E51C2AD3D1}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "True", + "toolTip": "Signaled if the condition provided evaluates to true.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{3B353484-F14C-4D93-AD1D-6F3EDAE4B71C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "False", + "toolTip": "Signaled if the condition provided evaluates to false.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 0 + }, + "isNullPointer": false, + "$type": "bool", + "value": false, + "label": "Condition" + } + ] + } + } + }, { "Id": { "id": 57025381737912 @@ -882,7 +1077,6 @@ ], "Datums": [ { - "isOverloadedStorage": false, "scriptCanvasType": { "m_type": 1 }, @@ -897,6 +1091,9 @@ "methodType": 2, "methodName": "AuthorityToClientNoParams_PlayFxByEntityId", "className": "NetworkTestLevelEntityComponent", + "resultSlotIDs": [ + {} + ], "inputSlots": [ { "m_id": "{029728DF-0939-4D64-A9A1-3DB4B8AF127E}" @@ -1036,7 +1233,6 @@ ], "Datums": [ { - "isOverloadedStorage": false, "scriptCanvasType": { "m_type": 4, "m_azType": "{F429F985-AF00-529B-8449-16E56694E5F9}" @@ -1223,34 +1419,6 @@ } } }, - { - "Id": { - "id": 57055446508984 - }, - "Name": "srcEndpoint=(TimeDelay: Done), destEndpoint=(Repeater: Start)", - "Components": { - "Component_[6292481678297438578]": { - "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", - "Id": 6292481678297438578, - "sourceEndpoint": { - "nodeId": { - "id": 57012496836024 - }, - "slotId": { - "m_id": "{158B30BE-BD39-40AE-A8A8-F0E5694F0180}" - } - }, - "targetEndpoint": { - "nodeId": { - "id": 56986727032248 - }, - "slotId": { - "m_id": "{07267CBA-B377-4B57-8A04-E322F8BFC07F}" - } - } - } - } - }, { "Id": { "id": 10269167405311 @@ -1530,6 +1698,118 @@ } } } + }, + { + "Id": { + "id": 13030898503658 + }, + "Name": "srcEndpoint=(TimeDelay: Done), destEndpoint=(IsNetEntityRoleAuthority: In)", + "Components": { + "Component_[14235185264262332827]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14235185264262332827, + "sourceEndpoint": { + "nodeId": { + "id": 57012496836024 + }, + "slotId": { + "m_id": "{158B30BE-BD39-40AE-A8A8-F0E5694F0180}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 11750998249450 + }, + "slotId": { + "m_id": "{98927A53-663A-452D-ABAF-01D31F7D5D53}" + } + } + } + } + }, + { + "Id": { + "id": 14005856079850 + }, + "Name": "srcEndpoint=(IsNetEntityRoleAuthority: Out), destEndpoint=(If: In)", + "Components": { + "Component_[16302238484508620286]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 16302238484508620286, + "sourceEndpoint": { + "nodeId": { + "id": 11750998249450 + }, + "slotId": { + "m_id": "{89F646CA-FBC6-45D2-916B-0B47474EE693}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 13206992162794 + }, + "slotId": { + "m_id": "{F651B19A-FD1A-44EB-9C16-0CDB44CD85AA}" + } + } + } + } + }, + { + "Id": { + "id": 14302208823274 + }, + "Name": "srcEndpoint=(IsNetEntityRoleAuthority: Is Role Authority), destEndpoint=(If: Condition)", + "Components": { + "Component_[3887593885874168259]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 3887593885874168259, + "sourceEndpoint": { + "nodeId": { + "id": 11750998249450 + }, + "slotId": { + "m_id": "{3FFC81A6-5C31-4CBA-8253-5DF361F10610}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 13206992162794 + }, + "slotId": { + "m_id": "{3896AA13-516C-410F-AB9C-2CAA5E71AEF6}" + } + } + } + } + }, + { + "Id": { + "id": 14637216272362 + }, + "Name": "srcEndpoint=(If: True), destEndpoint=(Repeater: Start)", + "Components": { + "Component_[8721834474263401249]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 8721834474263401249, + "sourceEndpoint": { + "nodeId": { + "id": 13206992162794 + }, + "slotId": { + "m_id": "{78807DC9-82B7-4893-ADA4-53E51C2AD3D1}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 56986727032248 + }, + "slotId": { + "m_id": "{07267CBA-B377-4B57-8A04-E322F8BFC07F}" + } + } + } + } } ] }, @@ -1571,6 +1851,37 @@ } } }, + { + "Key": { + "id": 11750998249450 + }, + "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": [ + 100.0, + 60.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{73B270BC-9743-41C1-9E48-0CAB5A63AC97}" + } + } + } + }, { "Key": { "id": 11993350262154 @@ -1587,8 +1898,8 @@ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - -120.0, - 340.0 + 60.0, + 480.0 ] }, "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { @@ -1618,8 +1929,8 @@ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - 340.0, - 360.0 + 520.0, + 500.0 ] }, "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { @@ -1633,6 +1944,36 @@ } } }, + { + "Key": { + "id": 13206992162794 + }, + "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": [ + 540.0, + 60.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{3F73BD0E-D02D-4A48-9E25-F9FD4A0F1B89}" + } + } + } + }, { "Key": { "id": 16962627423626 @@ -1649,8 +1990,8 @@ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - 440.0, - -40.0 + 1240.0, + 0.0 ] }, "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { @@ -1680,8 +2021,8 @@ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - 80.0, - -60.0 + 860.0, + 0.0 ] }, "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { @@ -1740,8 +2081,8 @@ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - 800.0, - 260.0 + 980.0, + 400.0 ] }, "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { @@ -1770,8 +2111,8 @@ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - 420.0, - 100.0 + 1220.0, + 140.0 ] }, "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { @@ -1800,8 +2141,8 @@ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { "$type": "GeometrySaveData", "Position": [ - 800.0, - 460.0 + 980.0, + 600.0 ] }, "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { @@ -1877,16 +2218,16 @@ }, { "Key": { - "id": 7369225496155711251 + "id": 7558387155527535988 }, "Value": { "ComponentData": { "{5F84B500-8C45-40D1-8EFC-A5306B241444}": { "$type": "SceneComponentSaveData", "ViewParams": { - "Scale": 0.7585823890144868, - "AnchorX": -205.64674377441406, - "AnchorY": -467.9781799316406 + "Scale": 0.9585879578077288, + "AnchorX": 488.2181091308594, + "AnchorY": -175.25778198242188 } } } @@ -1915,6 +2256,14 @@ "Key": 6462358712820489356, "Value": 1 }, + { + "Key": 8065262779685207188, + "Value": 1 + }, + { + "Key": 8452971738487658154, + "Value": 1 + }, { "Key": 10684225535275896474, "Value": 3 diff --git a/AutomatedTesting/Passes/MainPipeline.pass b/AutomatedTesting/Passes/MainPipeline.pass index c34c556983..39b992a11d 100644 --- a/AutomatedTesting/Passes/MainPipeline.pass +++ b/AutomatedTesting/Passes/MainPipeline.pass @@ -42,6 +42,16 @@ "RayTracingAccelerationStructurePass" ] }, + { + "Name": "TerrainDetailTextureComputePass", + "TemplateName": "TerrainDetailTextureComputePassTemplate", + "Enabled": false + }, + { + "Name": "TerrainMacroTextureComputePass", + "TemplateName": "TerrainMacroTextureComputePassTemplate", + "Enabled": false + }, { "Name": "DepthPrePass", "TemplateName": "DepthMSAAParentTemplate", @@ -215,7 +225,7 @@ // Note: The following two lines represent the choice of rendering pipeline for the hair. // You can either choose to use PPLL or ShortCut and accordingly change the flag // 'm_usePPLLRenderTechnique' in the class 'HairFeatureProcessor.cpp' -// "TemplateName": "HairParentPassTemplate", + // "TemplateName": "HairParentPassTemplate", "TemplateName": "HairParentShortCutPassTemplate", "Enabled": true, "Connections": [ diff --git a/Code/Editor/Controls/BitmapToolTip.cpp b/Code/Editor/Controls/BitmapToolTip.cpp deleted file mode 100644 index d639ac0677..0000000000 --- a/Code/Editor/Controls/BitmapToolTip.cpp +++ /dev/null @@ -1,369 +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 - * - */ - - -// Description : Tooltip that displays bitmap. - - -#include "EditorDefs.h" - -#include "BitmapToolTip.h" - -// Qt -#include - -// Editor -#include "Util/Image.h" -#include "Util/ImageUtil.h" - - -static const int STATIC_TEXT_C_HEIGHT = 42; -static const int HISTOGRAM_C_HEIGHT = 130; - -///////////////////////////////////////////////////////////////////////////// -// CBitmapToolTip -CBitmapToolTip::CBitmapToolTip(QWidget* parent) - : QWidget(parent, Qt::ToolTip) - , m_staticBitmap(new QLabel(this)) - , m_staticText(new QLabel(this)) - , m_rgbaHistogram(new CImageHistogramCtrl(this)) - , m_alphaChannelHistogram(new CImageHistogramCtrl(this)) -{ - m_nTimer = 0; - m_hToolWnd = nullptr; - m_bShowHistogram = true; - m_bShowFullsize = false; - m_eShowMode = ESHOW_RGB; - - connect(&m_timer, &QTimer::timeout, this, &CBitmapToolTip::OnTimer); - - auto* layout = new QVBoxLayout(this); - layout->setSizeConstraint(QLayout::SetFixedSize); - - layout->addWidget(m_staticBitmap); - layout->addWidget(m_staticText); - - auto* histogramLayout = new QHBoxLayout(); - histogramLayout->addWidget(m_rgbaHistogram); - histogramLayout->addWidget(m_alphaChannelHistogram); - m_alphaChannelHistogram->setVisible(false); - - layout->addLayout(histogramLayout); - - setLayout(layout); -} - -CBitmapToolTip::~CBitmapToolTip() -{ -} - -////////////////////////////////////////////////////////////////////////// -void CBitmapToolTip::GetShowMode(EShowMode& eShowMode, bool& bShowInOriginalSize) const -{ - bShowInOriginalSize = CheckVirtualKey(Qt::Key_Space); - eShowMode = ESHOW_RGB; - - if (m_bHasAlpha) - { - if (CheckVirtualKey(Qt::Key_Control)) - { - eShowMode = ESHOW_RGB_ALPHA; - } - else if (CheckVirtualKey(Qt::Key_Alt)) - { - eShowMode = ESHOW_ALPHA; - } - else if (CheckVirtualKey(Qt::Key_Shift)) - { - eShowMode = ESHOW_RGBA; - } - } - else if (m_bIsLimitedHDR) - { - if (CheckVirtualKey(Qt::Key_Shift)) - { - eShowMode = ESHOW_RGBE; - } - } -} - -const char* CBitmapToolTip::GetShowModeDescription(EShowMode eShowMode, [[maybe_unused]] bool bShowInOriginalSize) const -{ - switch (eShowMode) - { - case ESHOW_RGB: - return "RGB"; - case ESHOW_RGB_ALPHA: - return "RGB+A"; - case ESHOW_ALPHA: - return "Alpha"; - case ESHOW_RGBA: - return "RGBA"; - case ESHOW_RGBE: - return "RGBExp"; - } - - return ""; -} - -void CBitmapToolTip::RefreshViewmode() -{ - LoadImage(m_filename); - - if (m_eShowMode == ESHOW_RGB_ALPHA || m_eShowMode == ESHOW_RGBA) - { - m_rgbaHistogram->setVisible(true); - m_alphaChannelHistogram->setVisible(true); - } - else if (m_eShowMode == ESHOW_ALPHA) - { - m_rgbaHistogram->setVisible(false); - m_alphaChannelHistogram->setVisible(true); - } - else - { - m_rgbaHistogram->setVisible(true); - m_alphaChannelHistogram->setVisible(false); - } -} - -bool CBitmapToolTip::LoadImage(const QString& imageFilename) -{ - EShowMode eShowMode = ESHOW_RGB; - const char* pShowModeDescription = "RGB"; - bool bShowInOriginalSize = false; - - GetShowMode(eShowMode, bShowInOriginalSize); - pShowModeDescription = GetShowModeDescription(eShowMode, bShowInOriginalSize); - - QString convertedFileName = Path::GamePathToFullPath(Path::ReplaceExtension(imageFilename, ".dds")); - - // We need to check against both the image filename and the converted filename as it is possible that the - // converted file existed but failed to load previously and we reverted to loading the source asset. - bool alreadyLoadedImage = ((m_filename == convertedFileName) || (m_filename == imageFilename)); - if (alreadyLoadedImage && (m_eShowMode == eShowMode) && (m_bShowFullsize == bShowInOriginalSize)) - { - return true; - } - - CCryFile fileCheck; - if (!fileCheck.Open(convertedFileName.toUtf8().data(), "rb")) - { - // if we didn't find it, then default back to just using what we can find (if any) - convertedFileName = imageFilename; - } - else - { - fileCheck.Close(); - } - - m_eShowMode = eShowMode; - m_bShowFullsize = bShowInOriginalSize; - - CImageEx image; - image.SetHistogramEqualization(CheckVirtualKey(Qt::Key_Shift)); - bool loadedRequestedAsset = true; - if (!CImageUtil::LoadImage(convertedFileName, image)) - { - //Failed to load the requested asset, let's try loading the source asset if available. - loadedRequestedAsset = false; - if (!CImageUtil::LoadImage(imageFilename, image)) - { - m_staticBitmap->clear(); - return false; - } - } - - QString imginfo; - - m_filename = loadedRequestedAsset ? convertedFileName : imageFilename; - m_bHasAlpha = image.HasAlphaChannel(); - m_bIsLimitedHDR = image.IsLimitedHDR(); - - GetShowMode(eShowMode, bShowInOriginalSize); - pShowModeDescription = GetShowModeDescription(eShowMode, bShowInOriginalSize); - - if (m_bHasAlpha) - { - imginfo = tr("%1x%2 %3\nShowing %4 (ALT=Alpha, SHIFT=RGBA, CTRL=RGB+A, SPACE=see in original size)"); - } - else if (m_bIsLimitedHDR) - { - imginfo = tr("%1x%2 %3\nShowing %4 (SHIFT=see hist.-equalized, SPACE=see in original size)"); - } - else - { - imginfo = tr("%1x%2 %3\nShowing %4 (SPACE=see in original size)"); - } - - imginfo = imginfo.arg(image.GetWidth()).arg(image.GetHeight()).arg(image.GetFormatDescription()).arg(pShowModeDescription); - - m_staticText->setText(imginfo); - - int w = image.GetWidth(); - int h = image.GetHeight(); - int multiplier = (m_eShowMode == ESHOW_RGB_ALPHA ? 2 : 1); - int originalW = w * multiplier; - int originalH = h; - - if (!bShowInOriginalSize || (w == 0)) - { - w = 256; - } - if (!bShowInOriginalSize || (h == 0)) - { - h = 256; - } - - w *= multiplier; - - resize(w + 4, h + 4 + STATIC_TEXT_C_HEIGHT + HISTOGRAM_C_HEIGHT); - setVisible(true); - - CImageEx scaledImage; - - if (bShowInOriginalSize && (originalW < w)) - { - w = originalW; - } - if (bShowInOriginalSize && (originalH < h)) - { - h = originalH; - } - - scaledImage.Allocate(w, h); - - if (m_eShowMode == ESHOW_RGB_ALPHA) - { - CImageUtil::ScaleToDoubleFit(image, scaledImage); - } - else - { - CImageUtil::ScaleToFit(image, scaledImage); - } - - if (m_eShowMode == ESHOW_RGB || m_eShowMode == ESHOW_RGBE) - { - scaledImage.SwapRedAndBlue(); - scaledImage.FillAlpha(); - } - else if (m_eShowMode == ESHOW_ALPHA) - { - for (int hh = 0; hh < scaledImage.GetHeight(); hh++) - { - for (int ww = 0; ww < scaledImage.GetWidth(); ww++) - { - int a = scaledImage.ValueAt(ww, hh) >> 24; - scaledImage.ValueAt(ww, hh) = RGB(a, a, a); - } - } - } - else if (m_eShowMode == ESHOW_RGB_ALPHA) - { - int halfWidth = scaledImage.GetWidth() / 2; - for (int hh = 0; hh < scaledImage.GetHeight(); hh++) - { - for (int ww = 0; ww < halfWidth; ww++) - { - int r = GetRValue(scaledImage.ValueAt(ww, hh)); - int g = GetGValue(scaledImage.ValueAt(ww, hh)); - int b = GetBValue(scaledImage.ValueAt(ww, hh)); - int a = scaledImage.ValueAt(ww, hh) >> 24; - scaledImage.ValueAt(ww, hh) = RGB(b, g, r); - scaledImage.ValueAt(ww + halfWidth, hh) = RGB(a, a, a); - } - } - } - else //if (m_showMode == ESHOW_RGBA) - { - scaledImage.SwapRedAndBlue(); - } - - QImage qImage(scaledImage.GetWidth(), scaledImage.GetHeight(), QImage::Format_RGB32); - memcpy(qImage.bits(), scaledImage.GetData(), qImage.sizeInBytes()); - m_staticBitmap->setPixmap(QPixmap::fromImage(qImage)); - - if (m_bShowHistogram && scaledImage.GetData()) - { - m_rgbaHistogram->ComputeHistogram(image, CImageHistogram::eImageFormat_32BPP_BGRA); - m_rgbaHistogram->setDrawMode(EHistogramDrawMode::OverlappedRGB); - - m_alphaChannelHistogram->histogramDisplay()->CopyComputedDataFrom(m_rgbaHistogram->histogramDisplay()); - m_alphaChannelHistogram->setDrawMode(EHistogramDrawMode::AlphaChannel); - } - - return true; -} - -void CBitmapToolTip::OnTimer() -{ - /* - if (IsWindowVisible()) - { - if (m_bHaveAnythingToRender) - Invalidate(); - } - */ - if (m_hToolWnd) - { - QRect toolRc(m_toolRect); - QRect rc = geometry(); - QPoint cursorPos = QCursor::pos(); - toolRc.moveTopLeft(m_hToolWnd->mapToGlobal(toolRc.topLeft())); - if (!toolRc.contains(cursorPos) && !rc.contains(cursorPos)) - { - setVisible(false); - } - else - { - RefreshViewmode(); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CBitmapToolTip::showEvent([[maybe_unused]] QShowEvent* event) -{ - QPoint cursorPos = QCursor::pos(); - move(cursorPos); - m_timer.start(500); -} - -////////////////////////////////////////////////////////////////////////// -void CBitmapToolTip::hideEvent([[maybe_unused]] QHideEvent* event) -{ - m_timer.stop(); -} - -////////////////////////////////////////////////////////////////////////// - -void CBitmapToolTip::keyPressEvent(QKeyEvent* event) -{ - if (event->key() == Qt::Key_Control || event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift) - { - RefreshViewmode(); - } -} - -void CBitmapToolTip::keyReleaseEvent(QKeyEvent* event) -{ - if (event->key() == Qt::Key_Control || event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift) - { - RefreshViewmode(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CBitmapToolTip::SetTool(QWidget* pWnd, const QRect& rect) -{ - assert(pWnd); - m_hToolWnd = pWnd; - m_toolRect = rect; -} - -#include diff --git a/Code/Editor/Controls/BitmapToolTip.h b/Code/Editor/Controls/BitmapToolTip.h deleted file mode 100644 index 5b7c56cbf3..0000000000 --- a/Code/Editor/Controls/BitmapToolTip.h +++ /dev/null @@ -1,88 +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 - * - */ - - -// Description : Tooltip that displays bitmap. - - -#ifndef CRYINCLUDE_EDITOR_CONTROLS_BITMAPTOOLTIP_H -#define CRYINCLUDE_EDITOR_CONTROLS_BITMAPTOOLTIP_H -#pragma once - - -#if !defined(Q_MOC_RUN) -#include "Controls/ImageHistogramCtrl.h" - -#include -#include -#endif - -////////////////////////////////////////////////////////////////////////// -class CBitmapToolTip - : public QWidget -{ - Q_OBJECT - // Construction -public: - - enum EShowMode - { - ESHOW_RGB = 0, - ESHOW_ALPHA, - ESHOW_RGBA, - ESHOW_RGB_ALPHA, - ESHOW_RGBE - }; - - CBitmapToolTip(QWidget* parent = nullptr); - virtual ~CBitmapToolTip(); - - bool Create(const RECT& rect); - - // Attributes -public: - - // Operations -public: - void RefreshViewmode(); - - bool LoadImage(const QString& imageFilename); - void SetTool(QWidget* pWnd, const QRect& rect); - - // Generated message map functions -protected: - void OnTimer(); - - void keyPressEvent(QKeyEvent* event) override; - void keyReleaseEvent(QKeyEvent* event) override; - - void showEvent(QShowEvent* event) override; - void hideEvent(QHideEvent* event) override; - -private: - void GetShowMode(EShowMode& showMode, bool& showInOriginalSize) const; - const char* GetShowModeDescription(EShowMode showMode, bool showInOriginalSize) const; - - QLabel* m_staticBitmap; - QLabel* m_staticText; - QString m_filename; - bool m_bShowHistogram; - EShowMode m_eShowMode; - bool m_bShowFullsize; - bool m_bHasAlpha; - bool m_bIsLimitedHDR; - CImageHistogramCtrl* m_rgbaHistogram; - CImageHistogramCtrl* m_alphaChannelHistogram; - int m_nTimer; - QWidget* m_hToolWnd; - QRect m_toolRect; - QTimer m_timer; -}; - - -#endif // CRYINCLUDE_EDITOR_CONTROLS_BITMAPTOOLTIP_H diff --git a/Code/Editor/Controls/QBitmapPreviewDialog.cpp b/Code/Editor/Controls/QBitmapPreviewDialog.cpp deleted file mode 100644 index 912db3708c..0000000000 --- a/Code/Editor/Controls/QBitmapPreviewDialog.cpp +++ /dev/null @@ -1,172 +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 "EditorDefs.h" - -#include "QBitmapPreviewDialog.h" -#include - -#include -#include -#include -#include - -void QBitmapPreviewDialog::ImageData::setRgba8888(const void* buffer, const int& w, const int& h) -{ - const unsigned long bytes = w * h * 4; - m_buffer.resize(bytes); - memcpy(m_buffer.data(), buffer, bytes); - m_image = QImage((uchar*)m_buffer.constData(), w, h, QImage::Format::Format_RGBA8888); -} - -static void fillChecker(int w, int h, unsigned int* dst) -{ - for (int y = 0; y < h; y++) - { - for (int x = 0; x < w; x++) - { - dst[y * w + x] = 0xFF000000 | (((x >> 2) + (y >> 2)) % 2 == 0 ? 0x007F7F7F : 0x00000000); - } - } -} - -QBitmapPreviewDialog::QBitmapPreviewDialog(QWidget* parent) - : QWidget(parent) - , ui(new Ui::QBitmapTooltip) -{ - ui->setupUi(this); - setAttribute(Qt::WA_TranslucentBackground); - setAttribute(Qt::WA_ShowWithoutActivating); - - // Clear label text - ui->m_placeholderBitmap->setText(""); - ui->m_placeholderHistogram->setText(""); - - ui->m_bitmapSize->setProperty("tableRow", "Odd"); - ui->m_Mips->setProperty("tableRow", "Even"); - ui->m_Mean->setProperty("tableRow", "Odd"); - ui->m_StdDev->setProperty("tableRow", "Even"); - ui->m_Median->setProperty("tableRow", "Odd"); - ui->m_labelForBitmapSize->setProperty("tooltipLabel", "content"); - ui->m_labelForMean->setProperty("tooltipLabel", "content"); - ui->m_labelForMedian->setProperty("tooltipLabel", "content"); - ui->m_labelForMips->setProperty("tooltipLabel", "content"); - ui->m_labelForStdDev->setProperty("tooltipLabel", "content"); - ui->m_vBitmapSize->setProperty("tooltipLabel", "content"); - ui->m_vMean->setProperty("tooltipLabel", "content"); - ui->m_vMedian->setProperty("tooltipLabel", "content"); - ui->m_vMips->setProperty("tooltipLabel", "content"); - ui->m_vStdDev->setProperty("tooltipLabel", "content"); - - // Initialize placeholder images - const int w = 64; - const int h = 64; - QByteArray buffer; - buffer.resize(w * h * 4); - unsigned int* dst = (unsigned int*)buffer.data(); - fillChecker(w, h, dst); - m_checker.setRgba8888(buffer.constData(), w, h); - - m_initialSize = window()->window()->geometry().size(); -} - -QBitmapPreviewDialog::~QBitmapPreviewDialog() -{ - delete ui; -} - -void QBitmapPreviewDialog::setImageRgba8888(const void* buffer, const int& w, const int& h, [[maybe_unused]] const QString& info) -{ - m_imageMain.setRgba8888(buffer, w, h); -} - - -QRect QBitmapPreviewDialog::getHistogramArea() -{ - return QRect(ui->m_placeholderHistogram->pos(), ui->m_placeholderHistogram->size()); -} - -void QBitmapPreviewDialog::setFullSize(const bool& fullSize) -{ - if (fullSize) - { - QSize desktop = QApplication::screenAt(ui->m_placeholderBitmap->pos())->availableGeometry().size(); - QSize image = m_imageMain.m_image.size(); - QPoint location = mapToGlobal(ui->m_placeholderBitmap->pos()); - QSize finalSize; - finalSize.setWidth((image.width() < (desktop.width() - location.x())) ? image.width() : (desktop.width() - location.x())); - finalSize.setHeight((image.height() < (desktop.height() - location.y())) ? image.height() : (desktop.height() - location.y())); - float scale = (finalSize.width() < finalSize.height()) ? finalSize.width() / float(m_imageMain.m_image.width()) : finalSize.height() / float(m_imageMain.m_image.height()); - ui->m_placeholderBitmap->setFixedSize(scale * m_imageMain.m_image.size()); - } - else - { - ui->m_placeholderBitmap->setFixedSize(256, 256); - } - - adjustSize(); - - update(); -} - -void QBitmapPreviewDialog::paintEvent(QPaintEvent* e) -{ - QWidget::paintEvent(e); - QRect rect(ui->m_placeholderBitmap->pos(), ui->m_placeholderBitmap->size()); - drawImageData(rect, m_imageMain); -} - -void QBitmapPreviewDialog::drawImageData(const QRect& rect, const ImageData& imgData) -{ - // Draw the - QPainter p(this); - p.drawImage(rect.topLeft(), m_checker.m_image.scaled(rect.size())); - p.drawImage(rect.topLeft(), imgData.m_image.scaled(rect.size())); - - // Draw border - QPen pen; - pen.setColor(QColor(0, 0, 0)); - p.drawRect(rect.top(), rect.left(), rect.width() - 1, rect.height()); -} - -void QBitmapPreviewDialog::setSize(QString _value) -{ - ui->m_vBitmapSize->setText(_value); -} - -void QBitmapPreviewDialog::setMips(QString _value) -{ - ui->m_vMips->setText(_value); -} - -void QBitmapPreviewDialog::setMean(QString _value) -{ - ui->m_vMean->setText(_value); -} - -void QBitmapPreviewDialog::setMedian(QString _value) -{ - ui->m_vMedian->setText(_value); -} - -void QBitmapPreviewDialog::setStdDev(QString _value) -{ - ui->m_vStdDev->setText(_value); -} - -QSize QBitmapPreviewDialog::GetCurrentBitmapSize() -{ - return ui->m_placeholderBitmap->size(); -} - -QSize QBitmapPreviewDialog::GetOriginalImageSize() -{ - return m_imageMain.m_image.size(); -} - - -#include diff --git a/Code/Editor/Controls/QBitmapPreviewDialog.h b/Code/Editor/Controls/QBitmapPreviewDialog.h deleted file mode 100644 index a5429bc8f0..0000000000 --- a/Code/Editor/Controls/QBitmapPreviewDialog.h +++ /dev/null @@ -1,64 +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 - * - */ -#ifndef QBITMAPPREVIEWDIALOG_H -#define QBITMAPPREVIEWDIALOG_H - -#if !defined(Q_MOC_RUN) -#include -#include -#include -#endif - -class QLabel; - -namespace Ui { - class QBitmapTooltip; -} - -class QBitmapPreviewDialog - : public QWidget -{ - Q_OBJECT - - struct ImageData - { - QByteArray m_buffer; - QImage m_image; - - void setRgba8888(const void* buffer, const int& w, const int& h); - }; - -public: - explicit QBitmapPreviewDialog(QWidget* parent = 0); - virtual ~QBitmapPreviewDialog(); - QSize GetCurrentBitmapSize(); - QSize GetOriginalImageSize(); - -protected: - void setImageRgba8888(const void* buffer, const int& w, const int& h, const QString& info); - void setSize(QString _value); - void setMips(QString _value); - void setMean(QString _value); - void setMedian(QString _value); - void setStdDev(QString _value); - QRect getHistogramArea(); - void setFullSize(const bool& fullSize); - - void paintEvent(QPaintEvent* e) override; - -private: - void drawImageData(const QRect& rect, const ImageData& imgData); - -protected: - Ui::QBitmapTooltip* ui; - QSize m_initialSize; - ImageData m_checker; - ImageData m_imageMain; -}; - -#endif // QBITMAPPREVIEWDIALOG_H diff --git a/Code/Editor/Controls/QBitmapPreviewDialog.ui b/Code/Editor/Controls/QBitmapPreviewDialog.ui deleted file mode 100644 index 87b3a310ef..0000000000 --- a/Code/Editor/Controls/QBitmapPreviewDialog.ui +++ /dev/null @@ -1,390 +0,0 @@ - - - QBitmapTooltip - - - - 0 - 0 - 256 - 510 - - - - - 256 - 0 - - - - - 16777215 - 16777215 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 0 - 256 - - - - - 16777215 - 16777215 - - - - false - - - QFrame::NoFrame - - - QFrame::Sunken - - - Bitmap Area - - - Qt::AlignCenter - - - false - - - - - - - - 0 - 0 - - - - - 0 - 128 - - - - QFrame::NoFrame - - - QFrame::Sunken - - - Histogram Area - - - Qt::AlignCenter - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Size: - - - - - - - Qt::RightToLeft - - - Size Value - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - DXT5 Mips: - - - - - - - Qt::RightToLeft - - - Size Value - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Mean: - - - - - - - Qt::RightToLeft - - - Size Value - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - StdDev: - - - - - - - Qt::RightToLeft - - - Size Value - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - 0 - 24 - - - - - 16777215 - 24 - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Median: - - - - - - - Qt::RightToLeft - - - Size Value - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - diff --git a/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp b/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp deleted file mode 100644 index b47a535d2a..0000000000 --- a/Code/Editor/Controls/QBitmapPreviewDialogImp.cpp +++ /dev/null @@ -1,528 +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 "EditorDefs.h" - -#include "QBitmapPreviewDialogImp.h" - -// Cry -#include - -// EditorCore -#include -#include - -// QT -AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' -#include -#include -#include -#include -#include -AZ_POP_DISABLE_WARNING - -#include - -static const int kDefaultWidth = 256; -static const int kDefaultHeight = 256; - -QBitmapPreviewDialogImp::QBitmapPreviewDialogImp(QWidget* parent) - : QBitmapPreviewDialog(parent) - , m_image(new CImageEx()) - , m_showOriginalSize(false) - , m_showMode(ESHOW_RGB) - , m_histrogramMode(eHistogramMode_OverlappedRGB) -{ - setMouseTracking(true); - setImage(""); - ui->m_placeholderBitmap->setStyleSheet("background-color: rgba(0, 0, 0, 0);"); - ui->m_placeholderHistogram->setStyleSheet("background-color: rgba(0, 0, 0, 0);"); - - ui->m_labelForBitmapSize->setProperty("tooltipLabel", "Content"); - ui->m_labelForMean->setProperty("tooltipLabel", "Content"); - ui->m_labelForMedian->setProperty("tooltipLabel", "Content"); - ui->m_labelForMips->setProperty("tooltipLabel", "Content"); - ui->m_labelForStdDev->setProperty("tooltipLabel", "Content"); - - ui->m_vBitmapSize->setProperty("tooltipLabel", "Content"); - ui->m_vMean->setProperty("tooltipLabel", "Content"); - ui->m_vMedian->setProperty("tooltipLabel", "Content"); - ui->m_vMips->setProperty("tooltipLabel", "Content"); - ui->m_vStdDev->setProperty("tooltipLabel", "Content"); - - setUIStyleMode(EUISTYLE_IMAGE_ONLY); -} - -QBitmapPreviewDialogImp::~QBitmapPreviewDialogImp() -{ - SAFE_DELETE(m_image); -} - -void QBitmapPreviewDialogImp::setImage(const QString path) -{ - if (path.isEmpty() - || m_path == path - || !GetIEditor()->GetImageUtil()->LoadImage(path.toUtf8().data(), *m_image)) - { - return; - } - - m_showOriginalSize = isSizeSmallerThanDefault(); - m_path = path; - refreshData(); -} - -void QBitmapPreviewDialogImp::setShowMode(EShowMode mode) -{ - if (mode == ESHOW_NumModes) - { - return; - } - - m_showMode = mode; - refreshData(); - update(); -} - -void QBitmapPreviewDialogImp::toggleShowMode() -{ - m_showMode = (EShowMode)(((int)m_showMode + 1) % ESHOW_NumModes); - refreshData(); - update(); -} - -void QBitmapPreviewDialogImp::setUIStyleMode(EUIStyle mode) -{ - if (mode >= EUISTYLE_NumModes) - { - return; - } - - m_uiStyle = mode; - if (m_uiStyle == EUISTYLE_IMAGE_ONLY) - { - ui->m_placeholderHistogram->hide(); - - ui->m_labelForBitmapSize->hide(); - ui->m_labelForMean->hide(); - ui->m_labelForMedian->hide(); - ui->m_labelForMips->hide(); - ui->m_labelForStdDev->hide(); - - ui->m_vBitmapSize->hide(); - ui->m_vMean->hide(); - ui->m_vMedian->hide(); - ui->m_vMips->hide(); - ui->m_vStdDev->hide(); - } - else - { - ui->m_placeholderHistogram->show(); - - ui->m_labelForBitmapSize->show(); - ui->m_labelForMean->show(); - ui->m_labelForMedian->show(); - ui->m_labelForMips->show(); - ui->m_labelForStdDev->show(); - - ui->m_vBitmapSize->show(); - ui->m_vMean->show(); - ui->m_vMedian->show(); - ui->m_vMips->show(); - ui->m_vStdDev->show(); - } -} - -const QBitmapPreviewDialogImp::EShowMode& QBitmapPreviewDialogImp::getShowMode() const -{ - return m_showMode; -} - -void QBitmapPreviewDialogImp::setHistogramMode(EHistogramMode mode) -{ - if (mode == eHistogramMode_NumModes) - { - return; - } - - m_histrogramMode = mode; -} - -void QBitmapPreviewDialogImp::toggleHistrogramMode() -{ - m_histrogramMode = (EHistogramMode)(((int)m_histrogramMode + 1) % eHistogramMode_NumModes); - update(); -} - -const QBitmapPreviewDialogImp::EHistogramMode& QBitmapPreviewDialogImp::getHistogramMode() const -{ - return m_histrogramMode; -} - -void QBitmapPreviewDialogImp::toggleOriginalSize() -{ - m_showOriginalSize = !m_showOriginalSize; - - refreshData(); - update(); -} - -bool QBitmapPreviewDialogImp::isSizeSmallerThanDefault() -{ - return m_image->GetWidth() < kDefaultWidth && m_image->GetHeight() < kDefaultHeight; -} - -void QBitmapPreviewDialogImp::setOriginalSize(bool value) -{ - m_showOriginalSize = value; - - refreshData(); - update(); -} - - -const char* QBitmapPreviewDialogImp::GetShowModeDescription(EShowMode eShowMode, [[maybe_unused]] bool bShowInOriginalSize) const -{ - switch (eShowMode) - { - case ESHOW_RGB: - return "RGB"; - case ESHOW_RGB_ALPHA: - return "RGB+A"; - case ESHOW_ALPHA: - return "Alpha"; - case ESHOW_RGBA: - return "RGBA"; - case ESHOW_RGBE: - return "RGBExp"; - } - - return ""; -} - -const char* getHistrogramModeStr(QBitmapPreviewDialogImp::EHistogramMode mode, bool shortName) -{ - switch (mode) - { - case QBitmapPreviewDialogImp::eHistogramMode_Luminosity: - return shortName ? "Lum" : "Luminosity"; - case QBitmapPreviewDialogImp::eHistogramMode_OverlappedRGB: - return shortName ? "Overlap" : "Overlapped RGBA"; - case QBitmapPreviewDialogImp::eHistogramMode_SplitRGB: - return shortName ? "R|G|B" : "Split RGB"; - case QBitmapPreviewDialogImp::eHistogramMode_RedChannel: - return shortName ? "Red" : "Red Channel"; - case QBitmapPreviewDialogImp::eHistogramMode_GreenChannel: - return shortName ? "Green" : "Green Channel"; - case QBitmapPreviewDialogImp::eHistogramMode_BlueChannel: - return shortName ? "Blue" : "Blue Channel"; - case QBitmapPreviewDialogImp::eHistogramMode_AlphaChannel: - return shortName ? "Alpha" : "Alpha Channel"; - default: - break; - } - - return ""; -} - -void QBitmapPreviewDialogImp::refreshData() -{ - // Check if we have some usefull data loaded - if (m_image->GetWidth() * m_image->GetHeight() == 0) - { - return; - } - - int w = m_image->GetWidth(); - int h = m_image->GetHeight(); - - int multiplier = (m_showMode == ESHOW_RGB_ALPHA ? 2 : 1); - int originalW = w * multiplier; - int originalH = h; - - if (!m_showOriginalSize || (w == 0)) - { - w = kDefaultWidth; - } - if (!m_showOriginalSize || (h == 0)) - { - h = kDefaultHeight; - } - - w *= multiplier; - - CImageEx scaledImage; - - if (m_showOriginalSize && (originalW < w)) - { - w = originalW; - } - if (m_showOriginalSize && (originalH < h)) - { - h = originalH; - } - - scaledImage.Allocate(w, h); - - if (m_showMode == ESHOW_RGB_ALPHA) - { - GetIEditor()->GetImageUtil()->ScaleToDoubleFit(*m_image, scaledImage); - } - else - { - GetIEditor()->GetImageUtil()->ScaleToFit(*m_image, scaledImage); - } - - if (m_showMode == ESHOW_RGB || m_showMode == ESHOW_RGBE) - { - scaledImage.FillAlpha(); - } - else if (m_showMode == ESHOW_ALPHA) - { - for (int h2 = 0; h2 < scaledImage.GetHeight(); h2++) - { - for (int w2 = 0; w2 < scaledImage.GetWidth(); w2++) - { - int a = scaledImage.ValueAt(w2, h2) >> 24; - scaledImage.ValueAt(w2, h2) = RGB(a, a, a) | (a << 24); - } - } - } - else if (m_showMode == ESHOW_RGB_ALPHA) - { - int halfWidth = scaledImage.GetWidth() / 2; - for (int h2 = 0; h2 < scaledImage.GetHeight(); h2++) - { - for (int w2 = 0; w2 < halfWidth; w2++) - { - int r = GetRValue(scaledImage.ValueAt(w2, h2)); - int g = GetGValue(scaledImage.ValueAt(w2, h2)); - int b = GetBValue(scaledImage.ValueAt(w2, h2)); - int a = scaledImage.ValueAt(w2, h2) >> 24; - scaledImage.ValueAt(w2, h2) = RGB(r, g, b) | (a << 24); - scaledImage.ValueAt(w2 + halfWidth, h2) = RGB(a, a, a) | (a << 24); - } - } - } - - - setImageRgba8888(scaledImage.GetData(), w, h, ""); - setSize(QString().asprintf("%d x %d", m_image->GetWidth(), m_image->GetHeight())); - setMips(QString().asprintf("%d", m_image->GetNumberOfMipMaps())); - - setFullSize(m_showOriginalSize); - - // Compute histogram - m_histogram.ComputeHistogram((BYTE*)scaledImage.GetData(), w, h, CImageHistogram::eImageFormat_32BPP_RGBA); -} - -void QBitmapPreviewDialogImp::paintEvent(QPaintEvent* e) -{ - QBitmapPreviewDialog::paintEvent(e); - - //if showing original size hide other information so it's easier to see - if (m_showOriginalSize) - { - return; - } - if (m_uiStyle == EUISTYLE_IMAGE_ONLY) - { - return; - } - - QPainter p(this); - QPen pen; - QPainterPath path[4]; - - // Fill background color - QRect histogramRect = getHistogramArea(); - p.fillRect(histogramRect, QColor(255, 255, 255)); - - // Draw borders - pen.setColor(QColor(0, 0, 0)); - p.setPen(pen); - p.drawRect(histogramRect); - - // Draw histogram - - QVector drawChannels; - - switch (m_histrogramMode) - { - case eHistogramMode_Luminosity: - drawChannels.push_back(3); - break; - case eHistogramMode_SplitRGB: - drawChannels.push_back(0); - drawChannels.push_back(1); - drawChannels.push_back(2); - break; - case eHistogramMode_OverlappedRGB: - drawChannels.push_back(0); - drawChannels.push_back(1); - drawChannels.push_back(2); - break; - case eHistogramMode_RedChannel: - drawChannels.push_back(0); - break; - case eHistogramMode_GreenChannel: - drawChannels.push_back(1); - break; - case eHistogramMode_BlueChannel: - drawChannels.push_back(2); - break; - case eHistogramMode_AlphaChannel: - drawChannels.push_back(3); - break; - } - - int graphWidth = qMax(histogramRect.width(), 1); - int graphHeight = qMax(histogramRect.height() - 2, 0); - int graphBottom = histogramRect.bottom() + 1; - int currX[4] = {0, 0, 0, 0}; - int prevX[4] = {0, 0, 0, 0}; - float scale = 0.0f; - static const int numSubGraphs = 3; - const int subGraph = qCeil(graphWidth / numSubGraphs); - - // Fill background for Split RGB histogram - if (m_histrogramMode == eHistogramMode_SplitRGB) - { - const static QColor backgroundColor[numSubGraphs] = - { - QColor(255, 220, 220), - QColor(220, 255, 220), - QColor(220, 220, 255) - }; - - for (int i = 0; i < numSubGraphs; i++) - { - p.fillRect(histogramRect.left() + subGraph * i, - histogramRect.top(), - subGraph + (i == numSubGraphs - 1 ? 1 : 0), - histogramRect.height(), backgroundColor[i]); - } - } - - int lastHeight[CImageHistogram::kNumChannels] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX }; - - for (int x = 0; x < graphWidth; ++x) - { - for (int j = 0; j < drawChannels.size(); j++) - { - const int c = drawChannels[j]; - int& curr_x = currX[c]; - int& prev_x = prevX[c]; - int& last_height = lastHeight[c]; - QPainterPath& curr_path = path[c]; - - - curr_x = histogramRect.left() + x + 1; - int i = static_cast(((float)x / (graphWidth - 1)) * (CImageHistogram::kNumColorLevels - 1)); - if (m_histrogramMode == eHistogramMode_SplitRGB) - { - // Filter out to area which we are interested - const int k = x / subGraph; - if (k != c) - { - continue; - } - - i = qCeil((i - (subGraph * c)) * numSubGraphs); - i = qMin(i, CImageHistogram::kNumColorLevels - 1); - i = qMax(i, 0); - } - - if (m_histrogramMode == eHistogramMode_Luminosity) - { - scale = (float)m_histogram.m_lumCount[i] / m_histogram.m_maxLumCount; - } - else if (m_histogram.m_maxCount[c]) - { - scale = (float)m_histogram.m_count[c][i] / m_histogram.m_maxCount[c]; - } - - int height = static_cast(graphBottom - graphHeight * scale); - if (last_height == INT_MAX) - { - last_height = height; - } - - curr_path.moveTo(prev_x, last_height); - curr_path.lineTo(curr_x, height); - last_height = height; - - if (prev_x == INT_MAX) - { - prev_x = curr_x; - } - - prev_x = curr_x; - } - } - - static const QColor kChannelColor[4] = - { - QColor(255, 0, 0), - QColor(0, 255, 0), - QColor(0, 0, 255), - QColor(120, 120, 120) - }; - - for (int i = 0; i < drawChannels.size(); i++) - { - const int c = drawChannels[i]; - pen.setColor(kChannelColor[c]); - p.setPen(pen); - p.drawPath(path[c]); - } - - // Update histogram info - { - float mean = 0, stdDev = 0, median = 0; - - switch (m_histrogramMode) - { - case eHistogramMode_Luminosity: - case eHistogramMode_SplitRGB: - case eHistogramMode_OverlappedRGB: - mean = m_histogram.m_meanAvg; - stdDev = m_histogram.m_stdDevAvg; - median = m_histogram.m_medianAvg; - break; - case eHistogramMode_RedChannel: - mean = m_histogram.m_mean[0]; - stdDev = m_histogram.m_stdDev[0]; - median = m_histogram.m_median[0]; - break; - case eHistogramMode_GreenChannel: - mean = m_histogram.m_mean[1]; - stdDev = m_histogram.m_stdDev[1]; - median = m_histogram.m_median[1]; - break; - case eHistogramMode_BlueChannel: - mean = m_histogram.m_mean[2]; - stdDev = m_histogram.m_stdDev[2]; - median = m_histogram.m_median[2]; - break; - case eHistogramMode_AlphaChannel: - mean = m_histogram.m_mean[3]; - stdDev = m_histogram.m_stdDev[3]; - median = m_histogram.m_median[3]; - break; - } - QString val; - val.setNum(mean); - setMean(val); - val.setNum(stdDev); - setStdDev(val); - val.setNum(median); - setMedian(val); - } -} - -#include diff --git a/Code/Editor/Controls/QBitmapPreviewDialogImp.h b/Code/Editor/Controls/QBitmapPreviewDialogImp.h deleted file mode 100644 index 63de867e6c..0000000000 --- a/Code/Editor/Controls/QBitmapPreviewDialogImp.h +++ /dev/null @@ -1,89 +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 - * - */ -#ifndef QBITMAPPREVIEWDIALOG_IMP_H -#define QBITMAPPREVIEWDIALOG_IMP_H - -#if !defined(Q_MOC_RUN) -#include "QBitmapPreviewDialog.h" -#include -#endif - -class CImageEx; - -class QBitmapPreviewDialogImp - : public QBitmapPreviewDialog -{ - Q_OBJECT; -public: - - enum EUIStyle - { - EUISTYLE_IMAGE_ONLY, - EUISTYLE_IMAGE_HISTOGRAM, - EUISTYLE_NumModes - }; - - enum EShowMode - { - ESHOW_RGB = 0, - ESHOW_ALPHA, - ESHOW_RGBA, - ESHOW_RGB_ALPHA, - ESHOW_RGBE, - ESHOW_NumModes, - }; - - enum EHistogramMode - { - eHistogramMode_Luminosity, - eHistogramMode_OverlappedRGB, - eHistogramMode_SplitRGB, - eHistogramMode_RedChannel, - eHistogramMode_GreenChannel, - eHistogramMode_BlueChannel, - eHistogramMode_AlphaChannel, - eHistogramMode_NumModes, - }; - - explicit QBitmapPreviewDialogImp(QWidget* parent = 0); - virtual ~QBitmapPreviewDialogImp(); - - void setImage(const QString path); - - void setShowMode(EShowMode mode); - void toggleShowMode(); - void setUIStyleMode(EUIStyle mode); - const EShowMode& getShowMode() const; - - void setHistogramMode(EHistogramMode mode); - void toggleHistrogramMode(); - const EHistogramMode& getHistogramMode() const; - - void setOriginalSize(bool value); - void toggleOriginalSize(); - - bool isSizeSmallerThanDefault(); - void paintEvent(QPaintEvent* e) override; - -protected: - void refreshData(); - -private: - const char* GetShowModeDescription(EShowMode eShowMode, bool bShowInOriginalSize) const; - -private: - CImageEx* m_image; - QString m_path; - CImageHistogram m_histogram; - bool m_showOriginalSize; - EShowMode m_showMode; - EHistogramMode m_histrogramMode; - EUIStyle m_uiStyle; -}; - -#endif // QBITMAPPREVIEWDIALOG_IMP_H diff --git a/Code/Editor/Controls/QToolTipWidget.cpp b/Code/Editor/Controls/QToolTipWidget.cpp deleted file mode 100644 index 12a66a5d67..0000000000 --- a/Code/Editor/Controls/QToolTipWidget.cpp +++ /dev/null @@ -1,642 +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 "EditorDefs.h" - -#include - -#include "QBitmapPreviewDialogImp.h" -#include "qcoreapplication.h" -#include "qguiapplication.h" -#include "qapplication.h" -#include -#include -#include -#include - -void QToolTipWidget::RebuildLayout() -{ - if (m_title != nullptr) - { - m_title->hide(); - } - if (m_content != nullptr) - { - m_content->hide(); - } - if (m_specialContent != nullptr) - { - m_specialContent->hide(); - } - - //empty layout - while (m_layout->count() > 0) - { - m_layout->takeAt(0); - } - qDeleteAll(m_currentShortcuts); - m_currentShortcuts.clear(); - if (m_includeTextureShortcuts) - { - m_currentShortcuts.append(new QLabel(tr("Alt - Alpha"), this)); - m_currentShortcuts.back()->setProperty("tooltipLabel", "Shortcut"); - m_currentShortcuts.append(new QLabel(tr("Shift - RGBA"), this)); - m_currentShortcuts.back()->setProperty("tooltipLabel", "Shortcut"); - } - - if (m_title != nullptr && !m_title->text().isEmpty()) - { - m_layout->addWidget(m_title); - m_title->show(); - } - - for (QLabel* var : m_currentShortcuts) - { - if (var != nullptr) - { - m_layout->addWidget(var); - var->show(); - } - } - if (m_specialContent != nullptr) - { - m_layout->addWidget(m_specialContent); - m_specialContent->show(); - } - if (m_content != nullptr && !m_content->text().isEmpty()) - { - m_layout->addWidget(m_content); - m_content->show(); - } - m_background->adjustSize(); - adjustSize(); -} - -void QToolTipWidget::Hide() -{ - m_currentShortcuts.clear(); - hide(); -} - -void QToolTipWidget::Show(QPoint pos, ArrowDirection dir) -{ - if (!IsValid()) - { - return; - } - m_arrow->m_direction = dir; - pos = AdjustTipPosByArrowSize(pos, dir); - m_normalPos = pos; - move(pos); - RebuildLayout(); - show(); - m_arrow->show(); -} - -void QToolTipWidget::Display(QRect targetRect, ArrowDirection preferredArrowDir) -{ - if (!IsValid()) - { - return; - } - - KeepTipOnScreen(targetRect, preferredArrowDir); - - RebuildLayout(); - show(); - m_arrow->show(); -} - -void QToolTipWidget::TryDisplay(QPoint mousePos, const QRect& rect, [[maybe_unused]] ArrowDirection preferredArrowDir) -{ - if (rect.contains(mousePos)) - { - Display(rect, QToolTipWidget::ArrowDirection::ARROW_RIGHT); - } - else - { - hide(); - } - } - -void QToolTipWidget::TryDisplay(QPoint mousePos, const QWidget* widget, ArrowDirection preferredArrowDir) -{ - const QRect rect(widget->mapToGlobal(QPoint(0,0)), widget->size()); - TryDisplay(mousePos, rect, preferredArrowDir); -} - -void QToolTipWidget::SetTitle(QString title) -{ - if (!title.isEmpty()) - { - m_title->setText(title); - } - m_title->setProperty("tooltipLabel", "Title"); - - setWindowTitle("ToolTip - " + title); -} - -void QToolTipWidget::SetContent(QString content) -{ - m_content->setWordWrap(true); - - m_content->setProperty("tooltipLabel", "Content"); - //line-height is not supported via stylesheet so we use the html rich-text subset in QT for it. - m_content->setText(QString("%1").arg(content)); -} - -void QToolTipWidget::AppendContent(QString content) -{ - m_content->setText(m_content->text() + "\n\n" + content); - update(); - RebuildLayout(); - m_content->update(); - m_content->repaint(); -} - -QToolTipWidget::QToolTipWidget(QWidget* parent) - : QWidget(parent) -{ - m_background = new QWidget(this); - m_background->setProperty("tooltip", "Background"); - m_background->stackUnder(this); - m_title = new QLabel(this); - m_currentShortcuts = QVector(); - m_content = new QLabel(this); - m_specialContent = nullptr; - setWindowTitle("ToolTip"); - setObjectName("ToolTip"); - m_layout = new QVBoxLayout(this); - m_normalPos = QPoint(0, 0); - m_arrow = new QArrow(m_background); - setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint); - m_arrow->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint); - m_arrow->setAttribute(Qt::WA_TranslucentBackground, true); - m_background->setLayout(m_layout); - m_arrow->setObjectName("ToolTipArrow"); - m_background->setObjectName("ToolTipBackground"); - - //we need a drop shadow for the background - QGraphicsDropShadowEffect* dropShadow = new QGraphicsDropShadowEffect(this); - dropShadow->setBlurRadius(m_shadowRadius); - dropShadow->setColor(Qt::black); - dropShadow->setOffset(0); - dropShadow->setEnabled(true); - m_background->setGraphicsEffect(dropShadow); - //we need a second drop shadow effect for the arrow - dropShadow = new QGraphicsDropShadowEffect(m_arrow); - dropShadow->setBlurRadius(m_shadowRadius); - dropShadow->setColor(Qt::black); - dropShadow->setOffset(0); - dropShadow->setEnabled(true); - m_arrow->setGraphicsEffect(dropShadow); -} - -QToolTipWidget::~QToolTipWidget() -{ -} - -void QToolTipWidget::AddSpecialContent(QString type, QString dataStream) -{ - if (type.isEmpty()) - { - m_includeTextureShortcuts = false; - if (m_specialContent != nullptr) - { - delete m_specialContent; - m_specialContent = nullptr; - } - return; - } - if (type == "TEXTURE") - { - if (m_specialContent == nullptr) - { - QCoreApplication::instance()->installEventFilter(this); //grab the event filter while displaying the advanced texture tooltip - m_specialContent = new QBitmapPreviewDialogImp(this); - } - QString path(dataStream); - qobject_cast(m_specialContent)->setImage(path); - // set default showmode to RGB - qobject_cast(m_specialContent)->setShowMode(QBitmapPreviewDialogImp::EShowMode::ESHOW_RGB); - QString dir = (path.split("/").count() > path.split("\\").count()) ? path.split("/").back() : path.split("\\").back(); - SetTitle(dir); - //always use default size but not image size - qobject_cast(m_specialContent)->setOriginalSize(false); - m_includeTextureShortcuts = true; - } - else if (type == "ADD TO CONTENT") - { - AppendContent(dataStream); - - m_includeTextureShortcuts = false; - if (m_specialContent != nullptr) - { - delete m_specialContent; - m_specialContent = nullptr; - } - } - else if (type == "REPLACE TITLE") - { - SetTitle(dataStream); - m_includeTextureShortcuts = false; - if (m_specialContent != nullptr) - { - delete m_specialContent; - m_specialContent = nullptr; - } - } - else if (type == "REPLACE CONTENT") - { - SetContent(dataStream); - m_includeTextureShortcuts = false; - if (m_specialContent != nullptr) - { - delete m_specialContent; - m_specialContent = nullptr; - } - } - else - { - m_includeTextureShortcuts = false; - if (m_specialContent != nullptr) - { - delete m_specialContent; - m_specialContent = nullptr; - } - return; - } - - m_special = type; -} - - -bool QToolTipWidget::eventFilter(QObject* obj, QEvent* event) -{ - if (event->type() == QEvent::KeyPress) - { - if (m_special == "TEXTURE" && m_specialContent != nullptr) - { - const QKeyEvent* ke = static_cast(event); - Qt::KeyboardModifiers mods = ke->modifiers(); - if (mods & Qt::KeyboardModifier::AltModifier) - { - ((QBitmapPreviewDialogImp*)m_specialContent)->setShowMode(QBitmapPreviewDialogImp::ESHOW_ALPHA); - } - else if (mods & Qt::KeyboardModifier::ShiftModifier && !(mods & Qt::KeyboardModifier::ControlModifier)) - { - ((QBitmapPreviewDialogImp*)m_specialContent)->setShowMode(QBitmapPreviewDialogImp::ESHOW_RGBA); - } - } - } - if (event->type() == QEvent::KeyRelease) - { - if (m_special == "TEXTURE" && m_specialContent != nullptr) - { - const QKeyEvent* ke = static_cast(event); - Qt::KeyboardModifiers mods = ke->modifiers(); - if (!(mods& Qt::KeyboardModifier::AltModifier) && !(mods & Qt::KeyboardModifier::ShiftModifier)) - { - ((QBitmapPreviewDialogImp*)m_specialContent)->setShowMode(QBitmapPreviewDialogImp::ESHOW_RGB); - } - } - } - return QWidget::eventFilter(obj, event); -} - -void QToolTipWidget::hideEvent(QHideEvent* event) -{ - QWidget::hideEvent(event); - m_arrow->hide(); -} - -void QToolTipWidget::UpdateOptionalData(QString optionalData) -{ - AddSpecialContent(m_special, optionalData); -} - - - -QPoint QToolTipWidget::AdjustTipPosByArrowSize(QPoint pos, ArrowDirection dir) -{ - switch (dir) - { - case QToolTipWidget::ArrowDirection::ARROW_UP: - { - m_arrow->move(pos); - pos.setY(pos.y() + 10); - m_arrow->setFixedSize(20, 10); - pos -= QPoint(m_shadowRadius, m_shadowRadius); - break; - } - case QToolTipWidget::ArrowDirection::ARROW_LEFT: - { - m_arrow->move(pos); - pos.setX(pos.x() + 10); - m_arrow->setFixedSize(10, 20); - pos -= QPoint(m_shadowRadius, m_shadowRadius); - break; - } - case QToolTipWidget::ArrowDirection::ARROW_RIGHT: - { - pos.setX(pos.x() - 10); - m_arrow->move(QPoint(pos.x() + width(), pos.y())); - m_arrow->setFixedSize(10, 20); - pos -= QPoint(-m_shadowRadius, m_shadowRadius); - break; - } - case QToolTipWidget::ArrowDirection::ARROW_DOWN: - { - pos.setY(pos.y() - 10); - m_arrow->move(QPoint(pos.x(), pos.y() + height())); - m_arrow->setFixedSize(20, 10); - pos -= QPoint(m_shadowRadius, -m_shadowRadius); - break; - } - default: - m_arrow->move(-10, -10); - break; - } - return pos; -} - -bool QToolTipWidget::IsValid() -{ - if (m_title->text().isEmpty() || - (m_content->text().isEmpty() && m_specialContent == nullptr)) - { - return false; - } - return true; -} - -void QToolTipWidget::KeepTipOnScreen(QRect targetRect, ArrowDirection preferredArrowDir) -{ - QRect desktop = QApplication::desktop()->availableGeometry(this); - - if (this->isHidden()) - { - setAttribute(Qt::WA_DontShowOnScreen, true); - Show(QPoint(0, 0), preferredArrowDir); - hide(); - setAttribute(Qt::WA_DontShowOnScreen, false); - } - //else assume the size is right - - //calculate initial rect - QRect tipRect = QRect(0, 0, 0, 0); - switch (preferredArrowDir) - { - case QToolTipWidget::ArrowDirection::ARROW_UP: - { - //tip is below the widget with a left alignment - tipRect.setTopLeft(AdjustTipPosByArrowSize(targetRect.bottomLeft(), preferredArrowDir)); - break; - } - case QToolTipWidget::ArrowDirection::ARROW_LEFT: - { - //tip is on the right with the top being even - tipRect.setTopLeft(AdjustTipPosByArrowSize(targetRect.topRight(), preferredArrowDir)); - break; - } - case QToolTipWidget::ArrowDirection::ARROW_RIGHT: - { - //tip is on the left with the top being even - tipRect.setY(targetRect.top()); - tipRect.setX(targetRect.left() - width()); - tipRect.setTopLeft(AdjustTipPosByArrowSize(tipRect.topLeft(), preferredArrowDir)); - break; - } - case QToolTipWidget::ArrowDirection::ARROW_DOWN: - { - //tip is above the widget with a left alignment - tipRect.setX(targetRect.left()); - tipRect.setY(targetRect.top() - height()); - tipRect.setTopLeft(AdjustTipPosByArrowSize(tipRect.topLeft(), preferredArrowDir)); - break; - } - default: - { - //tip is on the right with the top being even - preferredArrowDir = QToolTipWidget::ArrowDirection::ARROW_LEFT; - tipRect.setTopLeft(AdjustTipPosByArrowSize(targetRect.topRight(), QToolTipWidget::ArrowDirection::ARROW_LEFT)); - break; - } - } - tipRect.setSize(size()); - - //FixPositioning - if (preferredArrowDir == ArrowDirection::ARROW_LEFT || preferredArrowDir == ArrowDirection::ARROW_RIGHT) - { - if (tipRect.left() <= desktop.left()) - { - m_arrow->m_direction = ArrowDirection::ARROW_LEFT; - tipRect.setTopLeft(AdjustTipPosByArrowSize(targetRect.topRight(), m_arrow->m_direction)); - } - else if (tipRect.right() >= desktop.right()) - { - m_arrow->m_direction = ArrowDirection::ARROW_RIGHT; - tipRect.setLeft(targetRect.left() - width()); - tipRect.setTopLeft(AdjustTipPosByArrowSize(tipRect.topLeft(), m_arrow->m_direction)); - } - } - else if (preferredArrowDir == ArrowDirection::ARROW_UP || preferredArrowDir == ArrowDirection::ARROW_DOWN) - { - if (tipRect.top() <= desktop.top()) - { - m_arrow->m_direction = ArrowDirection::ARROW_UP; - tipRect.setTopLeft(AdjustTipPosByArrowSize(targetRect.bottomLeft(), m_arrow->m_direction)); - } - else if (tipRect.bottom() >= desktop.bottom()) - { - m_arrow->m_direction = ArrowDirection::ARROW_DOWN; - tipRect.setY(targetRect.top() - height()); - tipRect.setTopLeft(AdjustTipPosByArrowSize(tipRect.topLeft(), m_arrow->m_direction)); - } - } - - //Nudge tip without arrow - if (preferredArrowDir == ArrowDirection::ARROW_UP || preferredArrowDir == ArrowDirection::ARROW_DOWN) - { - if (tipRect.left() <= desktop.left()) - { - tipRect.setLeft(desktop.left()); - } - else if (tipRect.right() >= desktop.right()) - { - tipRect.setLeft(desktop.right() - width()); - } - } - else if (preferredArrowDir == ArrowDirection::ARROW_RIGHT || preferredArrowDir == ArrowDirection::ARROW_LEFT) - { - if (tipRect.top() <= desktop.top()) - { - tipRect.setTop(desktop.top()); - } - else if (tipRect.bottom() >= desktop.bottom()) - { - tipRect.setTop(desktop.bottom() - height()); - } - } - - - m_normalPos = tipRect.topLeft(); - move(m_normalPos); -} - -QPolygonF QToolTipWidget::QArrow::CreateArrow() -{ - QVector vertex; - //3 points in triangle - vertex.reserve(3); - //all magic number below are given in order to draw smooth transitions between tooltip and arrow - if (m_direction == ArrowDirection::ARROW_UP) - { - vertex.push_back(QPointF(10, 1)); - vertex.push_back(QPointF(19, 10)); - vertex.push_back(QPointF(0, 10)); - } - else if (m_direction == ArrowDirection::ARROW_RIGHT) - { - vertex.push_back(QPointF(9, 10)); - vertex.push_back(QPointF(0, 19)); - vertex.push_back(QPointF(0, 1)); - } - else if (m_direction == ArrowDirection::ARROW_LEFT) - { - vertex.push_back(QPointF(1, 10)); - vertex.push_back(QPointF(10, 19)); - vertex.push_back(QPointF(10, 0)); - } - else //ArrowDirection::ARROW_DOWN - { - vertex.push_back(QPointF(10, 10)); - vertex.push_back(QPointF(19, 0)); - vertex.push_back(QPointF(0, 0)); - } - return QPolygonF(vertex); -} - -void QToolTipWidget::QArrow::paintEvent([[maybe_unused]] QPaintEvent* event) -{ - QColor color(255, 255, 255, 255); - QPainter painter(this); - painter.fillRect(rect(), Qt::transparent); //force transparency - painter.setRenderHint(QPainter::Antialiasing, false); - painter.setBrush(color); - painter.setPen(Qt::NoPen); - painter.drawPolygon(CreateArrow()); - //painter.setRenderHint(QPainter::Antialiasing, false); -} - -QToolTipWrapper::QToolTipWrapper(QWidget* parent) - : QObject(parent) -{ -} - -void QToolTipWrapper::SetTitle(QString title) -{ - m_title = title; -} - -void QToolTipWrapper::SetContent(QString content) -{ - AddSpecialContent("REPLACE CONTENT", content); -} - -void QToolTipWrapper::AppendContent(QString content) -{ - AddSpecialContent("ADD TO CONTENT", content); -} - -void QToolTipWrapper::AddSpecialContent(QString type, QString dataStream) -{ - if (type == "REPLACE CONTENT") - { - m_contentOperations.clear(); - } - m_contentOperations.push_back({type, dataStream}); -} - -void QToolTipWrapper::UpdateOptionalData(QString optionalData) -{ - m_contentOperations.push_back({"UPDATE OPTIONAL", optionalData}); -} - -void QToolTipWrapper::Display(QRect targetRect, QToolTipWidget::ArrowDirection preferredArrowDir) -{ - GetOrCreateToolTip()->Display(targetRect, preferredArrowDir); -} - -void QToolTipWrapper::TryDisplay(QPoint mousePos, const QWidget * widget, QToolTipWidget::ArrowDirection preferredArrowDir) -{ - GetOrCreateToolTip()->TryDisplay(mousePos, widget, preferredArrowDir); -} - -void QToolTipWrapper::TryDisplay(QPoint mousePos, const QRect & widget, QToolTipWidget::ArrowDirection preferredArrowDir) -{ - GetOrCreateToolTip()->TryDisplay(mousePos, widget, preferredArrowDir); -} - -void QToolTipWrapper::hide() -{ - DestroyToolTip(); -} - -void QToolTipWrapper::show() -{ - GetOrCreateToolTip()->show(); -} - -bool QToolTipWrapper::isVisible() const -{ - return m_actualTooltip && m_actualTooltip->isVisible(); -} - -void QToolTipWrapper::update() -{ - if (m_actualTooltip) - { - m_actualTooltip->update(); - } -} - -void QToolTipWrapper::ReplayContentOperations(QToolTipWidget* tooltipWidget) -{ - tooltipWidget->SetTitle(m_title); - for (const auto& operation : m_contentOperations) - { - if (operation.first == "UPDATE OPTIONAL") - { - tooltipWidget->UpdateOptionalData(operation.second); - } - else - { - tooltipWidget->AddSpecialContent(operation.first, operation.second); - } - } -} - -QToolTipWidget * QToolTipWrapper::GetOrCreateToolTip() -{ - if (!m_actualTooltip) - { - QToolTipWidget* tooltipWidget = new QToolTipWidget(static_cast(parent())); - tooltipWidget->setAttribute(Qt::WA_DeleteOnClose); - ReplayContentOperations(tooltipWidget); - m_actualTooltip = tooltipWidget; - } - return m_actualTooltip.data(); -} - -void QToolTipWrapper::DestroyToolTip() -{ - if (m_actualTooltip) - { - m_actualTooltip->deleteLater(); - } -} diff --git a/Code/Editor/Controls/QToolTipWidget.h b/Code/Editor/Controls/QToolTipWidget.h deleted file mode 100644 index 813f2a75fb..0000000000 --- a/Code/Editor/Controls/QToolTipWidget.h +++ /dev/null @@ -1,148 +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 - * - */ -#ifndef QToolTipWidget_h__ -#define QToolTipWidget_h__ - -#include "EditorCoreAPI.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -class IQToolTip -{ -public: - virtual void SetTitle(QString title) = 0; - virtual void SetContent(QString content) = 0; - virtual void AppendContent(QString content) = 0; - virtual void AddSpecialContent(QString type, QString dataStream) = 0; - virtual void UpdateOptionalData(QString optionalData) = 0; -}; - -class EDITOR_CORE_API QToolTipWidget - : public QWidget - , public IQToolTip -{ -public: - enum class ArrowDirection - { - ARROW_UP, - ARROW_LEFT, - ARROW_RIGHT, - ARROW_DOWN - }; - class QArrow - : public QWidget - { - public: - ArrowDirection m_direction; - QPoint m_pos; - QArrow(QWidget* parent) - : QWidget(parent){ setWindowFlags(Qt::ToolTip); } - virtual ~QArrow(){} - - QPolygonF CreateArrow(); - virtual void paintEvent(QPaintEvent*) override; - }; - QToolTipWidget(QWidget* parent); - ~QToolTipWidget(); - void SetTitle(QString title) override; - void SetContent(QString content) override; - void AppendContent(QString content) override; - void AddSpecialContent(QString type, QString dataStream) override; - void UpdateOptionalData(QString optionalData) override; - void Display(QRect targetRect, ArrowDirection preferredArrowDir); - - //! Displays the tooltip on the given widget, only if the mouse is over it. - void TryDisplay(QPoint mousePos, const QWidget* widget, ArrowDirection preferredArrowDir); - - //! Displays the tooltip on the given rect, only if the mouse is over it. - void TryDisplay(QPoint mousePos, const QRect& widget, ArrowDirection preferredArrowDir); - - void Hide(); - -protected: - void Show(QPoint pos, ArrowDirection dir); - bool IsValid(); - void KeepTipOnScreen(QRect targetRect, ArrowDirection preferredArrowDir); - QPoint AdjustTipPosByArrowSize(QPoint pos, ArrowDirection dir); - virtual bool eventFilter(QObject* obj, QEvent* event) override; - void RebuildLayout(); - virtual void hideEvent(QHideEvent*) override; - - QLabel* m_title; - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - QVector m_currentShortcuts; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - //can be anything from QLabel to QBitMapPreviewDialog - //must allow movement, and show/hide calls - QLabel* m_content; - QWidget* m_specialContent; - QWidget* m_background; - QVBoxLayout* m_layout; - QString m_special; - QPoint m_normalPos; - QArrow* m_arrow; - const int m_shadowRadius = 5; - bool m_includeTextureShortcuts; //added since Qt does not support modifier only shortcuts -}; - -// HACK: The EditorUI_QT classes all were keeping persistent references to QToolTipWidgets around -// This led to many, many top-level widget creations, which led to many platform-side window allocations -// which led to crashes in Qt5.15. As this is legacy code, this is a drop-in replacement that only -// allocates the actual QToolTipWidget (and thus platform window) while the tooltip is visible -class EDITOR_CORE_API QToolTipWrapper - : public QObject - , public IQToolTip -{ -public: - QToolTipWrapper(QWidget* parent); - - void SetTitle(QString title) override; - void SetContent(QString content) override; - void AppendContent(QString content) override; - void AddSpecialContent(QString type, QString dataStream) override; - void UpdateOptionalData(QString optionalData) override; - - void Display(QRect targetRect, QToolTipWidget::ArrowDirection preferredArrowDir); - void TryDisplay(QPoint mousePos, const QWidget* widget, QToolTipWidget::ArrowDirection preferredArrowDir); - void TryDisplay(QPoint mousePos, const QRect& widget, QToolTipWidget::ArrowDirection preferredArrowDir); - void hide(); - void show(); - bool isVisible() const; - void update(); - void repaint(){update();} //Things really shouldn't be calling repaint on these... - - void Hide(){hide();} - void close(){hide();} - -private: - void ReplayContentOperations(QToolTipWidget* tooltipWidget); - - QToolTipWidget* GetOrCreateToolTip(); - void DestroyToolTip(); - - AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // conditional expression is constant, needs to have dll-interface to be used by clients of class 'AzQtComponents::FilteredSearchWidget' - QPointer m_actualTooltip; - AZ_POP_DISABLE_WARNING - - QString m_title; - AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // conditional expression is constant, needs to have dll-interface to be used by clients of class 'AzQtComponents::FilteredSearchWidget' - QVector> m_contentOperations; - AZ_POP_DISABLE_WARNING -}; - - -#endif // QToolTipWidget_h__ diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp index 68c4acb95e..50d053ab9e 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp @@ -10,7 +10,6 @@ // Editor #include "PropertyCtrl.h" -#include "PropertyResourceCtrl.h" #include "PropertyGenericCtrl.h" #include "PropertyMiscCtrl.h" #include "PropertyMotionCtrl.h" @@ -21,7 +20,6 @@ void RegisterReflectedVarHandlers() if (!registered) { registered = true; - EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FileResourceSelectorWidgetHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequencePropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequenceIdPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LocalStringPropertyHandler()); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp b/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp deleted file mode 100644 index d26e978ae8..0000000000 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp +++ /dev/null @@ -1,383 +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 "EditorDefs.h" - -#include "PropertyResourceCtrl.h" - -// Qt -#include -#include - -// AzToolsFramework -#include -#include -#include - -// Editor -#include "Controls/QToolTipWidget.h" -#include "Controls/BitmapToolTip.h" - - -BrowseButton::BrowseButton(PropertyType type, QWidget* parent /*= nullptr*/) - : QToolButton(parent) - , m_propertyType(type) -{ - setAutoRaise(true); - setIcon(QIcon(QStringLiteral(":/stylesheet/img/UI20/browse-edit.svg"))); - connect(this, &QAbstractButton::clicked, this, &BrowseButton::OnClicked); -} - -void BrowseButton::SetPathAndEmit(const QString& path) -{ - //only emit if path changes. Old property control - if (path != m_path) - { - m_path = path; - emit PathChanged(m_path); - } -} - -class FileBrowseButton - : public BrowseButton -{ -public: - AZ_CLASS_ALLOCATOR(FileBrowseButton, AZ::SystemAllocator, 0); - FileBrowseButton(PropertyType type, QWidget* pParent = nullptr) - : BrowseButton(type, pParent) - { - setToolTip("Browse..."); - } - -private: - void OnClicked() override - { - QString tempValue(""); - if (!m_path.isEmpty() && !Path::GetExt(m_path).isEmpty()) - { - tempValue = m_path; - } - - AssetSelectionModel selection; - - if (m_propertyType == ePropertyTexture) - { - // Filters for texture. - selection = AssetSelectionModel::AssetGroupSelection("Texture"); - } - else - { - return; - } - - AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection); - if (selection.IsValid()) - { - QString newPath = Path::FullPathToGamePath(selection.GetResult()->GetFullPath().c_str()).c_str(); - - switch (m_propertyType) - { - case ePropertyTexture: - newPath.replace("\\\\", "/"); - if (newPath.size() > MAX_PATH) - { - newPath.resize(MAX_PATH); - } - } - - SetPathAndEmit(newPath); - } - } -}; - -class AudioControlSelectorButton - : public BrowseButton -{ -public: - AZ_CLASS_ALLOCATOR(AudioControlSelectorButton, AZ::SystemAllocator, 0); - - AudioControlSelectorButton(PropertyType type, QWidget* pParent = nullptr) - : BrowseButton(type, pParent) - { - setToolTip(tr("Select Audio Control")); - } - -private: - void OnClicked() override - { - AZStd::string resourceResult; - auto ConvertLegacyAudioPropertyType = [](const PropertyType type) -> AzToolsFramework::AudioPropertyType - { - switch (type) - { - case ePropertyAudioTrigger: - return AzToolsFramework::AudioPropertyType::Trigger; - case ePropertyAudioRTPC: - return AzToolsFramework::AudioPropertyType::Rtpc; - case ePropertyAudioSwitch: - return AzToolsFramework::AudioPropertyType::Switch; - case ePropertyAudioSwitchState: - return AzToolsFramework::AudioPropertyType::SwitchState; - case ePropertyAudioEnvironment: - return AzToolsFramework::AudioPropertyType::Environment; - case ePropertyAudioPreloadRequest: - return AzToolsFramework::AudioPropertyType::Preload; - default: - return AzToolsFramework::AudioPropertyType::NumTypes; - } - }; - - auto propType = ConvertLegacyAudioPropertyType(m_propertyType); - if (propType != AzToolsFramework::AudioPropertyType::NumTypes) - { - AzToolsFramework::AudioControlSelectorRequestBus::EventResult( - resourceResult, propType, &AzToolsFramework::AudioControlSelectorRequestBus::Events::SelectResource, - AZStd::string_view{ m_path.toUtf8().constData() }); - SetPathAndEmit(QString{ resourceResult.c_str() }); - } - } -}; - -class TextureEditButton - : public BrowseButton -{ -public: - AZ_CLASS_ALLOCATOR(TextureEditButton, AZ::SystemAllocator, 0); - TextureEditButton(QWidget* pParent = nullptr) - : BrowseButton(ePropertyTexture, pParent) - { - setIcon(QIcon(QStringLiteral(":/stylesheet/img/UI20/open-in-internal-app.svg"))); - setToolTip(tr("Launch default editor")); - } - -private: - void OnClicked() override - { - CFileUtil::EditTextureFile(m_path.toUtf8().data(), true); - } -}; - -FileResourceSelectorWidget::FileResourceSelectorWidget(QWidget* pParent /*= nullptr*/) - : QWidget(pParent) - , m_propertyType(ePropertyInvalid) - , m_tooltip(nullptr) -{ - m_pathEdit = new QLineEdit; - m_mainLayout = new QHBoxLayout(this); - m_mainLayout->addWidget(m_pathEdit, 1); - - m_mainLayout->setContentsMargins(0, 0, 0, 0); - -// KDAB just ported the MFC texture preview tooltip, but looks like Amazon added their own. Not sure which to use. -// To switch to Amazon QToolTipWidget, remove FileResourceSelectorWidget::event and m_previewTooltip -#ifdef USE_QTOOLTIPWIDGET - m_tooltip = new QToolTipWidget(this); - - installEventFilter(this); -#endif - connect(m_pathEdit, &QLineEdit::editingFinished, this, [this]() { OnPathChanged(m_pathEdit->text()); }); -} - -bool FileResourceSelectorWidget::eventFilter([[maybe_unused]] QObject* obj, QEvent* event) -{ - if (m_propertyType == ePropertyTexture) - { - if (event->type() == QEvent::ToolTip) - { - QHelpEvent* e = (QHelpEvent*)event; - - m_tooltip->AddSpecialContent("TEXTURE", m_path); - m_tooltip->TryDisplay(e->globalPos(), m_pathEdit, QToolTipWidget::ArrowDirection::ARROW_RIGHT); - - return true; - } - - if (event->type() == QEvent::Leave) - { - m_tooltip->hide(); - } - } - - return false; -} - -void FileResourceSelectorWidget::SetPropertyType(PropertyType type) -{ - if (m_propertyType == type) - { - return; - } - - //if the property type changed for some reason, delete all the existing widgets - if (!m_buttons.isEmpty()) - { - qDeleteAll(m_buttons.begin(), m_buttons.end()); - m_buttons.clear(); - } - - m_previewToolTip.reset(); - m_propertyType = type; - - switch (type) - { - case ePropertyTexture: - AddButton(new FileBrowseButton(type)); - AddButton(new TextureEditButton); - m_previewToolTip.reset(new CBitmapToolTip); - break; - case ePropertyAudioTrigger: - case ePropertyAudioSwitch: - case ePropertyAudioSwitchState: - case ePropertyAudioRTPC: - case ePropertyAudioEnvironment: - case ePropertyAudioPreloadRequest: - AddButton(new AudioControlSelectorButton(type)); - break; - default: - break; - } - - m_mainLayout->invalidate(); -} - -void FileResourceSelectorWidget::AddButton(BrowseButton* button) -{ - m_mainLayout->addWidget(button); - m_buttons.push_back(button); - connect(button, &BrowseButton::PathChanged, this, &FileResourceSelectorWidget::OnPathChanged); -} - -void FileResourceSelectorWidget::OnPathChanged(const QString& path) -{ - bool changed = SetPath(path); - if (changed) - { - emit PathChanged(m_path); - } -} - -bool FileResourceSelectorWidget::SetPath(const QString& path) -{ - bool changed = false; - - const QString newPath = path.toLower(); - if (m_path != newPath) - { - m_path = newPath; - UpdateWidgets(); - - changed = true; - } - - return changed; -} - - -void FileResourceSelectorWidget::UpdateWidgets() -{ - m_pathEdit->setText(m_path); - - foreach(BrowseButton * button, m_buttons) - { - button->SetPath(m_path); - } - - if (m_previewToolTip) - { - m_previewToolTip->SetTool(this, rect()); - } -} - -QString FileResourceSelectorWidget::GetPath() const -{ - return m_path; -} - - - -QWidget* FileResourceSelectorWidget::GetLastInTabOrder() -{ - return m_buttons.empty() ? nullptr : m_buttons.last(); -} - -QWidget* FileResourceSelectorWidget::GetFirstInTabOrder() -{ - return m_buttons.empty() ? nullptr : m_buttons.first(); -} - -void FileResourceSelectorWidget::UpdateTabOrder() -{ - if (m_buttons.count() >= 2) - { - for (int i = 0; i < m_buttons.count() - 1; ++i) - { - setTabOrder(m_buttons[i], m_buttons[i + 1]); - } - } -} - -bool FileResourceSelectorWidget::event(QEvent* event) -{ - if (event->type() == QEvent::ToolTip && m_previewToolTip && !m_previewToolTip->isVisible()) - { - if (!m_path.isEmpty()) - { - m_previewToolTip->LoadImage(m_path); - m_previewToolTip->setVisible(true); - } - event->accept(); - return true; - } - - if (event->type() == QEvent::Resize && m_previewToolTip) - { - m_previewToolTip->SetTool(this, rect()); - } - - return QWidget::event(event); -} - -QWidget* FileResourceSelectorWidgetHandler::CreateGUI(QWidget* pParent) -{ - FileResourceSelectorWidget* newCtrl = aznew FileResourceSelectorWidget(pParent); - connect(newCtrl, &FileResourceSelectorWidget::PathChanged, newCtrl, [newCtrl]() - { - EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl); - }); - return newCtrl; -} - -void FileResourceSelectorWidgetHandler::ConsumeAttribute(FileResourceSelectorWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) -{ - Q_UNUSED(GUI); - Q_UNUSED(attrib); - Q_UNUSED(attrValue); - Q_UNUSED(debugName); -} - -void FileResourceSelectorWidgetHandler::WriteGUIValuesIntoProperty(size_t index, FileResourceSelectorWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) -{ - Q_UNUSED(index); - Q_UNUSED(node); - CReflectedVarResource val = instance; - val.m_propertyType = GUI->GetPropertyType(); - val.m_path = GUI->GetPath().toUtf8().data(); - instance = static_cast(val); -} - -bool FileResourceSelectorWidgetHandler::ReadValuesIntoGUI(size_t index, FileResourceSelectorWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) -{ - Q_UNUSED(index); - Q_UNUSED(node); - CReflectedVarResource val = instance; - GUI->SetPropertyType(val.m_propertyType); - GUI->SetPath(val.m_path.c_str()); - return false; -} - -#include diff --git a/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.h b/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.h deleted file mode 100644 index 087ee9f1db..0000000000 --- a/Code/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.h +++ /dev/null @@ -1,118 +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 - * - */ - -#ifndef CRYINCLUDE_EDITOR_UTILS_PROPERTYRESOURCECTRL_H -#define CRYINCLUDE_EDITOR_UTILS_PROPERTYRESOURCECTRL_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#include -#include -#include "ReflectedVar.h" -#include "Util/VariablePropertyType.h" -#include -#include -#include -#endif - -class QLineEdit; -class QHBoxLayout; -class CBitmapToolTip; -class QToolTipWidget; - -class BrowseButton - : public QToolButton -{ - Q_OBJECT -public: - AZ_CLASS_ALLOCATOR(BrowseButton, AZ::SystemAllocator, 0); - - BrowseButton(PropertyType type, QWidget* parent = nullptr); - - void SetPath(const QString& path) { m_path = path; } - QString GetPath() const { return m_path; } - - PropertyType GetPropertyType() const {return m_propertyType; } - -signals: - void PathChanged(const QString& path); - -protected: - void SetPathAndEmit(const QString& path); - virtual void OnClicked() = 0; - - PropertyType m_propertyType; - QString m_path; -}; - -class FileResourceSelectorWidget - : public QWidget -{ - Q_OBJECT -public: - AZ_CLASS_ALLOCATOR(FileResourceSelectorWidget, AZ::SystemAllocator, 0); - FileResourceSelectorWidget(QWidget* pParent = nullptr); - - bool SetPath(const QString& path); - QString GetPath() const; - void SetPropertyType(PropertyType type); - PropertyType GetPropertyType() const { return m_propertyType; } - - QWidget* GetFirstInTabOrder(); - QWidget* GetLastInTabOrder(); - void UpdateTabOrder(); - - bool eventFilter(QObject* obj, QEvent* event) override; - -signals: - void PathChanged(const QString& path); - -protected: - bool event(QEvent* event) override; - -private: - void OnAssignClicked(); - void OnMaterialClicked(); - - void UpdateWidgets(); - void AddButton(BrowseButton* button); - void OnPathChanged(const QString& path); - -private: - QLineEdit* m_pathEdit; - PropertyType m_propertyType; - QString m_path; - - QHBoxLayout* m_mainLayout; - QVector m_buttons; - QScopedPointer m_previewToolTip; - QToolTipWidget* m_tooltip; -}; - -class FileResourceSelectorWidgetHandler - : QObject - , public AzToolsFramework::PropertyHandler < CReflectedVarResource, FileResourceSelectorWidget > -{ - Q_OBJECT -public: - AZ_CLASS_ALLOCATOR(FileResourceSelectorWidgetHandler, AZ::SystemAllocator, 0); - - virtual AZ::u32 GetHandlerName(void) const override { return AZ_CRC("Resource", 0xbc91f416); } - virtual bool IsDefaultHandler() const override { return true; } - virtual QWidget* GetFirstInTabOrder(FileResourceSelectorWidget* widget) override { return widget->GetFirstInTabOrder(); } - virtual QWidget* GetLastInTabOrder(FileResourceSelectorWidget* widget) override { return widget->GetLastInTabOrder(); } - virtual void UpdateWidgetInternalTabbing(FileResourceSelectorWidget* widget) override { widget->UpdateTabOrder(); } - - virtual QWidget* CreateGUI(QWidget* pParent) override; - virtual void ConsumeAttribute(FileResourceSelectorWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override; - virtual void WriteGUIValuesIntoProperty(size_t index, FileResourceSelectorWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override; - virtual bool ReadValuesIntoGUI(size_t index, FileResourceSelectorWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override; -}; - -#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYRESOURCECTRL_H diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp index 263c17a8bb..268faaa335 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp @@ -70,12 +70,6 @@ void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext) AZ::EditContext* ec = serializeContext->GetEditContext(); if (ec) { - ec->Class< CReflectedVarResource >("VarResource", "Resource") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarResource::varName) - ->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarResource::description) - ; - ec->Class< CReflectedVarUser >("VarUser", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarUser::varName) diff --git a/Code/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Editor/Core/LevelEditorMenuHandler.cpp index 05f06c87aa..d359d9ef5d 100644 --- a/Code/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Editor/Core/LevelEditorMenuHandler.cpp @@ -588,7 +588,7 @@ QMenu* LevelEditorMenuHandler::CreateGameMenu() bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (!usePrefabSystemForLevels) { // Export to Engine diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 480a973282..f3c38fdef7 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -706,7 +706,7 @@ void CCryEditApp::OnFileSave() bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (!usePrefabSystemForLevels) { @@ -2364,7 +2364,7 @@ void CCryEditApp::ExportLevel(bool bExportToGame, bool bExportTexture, bool bAut { bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (usePrefabSystemForLevels) { AZ_Assert(false, "Prefab system doesn't require level exports."); @@ -2405,7 +2405,7 @@ bool CCryEditApp::UserExportToGame(bool bNoMsgBox) { bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (usePrefabSystemForLevels) { AZ_Assert(false, "Export Level should no longer exist."); @@ -2453,7 +2453,7 @@ void CCryEditApp::ExportToGame(bool bNoMsgBox) { bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (usePrefabSystemForLevels) { AZ_Assert(false, "Prefab system no longer exports levels."); @@ -2961,7 +2961,7 @@ CCryEditApp::ECreateLevelResult CCryEditApp::CreateLevel(const QString& levelNam { bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); // If we are creating a new level and we're in simulate mode, then switch it off before we do anything else if (GetIEditor()->GetGameEngine() && GetIEditor()->GetGameEngine()->GetSimulationMode()) @@ -3107,7 +3107,7 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled) { bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (!usePrefabSystemForLevels) { QString str = QObject::tr("Level %1 has been changed. Save Level?").arg(GetIEditor()->GetGameEngine()->GetLevelName()); @@ -3321,7 +3321,7 @@ CCryEditDoc* CCryEditApp::OpenDocumentFile(const char* filename, bool addToMostR bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); // If we are loading and we're in simulate mode, then switch it off before we do anything else if (GetIEditor()->GetGameEngine() && GetIEditor()->GetGameEngine()->GetSimulationMode()) diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index c7d719184d..cabb82db89 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -371,7 +371,7 @@ void CCryEditDoc::Load(TDocMultiArchive& arrXmlAr, const QString& szFilename) bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (!usePrefabSystemForLevels) { @@ -636,7 +636,7 @@ bool CCryEditDoc::SaveModified() bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (!usePrefabSystemForLevels) { QMessageBox saveModifiedMessageBox(AzToolsFramework::GetActiveWindow()); @@ -699,7 +699,7 @@ void CCryEditDoc::OnFileSaveAs() CCryEditApp::instance()->AddToRecentFileList(levelFileDialog.GetFileName()); bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (usePrefabSystemForLevels) { AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = @@ -728,7 +728,7 @@ bool CCryEditDoc::BeforeOpenDocument(const QString& lpszPathName, TOpenDocContex bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (!usePrefabSystemForLevels) { diff --git a/Code/Editor/GameEngine.cpp b/Code/Editor/GameEngine.cpp index 8aab168b6d..200c48ab81 100644 --- a/Code/Editor/GameEngine.cpp +++ b/Code/Editor/GameEngine.cpp @@ -489,7 +489,7 @@ bool CGameEngine::LoadLevel( bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (!usePrefabSystemForLevels) { diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 635281aee5..32429f7f0b 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -100,7 +100,7 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (usePrefabSystemForLevels) { diff --git a/Code/Editor/GameExporter.h b/Code/Editor/GameExporter.h index ee4e8df3d9..1ecd2403f2 100644 --- a/Code/Editor/GameExporter.h +++ b/Code/Editor/GameExporter.h @@ -70,7 +70,7 @@ private: { bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (usePrefabSystemForLevels) { AZ_Assert(false, "Level.pak should no longer be used when prefabs are used for levels."); diff --git a/Code/Editor/MainWindow.cpp b/Code/Editor/MainWindow.cpp index 3a52bb85a1..a1f054b57f 100644 --- a/Code/Editor/MainWindow.cpp +++ b/Code/Editor/MainWindow.cpp @@ -659,7 +659,7 @@ void MainWindow::InitActions() bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (!usePrefabSystemForLevels) { am->AddAction(ID_FILE_EXPORTTOGAMENOSURFACETEXTURE, tr("&Export to Engine")) diff --git a/Code/Editor/editor_core_files.cmake b/Code/Editor/editor_core_files.cmake index 4cf092e774..447d763a63 100644 --- a/Code/Editor/editor_core_files.cmake +++ b/Code/Editor/editor_core_files.cmake @@ -22,13 +22,6 @@ set(FILES Controls/ReflectedPropertyControl/ReflectedVar.h Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp Controls/ReflectedPropertyControl/ReflectedVarWrapper.h - Controls/QBitmapPreviewDialog.cpp - Controls/QBitmapPreviewDialog.h - Controls/QBitmapPreviewDialog.ui - Controls/QBitmapPreviewDialogImp.cpp - Controls/QBitmapPreviewDialogImp.h - Controls/QToolTipWidget.h - Controls/QToolTipWidget.cpp UsedResources.cpp LyViewPaneNames.h QtViewPaneManager.cpp diff --git a/Code/Editor/editor_lib_files.cmake b/Code/Editor/editor_lib_files.cmake index 7908d1e720..53cfe243b1 100644 --- a/Code/Editor/editor_lib_files.cmake +++ b/Code/Editor/editor_lib_files.cmake @@ -313,8 +313,6 @@ set(FILES AssetEditor/AssetEditorWindow.ui Commands/CommandManager.cpp Commands/CommandManager.h - Controls/BitmapToolTip.cpp - Controls/BitmapToolTip.h Controls/ConsoleSCB.cpp Controls/ConsoleSCB.h Controls/ConsoleSCB.ui @@ -336,8 +334,6 @@ set(FILES Controls/ReflectedPropertyControl/PropertyMiscCtrl.h Controls/ReflectedPropertyControl/PropertyMotionCtrl.cpp Controls/ReflectedPropertyControl/PropertyMotionCtrl.h - Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp - Controls/ReflectedPropertyControl/PropertyResourceCtrl.h Controls/ReflectedPropertyControl/PropertyCtrl.cpp Controls/ReflectedPropertyControl/PropertyCtrl.h MainStatusBar.cpp diff --git a/Code/Framework/AzCore/Tests/TaskTests.cpp b/Code/Framework/AzCore/Tests/TaskTests.cpp index 4f53772d51..53fa89900e 100644 --- a/Code/Framework/AzCore/Tests/TaskTests.cpp +++ b/Code/Framework/AzCore/Tests/TaskTests.cpp @@ -447,13 +447,13 @@ namespace UnitTest { x -= 1; }); - - // a <-- Root - // / \ - // b c - // \ / - // d - + /* + a <-- Root + / \ + b c + \ / + d + */ a.Precedes(b, c); d.Follows(b, c); @@ -522,20 +522,20 @@ namespace UnitTest { x -= 1; }); - - // NOTE: The ideal way to express this topology is without the wait on the subgraph - // at task g, but this is more an illustrative test. Better is to express the entire - // graph in a single larger graph. - // a <-- Root - // / \ - // b c - f - // \ \ \ - // \ e - g - // \ / - // \ / - // \ / - // d - + /* + NOTE: The ideal way to express this topology is without the wait on the subgraph + at task g, but this is more an illustrative test. Better is to express the entire + graph in a single larger graph. + a <-- Root + / \ + b c - f + \ \ \ + \ e - g + \ / + \ / + \ / + d + */ a.Precedes(b); a.Precedes(c); b.Precedes(d); @@ -593,17 +593,17 @@ namespace UnitTest { x += 0b1000; }); - - // a <-- Root - // / \ - // b c - f - // \ \ \ - // \ e - g - // \ / - // \ / - // \ / - // d - + /* + a <-- Root + / \ + b c - f + \ \ \ + \ e - g + \ / + \ / + \ / + d + */ a.Precedes(b, c); b.Precedes(d); c.Precedes(e, f); diff --git a/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h b/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h index e536082d61..c7a9256c9c 100644 --- a/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h +++ b/Code/Framework/AzFramework/AzFramework/API/ApplicationAPI.h @@ -112,6 +112,7 @@ namespace AzFramework virtual void SetPrefabSystemEnabled([[maybe_unused]] bool enable) {} /// Returns true if Prefab System is enabled for use with levels, false if legacy level system is enabled (level.pak) + /// @deprecated Use 'IsPrefabSystemEnabled' instead virtual bool IsPrefabSystemForLevelsEnabled() const { return false; } /// Returns true if code should assert when the Legacy Slice System is used diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp index b3521a877f..b3fed38715 100644 --- a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp +++ b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp @@ -765,6 +765,7 @@ namespace AzFramework bool Application::IsPrefabSystemForLevelsEnabled() const { + AZ_Warning("Application", false, "'IsPrefabSystemForLevelsEnabled' is deprecated, please use 'IsPrefabSystemEnabled' instead."); return IsPrefabSystemEnabled(); } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp index c2fba5c5a3..6f0f3e6d13 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp @@ -1208,7 +1208,7 @@ namespace AZ::IO bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (usePrefabSystemForLevels) { @@ -1274,7 +1274,7 @@ namespace AZ::IO bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); AZStd::unique_lock lock(m_csZips); for (auto it = m_arrZips.begin(); it != m_arrZips.end();) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.cpp index 6647f48c31..9b3a6379af 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.cpp @@ -295,7 +295,7 @@ namespace AzToolsFramework bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); for (const AzToolsFramework::AssetFileInfo& assetFileInfo : assetFileInfoList.m_fileInfoList) { diff --git a/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.h b/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.h index 76b7958085..30a9f99436 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.h +++ b/Code/Framework/GridMate/GridMate/Carrier/SecureSocketDriver.h @@ -19,13 +19,15 @@ #define AZ_DebugSecureSocket(...) #define AZ_DebugSecureSocketConnection(window, fmt, ...) -//#define AZ_DebugUseSocketDebugLog -//#define AZ_DebugSecureSocket AZ_TracePrintf -//#define AZ_DebugSecureSocketConnection(window, fmt, ...) \ -//{\ -// AZStd::string line = AZStd::string::format(fmt, __VA_ARGS__);\ -// this->m_dbgLog += line;\ -//} +/* + #define AZ_DebugUseSocketDebugLog + #define AZ_DebugSecureSocket AZ_TracePrintf + #define AZ_DebugSecureSocketConnection(window, fmt, ...) \ + {\ + AZStd::string line = AZStd::string::format(fmt, __VA_ARGS__);\ + this->m_dbgLog += line;\ + } +*/ #if AZ_TRAIT_GRIDMATE_SECURE_SOCKET_DRIVER_HOOK_ENABLED struct ssl_st; diff --git a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp index 0b90e73bc0..bd788fdd73 100644 --- a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp @@ -41,7 +41,7 @@ bool CLevelInfo::OpenLevelPak() { bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); // The prefab system doesn't use level.pak if (usePrefabSystemForLevels) @@ -62,7 +62,7 @@ void CLevelInfo::CloseLevelPak() { bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); // The prefab system doesn't use level.pak if (usePrefabSystemForLevels) @@ -82,7 +82,7 @@ bool CLevelInfo::ReadInfo() { bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); // Set up a default game type for legacy code. m_defaultGameTypeName = "mission0"; diff --git a/Code/Legacy/CrySystem/SystemInit.cpp b/Code/Legacy/CrySystem/SystemInit.cpp index 600a799bc1..cad914e29d 100644 --- a/Code/Legacy/CrySystem/SystemInit.cpp +++ b/Code/Legacy/CrySystem/SystemInit.cpp @@ -1046,7 +1046,7 @@ AZ_POP_DISABLE_WARNING // LEVEL SYSTEM bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (usePrefabSystemForLevels) { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Filter.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Filter.cpp index 0387ec5c7b..2b1e822db4 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Filter.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/FIR-Filter.cpp @@ -999,79 +999,81 @@ namespace ImageProcessingAtom } // TODO: not working yet, debug and enable - //static void SplitAlgorithm(const void* i, void* o, struct prcparm* templ, int threads = 8) - //{ - // struct prcparm fraction[32]; - // int t, istart = 0, sstart = 0, ostart = 0; - // const bool scaler = true; + /* + static void SplitAlgorithm(const void* i, void* o, struct prcparm* templ, int threads = 8) + { + struct prcparm fraction[32]; + int t, istart = 0, sstart = 0, ostart = 0; + const bool scaler = true; - // int theight = 0; + int theight = 0; - // /* prepare data to be emitted to the threads */ - // for (t = 0; t < threads; t++) - // { - // fraction[t] = *templ; + // prepare data to be emitted to the threads + for (t = 0; t < threads; t++) + { + fraction[t] = *templ; - // /* adjust the processing-region according to the available threads */ - // { - //#undef split /* only prefix-threads need aligned transpose (for not trashing suffix-thread data) */ - //#define split(rows) !scaler \ - // ? ((rows * (t + 1)) / threads) & (~(t != threads - 1 ? 15 : 0)) \ - // : ((rows * (t + 1)) / threads) & (~0) + // adjust the processing-region according to the available threads + { + #undef split // only prefix-threads need aligned transpose (for not trashing suffix-thread data) + #define split(rows) !scaler \ + ? ((rows * (t + 1)) / threads) & (~(t != threads - 1 ? 15 : 0)) \ + : ((rows * (t + 1)) / threads) & (~0) - // /* area covered */ - // const int inrows = (fraction[t].regional ? fraction[t].region.inrows : fraction[t].inrows); - // const int incols = (fraction[t].regional ? fraction[t].region.incols : fraction[t].incols); - // const int subrows = (fraction[t].regional ? fraction[t].region.subrows : fraction[t].subrows); - // const int subcols = (fraction[t].regional ? fraction[t].region.subcols : fraction[t].subcols); - // const int outrows = (fraction[t].regional ? fraction[t].region.outrows : fraction[t].outrows); - // const int outcols = (fraction[t].regional ? fraction[t].region.outcols : fraction[t].outcols); + // area covered + const int inrows = (fraction[t].regional ? fraction[t].region.inrows : fraction[t].inrows); + const int incols = (fraction[t].regional ? fraction[t].region.incols : fraction[t].incols); + const int subrows = (fraction[t].regional ? fraction[t].region.subrows : fraction[t].subrows); + const int subcols = (fraction[t].regional ? fraction[t].region.subcols : fraction[t].subcols); + const int outrows = (fraction[t].regional ? fraction[t].region.outrows : fraction[t].outrows); + const int outcols = (fraction[t].regional ? fraction[t].region.outcols : fraction[t].outcols); - // /* splitting blocks */ - // const int istop = split(inrows), sstop = split(subrows), ostop = split(outrows); - // const int irows = istop - istart, srows = sstop - sstart, orows = ostop - ostart; - // const int icols = incols, scols = subcols, ocols = outcols; + // splitting blocks + const int istop = split(inrows), sstop = split(subrows), ostop = split(outrows); + const int irows = istop - istart, srows = sstop - sstart, orows = ostop - ostart; + const int icols = incols, scols = subcols, ocols = outcols; - // AZ_Assert(irows > 0, "%s: Expect row count to be above zero!", __FUNCTION__); - // AZ_Assert(orows > 0, "%s: Expect row count to be above zero!", __FUNCTION__); - // AZ_Assert(icols > 0, "%s: Expect column count to be above zero!", __FUNCTION__); - // AZ_Assert(ocols > 0, "%s: Expect column count to be above zero!", __FUNCTION__); + AZ_Assert(irows > 0, "%s: Expect row count to be above zero!", __FUNCTION__); + AZ_Assert(orows > 0, "%s: Expect row count to be above zero!", __FUNCTION__); + AZ_Assert(icols > 0, "%s: Expect column count to be above zero!", __FUNCTION__); + AZ_Assert(ocols > 0, "%s: Expect column count to be above zero!", __FUNCTION__); - // /* now we are regional */ - // fraction[t].regional = true; + // now we are regional + fraction[t].regional = true; - // /* take previous regionality into account */ - // fraction[t].region.intop += istart; - // fraction[t].region.subtop += sstart; - // fraction[t].region.outtop += ostart; - // fraction[t].region.inrows = irows; - // fraction[t].region.subrows = srows; - // fraction[t].region.outrows = orows; + // take previous regionality into account + fraction[t].region.intop += istart; + fraction[t].region.subtop += sstart; + fraction[t].region.outtop += ostart; + fraction[t].region.inrows = irows; + fraction[t].region.subrows = srows; + fraction[t].region.outrows = orows; - // /* take previous regionality into account */ - // fraction[t].region.inleft += 0; - // fraction[t].region.subleft += 0; - // fraction[t].region.outleft += 0; - // fraction[t].region.incols = icols; - // fraction[t].region.subcols = scols; - // fraction[t].region.outcols = ocols; + // take previous regionality into account + fraction[t].region.inleft += 0; + fraction[t].region.subleft += 0; + fraction[t].region.outleft += 0; + fraction[t].region.incols = icols; + fraction[t].region.subcols = scols; + fraction[t].region.outcols = ocols; - // /* advance block */ - // istart = istop; - // sstart = sstop; - // ostart = ostop; + // advance block + istart = istop; + sstart = sstop; + ostart = ostop; - // /* check */ - // theight += irows; - // } + // check + theight += irows; + } - // // the algorithm supports "i" and "o" pointing to the same memory - // CheckBoundaries((float*)i, (float*)o, &fraction[t]); - // RunAlgorithm((float*)i, (float*)o, &fraction[t]); - // } + // the algorithm supports "i" and "o" pointing to the same memory + CheckBoundaries((float*)i, (float*)o, &fraction[t]); + RunAlgorithm((float*)i, (float*)o, &fraction[t]); + } - // AZ_Assert(theight >= (templ->regional ? templ->region.inrows : templ->inrows), "%s: Invalid height!", __FUNCTION__); - //} + AZ_Assert(theight >= (templ->regional ? templ->region.inrows : templ->inrows), "%s: Invalid height!", __FUNCTION__); + } + */ /* #################################################################################################################### \ */ diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index f324394309..a08fe60fd5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -10,1013 +10,1010 @@ } ], "propertyLayout": { - "groups": [ + "propertyGroups": [ { "name": "baseColor", "displayName": "Base Color", - "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." + "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals.", + "properties": [ + { + "name": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ], + "connection": { + "type": "ShaderInput", + "name": "m_baseColor" + } + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_baseColorFactor" + } + }, + { + "name": "textureMap", + "displayName": "Texture", + "description": "Base color texture map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_baseColorMap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Base color map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_baseColorMapUvIndex" + } + }, + { + "name": "textureBlendMode", + "displayName": "Texture Blend Mode", + "description": "Selects the equation to use when combining Color, Factor, and Texture.", + "type": "Enum", + "enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ], + "defaultValue": "Multiply", + "connection": { + "type": "ShaderOption", + "name": "o_baseColorTextureBlendMode" + } + } + ] }, { "name": "metallic", "displayName": "Metallic", - "description": "Properties for configuring whether the surface is metallic or not." + "description": "Properties for configuring whether the surface is metallic or not.", + "properties": [ + { + "name": "factor", + "displayName": "Factor", + "description": "This value is linear, black is non-metal and white means raw metal.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_metallicFactor" + } + }, + { + "name": "textureMap", + "displayName": "Texture", + "description": "", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_metallicMap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Metallic map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_metallicMapUvIndex" + } + } + ] }, { "name": "roughness", "displayName": "Roughness", - "description": "Properties for configuring how rough the surface appears." + "description": "Properties for configuring how rough the surface appears.", + "properties": [ + { + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining surface roughness.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_roughnessMap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Roughness map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_roughnessMapUvIndex" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "name": "lowerBound", + "displayName": "Lower Bound", + "description": "The roughness value that corresponds to black in the texture.", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_roughnessLowerBound" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "name": "upperBound", + "displayName": "Upper Bound", + "description": "The roughness value that corresponds to white in the texture.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_roughnessUpperBound" + } + }, + { + // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. + "name": "factor", + "displayName": "Factor", + "description": "Controls the roughness value", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_roughnessFactor" + } + } + ] }, { "name": "specularF0", "displayName": "Specular Reflectance f0", - "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces." + "description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces.", + "properties": [ + { + "name": "factor", + "displayName": "Factor", + "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", + "type": "Float", + "defaultValue": 0.5, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_specularF0Factor" + } + }, + { + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining surface reflectance.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_specularF0Map" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Specular reflection map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_specularF0MapUvIndex" + } + }, + // Consider moving this to the "general" group to be consistent with StandardMultilayerPBR + { + "name": "enableMultiScatterCompensation", + "displayName": "Multiscattering Compensation", + "description": "Whether to enable multiple scattering compensation.", + "type": "Bool", + "connection": { + "type": "ShaderOption", + "name": "o_specularF0_enableMultiScatterCompensation" + } + } + ] }, { "name": "normal", "displayName": "Normal", - "description": "Properties related to configuring surface normal." + "description": "Properties related to configuring surface normal.", + "properties": [ + { + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining surface normal direction.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_normalMap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture, or just rely on vertex normals.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Normal map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_normalMapUvIndex" + } + }, + { + "name": "flipX", + "displayName": "Flip X Channel", + "description": "Flip tangent direction for this normal map.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderInput", + "name": "m_flipNormalX" + } + }, + { + "name": "flipY", + "displayName": "Flip Y Channel", + "description": "Flip bitangent direction for this normal map.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderInput", + "name": "m_flipNormalY" + } + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the values", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "name": "m_normalFactor" + } + } + ] }, { "name": "occlusion", "displayName": "Occlusion", - "description": "Properties for baked textures that represent geometric occlusion of light." + "description": "Properties for baked textures that represent geometric occlusion of light.", + "properties": [ + { + "name": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture for defining occlusion area for diffuse ambient lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_diffuseOcclusionMap" + } + }, + { + "name": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO map.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_diffuseOcclusionMapUvIndex" + } + }, + { + "name": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "name": "m_diffuseOcclusionFactor" + } + }, + { + "name": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture for defining occlusion area for specular lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_specularOcclusionMap" + } + }, + { + "name": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity map.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_specularOcclusionMapUvIndex" + } + }, + { + "name": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "name": "m_specularOcclusionFactor" + } + } + ] }, { "name": "emissive", "displayName": "Emissive", - "description": "Properties to add light emission, independent of other lights in the scene." + "description": "Properties to add light emission, independent of other lights in the scene.", + "properties": [ + { + "name": "enable", + "displayName": "Enable", + "description": "Enable the emissive group", + "type": "Bool", + "defaultValue": false + }, + { + "name": "unit", + "displayName": "Units", + "description": "The photometric units of the Intensity property.", + "type": "Enum", + "enumValues": ["Ev100"], + "defaultValue": "Ev100" + }, + { + "name": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ], + "connection": { + "type": "ShaderInput", + "name": "m_emissiveColor" + } + }, + { + "name": "intensity", + "displayName": "Intensity", + "description": "The amount of energy emitted.", + "type": "Float", + "defaultValue": 4, + "min": -10, + "max": 20, + "softMin": -6, + "softMax": 16 + }, + { + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining emissive area.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_emissiveMap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Emissive map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_emissiveMapUvIndex" + } + } + ] }, { "name": "clearCoat", "displayName": "Clear Coat", - "description": "Properties for configuring gloss clear coat" - }, + "description": "Properties for configuring gloss clear coat", + "properties": [ + { + "name": "enable", + "displayName": "Enable", + "description": "Enable clear coat", + "type": "Bool", + "defaultValue": false + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the percentage of effect applied", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatFactor" + } + }, + { + "name": "influenceMap", + "displayName": " Influence Map", + "description": "Strength factor texture", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatInfluenceMap" + } + }, + { + "name": "useInfluenceMap", + "displayName": " Use Texture", + "description": "Whether to use the texture, or just default to the Factor value.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "influenceMapUv", + "displayName": " UV", + "description": "Strength factor map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatInfluenceMapUvIndex" + } + }, + { + "name": "roughness", + "displayName": "Roughness", + "description": "Clear coat layer roughness", + "type": "Float", + "defaultValue": 0.0, + "min": 0.0, + "max": 1.0, + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatRoughness" + } + }, + { + "name": "roughnessMap", + "displayName": " Roughness Map", + "description": "Texture for defining surface roughness", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatRoughnessMap" + } + }, + { + "name": "useRoughnessMap", + "displayName": " Use Texture", + "description": "Whether to use the texture, or just default to the roughness value.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "roughnessMapUv", + "displayName": " UV", + "description": "Roughness map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatRoughnessMapUvIndex" + } + }, + { + "name": "normalStrength", + "displayName": "Normal Strength", + "description": "Scales the impact of the clear coat normal map", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 2.0, + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatNormalStrength" + } + }, + { + "name": "normalMap", + "displayName": "Normal Map", + "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatNormalMap" + } + }, + { + "name": "useNormalMap", + "displayName": " Use Texture", + "description": "Whether to use the normal map", + "type": "Bool", + "defaultValue": true + }, + { + "name": "normalMapUv", + "displayName": " UV", + "description": "Normal map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_clearCoatNormalMapUvIndex" + } + } + ] + }, { "name": "parallax", "displayName": "Displacement", - "description": "Properties for parallax effect produced by a height map." + "description": "Properties for parallax effect produced by a height map.", + "properties": [ + { + "name": "textureMap", + "displayName": "Height Map", + "description": "Displacement height map to create parallax effect.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_heightmap" + } + }, + { + "name": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the height map.", + "type": "Bool", + "defaultValue": true + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Height map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_parallaxUvIndex" + } + }, + { + "name": "factor", + "displayName": "Height Map Scale", + "description": "The total height of the height map in local model units.", + "type": "Float", + "defaultValue": 0.05, + "min": 0.0, + "softMax": 0.1, + "connection": { + "type": "ShaderInput", + "name": "m_heightmapScale" + } + }, + { + "name": "offset", + "displayName": "Offset", + "description": "Adjusts the overall displacement amount in local model units.", + "type": "Float", + "defaultValue": 0.0, + "softMin": -0.1, + "softMax": 0.1, + "connection": { + "type": "ShaderInput", + "name": "m_heightmapOffset" + } + }, + { + "name": "algorithm", + "displayName": "Algorithm", + "description": "Select the algorithm to use for parallax mapping.", + "type": "Enum", + "enumValues": [ "Basic", "Steep", "POM", "Relief", "ContactRefinement" ], + "defaultValue": "POM", + "connection": { + "type": "ShaderOption", + "name": "o_parallax_algorithm" + } + }, + { + "name": "quality", + "displayName": "Quality", + "description": "Quality of parallax mapping.", + "type": "Enum", + "enumValues": [ "Low", "Medium", "High", "Ultra" ], + "defaultValue": "Low", + "connection": { + "type": "ShaderOption", + "name": "o_parallax_quality" + } + }, + { + "name": "pdo", + "displayName": "Pixel Depth Offset", + "description": "Enable PDO to offset the original pixel depths. This will affect any shaders using depth, for example, when receiving shadows.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "name": "o_parallax_enablePixelDepthOffset" + } + }, + { + "name": "showClipping", + "displayName": "Show Clipping", + "description": "Highlight areas where the height map is clipped by the mesh surface.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "name": "o_parallax_highlightClipping" + } + } + ] }, { "name": "opacity", "displayName": "Opacity", - "description": "Properties for configuring the materials transparency." + "description": "Properties for configuring the materials transparency.", + "properties": [ + { + "name": "mode", + "displayName": "Opacity Mode", + "description": "Indicates the general approach how transparency is to be applied.", + "type": "Enum", + "enumValues": [ "Opaque", "Cutout", "Blended", "TintedTransparent" ], + "defaultValue": "Opaque", + "connection": { + "type": "ShaderOption", + "name": "o_opacity_mode" + } + }, + { + "name": "alphaSource", + "displayName": "Alpha Source", + "description": "Indicates whether to get the opacity texture from the Base Color map (Packed) or from a separate greyscale texture (Split).", + "type": "Enum", + "enumValues": [ "Packed", "Split", "None" ], + "defaultValue": "Packed", + "connection": { + "type": "ShaderOption", + "name": "o_opacity_source" + } + }, + { + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining surface opacity.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "name": "m_opacityMap" + } + }, + { + "name": "textureMapUv", + "displayName": "UV", + "description": "Opacity map UV set", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "name": "m_opacityMapUvIndex" + } + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Factor for cutout threshold and blending", + "type": "Float", + "min": 0.0, + "max": 1.0, + "defaultValue": 0.5, + "connection": { + "type": "ShaderInput", + "name": "m_opacityFactor" + } + }, + { + "name": "alphaAffectsSpecular", + "displayName": "Alpha affects specular", + "description": "How much the alpha value should also affect specular reflection. This should be 0.0 for materials where light can transmit through their physical surface (like glass), but 1.0 when alpha determines the very presence of a surface (like hair or grass)", + "type": "float", + "min": 0.0, + "max": 1.0, + "defaultValue": 0.0, + "connection": { + "type": "ShaderInput", + "name": "m_opacityAffectsSpecularFactor" + } + } + ] }, { "name": "uv", "displayName": "UVs", - "description": "Properties for configuring UV transforms." + "description": "Properties for configuring UV transforms.", + "properties": [ + { + "name": "center", + "displayName": "Center", + "description": "Center point for scaling and rotation transformations.", + "type": "vector2", + "vectorLabels": [ "U", "V" ], + "defaultValue": [ 0.5, 0.5 ] + }, + { + "name": "tileU", + "displayName": "Tile U", + "description": "Scales texture coordinates in U.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "name": "tileV", + "displayName": "Tile V", + "description": "Scales texture coordinates in V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + }, + { + "name": "offsetU", + "displayName": "Offset U", + "description": "Offsets texture coordinates in the U direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0 + }, + { + "name": "offsetV", + "displayName": "Offset V", + "description": "Offsets texture coordinates in the V direction.", + "type": "float", + "defaultValue": 0.0, + "min": -1.0, + "max": 1.0 + }, + { + "name": "rotateDegrees", + "displayName": "Rotate", + "description": "Rotates the texture coordinates (degrees).", + "type": "float", + "defaultValue": 0.0, + "min": -180.0, + "max": 180.0, + "step": 1.0 + }, + { + "name": "scale", + "displayName": "Scale", + "description": "Scales texture coordinates in both U and V.", + "type": "float", + "defaultValue": 1.0, + "step": 0.1 + } + ] }, { // Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader "name": "irradiance", "displayName": "Irradiance", - "description": "Properties for configuring the irradiance used in global illumination." + "description": "Properties for configuring the irradiance used in global illumination.", + "properties": [ + { + "name": "color", + "displayName": "Color", + "description": "Color is displayed as sRGB but the values are stored as linear color.", + "type": "Color", + "defaultValue": [ 1.0, 1.0, 1.0 ] + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the irradiance color values. Zero (0.0) is black, white (1.0) is full color.", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "max": 1.0 + } + ] }, { "name": "general", "displayName": "General Settings", - "description": "General settings." + "description": "General settings.", + "properties": [ + { + "name": "doubleSided", + "displayName": "Double-sided", + "description": "Whether to render back-faces or just front-faces.", + "type": "Bool" + }, + { + "name": "applySpecularAA", + "displayName": "Apply Specular AA", + "description": "Whether to apply specular anti-aliasing in the shader.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "name": "o_applySpecularAA" + } + }, + { + "name": "enableShadows", + "displayName": "Enable Shadows", + "description": "Whether to use the shadow maps.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "name": "o_enableShadows" + } + }, + { + "name": "enableDirectionalLights", + "displayName": "Enable Directional Lights", + "description": "Whether to use directional lights.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "name": "o_enableDirectionalLights" + } + }, + { + "name": "enablePunctualLights", + "displayName": "Enable Punctual Lights", + "description": "Whether to use punctual lights.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "name": "o_enablePunctualLights" + } + }, + { + "name": "enableAreaLights", + "displayName": "Enable Area Lights", + "description": "Whether to use area lights.", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "name": "o_enableAreaLights" + } + }, + { + "name": "enableIBL", + "displayName": "Enable IBL", + "description": "Whether to use Image Based Lighting (IBL).", + "type": "Bool", + "defaultValue": true, + "connection": { + "type": "ShaderOption", + "name": "o_enableIBL" + } + }, + { + "name": "forwardPassIBLSpecular", + "displayName": "Forward Pass IBL Specular", + "description": "Whether to apply IBL specular in the forward pass.", + "type": "Bool", + "defaultValue": false, + "connection": { + "type": "ShaderOption", + "name": "o_materialUseForwardPassIBLSpecular" + } + } + ] } - ], - "properties": { - "general": [ - { - "name": "doubleSided", - "displayName": "Double-sided", - "description": "Whether to render back-faces or just front-faces.", - "type": "Bool" - }, - { - "name": "applySpecularAA", - "displayName": "Apply Specular AA", - "description": "Whether to apply specular anti-aliasing in the shader.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "name": "o_applySpecularAA" - } - }, - { - "name": "enableShadows", - "displayName": "Enable Shadows", - "description": "Whether to use the shadow maps.", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderOption", - "name": "o_enableShadows" - } - }, - { - "name": "enableDirectionalLights", - "displayName": "Enable Directional Lights", - "description": "Whether to use directional lights.", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderOption", - "name": "o_enableDirectionalLights" - } - }, - { - "name": "enablePunctualLights", - "displayName": "Enable Punctual Lights", - "description": "Whether to use punctual lights.", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderOption", - "name": "o_enablePunctualLights" - } - }, - { - "name": "enableAreaLights", - "displayName": "Enable Area Lights", - "description": "Whether to use area lights.", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderOption", - "name": "o_enableAreaLights" - } - }, - { - "name": "enableIBL", - "displayName": "Enable IBL", - "description": "Whether to use Image Based Lighting (IBL).", - "type": "Bool", - "defaultValue": true, - "connection": { - "type": "ShaderOption", - "name": "o_enableIBL" - } - }, - { - "name": "forwardPassIBLSpecular", - "displayName": "Forward Pass IBL Specular", - "description": "Whether to apply IBL specular in the forward pass.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "name": "o_materialUseForwardPassIBLSpecular" - } - } - ], - "baseColor": [ - { - "name": "color", - "displayName": "Color", - "description": "Color is displayed as sRGB but the values are stored as linear color.", - "type": "Color", - "defaultValue": [ 1.0, 1.0, 1.0 ], - "connection": { - "type": "ShaderInput", - "name": "m_baseColor" - } - }, - { - "name": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "name": "m_baseColorFactor" - } - }, - { - "name": "textureMap", - "displayName": "Texture", - "description": "Base color texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_baseColorMap" - } - }, - { - "name": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "textureMapUv", - "displayName": "UV", - "description": "Base color map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_baseColorMapUvIndex" - } - }, - { - "name": "textureBlendMode", - "displayName": "Texture Blend Mode", - "description": "Selects the equation to use when combining Color, Factor, and Texture.", - "type": "Enum", - "enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ], - "defaultValue": "Multiply", - "connection": { - "type": "ShaderOption", - "name": "o_baseColorTextureBlendMode" - } - } - ], - "metallic": [ - { - "name": "factor", - "displayName": "Factor", - "description": "This value is linear, black is non-metal and white means raw metal.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "name": "m_metallicFactor" - } - }, - { - "name": "textureMap", - "displayName": "Texture", - "description": "", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_metallicMap" - } - }, - { - "name": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "textureMapUv", - "displayName": "UV", - "description": "Metallic map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_metallicMapUvIndex" - } - } - ], - "roughness": [ - { - "name": "textureMap", - "displayName": "Texture", - "description": "Texture for defining surface roughness.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_roughnessMap" - } - }, - { - "name": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "textureMapUv", - "displayName": "UV", - "description": "Roughness map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_roughnessMapUvIndex" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "name": "lowerBound", - "displayName": "Lower Bound", - "description": "The roughness value that corresponds to black in the texture.", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "name": "m_roughnessLowerBound" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "name": "upperBound", - "displayName": "Upper Bound", - "description": "The roughness value that corresponds to white in the texture.", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "name": "m_roughnessUpperBound" - } - }, - { - // Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor. - "name": "factor", - "displayName": "Factor", - "description": "Controls the roughness value", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "name": "m_roughnessFactor" - } - } - ], - "specularF0": [ - { - "name": "factor", - "displayName": "Factor", - "description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.", - "type": "Float", - "defaultValue": 0.5, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "name": "m_specularF0Factor" - } - }, - { - "name": "textureMap", - "displayName": "Texture", - "description": "Texture for defining surface reflectance.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_specularF0Map" - } - }, - { - "name": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "textureMapUv", - "displayName": "UV", - "description": "Specular reflection map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_specularF0MapUvIndex" - } - }, - // Consider moving this to the "general" group to be consistent with StandardMultilayerPBR - { - "name": "enableMultiScatterCompensation", - "displayName": "Multiscattering Compensation", - "description": "Whether to enable multiple scattering compensation.", - "type": "Bool", - "connection": { - "type": "ShaderOption", - "name": "o_specularF0_enableMultiScatterCompensation" - } - } - ], - "clearCoat": [ - { - "name": "enable", - "displayName": "Enable", - "description": "Enable clear coat", - "type": "Bool", - "defaultValue": false - }, - { - "name": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the percentage of effect applied", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "name": "m_clearCoatFactor" - } - }, - { - "name": "influenceMap", - "displayName": " Influence Map", - "description": "Strength factor texture", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_clearCoatInfluenceMap" - } - }, - { - "name": "useInfluenceMap", - "displayName": " Use Texture", - "description": "Whether to use the texture, or just default to the Factor value.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "influenceMapUv", - "displayName": " UV", - "description": "Strength factor map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_clearCoatInfluenceMapUvIndex" - } - }, - { - "name": "roughness", - "displayName": "Roughness", - "description": "Clear coat layer roughness", - "type": "Float", - "defaultValue": 0.0, - "min": 0.0, - "max": 1.0, - "connection": { - "type": "ShaderInput", - "name": "m_clearCoatRoughness" - } - }, - { - "name": "roughnessMap", - "displayName": " Roughness Map", - "description": "Texture for defining surface roughness", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_clearCoatRoughnessMap" - } - }, - { - "name": "useRoughnessMap", - "displayName": " Use Texture", - "description": "Whether to use the texture, or just default to the roughness value.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "roughnessMapUv", - "displayName": " UV", - "description": "Roughness map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_clearCoatRoughnessMapUvIndex" - } - }, - { - "name": "normalStrength", - "displayName": "Normal Strength", - "description": "Scales the impact of the clear coat normal map", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 2.0, - "connection": { - "type": "ShaderInput", - "name": "m_clearCoatNormalStrength" - } - }, - { - "name": "normalMap", - "displayName": "Normal Map", - "description": "Normal map for clear coat layer, as top layer material clear coat doesn't affect by base layer normal map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_clearCoatNormalMap" - } - }, - { - "name": "useNormalMap", - "displayName": " Use Texture", - "description": "Whether to use the normal map", - "type": "Bool", - "defaultValue": true - }, - { - "name": "normalMapUv", - "displayName": " UV", - "description": "Normal map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_clearCoatNormalMapUvIndex" - } - } - ], - "normal": [ - { - "name": "textureMap", - "displayName": "Texture", - "description": "Texture for defining surface normal direction.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_normalMap" - } - }, - { - "name": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture, or just rely on vertex normals.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "textureMapUv", - "displayName": "UV", - "description": "Normal map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_normalMapUvIndex" - } - }, - { - "name": "flipX", - "displayName": "Flip X Channel", - "description": "Flip tangent direction for this normal map.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderInput", - "name": "m_flipNormalX" - } - }, - { - "name": "flipY", - "displayName": "Flip Y Channel", - "description": "Flip bitangent direction for this normal map.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderInput", - "name": "m_flipNormalY" - } - }, - { - "name": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "name": "m_normalFactor" - } - } - ], - "opacity": [ - { - "name": "mode", - "displayName": "Opacity Mode", - "description": "Indicates the general approach how transparency is to be applied.", - "type": "Enum", - "enumValues": [ "Opaque", "Cutout", "Blended", "TintedTransparent" ], - "defaultValue": "Opaque", - "connection": { - "type": "ShaderOption", - "name": "o_opacity_mode" - } - }, - { - "name": "alphaSource", - "displayName": "Alpha Source", - "description": "Indicates whether to get the opacity texture from the Base Color map (Packed) or from a separate greyscale texture (Split).", - "type": "Enum", - "enumValues": [ "Packed", "Split", "None" ], - "defaultValue": "Packed", - "connection": { - "type": "ShaderOption", - "name": "o_opacity_source" - } - }, - { - "name": "textureMap", - "displayName": "Texture", - "description": "Texture for defining surface opacity.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_opacityMap" - } - }, - { - "name": "textureMapUv", - "displayName": "UV", - "description": "Opacity map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_opacityMapUvIndex" - } - }, - { - "name": "factor", - "displayName": "Factor", - "description": "Factor for cutout threshold and blending", - "type": "Float", - "min": 0.0, - "max": 1.0, - "defaultValue": 0.5, - "connection": { - "type": "ShaderInput", - "name": "m_opacityFactor" - } - }, - { - "name": "alphaAffectsSpecular", - "displayName": "Alpha affects specular", - "description": "How much the alpha value should also affect specular reflection. This should be 0.0 for materials where light can transmit through their physical surface (like glass), but 1.0 when alpha determines the very presence of a surface (like hair or grass)", - "type": "float", - "min": 0.0, - "max": 1.0, - "defaultValue": 0.0, - "connection": { - "type": "ShaderInput", - "name": "m_opacityAffectsSpecularFactor" - } - } - ], - "uv": [ - { - "name": "center", - "displayName": "Center", - "description": "Center point for scaling and rotation transformations.", - "type": "vector2", - "vectorLabels": [ "U", "V" ], - "defaultValue": [ 0.5, 0.5 ] - }, - { - "name": "tileU", - "displayName": "Tile U", - "description": "Scales texture coordinates in U.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - }, - { - "name": "tileV", - "displayName": "Tile V", - "description": "Scales texture coordinates in V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - }, - { - "name": "offsetU", - "displayName": "Offset U", - "description": "Offsets texture coordinates in the U direction.", - "type": "float", - "defaultValue": 0.0, - "min": -1.0, - "max": 1.0 - }, - { - "name": "offsetV", - "displayName": "Offset V", - "description": "Offsets texture coordinates in the V direction.", - "type": "float", - "defaultValue": 0.0, - "min": -1.0, - "max": 1.0 - }, - { - "name": "rotateDegrees", - "displayName": "Rotate", - "description": "Rotates the texture coordinates (degrees).", - "type": "float", - "defaultValue": 0.0, - "min": -180.0, - "max": 180.0, - "step": 1.0 - }, - { - "name": "scale", - "displayName": "Scale", - "description": "Scales texture coordinates in both U and V.", - "type": "float", - "defaultValue": 1.0, - "step": 0.1 - } - ], - "occlusion": [ - { - "name": "diffuseTextureMap", - "displayName": "Diffuse AO", - "description": "Texture for defining occlusion area for diffuse ambient lighting.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_diffuseOcclusionMap" - } - }, - { - "name": "diffuseUseTexture", - "displayName": " Use Texture", - "description": "Whether to use the Diffuse AO map.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "diffuseTextureMapUv", - "displayName": " UV", - "description": "Diffuse AO map UV set.", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_diffuseOcclusionMapUvIndex" - } - }, - { - "name": "diffuseFactor", - "displayName": " Factor", - "description": "Strength factor for scaling the values of Diffuse AO", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "name": "m_diffuseOcclusionFactor" - } - }, - { - "name": "specularTextureMap", - "displayName": "Specular Cavity", - "description": "Texture for defining occlusion area for specular lighting.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_specularOcclusionMap" - } - }, - { - "name": "specularUseTexture", - "displayName": " Use Texture", - "description": "Whether to use the Specular Cavity map.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "specularTextureMapUv", - "displayName": " UV", - "description": "Specular Cavity map UV set.", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_specularOcclusionMapUvIndex" - } - }, - { - "name": "specularFactor", - "displayName": " Factor", - "description": "Strength factor for scaling the values of Specular Cavity", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "softMax": 2.0, - "connection": { - "type": "ShaderInput", - "name": "m_specularOcclusionFactor" - } - } - ], - "emissive": [ - { - "name": "enable", - "displayName": "Enable", - "description": "Enable the emissive group", - "type": "Bool", - "defaultValue": false - }, - { - "name": "unit", - "displayName": "Units", - "description": "The photometric units of the Intensity property.", - "type": "Enum", - "enumValues": ["Ev100"], - "defaultValue": "Ev100" - }, - { - "name": "color", - "displayName": "Color", - "description": "Color is displayed as sRGB but the values are stored as linear color.", - "type": "Color", - "defaultValue": [ 1.0, 1.0, 1.0 ], - "connection": { - "type": "ShaderInput", - "name": "m_emissiveColor" - } - }, - { - "name": "intensity", - "displayName": "Intensity", - "description": "The amount of energy emitted.", - "type": "Float", - "defaultValue": 4, - "min": -10, - "max": 20, - "softMin": -6, - "softMax": 16 - }, - { - "name": "textureMap", - "displayName": "Texture", - "description": "Texture for defining emissive area.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_emissiveMap" - } - }, - { - "name": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "textureMapUv", - "displayName": "UV", - "description": "Emissive map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_emissiveMapUvIndex" - } - } - ], - "parallax": [ - { - "name": "textureMap", - "displayName": "Height Map", - "description": "Displacement height map to create parallax effect.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "name": "m_heightmap" - } - }, - { - "name": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the height map.", - "type": "Bool", - "defaultValue": true - }, - { - "name": "textureMapUv", - "displayName": "UV", - "description": "Height map UV set", - "type": "Enum", - "enumIsUv": true, - "defaultValue": "Tiled", - "connection": { - "type": "ShaderInput", - "name": "m_parallaxUvIndex" - } - }, - { - "name": "factor", - "displayName": "Height Map Scale", - "description": "The total height of the height map in local model units.", - "type": "Float", - "defaultValue": 0.05, - "min": 0.0, - "softMax": 0.1, - "connection": { - "type": "ShaderInput", - "name": "m_heightmapScale" - } - }, - { - "name": "offset", - "displayName": "Offset", - "description": "Adjusts the overall displacement amount in local model units.", - "type": "Float", - "defaultValue": 0.0, - "softMin": -0.1, - "softMax": 0.1, - "connection": { - "type": "ShaderInput", - "name": "m_heightmapOffset" - } - }, - { - "name": "algorithm", - "displayName": "Algorithm", - "description": "Select the algorithm to use for parallax mapping.", - "type": "Enum", - "enumValues": [ "Basic", "Steep", "POM", "Relief", "ContactRefinement" ], - "defaultValue": "POM", - "connection": { - "type": "ShaderOption", - "name": "o_parallax_algorithm" - } - }, - { - "name": "quality", - "displayName": "Quality", - "description": "Quality of parallax mapping.", - "type": "Enum", - "enumValues": [ "Low", "Medium", "High", "Ultra" ], - "defaultValue": "Low", - "connection": { - "type": "ShaderOption", - "name": "o_parallax_quality" - } - }, - { - "name": "pdo", - "displayName": "Pixel Depth Offset", - "description": "Enable PDO to offset the original pixel depths. This will affect any shaders using depth, for example, when receiving shadows.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "name": "o_parallax_enablePixelDepthOffset" - } - }, - { - "name": "showClipping", - "displayName": "Show Clipping", - "description": "Highlight areas where the height map is clipped by the mesh surface.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderOption", - "name": "o_parallax_highlightClipping" - } - } - ], - "irradiance": [ - // Note: this property group is used in the DiffuseGlobalIllumination pass and not by the main forward shader - { - "name": "color", - "displayName": "Color", - "description": "Color is displayed as sRGB but the values are stored as linear color.", - "type": "Color", - "defaultValue": [ 1.0, 1.0, 1.0 ] - }, - { - "name": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the irradiance color values. Zero (0.0) is black, white (1.0) is full color.", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 1.0 - } - ] - } + ] }, "shaders": [ { @@ -1199,4 +1196,4 @@ "UV0": "Tiled", "UV1": "Unwrapped" } -} +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Models/DiffuseProbeSphere.fbx b/Gems/Atom/Feature/Common/Assets/Models/DiffuseProbeSphere.fbx new file mode 100644 index 0000000000..0fdf350c1f --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Models/DiffuseProbeSphere.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18a2bfdeeabfbbf6397daab7c89f9f7321e4863b54a4669fa87e457cb113322c +size 78256 diff --git a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseGlobalIllumination.pass b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseGlobalIllumination.pass index 45278cd511..a70f4446a4 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseGlobalIllumination.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseGlobalIllumination.pass @@ -42,6 +42,22 @@ }, "LoadAction": "Clear" } + }, + { + "Name": "VisualizationOutput", + "SlotType": "Output", + "ScopeAttachmentUsage": "RenderTarget", + "LoadStoreAction": { + "ClearValue": { + "Value": [ + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "LoadAction": "Clear" + } } ], "ImageAttachments": [ @@ -73,7 +89,14 @@ "AttachmentRef": { "Pass": "This", "Attachment": "IrradianceImage" - } + } + }, + { + "LocalSlot": "VisualizationOutput", + "AttachmentRef": { + "Pass": "DiffuseProbeGridVisualizationRayTracingPass", + "Attachment": "Output" + } } ], "PassRequests": [ @@ -193,6 +216,18 @@ } } ] + }, + { + "Name": "DiffuseProbeGridVisualizationPreparePass", + "TemplateName": "DiffuseProbeGridVisualizationPreparePassTemplate" + }, + { + "Name": "DiffuseProbeGridVisualizationAccelerationStructurePass", + "TemplateName": "DiffuseProbeGridVisualizationAccelerationStructurePassTemplate" + }, + { + "Name": "DiffuseProbeGridVisualizationRayTracingPass", + "TemplateName": "DiffuseProbeGridVisualizationRayTracingPassTemplate" } ] } diff --git a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationAccelerationStructure.pass b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationAccelerationStructure.pass new file mode 100644 index 0000000000..78d4c82dcf --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationAccelerationStructure.pass @@ -0,0 +1,13 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": + { + "PassTemplate": + { + "Name": "DiffuseProbeGridVisualizationAccelerationStructurePassTemplate", + "PassClass": "DiffuseProbeGridVisualizationAccelerationStructurePass" + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationComposite.pass b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationComposite.pass new file mode 100644 index 0000000000..9f19fde4af --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationComposite.pass @@ -0,0 +1,40 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "DiffuseProbeGridVisualizationCompositePassTemplate", + "PassClass": "DiffuseProbeGridVisualizationCompositePass", + "Slots": [ + { + "Name": "VisualizationInput", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader" + }, + { + "Name": "Depth", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader", + "ImageViewDesc": { + "AspectFlags": [ + "Depth" + ] + } + }, + { + "Name": "ColorInputOutput", + "SlotType": "InputOutput", + "ScopeAttachmentUsage": "RenderTarget" + } + ], + "PassData": { + "$type": "FullscreenTrianglePassData", + "ShaderAsset": { + "FilePath": "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.shader" + }, + "PipelineViewTag": "MainCamera" + } + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationPrepare.pass b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationPrepare.pass new file mode 100644 index 0000000000..aa95128a2e --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationPrepare.pass @@ -0,0 +1,13 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": + { + "PassTemplate": + { + "Name": "DiffuseProbeGridVisualizationPreparePassTemplate", + "PassClass": "DiffuseProbeGridVisualizationPreparePass" + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationRayTracing.pass b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationRayTracing.pass new file mode 100644 index 0000000000..bdfba0d478 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationRayTracing.pass @@ -0,0 +1,54 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "DiffuseProbeGridVisualizationRayTracingPassTemplate", + "PassClass": "DiffuseProbeGridVisualizationRayTracingPass", + "Slots": [ + { + "Name": "Output", + "SlotType": "Output", + "ShaderInputName": "m_output", + "ScopeAttachmentUsage": "Shader", + "LoadStoreAction": { + "ClearValue": { + "Value": [ + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "LoadAction": "Clear" + } + } + ], + "ImageAttachments": [ + { + "Name": "VisualizationImage", + "SizeSource": { + "Source": { + "Pass": "Parent", + "Attachment": "NormalInput" + } + }, + "ImageDescriptor": { + "Format": "R32G32B32A32_FLOAT", + "SharedQueueMask": "Graphics" + } + } + ], + "Connections": [ + { + "LocalSlot": "Output", + "AttachmentRef": { + "Pass": "This", + "Attachment": "VisualizationImage" + } + } + ] + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass index 314d999e4d..f0c1c212c0 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass @@ -357,6 +357,33 @@ } ] }, + { + "Name": "DiffuseProbeGridVisualizationCompositePass", + "TemplateName": "DiffuseProbeGridVisualizationCompositePassTemplate", + "Connections": [ + { + "LocalSlot": "VisualizationInput", + "AttachmentRef": { + "Pass": "OpaquePass", + "Attachment": "DiffuseProbeGridVisualization" + } + }, + { + "LocalSlot": "Depth", + "AttachmentRef": { + "Pass": "DepthPrePass", + "Attachment": "Depth" + } + }, + { + "LocalSlot": "ColorInputOutput", + "AttachmentRef": { + "Pass": "PostProcessPass", + "Attachment": "Output" + } + } + ] + }, { "Name": "AuxGeomPass", "TemplateName": "AuxGeomPassTemplate", @@ -365,8 +392,8 @@ { "LocalSlot": "ColorInputOutput", "AttachmentRef": { - "Pass": "PostProcessPass", - "Attachment": "Output" + "Pass": "DiffuseProbeGridVisualizationCompositePass", + "Attachment": "ColorInputOutput" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass index 752d565234..dcf5ef3550 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass @@ -46,6 +46,10 @@ "Name": "Output", "SlotType": "Output" }, + { + "Name": "DiffuseProbeGridVisualization", + "SlotType": "Output" + }, // SwapChain here is only used to reference the frame height and format { "Name": "SwapChainOutput", @@ -59,6 +63,13 @@ "Pass": "DiffuseSpecularMergePass", "Attachment": "Output" } + }, + { + "LocalSlot": "DiffuseProbeGridVisualization", + "AttachmentRef": { + "Pass": "DiffuseGlobalIlluminationPass", + "Attachment": "VisualizationOutput" + } } ], "PassRequests": [ diff --git a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset index 96cf769690..16e6a7ee72 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset +++ b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset @@ -476,6 +476,22 @@ "Name": "DiffuseCompositePassTemplate", "Path": "Passes/DiffuseComposite.pass" }, + { + "Name": "DiffuseProbeGridVisualizationPreparePassTemplate", + "Path": "Passes/DiffuseProbeGridVisualizationPrepare.pass" + }, + { + "Name": "DiffuseProbeGridVisualizationAccelerationStructurePassTemplate", + "Path": "Passes/DiffuseProbeGridVisualizationAccelerationStructure.pass" + }, + { + "Name": "DiffuseProbeGridVisualizationRayTracingPassTemplate", + "Path": "Passes/DiffuseProbeGridVisualizationRayTracing.pass" + }, + { + "Name": "DiffuseProbeGridVisualizationCompositePassTemplate", + "Path": "Passes/DiffuseProbeGridVisualizationComposite.pass" + }, { "Name": "DiffuseGlobalFullscreenPassTemplate", "Path": "Passes/DiffuseGlobalFullscreen.pass" diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.azsl new file mode 100644 index 0000000000..e6b28da8c8 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.azsl @@ -0,0 +1,65 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + Texture2D m_visualization; + Texture2D m_depth; + + Sampler LinearSampler + { + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +// Vertex Shader +VSOutput MainVS(VSInput input) +{ + VSOutput OUT; + + float4 posTex = GetVertexPositionAndTexCoords(input.m_vertexID); + OUT.m_position = float4(posTex.x, posTex.y, 0.0, 1.0); + + return OUT; +} + +// Pixel Shader +PSOutput MainPS(VSOutput IN) +{ + uint2 screenCoords = IN.m_position.xy; + float depth = PassSrg::m_depth.Load(uint3(screenCoords, 0)).r; + float4 visualization = PassSrg::m_visualization.Load(uint3(screenCoords, 0)); + + if (!any(visualization)) + { + discard; + } + + if (depth > visualization.a) + { + discard; + } + + PSOutput OUT; + OUT.m_color = float4(visualization.rgb, 1.0f); + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.shader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.shader new file mode 100644 index 0000000000..8d758b9b6d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.shader @@ -0,0 +1,42 @@ +{ + "Source" : "DiffuseProbeGridVisualizationComposite.azsl", + + "RasterState" : + { + "CullMode" : "Back" + }, + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : false + } + }, + + "DrawList" : "forward", + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + }, + + "Supervariants": + [ + { + "Name": "NoMSAA", + "PlusArguments": "--no-ms", + "MinusArguments": "" + } + ] +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPrepare.precompiledshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPrepare.precompiledshader new file mode 100644 index 0000000000..d77b7fcb0e --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPrepare.precompiledshader @@ -0,0 +1,34 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PrecompiledShaderAssetSourceData", + "ClassData": + { + "ShaderAssetFileName": "diffuseprobegridvisualizationprepare.azshader", + "PlatformIdentifiers": [ + "pc", + "linux" + ], + "Supervariants": + [ + { + "Name": "", + "RootShaderVariantAssets": + [ + { + "APIName": "dx12", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationprepare_dx12_0.azshadervariant" + }, + { + "APIName": "vulkan", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationprepare_vulkan_0.azshadervariant" + }, + { + "APIName": "null", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationprepare_null_0.azshadervariant" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracing.precompiledshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracing.precompiledshader new file mode 100644 index 0000000000..ff38bfd843 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracing.precompiledshader @@ -0,0 +1,34 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PrecompiledShaderAssetSourceData", + "ClassData": + { + "ShaderAssetFileName": "diffuseprobegridvisualizationraytracing.azshader", + "PlatformIdentifiers": [ + "pc", + "linux" + ], + "Supervariants": + [ + { + "Name": "", + "RootShaderVariantAssets": + [ + { + "APIName": "dx12", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracing_dx12_0.azshadervariant" + }, + { + "APIName": "vulkan", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracing_vulkan_0.azshadervariant" + }, + { + "APIName": "null", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracing_null_0.azshadervariant" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingClosestHit.precompiledshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingClosestHit.precompiledshader new file mode 100644 index 0000000000..1f0d0f7e11 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingClosestHit.precompiledshader @@ -0,0 +1,35 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PrecompiledShaderAssetSourceData", + "ClassData": + { + "ShaderAssetFileName": "diffuseprobegridvisualizationraytracingclosesthit.azshader", + "PlatformIdentifiers": + [ + "pc", + "linux" + ], + "Supervariants": + [ + { + "Name": "", + "RootShaderVariantAssets": + [ + { + "APIName": "dx12", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingclosesthit_dx12_0.azshadervariant" + }, + { + "APIName": "vulkan", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingclosesthit_vulkan_0.azshadervariant" + }, + { + "APIName": "null", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingclosesthit_null_0.azshadervariant" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingMiss.precompiledshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingMiss.precompiledshader new file mode 100644 index 0000000000..905006d92a --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingMiss.precompiledshader @@ -0,0 +1,35 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PrecompiledShaderAssetSourceData", + "ClassData": + { + "ShaderAssetFileName": "diffuseprobegridvisualizationraytracingmiss.azshader", + "PlatformIdentifiers": + [ + "pc", + "linux" + ], + "Supervariants": + [ + { + "Name": "", + "RootShaderVariantAssets": + [ + { + "APIName": "dx12", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingmiss_dx12_0.azshadervariant" + }, + { + "APIName": "vulkan", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingmiss_vulkan_0.azshadervariant" + }, + { + "APIName": "null", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingmiss_null_0.azshadervariant" + } + ] + } + ] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader index 4186489303..69507ebd96 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant index 7cfce8e245..e2e46af613 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant index 3fa87b4e79..b7a82735bc 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant index 9b831386eb..570f94dc34 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare.azshader new file mode 100644 index 0000000000..3d9904c607 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_dx12_0.azshadervariant new file mode 100644 index 0000000000..507fd5e5a9 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_null_0.azshadervariant new file mode 100644 index 0000000000..84b6226022 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_vulkan_0.azshadervariant new file mode 100644 index 0000000000..9ad3c0deb1 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing.azshader new file mode 100644 index 0000000000..0b8181e53f Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_dx12_0.azshadervariant new file mode 100644 index 0000000000..99c5a3791b Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_null_0.azshadervariant new file mode 100644 index 0000000000..6c9bcb846b Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_vulkan_0.azshadervariant new file mode 100644 index 0000000000..8d0eb8a2a8 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit.azshader new file mode 100644 index 0000000000..045817ff6a Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_dx12_0.azshadervariant new file mode 100644 index 0000000000..e20b15d485 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_null_0.azshadervariant new file mode 100644 index 0000000000..4f3437ccda Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_vulkan_0.azshadervariant new file mode 100644 index 0000000000..918e729d99 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss.azshader new file mode 100644 index 0000000000..bf5102b8fa Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_dx12_0.azshadervariant new file mode 100644 index 0000000000..db77503c25 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_null_0.azshadervariant new file mode 100644 index 0000000000..b44637279f Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_vulkan_0.azshadervariant new file mode 100644 index 0000000000..095e78c700 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessorInterface.h index 066efabb96..5aedc2f6c6 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessorInterface.h @@ -125,6 +125,9 @@ namespace AZ virtual void SetUseDiffuseIbl(const DiffuseProbeGridHandle& probeGrid, bool useDiffuseIbl) = 0; virtual void SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode) = 0; virtual void SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures) = 0; + virtual void SetVisualizationEnabled(const DiffuseProbeGridHandle& probeGrid, bool visualizationEnabled) = 0; + virtual void SetVisualizationShowInactiveProbes(const DiffuseProbeGridHandle& probeGrid, bool visualizationShowInactiveProbes) = 0; + virtual void SetVisualizationSphereRadius(const DiffuseProbeGridHandle& probeGrid, float visualizationSphereRadius) = 0; virtual void BakeTextures( const DiffuseProbeGridHandle& probeGrid, diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/ParamMacrosHowTo.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/ParamMacrosHowTo.inl index e6fd6c10ba..ecf63ff5f6 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/ParamMacrosHowTo.inl +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/ParamMacrosHowTo.inl @@ -6,239 +6,241 @@ * */ -// -// This is a quick guide on how to use the parameter macros included in this folder -// -// Part I: The Pattern -// -// The aim of this macro system is to allow users to define parameters once and have the macros generate a bunch of boilerplate code for each defined parameter. -// While these macros makes things a little more complex upfront, the ability to add and remove variables in just one place without having to dig -// through multiple files every time is great for iteration speed and maintenance. To accomplish this, we use a pattern similar to the following example: -// -// Let's say we want to specify class members in one place and have the members, getters and setters be auto generated. -// First, we define a macro MY_CLASS_PARAMS that uses a yet-undefined macro MAKE_PARAM(TYPE, NAME): -// -// #define MY_CLASS_PARAMS \ -// MAKE_PARAM(float, Width) \ -// MAKE_PARAM(float, Height) \ -// MAKE_PARAM(float, Depth) \ -// -// Now we need only specify what MAKE_PARAM needs to do and then we can call the MY_CLASS_PARAMS macro to apply the logic to all defined params. For instance: -// -// #define MAKE_PARAM(TYPE, NAME) TYPE m_##NAME; -// MY_CLASS_PARAMS -// #undef MAKE_PARAM -// -// This will generate the members as follows: -// -// float m_Width; -// float m_Height; -// float m_Depth; -// -// Now elsewhere in the class definition we can generate getters and setters: -// -// #define MAKE_PARAM(TYPE, NAME) \ -// TYPE Get##NAME() { return m_##NAME; } \ -// void Set##NAME(TYPE NAME) { m_##NAME = NAME; } \ -// -// MY_CLASS_PARAMS -// -// #undef MAKE_PARAM -// -// This will generate the following: -// -// float GetWidth() { return m_Width; } -// void SetWidth(float Width) { m_Width = Width; } -// float GetHeight() { return m_Height; } -// void SetHeight(float Width) { m_Height = Height; } -// float GetDepth() { return m_Width; } -// void SetDepth(float Depth) { m_Depth = Depth; } -// -// If we wanted to generate further code for each variable, we need only redefine the MAKE_PARAM macro and invoke MY_CLASS_PARAMS -// -// ___________________________________________________________________________________________________________________________________________________ -// -// Part II: Using .inl files -// -// A key difference between the above example and our macro system is that we put macro definitions in .inl files so they can be easily reused -// If we were to reuse the above example, it would look something like this: -// -// GenerateMembers.inl -// -// #define MAKE_PARAM(TYPE, NAME) TYPE m_##NAME; -// -// GenerateGettersAndSetters.inl -// -// #define MAKE_PARAM(TYPE, NAME) \ -// TYPE Get##NAME() { return m_##NAME; } \ -// void Set##NAME(TYPE NAME) { m_##NAME = NAME; } \ -// -// BoxParams.inl -// -// MAKE_PARAM(float, Width) \ -// MAKE_PARAM(float, Height) \ -// MAKE_PARAM(float, Depth) \ -// -// CylinderParams.inl -// -// MAKE_PARAM(float, Radius) \ -// MAKE_PARAM(float, Height) \ -// -// Now we can use these .inl files to generate two classes, each with members, getters and setters -// -// class Box -// { -// // Auto-gen members from BoxParams.inl -// #include -// #include -// #undef MAKE_PARAM -// -// // Auto-gen getters and setters from BoxParams.inl -// #include -// #include -// #undef MAKE_PARAM -// } -// -// class Cylinder -// { -// // Auto-gen members from CylinderParams.inl -// #include -// #include -// #undef MAKE_PARAM -// -// // Auto-gen getters and setters from CylinderParams.inl -// #include -// #include -// #undef MAKE_PARAM -// } -// -// This will result in the following code: -// -// class Box -// { -// // Auto-gen members from BoxParams.inl -// float m_Width; -// float m_Height; -// float m_Depth; -// -// // Auto-gen getters and setters from BoxParams.inl -// float GetWidth() { return m_Width; } -// void SetWidth(float Width) { m_Width = Width; } -// float GetHeight() { return m_Height; } -// void SetHeight(float Width) { m_Height = Height; } -// float GetDepth() { return m_Width; } -// void SetDepth(float Depth) { m_Depth = Depth; } -// } -// -// class Cylinder -// { -// // Auto-gen members from CylinderParams.inl -// float m_Radius; -// float m_Height; -// -// // Auto-gen getters and setters from CylinderParams.inl -// float GetRadius() { return m_Radius; } -// void SetRadius(float Radius) { m_Radius = Raidus; } -// float GetHeight() { return m_Height; } -// void SetHeight(float Width) { m_Height = Height; } -// } -// -// As you can see, this macro pattern allows us to add a member to Box or Cylinder by adding a single line to BoxParams.inl or CylinderParams.inl -// Because of the number of classes an boiler plate code involved in creating Open 3D Engine Component, this macro system allows us to change one line -// in one file instead of changing over a dozens of lines in half a dozen files. -// -// ___________________________________________________________________________________________________________________________________________________ -// -// Part III: Using the Macros for Post Process members -// -// If you want to create a new post process, you can create a .inl file (see DepthOfFieldParams.inl for an example) and declare members using the macros below: -// -// #define AZ_GFX_BOOL_PARAM(Name, MemberName, DefaultValue) -// #define AZ_GFX_FLOAT_PARAM(Name, MemberName, DefaultValue) -// #define AZ_GFX_UINT32_PARAM(Name, MemberName, DefaultValue) -// #define AZ_GFX_VEC2_PARAM(Name, MemberName, DefaultValue) -// #define AZ_GFX_VEC3_PARAM(Name, MemberName, DefaultValue) -// #define AZ_GFX_VEC4_PARAM(Name, MemberName, DefaultValue) -// -// Where: -// Name - The name of the param that will be used for reflection and appended to setters and getters, for example Width -// MemberName - The name of the member defined inside your class, for example m_width -// DefaultValue - The default value that the member will be statically initialized to, for example 1.0f -// BOOL, FLOAT, UINT32, VEC2 etc. all designate the type of the param you are defining -// -// If you have a custom type for your parameter, you can use the AZ_GFX_COMMON_PARAM macro: -// AZ_GFX_COMMON_PARAM(Name, MemberName, DefaultValue, ValueType) -// The keywords here are the same as above, with the addition of ValueType: the custom type you want your param to be -// -// Example usages: -// -// #define AZ_GFX_VEC3_PARAM(Position, m_position, Vector3(0.0f, 0.0f, 0.0f)) -// -// #define AZ_GFX_COMMON_PARAM(Format, m_format, Format::Unknown, FormatEnum) -// -// ___________________________________________________________________________________________________________________________________________________ -// -// Part IV: Using the Macros for Post Process overrides -// -// The Post Process System allows users to specify whether settings should be overridden or not on a per-member basis. -// To enable this, when you declare a member that can be overridden by higher priority Post Process Settings, in addition -// to using the above macros to define the member, you should also use one of the following to specify the override: -// -// #define AZ_GFX_ANY_PARAM_BOOL_OVERRIDE(Name, MemberName, ValueType) -// #define AZ_GFX_INTEGER_PARAM_FLOAT_OVERRIDE(Name, MemberName, ValueType) -// #define AZ_GFX_FLOAT_PARAM_FLOAT_OVERRIDE(Name, MemberName, ValueType) -// -// Where: -// Name - The name of the param that will be used for reflection and appended to setters and getters, for example Width -// MemberName - The name of the member defined inside your class, for example m_width -// ValueType - The type of the parameter you defined (bool, float, uint32_t, Vector2 etc.) -// -// A bit more details on each of the override macros: -// -// AZ_GFX_ANY_PARAM_BOOL_OVERRIDE can be used for params of any type. The override variable will be a bool (checkbox in the UI). -// The override application is a simple binary operation: take all of the source or the target (no lerp) depending on the bool. -// -// AZ_GFX_INTEGER_PARAM_FLOAT_OVERRIDE should be used for params of integer types (int, uint, integer vectors...) The override variable -// will be a float from 0.0 to 1.0 (slider in the UI). The override will lerp between target and source using the override float -// variable. Note that for this reason the param integer type must support multiplication by a float value. -// -// AZ_GFX_FLOAT_PARAM_FLOAT_OVERRIDE should be used for params of floating point types (float, double, Vector4...) The override variable -// will be a float from 0.0 to 1.0 (slider in the UI). The override will lerp between target and source using the override float. -// -// Example usage: -// -// #define AZ_GFX_VEC3_PARAM(Position, m_position, Vector3(0.0f, 0.0f, 0.0f)) -// #define AZ_GFX_FLOAT_PARAM_FLOAT_OVERRIDE(Position, m_position, Vector3) -// -// ___________________________________________________________________________________________________________________________________________________ -// -// Part V: Defining functionality with .inl files -// -// There are many .inl fies in this folder that provide pre-defined behaviors for params declared with the above macros -// To use these files, start by including the .inl file that specifies the behavior, then include your own .inl that defines your params -// then include EndParams.inl (this will #undef all used macros so as to avoid collisions with subsequent macro usage further in the file) -// -// Here is an example of how that looks: -// -// #include <- The behavior you want (behavior is described in each file) -// #include <- Your file in which you declare your params -// #include <- This #undef a bunch of macros to avoid conflicts -// -// You may of course use your own custom behaviors by specifying your definition for the param and override macros. -// You can specify each macro individually (AZ_GFX_BOOL_PARAM, AZ_GFX_FLOAT_PARAM, AZ_GFX_UINT32_PARAM, AZ_GFX_VEC2_PARAM, etc.) -// or you can specify the AZ_GFX_COMMON_PARAM and AZ_GFX_COMMON_OVERRIDE macros if there's no difference between variable types. -// -// AZ_GFX_COMMON_PARAM and AZ_GFX_COMMON_OVERRIDE are helper macros that the other _PARAM and _OVERRIDE macros can be mapped to -// using MapAllCommon.inl, allowing you to specify one definition for all types rather than each type individually. -// Here is an example of how we can use AZ_GFX_COMMON_PARAM and AZ_GFX_COMMON_OVERRIDE to auto-generate getters for our member parameters: -// -// #define AZ_GFX_COMMON_PARAM(Name, MemberName, DefaultValue, ValueType) \ -// ValueType Get##Name() const override { return MemberName; } \ -// -// #define AZ_GFX_COMMON_OVERRIDE(Name, MemberName, ValueType, OverrideValueType) \ -// OverrideValueType Get##Name##Override() const override { return MemberName##Override; } \ -// -// #include -// #include -// #include -// +/* + + This is a quick guide on how to use the parameter macros included in this folder + + Part I: The Pattern + + The aim of this macro system is to allow users to define parameters once and have the macros generate a bunch of boilerplate code for each defined parameter. + While these macros makes things a little more complex upfront, the ability to add and remove variables in just one place without having to dig + through multiple files every time is great for iteration speed and maintenance. To accomplish this, we use a pattern similar to the following example: + + Let's say we want to specify class members in one place and have the members, getters and setters be auto generated. + First, we define a macro MY_CLASS_PARAMS that uses a yet-undefined macro MAKE_PARAM(TYPE, NAME): + + #define MY_CLASS_PARAMS \ + MAKE_PARAM(float, Width) \ + MAKE_PARAM(float, Height) \ + MAKE_PARAM(float, Depth) \ + + Now we need only specify what MAKE_PARAM needs to do and then we can call the MY_CLASS_PARAMS macro to apply the logic to all defined params. For instance: + + #define MAKE_PARAM(TYPE, NAME) TYPE m_##NAME; + MY_CLASS_PARAMS + #undef MAKE_PARAM + + This will generate the members as follows: + + float m_Width; + float m_Height; + float m_Depth; + + Now elsewhere in the class definition we can generate getters and setters: + + #define MAKE_PARAM(TYPE, NAME) \ + TYPE Get##NAME() { return m_##NAME; } \ + void Set##NAME(TYPE NAME) { m_##NAME = NAME; } \ + + MY_CLASS_PARAMS + + #undef MAKE_PARAM + + This will generate the following: + + float GetWidth() { return m_Width; } + void SetWidth(float Width) { m_Width = Width; } + float GetHeight() { return m_Height; } + void SetHeight(float Width) { m_Height = Height; } + float GetDepth() { return m_Width; } + void SetDepth(float Depth) { m_Depth = Depth; } + + If we wanted to generate further code for each variable, we need only redefine the MAKE_PARAM macro and invoke MY_CLASS_PARAMS + + ___________________________________________________________________________________________________________________________________________________ + + Part II: Using .inl files + + A key difference between the above example and our macro system is that we put macro definitions in .inl files so they can be easily reused + If we were to reuse the above example, it would look something like this: + + GenerateMembers.inl + + #define MAKE_PARAM(TYPE, NAME) TYPE m_##NAME; + + GenerateGettersAndSetters.inl + + #define MAKE_PARAM(TYPE, NAME) \ + TYPE Get##NAME() { return m_##NAME; } \ + void Set##NAME(TYPE NAME) { m_##NAME = NAME; } \ + + BoxParams.inl + + MAKE_PARAM(float, Width) \ + MAKE_PARAM(float, Height) \ + MAKE_PARAM(float, Depth) \ + + CylinderParams.inl + + MAKE_PARAM(float, Radius) \ + MAKE_PARAM(float, Height) \ + + Now we can use these .inl files to generate two classes, each with members, getters and setters + + class Box + { + // Auto-gen members from BoxParams.inl + #include + #include + #undef MAKE_PARAM + + // Auto-gen getters and setters from BoxParams.inl + #include + #include + #undef MAKE_PARAM + } + + class Cylinder + { + // Auto-gen members from CylinderParams.inl + #include + #include + #undef MAKE_PARAM + + // Auto-gen getters and setters from CylinderParams.inl + #include + #include + #undef MAKE_PARAM + } + + This will result in the following code: + + class Box + { + // Auto-gen members from BoxParams.inl + float m_Width; + float m_Height; + float m_Depth; + + // Auto-gen getters and setters from BoxParams.inl + float GetWidth() { return m_Width; } + void SetWidth(float Width) { m_Width = Width; } + float GetHeight() { return m_Height; } + void SetHeight(float Width) { m_Height = Height; } + float GetDepth() { return m_Width; } + void SetDepth(float Depth) { m_Depth = Depth; } + } + + class Cylinder + { + // Auto-gen members from CylinderParams.inl + float m_Radius; + float m_Height; + + // Auto-gen getters and setters from CylinderParams.inl + float GetRadius() { return m_Radius; } + void SetRadius(float Radius) { m_Radius = Raidus; } + float GetHeight() { return m_Height; } + void SetHeight(float Width) { m_Height = Height; } + } + + As you can see, this macro pattern allows us to add a member to Box or Cylinder by adding a single line to BoxParams.inl or CylinderParams.inl + Because of the number of classes an boiler plate code involved in creating Open 3D Engine Component, this macro system allows us to change one line + in one file instead of changing over a dozens of lines in half a dozen files. + + ___________________________________________________________________________________________________________________________________________________ + + Part III: Using the Macros for Post Process members + + If you want to create a new post process, you can create a .inl file (see DepthOfFieldParams.inl for an example) and declare members using the macros below: + + #define AZ_GFX_BOOL_PARAM(Name, MemberName, DefaultValue) + #define AZ_GFX_FLOAT_PARAM(Name, MemberName, DefaultValue) + #define AZ_GFX_UINT32_PARAM(Name, MemberName, DefaultValue) + #define AZ_GFX_VEC2_PARAM(Name, MemberName, DefaultValue) + #define AZ_GFX_VEC3_PARAM(Name, MemberName, DefaultValue) + #define AZ_GFX_VEC4_PARAM(Name, MemberName, DefaultValue) + + Where: + Name - The name of the param that will be used for reflection and appended to setters and getters, for example Width + MemberName - The name of the member defined inside your class, for example m_width + DefaultValue - The default value that the member will be statically initialized to, for example 1.0f + BOOL, FLOAT, UINT32, VEC2 etc. all designate the type of the param you are defining + + If you have a custom type for your parameter, you can use the AZ_GFX_COMMON_PARAM macro: + AZ_GFX_COMMON_PARAM(Name, MemberName, DefaultValue, ValueType) + The keywords here are the same as above, with the addition of ValueType: the custom type you want your param to be + + Example usages: + + #define AZ_GFX_VEC3_PARAM(Position, m_position, Vector3(0.0f, 0.0f, 0.0f)) + + #define AZ_GFX_COMMON_PARAM(Format, m_format, Format::Unknown, FormatEnum) + + ___________________________________________________________________________________________________________________________________________________ + + Part IV: Using the Macros for Post Process overrides + + The Post Process System allows users to specify whether settings should be overridden or not on a per-member basis. + To enable this, when you declare a member that can be overridden by higher priority Post Process Settings, in addition + to using the above macros to define the member, you should also use one of the following to specify the override: + + #define AZ_GFX_ANY_PARAM_BOOL_OVERRIDE(Name, MemberName, ValueType) + #define AZ_GFX_INTEGER_PARAM_FLOAT_OVERRIDE(Name, MemberName, ValueType) + #define AZ_GFX_FLOAT_PARAM_FLOAT_OVERRIDE(Name, MemberName, ValueType) + + Where: + Name - The name of the param that will be used for reflection and appended to setters and getters, for example Width + MemberName - The name of the member defined inside your class, for example m_width + ValueType - The type of the parameter you defined (bool, float, uint32_t, Vector2 etc.) + + A bit more details on each of the override macros: + + AZ_GFX_ANY_PARAM_BOOL_OVERRIDE can be used for params of any type. The override variable will be a bool (checkbox in the UI). + The override application is a simple binary operation: take all of the source or the target (no lerp) depending on the bool. + + AZ_GFX_INTEGER_PARAM_FLOAT_OVERRIDE should be used for params of integer types (int, uint, integer vectors...) The override variable + will be a float from 0.0 to 1.0 (slider in the UI). The override will lerp between target and source using the override float + variable. Note that for this reason the param integer type must support multiplication by a float value. + + AZ_GFX_FLOAT_PARAM_FLOAT_OVERRIDE should be used for params of floating point types (float, double, Vector4...) The override variable + will be a float from 0.0 to 1.0 (slider in the UI). The override will lerp between target and source using the override float. + + Example usage: + + #define AZ_GFX_VEC3_PARAM(Position, m_position, Vector3(0.0f, 0.0f, 0.0f)) + #define AZ_GFX_FLOAT_PARAM_FLOAT_OVERRIDE(Position, m_position, Vector3) + + ___________________________________________________________________________________________________________________________________________________ + + Part V: Defining functionality with .inl files + + There are many .inl fies in this folder that provide pre-defined behaviors for params declared with the above macros + To use these files, start by including the .inl file that specifies the behavior, then include your own .inl that defines your params + then include EndParams.inl (this will #undef all used macros so as to avoid collisions with subsequent macro usage further in the file) + + Here is an example of how that looks: + + #include <- The behavior you want (behavior is described in each file) + #include <- Your file in which you declare your params + #include <- This #undef a bunch of macros to avoid conflicts + + You may of course use your own custom behaviors by specifying your definition for the param and override macros. + You can specify each macro individually (AZ_GFX_BOOL_PARAM, AZ_GFX_FLOAT_PARAM, AZ_GFX_UINT32_PARAM, AZ_GFX_VEC2_PARAM, etc.) + or you can specify the AZ_GFX_COMMON_PARAM and AZ_GFX_COMMON_OVERRIDE macros if there's no difference between variable types. + + AZ_GFX_COMMON_PARAM and AZ_GFX_COMMON_OVERRIDE are helper macros that the other _PARAM and _OVERRIDE macros can be mapped to + using MapAllCommon.inl, allowing you to specify one definition for all types rather than each type individually. + Here is an example of how we can use AZ_GFX_COMMON_PARAM and AZ_GFX_COMMON_OVERRIDE to auto-generate getters for our member parameters: + + #define AZ_GFX_COMMON_PARAM(Name, MemberName, DefaultValue, ValueType) \ + ValueType Get##Name() const override { return MemberName; } \ + + #define AZ_GFX_COMMON_OVERRIDE(Name, MemberName, ValueType, OverrideValueType) \ + OverrideValueType Get##Name##Override() const override { return MemberName##Override; } \ + + #include + #include + #include + +*/ diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp index fa473cb8c6..2294c00d71 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp @@ -94,6 +94,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -278,6 +282,10 @@ namespace AZ passSystem->AddPassCreator(Name("DiffuseProbeGridClassificationPass"), &Render::DiffuseProbeGridClassificationPass::Create); passSystem->AddPassCreator(Name("DiffuseProbeGridDownsamplePass"), &Render::DiffuseProbeGridDownsamplePass::Create); passSystem->AddPassCreator(Name("DiffuseProbeGridRenderPass"), &Render::DiffuseProbeGridRenderPass::Create); + passSystem->AddPassCreator(Name("DiffuseProbeGridVisualizationPreparePass"), &Render::DiffuseProbeGridVisualizationPreparePass::Create); + passSystem->AddPassCreator(Name("DiffuseProbeGridVisualizationAccelerationStructurePass"), &Render::DiffuseProbeGridVisualizationAccelerationStructurePass::Create); + passSystem->AddPassCreator(Name("DiffuseProbeGridVisualizationRayTracingPass"), &Render::DiffuseProbeGridVisualizationRayTracingPass::Create); + passSystem->AddPassCreator(Name("DiffuseProbeGridVisualizationCompositePass"), &Render::DiffuseProbeGridVisualizationCompositePass::Create); passSystem->AddPassCreator(Name("LuminanceHistogramGeneratorPass"), &LuminanceHistogramGeneratorPass::Create); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp index 798ebc502b..ac7d4bbb4d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp @@ -43,10 +43,15 @@ namespace AZ m_irradianceImageAttachmentId = AZStd::string::format("ProbeIrradianceImageAttachmentId_%s", uuidString.c_str()); m_distanceImageAttachmentId = AZStd::string::format("ProbeDistanceImageAttachmentId_%s", uuidString.c_str()); m_probeDataImageAttachmentId = AZStd::string::format("ProbeDataImageAttachmentId_%s", uuidString.c_str()); + m_visualizationTlasAttachmentId = AZStd::string::format("ProbeVisualizationTlasAttachmentId_%s", uuidString.c_str()); + m_visualizationTlasInstancesAttachmentId = AZStd::string::format("ProbeVisualizationTlasInstancesAttachmentId_%s", uuidString.c_str()); // setup culling m_cullable.m_cullData.m_scene = m_scene; m_cullable.SetDebugName(AZ::Name("DiffuseProbeGrid Volume")); + + // create the visualization TLAS + m_visualizationTlas = AZ::RHI::RayTracingTlas::CreateRHIRayTracingTlas(); } void DiffuseProbeGrid::Simulate(uint32_t probeIndex) @@ -116,9 +121,6 @@ namespace AZ // recompute the number of probes since the spacing changed UpdateProbeCount(); - // probes need to be relocated since the grid density changed - m_remainingRelocationIterations = DefaultNumRelocationIterations; - m_updateTextures = true; } @@ -169,9 +171,6 @@ namespace AZ m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_renderExtents / 2.0f); - // probes need to be relocated since the grid extents changed - m_remainingRelocationIterations = DefaultNumRelocationIterations; - m_updateTextures = true; } @@ -201,9 +200,6 @@ namespace AZ } m_updateTextures = true; - - // probes need to be relocated since the mode has changed - m_remainingRelocationIterations = DefaultNumRelocationIterations; } void DiffuseProbeGrid::SetBakedTextures(const DiffuseProbeGridBakedTextures& bakedTextures) @@ -253,6 +249,23 @@ namespace AZ return m_cullable.m_isVisible; } + void DiffuseProbeGrid::SetVisualizationEnabled(bool visualizationEnabled) + { + m_visualizationEnabled = visualizationEnabled; + m_visualizationTlasUpdateRequired = true; + } + + void DiffuseProbeGrid::SetVisualizationSphereRadius(float visualizationSphereRadius) + { + m_visualizationSphereRadius = visualizationSphereRadius; + m_visualizationTlasUpdateRequired = true; + } + + bool DiffuseProbeGrid::GetVisualizationTlasUpdateRequired() const + { + return m_visualizationTlasUpdateRequired || m_remainingRelocationIterations > 0; + } + uint32_t DiffuseProbeGrid::GetTotalProbeCount() const { return m_probeCountX * m_probeCountY * m_probeCountZ; @@ -341,6 +354,9 @@ namespace AZ [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeDataImage image"); } + + // probes need to be relocated since the textures changed + m_remainingRelocationIterations = DefaultNumRelocationIterations; } m_updateTextures = false; @@ -348,8 +364,8 @@ namespace AZ // textures have changed so we need to update the render Srg to bind the new ones m_updateRenderObjectSrg = true; - // we need to clear the irradiance texture - m_irradianceClearRequired = true; + // we need to clear the Irradiance, Distance, and ProbeData textures + m_textureClearRequired = true; } void DiffuseProbeGrid::ComputeProbeCount(const AZ::Vector3& extents, const AZ::Vector3& probeSpacing, uint32_t& probeCountX, uint32_t& probeCountY, uint32_t& probeCountZ) @@ -753,6 +769,77 @@ namespace AZ UpdateCulling(); } + void DiffuseProbeGrid::UpdateVisualizationPrepareSrg(const Data::Instance& shader, const RHI::Ptr& layout) + { + if (!m_visualizationPrepareSrg) + { + m_visualizationPrepareSrg = RPI::ShaderResourceGroup::Create(shader->GetAsset(), shader->GetSupervariantIndex(), layout->GetName()); + AZ_Error("DiffuseProbeGrid", m_visualizationPrepareSrg.get(), "Failed to create VisualizationPrepare shader resource group"); + } + + RHI::ShaderInputConstantIndex constantIndex; + RHI::ShaderInputImageIndex imageIndex; + RHI::ShaderInputBufferIndex bufferIndex; + + // TLAS instances + bufferIndex = layout->FindShaderInputBufferIndex(AZ::Name("m_tlasInstances")); + uint32_t tlasInstancesBufferByteCount = aznumeric_cast(m_visualizationTlas->GetTlasInstancesBuffer()->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateStructured(0, tlasInstancesBufferByteCount / RayTracingTlasInstanceElementSize, RayTracingTlasInstanceElementSize); + m_visualizationPrepareSrg->SetBufferView(bufferIndex, m_visualizationTlas->GetTlasInstancesBuffer()->GetBufferView(bufferViewDescriptor).get()); + + // probe data + imageIndex = layout->FindShaderInputImageIndex(AZ::Name("m_probeData")); + m_visualizationPrepareSrg->SetImageView(imageIndex, GetProbeDataImage()->GetImageView(m_renderData->m_probeDataImageViewDescriptor).get()); + + // probe sphere radius + constantIndex = layout->FindShaderInputConstantIndex(Name("m_probeSphereRadius")); + m_visualizationPrepareSrg->SetConstant(constantIndex, m_visualizationSphereRadius); + + SetGridConstants(m_visualizationPrepareSrg); + } + + void DiffuseProbeGrid::UpdateVisualizationRayTraceSrg(const Data::Instance& shader, const RHI::Ptr& layout, const RHI::ImageView* outputImageView) + { + if (!m_visualizationRayTraceSrg) + { + m_visualizationRayTraceSrg = RPI::ShaderResourceGroup::Create(shader->GetAsset(), shader->GetSupervariantIndex(), layout->GetName()); + AZ_Error("DiffuseProbeGrid", m_visualizationRayTraceSrg.get(), "Failed to create VisualizationRayTrace shader resource group"); + } + + RHI::ShaderInputConstantIndex constantIndex; + RHI::ShaderInputImageIndex imageIndex; + RHI::ShaderInputBufferIndex bufferIndex; + + // TLAS + uint32_t tlasBufferByteCount = aznumeric_cast(m_visualizationTlas->GetTlasBuffer()->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRayTracingTLAS(tlasBufferByteCount); + + bufferIndex = layout->FindShaderInputBufferIndex(AZ::Name("m_tlas")); + m_visualizationRayTraceSrg->SetBufferView(bufferIndex, m_visualizationTlas->GetTlasBuffer()->GetBufferView(bufferViewDescriptor).get()); + + // probe irradiance + imageIndex = layout->FindShaderInputImageIndex(AZ::Name("m_probeIrradiance")); + m_visualizationRayTraceSrg->SetImageView(imageIndex, GetIrradianceImage()->GetImageView(m_renderData->m_probeIrradianceImageViewDescriptor).get()); + + // probe distance + imageIndex = layout->FindShaderInputImageIndex(AZ::Name("m_probeDistance")); + m_visualizationRayTraceSrg->SetImageView(imageIndex, GetDistanceImage()->GetImageView(m_renderData->m_probeDistanceImageViewDescriptor).get()); + + // probe data + imageIndex = layout->FindShaderInputImageIndex(AZ::Name("m_probeData")); + m_visualizationRayTraceSrg->SetImageView(imageIndex, GetProbeDataImage()->GetImageView(m_renderData->m_probeDataImageViewDescriptor).get()); + + // show inactive probes + constantIndex = layout->FindShaderInputConstantIndex(Name("m_showInactiveProbes")); + m_visualizationRayTraceSrg->SetConstant(constantIndex, m_visualizationShowInactiveProbes); + + // output + imageIndex = layout->FindShaderInputImageIndex(AZ::Name("m_output")); + m_visualizationRayTraceSrg->SetImageView(imageIndex, outputImageView); + + SetGridConstants(m_visualizationRayTraceSrg); + } + void DiffuseProbeGrid::UpdateCulling() { if (!m_drawPacket) diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h index 8c8470cdad..3f65d6083a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include #include @@ -98,6 +99,15 @@ namespace AZ DiffuseProbeGridMode GetMode() const { return m_mode; } void SetMode(DiffuseProbeGridMode mode); + bool GetVisualizationEnabled() const { return m_visualizationEnabled; } + void SetVisualizationEnabled(bool visualizationEnabled); + + bool GetVisualizationShowInactiveProbes() const { return m_visualizationShowInactiveProbes; } + void SetVisualizationShowInactiveProbes(bool visualizationShowInactiveProbes) { m_visualizationShowInactiveProbes = visualizationShowInactiveProbes; } + + float GetVisualizationSphereRadius() const { return m_visualizationSphereRadius; } + void SetVisualizationSphereRadius(float visualizationSphereRadius); + uint32_t GetRemainingRelocationIterations() const { return aznumeric_cast(m_remainingRelocationIterations); } void DecrementRemainingRelocationIterations() { m_remainingRelocationIterations = AZStd::max(0, m_remainingRelocationIterations - 1); } void ResetRemainingRelocationIterations() { m_remainingRelocationIterations = DefaultNumRelocationIterations; } @@ -125,6 +135,8 @@ namespace AZ const Data::Instance& GetRelocationSrg() const { return m_relocationSrg; } const Data::Instance& GetClassificationSrg() const { return m_classificationSrg; } const Data::Instance& GetRenderObjectSrg() const { return m_renderObjectSrg; } + const Data::Instance& GetVisualizationPrepareSrg() const { return m_visualizationPrepareSrg; } + const Data::Instance& GetVisualizationRayTraceSrg() const { return m_visualizationRayTraceSrg; } // Srg updates void UpdateRayTraceSrg(const Data::Instance& shader, const RHI::Ptr& srgLayout); @@ -135,6 +147,8 @@ namespace AZ void UpdateRelocationSrg(const Data::Instance& shader, const RHI::Ptr& srgLayout); void UpdateClassificationSrg(const Data::Instance& shader, const RHI::Ptr& srgLayout); void UpdateRenderObjectSrg(); + void UpdateVisualizationPrepareSrg(const Data::Instance& shader, const RHI::Ptr& srgLayout); + void UpdateVisualizationRayTraceSrg(const Data::Instance& shader, const RHI::Ptr& srgLayout, const RHI::ImageView* outputImageView); // textures const RHI::Ptr GetRayTraceImage() { return m_rayTraceImage[m_currentImageIndex]; } @@ -151,12 +165,14 @@ namespace AZ const RHI::AttachmentId GetIrradianceImageAttachmentId() const { return m_irradianceImageAttachmentId; } const RHI::AttachmentId GetDistanceImageAttachmentId() const { return m_distanceImageAttachmentId; } const RHI::AttachmentId GetProbeDataImageAttachmentId() const { return m_probeDataImageAttachmentId; } + const RHI::AttachmentId GetProbeVisualizationTlasAttachmentId() const { return m_visualizationTlasAttachmentId; } + const RHI::AttachmentId GetProbeVisualizationTlasInstancesAttachmentId() const { return m_visualizationTlasInstancesAttachmentId; } const DiffuseProbeGridRenderData* GetRenderData() const { return m_renderData; } - // the irradiance image needs to be manually cleared after it is resized in the editor - bool GetIrradianceClearRequired() const { return m_irradianceClearRequired; } - void ResetIrradianceClearRequired() { m_irradianceClearRequired = false; } + // the Irradiance, Distance, and ProbeData images need to be manually cleared after certain operations, e.g., changing the grid size + bool GetTextureClearRequired() const { return m_textureClearRequired; } + void ResetTextureClearRequired() { m_textureClearRequired = false; } // texture readback DiffuseProbeGridTextureReadback& GetTextureReadback() { return m_textureReadback; } @@ -168,7 +184,16 @@ namespace AZ static constexpr uint32_t DefaultNumDistanceTexels = 14; static constexpr int32_t DefaultNumRelocationIterations = 100; + // visualization TLAS + const RHI::Ptr& GetVisualizationTlas() const { return m_visualizationTlas; } + RHI::Ptr& GetVisualizationTlas() { return m_visualizationTlas; } + + bool GetVisualizationTlasUpdateRequired() const; + void ResetVisualizationTlasUpdateRequired() { m_visualizationTlasUpdateRequired = false; } + private: + + // helper functions void UpdateTextures(); void ComputeProbeCount(const AZ::Vector3& extents, const AZ::Vector3& probeSpacing, uint32_t& probeCountX, uint32_t& probeCountY, uint32_t& probeCountZ); bool ValidateProbeCount(const AZ::Vector3& extents, const AZ::Vector3& probeSpacing); @@ -248,7 +273,7 @@ namespace AZ RHI::Ptr m_probeDataImage[ImageFrameCount]; uint32_t m_currentImageIndex = 0; bool m_updateTextures = false; - bool m_irradianceClearRequired = true; + bool m_textureClearRequired = true; // baked textures Data::Instance m_bakedIrradianceImage; @@ -281,6 +306,17 @@ namespace AZ RHI::AttachmentId m_irradianceImageAttachmentId; RHI::AttachmentId m_distanceImageAttachmentId; RHI::AttachmentId m_probeDataImageAttachmentId; + + // probe visualization + bool m_visualizationEnabled = false; + bool m_visualizationShowInactiveProbes = false; + float m_visualizationSphereRadius = 0.5f; + RHI::Ptr m_visualizationTlas; + bool m_visualizationTlasUpdateRequired = false; + RHI::AttachmentId m_visualizationTlasAttachmentId; + RHI::AttachmentId m_visualizationTlasInstancesAttachmentId; + Data::Instance m_visualizationPrepareSrg; + Data::Instance m_visualizationRayTraceSrg; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp index a5da79a482..0b2f74191f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp @@ -75,27 +75,34 @@ namespace AZ } } - void DiffuseProbeGridBlendDistancePass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridBlendDistancePass::IsEnabled() const { - RPI::Scene* scene = m_pipeline->GetScene(); - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + if (!RenderPass::IsEnabled()) { - // no diffuse probe grids - return; + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; } RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridBlendDistancePass requires the RayTracingFeatureProcessor"); - - if (!rayTracingFeatureProcessor->GetSubMeshCount()) + if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount()) { // empty scene - return; + return false; } - RenderPass::FrameBeginInternal(params); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; + } + + return true; } void DiffuseProbeGridBlendDistancePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.h index 942f90eb10..6d9d26f9b3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.h @@ -42,8 +42,7 @@ namespace AZ void LoadShader(); // Pass overrides - void FrameBeginInternal(FramePrepareParams params) override; - + bool IsEnabled() const override; void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; void CompileResources(const RHI::FrameGraphCompileContext& context) override; void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp index 7a12fc5415..4e29339a38 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp @@ -75,27 +75,34 @@ namespace AZ } } - void DiffuseProbeGridBlendIrradiancePass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridBlendIrradiancePass::IsEnabled() const { - RPI::Scene* scene = m_pipeline->GetScene(); - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + if (!RenderPass::IsEnabled()) { - // no diffuse probe grids - return; + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; } RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridBlendIrradiancePass requires the RayTracingFeatureProcessor"); - - if (!rayTracingFeatureProcessor->GetSubMeshCount()) + if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount()) { // empty scene - return; + return false; } - RenderPass::FrameBeginInternal(params); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; + } + + return true; } void DiffuseProbeGridBlendIrradiancePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.h index 77dba9745c..a9bf9bfc31 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.h @@ -42,8 +42,7 @@ namespace AZ void LoadShader(); // Pass overrides - void FrameBeginInternal(FramePrepareParams params) override; - + bool IsEnabled() const override; void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; void CompileResources(const RHI::FrameGraphCompileContext& context) override; void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp index c4fcb49c17..ee2b638cb7 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp @@ -83,27 +83,34 @@ namespace AZ } } - void DiffuseProbeGridBorderUpdatePass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridBorderUpdatePass::IsEnabled() const { - RPI::Scene* scene = m_pipeline->GetScene(); - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + if (!RenderPass::IsEnabled()) { - // no diffuse probe grids - return; + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; } RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridBorderUpdatePass requires the RayTracingFeatureProcessor"); - - if (!rayTracingFeatureProcessor->GetSubMeshCount()) + if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount()) { // empty scene - return; + return false; } - RenderPass::FrameBeginInternal(params); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; + } + + return true; } void DiffuseProbeGridBorderUpdatePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.h index ee49c66f78..415231c281 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.h @@ -40,8 +40,7 @@ namespace AZ RHI::DispatchDirect& dispatchArgs); // Pass overrides - void FrameBeginInternal(FramePrepareParams params) override; - + bool IsEnabled() const override; void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; void CompileResources(const RHI::FrameGraphCompileContext& context) override; void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp index 1d1e6f745f..acb5b73c1a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp @@ -79,27 +79,34 @@ namespace AZ } } - void DiffuseProbeGridClassificationPass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridClassificationPass::IsEnabled() const { - RPI::Scene* scene = m_pipeline->GetScene(); - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + if (!RenderPass::IsEnabled()) { - // no diffuse probe grids - return; + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; } RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridClassificationPass requires the RayTracingFeatureProcessor"); - - if (!rayTracingFeatureProcessor->GetSubMeshCount()) + if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount()) { // empty scene - return; + return false; } - RenderPass::FrameBeginInternal(params); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; + } + + return true; } void DiffuseProbeGridClassificationPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) @@ -160,15 +167,11 @@ namespace AZ const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetClassificationSrg()->GetRHIShaderResourceGroup(); commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup); - uint32_t probeCountX; - uint32_t probeCountY; - diffuseProbeGrid->GetTexture2DProbeCount(probeCountX, probeCountY); - RHI::DispatchItem dispatchItem; dispatchItem.m_arguments = shader.m_dispatchArgs; dispatchItem.m_pipelineState = shader.m_pipelineState; - dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX; - dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY; + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = diffuseProbeGrid->GetTotalProbeCount(); + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = 1; dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1; commandList->Submit(dispatchItem); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.h index 3ec76fd0f0..894e9df098 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.h @@ -43,8 +43,7 @@ namespace AZ void LoadShader(); // Pass overrides - void FrameBeginInternal(FramePrepareParams params) override; - + bool IsEnabled() const override; void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; void CompileResources(const RHI::FrameGraphCompileContext& context) override; void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp index d690c57dea..84c066604a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -39,6 +40,7 @@ namespace AZ void DiffuseProbeGridFeatureProcessor::Activate() { RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get(); + RHI::Ptr device = rhiSystem->GetDevice(); m_diffuseProbeGrids.reserve(InitialProbeGridAllocationSize); m_realTimeDiffuseProbeGrids.reserve(InitialProbeGridAllocationSize); @@ -49,7 +51,7 @@ namespace AZ m_bufferPool = RHI::Factory::Get().CreateBufferPool(); m_bufferPool->SetName(Name("DiffuseProbeGridBoxBufferPool")); - [[maybe_unused]] RHI::ResultCode resultCode = m_bufferPool->Init(*rhiSystem->GetDevice(), desc); + [[maybe_unused]] RHI::ResultCode resultCode = m_bufferPool->Init(*device, desc); AZ_Error("DiffuseProbeGridFeatureProcessor", resultCode == RHI::ResultCode::Success, "Failed to initialize buffer pool"); // create box mesh vertices and indices @@ -61,7 +63,7 @@ namespace AZ imagePoolDesc.m_bindFlags = RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead; m_probeGridRenderData.m_imagePool = RHI::Factory::Get().CreateImagePool(); - [[maybe_unused]] RHI::ResultCode result = m_probeGridRenderData.m_imagePool->Init(*rhiSystem->GetDevice(), imagePoolDesc); + [[maybe_unused]] RHI::ResultCode result = m_probeGridRenderData.m_imagePool->Init(*device, imagePoolDesc); AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize output image pool"); } @@ -90,6 +92,22 @@ namespace AZ AZ_Error("DiffuseProbeGridFeatureProcessor", m_probeGridRenderData.m_srgLayout != nullptr, "Failed to find ObjectSrg layout"); } + // initialize the buffer pools for the DiffuseProbeGrid visualization + m_visualizationBufferPools = RHI::RayTracingBufferPools::CreateRHIRayTracingBufferPools(); + m_visualizationBufferPools->Init(device); + + // load probe visualization model, the BLAS will be created in OnAssetReady() + m_visualizationModelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath( + "Models/DiffuseProbeSphere.azmodel", + AZ::RPI::AssetUtils::TraceLevel::Assert); + + if (!m_visualizationModelAsset.IsReady()) + { + m_visualizationModelAsset.QueueLoad(); + } + + Data::AssetBus::MultiHandler::BusConnect(m_visualizationModelAsset.GetId()); + EnableSceneNotification(); } @@ -106,6 +124,8 @@ namespace AZ { m_bufferPool.reset(); } + + Data::AssetBus::MultiHandler::BusDisconnect(); } void DiffuseProbeGridFeatureProcessor::Simulate([[maybe_unused]] const FeatureProcessor::SimulatePacket& packet) @@ -186,13 +206,19 @@ namespace AZ void DiffuseProbeGridFeatureProcessor::OnEndPrepareRender() { - // re-build the list of visible real-time diffuse probe grids + // re-build the list of visible diffuse probe grids + m_visibleDiffuseProbeGrids.clear(); m_visibleRealTimeDiffuseProbeGrids.clear(); - for (auto& diffuseProbeGrid : m_realTimeDiffuseProbeGrids) + for (auto& diffuseProbeGrid : m_diffuseProbeGrids) { if (diffuseProbeGrid->GetIsVisible()) { - m_visibleRealTimeDiffuseProbeGrids.push_back(diffuseProbeGrid); + if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::RealTime) + { + m_visibleRealTimeDiffuseProbeGrids.push_back(diffuseProbeGrid); + } + + m_visibleDiffuseProbeGrids.push_back(diffuseProbeGrid); } } } @@ -237,6 +263,17 @@ namespace AZ m_realTimeDiffuseProbeGrids.erase(itEntry); } + // remove from side list of visible grids + itEntry = AZStd::find_if(m_visibleDiffuseProbeGrids.begin(), m_visibleDiffuseProbeGrids.end(), [&](AZStd::shared_ptr const& entry) + { + return (entry == probeGrid); + }); + + if (itEntry != m_visibleDiffuseProbeGrids.end()) + { + m_visibleDiffuseProbeGrids.erase(itEntry); + } + // remove from side list of visible real-time grids itEntry = AZStd::find_if(m_visibleRealTimeDiffuseProbeGrids.begin(), m_visibleRealTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr const& entry) { @@ -449,6 +486,24 @@ namespace AZ probeGrid->SetBakedTextures(bakedTextures); } + void DiffuseProbeGridFeatureProcessor::SetVisualizationEnabled(const DiffuseProbeGridHandle& probeGrid, bool visualizationEnabled) + { + AZ_Assert(probeGrid.get(), "SetVisualizationEnabled called with an invalid handle"); + probeGrid->SetVisualizationEnabled(visualizationEnabled); + } + + void DiffuseProbeGridFeatureProcessor::SetVisualizationShowInactiveProbes(const DiffuseProbeGridHandle& probeGrid, bool visualizationShowInactiveProbes) + { + AZ_Assert(probeGrid.get(), "SetVisualizationShowInactiveProbes called with an invalid handle"); + probeGrid->SetVisualizationShowInactiveProbes(visualizationShowInactiveProbes); + } + + void DiffuseProbeGridFeatureProcessor::SetVisualizationSphereRadius(const DiffuseProbeGridHandle& probeGrid, float visualizationSphereRadius) + { + AZ_Assert(probeGrid.get(), "SetVisualizationSphereRadius called with an invalid handle"); + probeGrid->SetVisualizationSphereRadius(visualizationSphereRadius); + } + void DiffuseProbeGridFeatureProcessor::CreateBoxMesh() { // vertex positions @@ -613,6 +668,71 @@ namespace AZ } } + void DiffuseProbeGridFeatureProcessor::OnVisualizationModelAssetReady(Data::Asset asset) + { + Data::Asset modelAsset = asset; + + m_visualizationModel = RPI::Model::FindOrCreate(modelAsset); + AZ_Assert(m_visualizationModel.get(), "Failed to load DiffuseProbeGrid visualization model"); + + const AZStd::span>& modelLods = m_visualizationModel->GetLods(); + AZ_Assert(!modelLods.empty(), "Invalid DiffuseProbeGrid visualization model"); + if (modelLods.empty()) + { + return; + } + + const Data::Instance& modelLod = modelLods[0]; + AZ_Assert(!modelLod->GetMeshes().empty(), "Invalid DiffuseProbeGrid visualization model asset"); + if (modelLod->GetMeshes().empty()) + { + return; + } + + const RPI::ModelLod::Mesh& mesh = modelLod->GetMeshes()[0]; + + // setup a stream layout and shader input contract for the position vertex stream + static const char* PositionSemantic = "POSITION"; + static const RHI::Format PositionStreamFormat = RHI::Format::R32G32B32_FLOAT; + + RHI::InputStreamLayoutBuilder layoutBuilder; + layoutBuilder.AddBuffer()->Channel(PositionSemantic, PositionStreamFormat); + RHI::InputStreamLayout inputStreamLayout = layoutBuilder.End(); + + RPI::ShaderInputContract::StreamChannelInfo positionStreamChannelInfo; + positionStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(PositionSemantic)); + positionStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(PositionStreamFormat); + + RPI::ShaderInputContract shaderInputContract; + shaderInputContract.m_streamChannels.emplace_back(positionStreamChannelInfo); + + // retrieve vertex/index buffers + RPI::ModelLod::StreamBufferViewList streamBufferViews; + [[maybe_unused]] bool result = modelLod->GetStreamsForMesh( + inputStreamLayout, + streamBufferViews, + nullptr, + shaderInputContract, + 0); + AZ_Assert(result, "Failed to retrieve DiffuseProbeGrid visualization mesh stream buffer views"); + + m_visualizationVB = streamBufferViews[0]; + m_visualizationIB = mesh.m_indexBufferView; + + // create the BLAS object + RHI::RayTracingBlasDescriptor blasDescriptor; + blasDescriptor.Build() + ->Geometry() + ->VertexFormat(PositionStreamFormat) + ->VertexBuffer(m_visualizationVB) + ->IndexBuffer(m_visualizationIB) + ; + + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + m_visualizationBlas = AZ::RHI::RayTracingBlas::CreateRHIRayTracingBlas(); + m_visualizationBlas->CreateBuffers(*device, &blasDescriptor, *m_visualizationBufferPools); + } + void DiffuseProbeGridFeatureProcessor::HandleAssetNotification(Data::Asset asset, DiffuseProbeGridTextureNotificationType notificationType) { for (NotifyTextureAssetVector::iterator itNotification = m_notifyTextureAssets.begin(); itNotification != m_notifyTextureAssets.end(); ++itNotification) @@ -633,14 +753,28 @@ namespace AZ void DiffuseProbeGridFeatureProcessor::OnAssetReady(Data::Asset asset) { - HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Ready); + if (asset.GetId() == m_visualizationModelAsset.GetId()) + { + OnVisualizationModelAssetReady(asset); + } + else + { + HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Ready); + } } void DiffuseProbeGridFeatureProcessor::OnAssetError(Data::Asset asset) { - AZ_Error("ReflectionProbeFeatureProcessor", false, "Failed to load cubemap [%s]", asset.GetHint().c_str()); + if (asset.GetId() == m_visualizationModelAsset.GetId()) + { + AZ_Error("DiffuseProbeGridFeatureProcessor", false, "Failed to load probe visualization model asset [%s]", asset.GetHint().c_str()); + } + else + { + AZ_Error("DiffuseProbeGridFeatureProcessor", false, "Failed to load cubemap [%s]", asset.GetHint().c_str()); - HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Error); + HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Error); + } } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h index d0df7dfbfe..239de5ea27 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h @@ -9,6 +9,9 @@ #pragma once #include +#include +#include +#include #include namespace AZ @@ -46,6 +49,9 @@ namespace AZ void SetUseDiffuseIbl(const DiffuseProbeGridHandle& probeGrid, bool useDiffuseIbl) override; void SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode) override; void SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures) override; + void SetVisualizationEnabled(const DiffuseProbeGridHandle& probeGrid, bool visualizationEnabled) override; + void SetVisualizationShowInactiveProbes(const DiffuseProbeGridHandle& probeGrid, bool visualizationShowInactiveProbes) override; + void SetVisualizationSphereRadius(const DiffuseProbeGridHandle& probeGrid, float visualizationSphereRadius) override; void BakeTextures( const DiffuseProbeGridHandle& probeGrid, @@ -76,9 +82,19 @@ namespace AZ // retrieve the side list of probe grids that are using real-time (raytraced) mode DiffuseProbeGridVector& GetRealTimeProbeGrids() { return m_realTimeDiffuseProbeGrids; } - // retrieve the side list of probe grids that are using real-time (raytraced) mode and visible (on screen) + // retrieve the side list of probe grids that are visible (on screen), both real-time (raytraced) and baked + DiffuseProbeGridVector& GetVisibleProbeGrids() { return m_visibleDiffuseProbeGrids; } + + // retrieve the side list of probe grids that are real-time (raytraced) and visible (on screen) DiffuseProbeGridVector& GetVisibleRealTimeProbeGrids() { return m_visibleRealTimeDiffuseProbeGrids; } + // returns the RayTracingBufferPool used for the DiffuseProbeGrid visualization + RHI::RayTracingBufferPools& GetVisualizationBufferPools() { return *m_visualizationBufferPools; } + + // returns the RayTracingBlas for the visualization model + const RHI::Ptr& GetVisualizationBlas() const { return m_visualizationBlas; } + RHI::Ptr& GetVisualizationBlas() { return m_visualizationBlas; } + private: AZ_DISABLE_COPY_MOVE(DiffuseProbeGridFeatureProcessor); @@ -108,6 +124,9 @@ namespace AZ void UpdatePipelineStates(); void UpdatePasses(); + // loads the probe visualization model and creates the BLAS + void OnVisualizationModelAssetReady(Data::Asset asset); + // list of all diffuse probe grids const size_t InitialProbeGridAllocationSize = 64; DiffuseProbeGridVector m_diffuseProbeGrids; @@ -115,6 +134,9 @@ namespace AZ // side list of diffuse probe grids that are in real-time mode (subset of m_diffuseProbeGrids) DiffuseProbeGridVector m_realTimeDiffuseProbeGrids; + // side list of diffuse probe grids that are visible, both real-time and baked modes (subset of m_diffuseProbeGrids) + DiffuseProbeGridVector m_visibleDiffuseProbeGrids; + // side list of diffuse probe grids that are in real-time mode and visible (subset of m_realTimeDiffuseProbeGrids) DiffuseProbeGridVector m_visibleRealTimeDiffuseProbeGrids; @@ -157,6 +179,14 @@ namespace AZ }; typedef AZStd::vector NotifyTextureAssetVector; NotifyTextureAssetVector m_notifyTextureAssets; + + // visualization + RHI::Ptr m_visualizationBufferPools; + Data::Asset m_visualizationModelAsset; + RHI::Ptr m_visualizationBlas; + Data::Instance m_visualizationModel; + RHI::StreamBufferView m_visualizationVB; + RHI::IndexBufferView m_visualizationIB; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp index 7af6f4c8ec..3fa4837a23 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp @@ -107,14 +107,39 @@ namespace AZ m_rayTracingPipelineState->Init(*device.get(), &descriptor); } + bool DiffuseProbeGridRayTracingPass::IsEnabled() const + { + if (!RenderPass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); + if (!rayTracingFeatureProcessor) + { + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; + } + + return true; + } + void DiffuseProbeGridRayTracingPass::FrameBeginInternal(FramePrepareParams params) { RPI::Scene* scene = m_pipeline->GetScene(); RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - if (!rayTracingFeatureProcessor) - { - return; - } if (!m_initialized) { @@ -131,13 +156,6 @@ namespace AZ m_rayTracingShaderTable->Init(*device.get(), rayTracingBufferPools); } - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) - { - // no diffuse probe grids - return; - } - RenderPass::FrameBeginInternal(params); } @@ -156,9 +174,16 @@ namespace AZ // TLAS { AZ::RHI::AttachmentId tlasAttachmentId = rayTracingFeatureProcessor->GetTlasAttachmentId(); - if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(tlasAttachmentId)) + const RHI::Ptr& rayTracingTlasBuffer = rayTracingFeatureProcessor->GetTlas()->GetTlasBuffer(); + if (rayTracingTlasBuffer) { - uint32_t tlasBufferByteCount = aznumeric_cast(rayTracingFeatureProcessor->GetTlas()->GetTlasBuffer()->GetDescriptor().m_byteCount); + if (!frameGraph.GetAttachmentDatabase().IsAttachmentValid(tlasAttachmentId)) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(tlasAttachmentId, rayTracingTlasBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import ray tracing TLAS buffer with error %d", result); + } + + uint32_t tlasBufferByteCount = aznumeric_cast(rayTracingTlasBuffer->GetDescriptor().m_byteCount); RHI::BufferViewDescriptor tlasBufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tlasBufferByteCount); RHI::BufferScopeAttachmentDescriptor desc; @@ -191,10 +216,10 @@ namespace AZ RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = diffuseProbeGrid->GetIrradianceImageAttachmentId(); desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeIrradianceImageViewDescriptor; - if (diffuseProbeGrid->GetIrradianceClearRequired()) + + if (diffuseProbeGrid->GetTextureClearRequired()) { desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Clear; - diffuseProbeGrid->ResetIrradianceClearRequired(); } else { @@ -212,7 +237,15 @@ namespace AZ RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = diffuseProbeGrid->GetDistanceImageAttachmentId(); desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDistanceImageViewDescriptor; - desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::DontCare; + + if (diffuseProbeGrid->GetTextureClearRequired()) + { + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Clear; + } + else + { + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + } frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite); } @@ -225,10 +258,20 @@ namespace AZ RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = diffuseProbeGrid->GetProbeDataImageAttachmentId(); desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDataImageViewDescriptor; - desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + if (diffuseProbeGrid->GetTextureClearRequired()) + { + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Clear; + } + else + { + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + } frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite); } + + diffuseProbeGrid->ResetTextureClearRequired(); } } diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.h index f5775f7624..13063b57a7 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.h @@ -45,6 +45,7 @@ namespace AZ void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; // Pass overrides + bool IsEnabled() const override; void FrameBeginInternal(FramePrepareParams params) override; // revision number of the ray tracing TLAS when the shader table was built diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp index fd23dadf6f..3922be0481 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp @@ -74,49 +74,70 @@ namespace AZ } } + bool DiffuseProbeGridRelocationPass::IsEnabled() const + { + if (!RenderPass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); + if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount()) + { + // empty scene + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; + } + + // check TLAS version + uint32_t rayTracingDataRevision = rayTracingFeatureProcessor->GetRevision(); + if (rayTracingDataRevision != m_rayTracingDataRevision) + { + return true; + } + + // check to see if any grids need relocation + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids()) + { + if (diffuseProbeGrid->GetRemainingRelocationIterations() > 0) + { + return true; + } + } + + return false; + } + void DiffuseProbeGridRelocationPass::FrameBeginInternal(FramePrepareParams params) { RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) - { - // no diffuse probe grids - return; - } - RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridRelocationPass requires the RayTracingFeatureProcessor"); - if (!rayTracingFeatureProcessor->GetSubMeshCount()) + // reset the relocation iterations on the grids if the TLAS was updated + uint32_t rayTracingDataRevision = rayTracingFeatureProcessor->GetRevision(); + if (rayTracingDataRevision != m_rayTracingDataRevision) { - // empty scene - return; - } - - // create the Relocation Srgs for each DiffuseProbeGrid, and check to see if any grids need relocation - bool needRelocation = false; - for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids()) - { - uint32_t rayTracingDataRevision = rayTracingFeatureProcessor->GetRevision(); - if (rayTracingDataRevision != m_rayTracingDataRevision) + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids()) { - // the TLAS changed, relocate probes - m_rayTracingDataRevision = rayTracingDataRevision; diffuseProbeGrid->ResetRemainingRelocationIterations(); } - - if (diffuseProbeGrid->GetRemainingRelocationIterations() > 0) - { - needRelocation = true; - } } - if (!needRelocation) - { - // no diffuseProbeGrids require relocation, this pass can be skipped entirely - return; - } + m_rayTracingDataRevision = rayTracingDataRevision; RenderPass::FrameBeginInternal(params); } @@ -160,11 +181,7 @@ namespace AZ // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs // (see ValidateSetImageView() in ShaderResourceGroupData.cpp) diffuseProbeGrid->UpdateRelocationSrg(m_shader, m_srgLayout); - diffuseProbeGrid->GetRelocationSrg()->Compile(); - - // relocation stops after a limited number of iterations - diffuseProbeGrid->DecrementRemainingRelocationIterations(); } } @@ -180,19 +197,30 @@ namespace AZ const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetRelocationSrg()->GetRHIShaderResourceGroup(); commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup); - uint32_t probeCountX; - uint32_t probeCountY; - diffuseProbeGrid->GetTexture2DProbeCount(probeCountX, probeCountY); - RHI::DispatchItem dispatchItem; dispatchItem.m_arguments = m_dispatchArgs; dispatchItem.m_pipelineState = m_pipelineState; - dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX; - dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY; + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = diffuseProbeGrid->GetTotalProbeCount(); + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = 1; dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1; commandList->Submit(dispatchItem); } } + + void DiffuseProbeGridRelocationPass::FrameEndInternal() + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + // submit the DispatchItems for each DiffuseProbeGrid + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids()) + { + // relocation stops after a limited number of iterations + diffuseProbeGrid->DecrementRemainingRelocationIterations(); + } + + RenderPass::FrameEndInternal(); + } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.h index a6ede22ee6..121c51050d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.h @@ -42,11 +42,12 @@ namespace AZ void LoadShader(); // Pass overrides + bool IsEnabled() const override; void FrameBeginInternal(FramePrepareParams params) override; - void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; void CompileResources(const RHI::FrameGraphCompileContext& context) override; void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; + void FrameEndInternal() override; // shader Data::Instance m_shader; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp index f444c0c6ba..db95e17a9e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp @@ -51,18 +51,35 @@ namespace AZ AZ_Assert(m_shaderResourceGroup, "[DiffuseProbeGridRenderPass '%s']: Failed to create SRG", GetPathName().GetCStr()); } + bool DiffuseProbeGridRenderPass::IsEnabled() const + { + if (!RenderPass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty()) + { + // no diffuse probe grids + return false; + } + + return true; + } + void DiffuseProbeGridRenderPass::FrameBeginInternal(FramePrepareParams params) { RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); RPI::Scene* scene = m_pipeline->GetScene(); DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty()) - { - // no diffuse probe grids - return; - } - // get output attachment size AZ_Assert(GetInputOutputCount() > 0, "DiffuseProbeGridRenderPass: Could not find output bindings"); RPI::PassAttachment* m_outputAttachment = GetInputOutputBinding(0).m_attachment.get(); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.h index 6f4a91d9c6..c3612649fa 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.h @@ -36,7 +36,8 @@ namespace AZ explicit DiffuseProbeGridRenderPass(const RPI::PassDescriptor& descriptor); // Pass behavior overrides... - virtual void FrameBeginInternal(FramePrepareParams params) override; + bool IsEnabled() const override; + void FrameBeginInternal(FramePrepareParams params) override; // Scope producer functions... void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.cpp new file mode 100644 index 0000000000..29e50fb158 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.cpp @@ -0,0 +1,192 @@ +/* + * 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 + +namespace AZ +{ + namespace Render + { + RPI::Ptr DiffuseProbeGridVisualizationAccelerationStructurePass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr diffuseProbeGridVisualizationAccelerationStructurePass = aznew DiffuseProbeGridVisualizationAccelerationStructurePass(descriptor); + return AZStd::move(diffuseProbeGridVisualizationAccelerationStructurePass); + } + + DiffuseProbeGridVisualizationAccelerationStructurePass::DiffuseProbeGridVisualizationAccelerationStructurePass(const RPI::PassDescriptor& descriptor) + : Pass(descriptor) + { + // disable this pass if we're on a platform that doesn't support raytracing + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + if (device->GetFeatures().m_rayTracing == false || !AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED) + { + SetEnabled(false); + } + } + + bool DiffuseProbeGridVisualizationAccelerationStructurePass::ShouldUpdate(const AZStd::shared_ptr& diffuseProbeGrid) const + { + return (diffuseProbeGrid->GetVisualizationEnabled() && diffuseProbeGrid->GetVisualizationTlasUpdateRequired()); + } + + bool DiffuseProbeGridVisualizationAccelerationStructurePass::IsEnabled() const + { + if (!Pass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (diffuseProbeGridFeatureProcessor) + { + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (ShouldUpdate(diffuseProbeGrid)) + { + return true; + } + } + } + + return false; + } + + void DiffuseProbeGridVisualizationAccelerationStructurePass::BuildInternal() + { + SetScopeId(RHI::ScopeId(GetPathName())); + } + + void DiffuseProbeGridVisualizationAccelerationStructurePass::FrameBeginInternal(FramePrepareParams params) + { + params.m_frameGraphBuilder->ImportScopeProducer(*this); + } + + void DiffuseProbeGridVisualizationAccelerationStructurePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + // import and attach the visualization TLAS buffers + RHI::Ptr& visualizationTlas = diffuseProbeGrid->GetVisualizationTlas(); + const RHI::Ptr& tlasBuffer = visualizationTlas->GetTlasBuffer(); + const RHI::Ptr& tlasInstancesBuffer = visualizationTlas->GetTlasInstancesBuffer(); + if (tlasBuffer && tlasInstancesBuffer) + { + // TLAS buffer + { + AZ::RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeVisualizationTlasAttachmentId(); + if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId) == false) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(attachmentId, tlasBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import DiffuseProbeGrid visualization TLAS buffer with error %d", result); + } + + uint32_t byteCount = aznumeric_cast(tlasBuffer->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRayTracingTLAS(byteCount); + + RHI::BufferScopeAttachmentDescriptor desc; + desc.m_attachmentId = attachmentId; + desc.m_bufferViewDescriptor = bufferViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::DontCare; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Write); + } + + // TLAS Instances buffer + { + AZ::RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeVisualizationTlasInstancesAttachmentId(); + if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId) == false) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(attachmentId, tlasInstancesBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import DiffuseProbeGrid visualization TLAS Instances buffer with error %d", result); + } + + uint32_t byteCount = aznumeric_cast(tlasInstancesBuffer->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateStructured(0, byteCount / RayTracingTlasInstanceElementSize, RayTracingTlasInstanceElementSize); + + RHI::BufferScopeAttachmentDescriptor desc; + desc.m_attachmentId = attachmentId; + desc.m_bufferViewDescriptor = bufferViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read); + } + } + } + } + + void DiffuseProbeGridVisualizationAccelerationStructurePass::BuildCommandList(const RHI::FrameGraphExecuteContext& context) + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + // build the visualization BLAS from the DiffuseProbeGridFeatureProcessor + // Note: the BLAS is used by all DiffuseProbeGrid visualization TLAS objects + if (m_visualizationBlasBuilt == false) + { + context.GetCommandList()->BuildBottomLevelAccelerationStructure(*diffuseProbeGridFeatureProcessor->GetVisualizationBlas()); + m_visualizationBlasBuilt = true; + } + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + if (!diffuseProbeGrid->GetVisualizationTlas()->GetTlasBuffer()) + { + continue; + } + + // build the TLAS object + context.GetCommandList()->BuildTopLevelAccelerationStructure(*diffuseProbeGrid->GetVisualizationTlas()); + } + } + + void DiffuseProbeGridVisualizationAccelerationStructurePass::FrameEndInternal() + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + // TLAS is now updated + diffuseProbeGrid->ResetVisualizationTlasUpdateRequired(); + } + } + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.h new file mode 100644 index 0000000000..b353b9a41a --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.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 + * + */ +#pragma once + +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + //! This pass builds the DiffuseProbeGrid visualization acceleration structure + class DiffuseProbeGridVisualizationAccelerationStructurePass final + : public RPI::Pass + , public RHI::ScopeProducer + { + public: + AZ_RPI_PASS(DiffuseProbeGridVisualizationAccelerationStructurePass); + + AZ_RTTI(DiffuseProbeGridVisualizationAccelerationStructurePass, "{103D8917-D4DC-4CA3-BFB4-CD62846D282A}", Pass); + AZ_CLASS_ALLOCATOR(DiffuseProbeGridVisualizationAccelerationStructurePass, SystemAllocator, 0); + + //! Creates a DiffuseProbeGridVisualizationAccelerationStructurePass + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + ~DiffuseProbeGridVisualizationAccelerationStructurePass() = default; + + private: + explicit DiffuseProbeGridVisualizationAccelerationStructurePass(const RPI::PassDescriptor& descriptor); + + bool ShouldUpdate(const AZStd::shared_ptr& diffuseProbeGrid) const; + + // Scope producer functions + void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; + void BuildCommandList(const RHI::FrameGraphExecuteContext& context) override; + + // Pass overrides + bool IsEnabled() const override; + void BuildInternal() override; + void FrameBeginInternal(FramePrepareParams params) override; + void FrameEndInternal() override; + + bool m_visualizationBlasBuilt = false; + }; + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.cpp new file mode 100644 index 0000000000..722b42daf7 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.cpp @@ -0,0 +1,62 @@ +/* + * 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 AZ +{ + namespace Render + { + RPI::Ptr DiffuseProbeGridVisualizationCompositePass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew DiffuseProbeGridVisualizationCompositePass(descriptor); + return AZStd::move(pass); + } + + DiffuseProbeGridVisualizationCompositePass::DiffuseProbeGridVisualizationCompositePass(const RPI::PassDescriptor& descriptor) + : RPI::FullscreenTrianglePass(descriptor) + { + if (!AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED) + { + SetEnabled(false); + } + } + + bool DiffuseProbeGridVisualizationCompositePass::IsEnabled() const + { + if (!FullscreenTrianglePass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (diffuseProbeGridFeatureProcessor) + { + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (diffuseProbeGrid->GetVisualizationEnabled()) + { + return true; + } + } + } + + return false; + } + + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.h new file mode 100644 index 0000000000..af0109039b --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.h @@ -0,0 +1,39 @@ +/* + * 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 Render + { + //! This pass composites the DiffuseProbeGrid visualization image onto the main scene + class DiffuseProbeGridVisualizationCompositePass + : public RPI::FullscreenTrianglePass + { + public: + AZ_RPI_PASS(DiffuseProbeGridVisualizationCompositePass); + + AZ_RTTI(Render::DiffuseProbeGridVisualizationCompositePass, "{64BD5779-AB30-41C1-81B7-B93D864355E5}", RPI::FullscreenTrianglePass); + AZ_CLASS_ALLOCATOR(Render::DiffuseProbeGridVisualizationCompositePass, SystemAllocator, 0); + + //! Creates a new pass without a PassTemplate + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + ~DiffuseProbeGridVisualizationCompositePass() = default; + + private: + explicit DiffuseProbeGridVisualizationCompositePass(const RPI::PassDescriptor& descriptor); + + // Pass behavior overrides... + bool IsEnabled() const override; + }; + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.cpp new file mode 100644 index 0000000000..29d7ff4aaa --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.cpp @@ -0,0 +1,270 @@ +/* + * 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 + +namespace AZ +{ + namespace Render + { + RPI::Ptr DiffuseProbeGridVisualizationPreparePass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr diffuseProbeGridVisualizationPreparePass = aznew DiffuseProbeGridVisualizationPreparePass(descriptor); + return AZStd::move(diffuseProbeGridVisualizationPreparePass); + } + + DiffuseProbeGridVisualizationPreparePass::DiffuseProbeGridVisualizationPreparePass(const RPI::PassDescriptor& descriptor) + : RenderPass(descriptor) + { + // disable this pass if we're on a platform that doesn't support raytracing + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + if (device->GetFeatures().m_rayTracing == false || !AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED) + { + SetEnabled(false); + } + else + { + LoadShader(); + } + } + + void DiffuseProbeGridVisualizationPreparePass::LoadShader() + { + // load shaders + // Note: the shader may not be available on all platforms + AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPrepare.azshader"; + m_shader = RPI::LoadCriticalShader(shaderFilePath); + if (m_shader == nullptr) + { + return; + } + + RHI::PipelineStateDescriptorForDispatch pipelineStateDescriptor; + const auto& shaderVariant = m_shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); + shaderVariant.ConfigurePipelineState(pipelineStateDescriptor); + m_pipelineState = m_shader->AcquirePipelineState(pipelineStateDescriptor); + AZ_Assert(m_pipelineState, "Failed to acquire pipeline state"); + + m_srgLayout = m_shader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Pass); + AZ_Assert(m_srgLayout.get(), "Failed to find Srg layout"); + + const auto outcome = RPI::GetComputeShaderNumThreads(m_shader->GetAsset(), m_dispatchArgs); + if (!outcome.IsSuccess()) + { + AZ_Error("PassSystem", false, "[DiffuseProbeGridVisualizationPreparePass '%s']: Shader '%s' contains invalid numthreads arguments:\n%s", GetPathName().GetCStr(), shaderFilePath.c_str(), outcome.GetError().c_str()); + } + } + + bool DiffuseProbeGridVisualizationPreparePass::ShouldUpdate(const AZStd::shared_ptr& diffuseProbeGrid) const + { + return (diffuseProbeGrid->GetVisualizationEnabled() && diffuseProbeGrid->GetVisualizationTlasUpdateRequired()); + } + + bool DiffuseProbeGridVisualizationPreparePass::IsEnabled() const + { + if (!RenderPass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (diffuseProbeGridFeatureProcessor) + { + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (ShouldUpdate(diffuseProbeGrid)) + { + return true; + } + } + } + + return false; + } + + void DiffuseProbeGridVisualizationPreparePass::FrameBeginInternal(FramePrepareParams params) + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + // create the TLAS descriptor by adding an instance entry for each probe in the grid + RHI::RayTracingTlasDescriptor tlasDescriptor; + RHI::RayTracingTlasDescriptor* tlasDescriptorBuild = tlasDescriptor.Build(); + + // initialize the transform for each probe to Identity(), they will be updated by the compute shader + AZ::Transform transform = AZ::Transform::Identity(); + + uint32_t probeCount = diffuseProbeGrid->GetTotalProbeCount(); + for (uint32_t index = 0; index < probeCount; ++index) + { + tlasDescriptorBuild->Instance() + ->InstanceID(index) + ->HitGroupIndex(0) + ->Blas(diffuseProbeGridFeatureProcessor->GetVisualizationBlas()) + ->Transform(transform) + ; + } + + // create the TLAS buffers from on the descriptor + RHI::Ptr& visualizationTlas = diffuseProbeGrid->GetVisualizationTlas(); + visualizationTlas->CreateBuffers(*device, &tlasDescriptor, diffuseProbeGridFeatureProcessor->GetVisualizationBufferPools()); + } + + RenderPass::FrameBeginInternal(params); + } + + void DiffuseProbeGridVisualizationPreparePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) + { + RenderPass::SetupFrameGraphDependencies(frameGraph); + + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + // import and attach the visualization TLAS and probe data + RHI::Ptr& visualizationTlas = diffuseProbeGrid->GetVisualizationTlas(); + const RHI::Ptr& tlasBuffer = visualizationTlas->GetTlasBuffer(); + const RHI::Ptr& tlasInstancesBuffer = visualizationTlas->GetTlasInstancesBuffer(); + if (tlasBuffer && tlasInstancesBuffer) + { + // TLAS buffer + { + AZ::RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeVisualizationTlasAttachmentId(); + if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId) == false) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(attachmentId, tlasBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import DiffuseProbeGrid visualization TLAS buffer with error %d", result); + } + + uint32_t byteCount = aznumeric_cast(tlasBuffer->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRayTracingTLAS(byteCount); + + RHI::BufferScopeAttachmentDescriptor desc; + desc.m_attachmentId = attachmentId; + desc.m_bufferViewDescriptor = bufferViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::DontCare; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Write); + } + + // TLAS Instances buffer + { + AZ::RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeVisualizationTlasInstancesAttachmentId(); + if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId) == false) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(attachmentId, tlasInstancesBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import DiffuseProbeGrid visualization TLAS Instances buffer with error %d", result); + } + + uint32_t byteCount = aznumeric_cast(tlasInstancesBuffer->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateStructured(0, byteCount / RayTracingTlasInstanceElementSize, RayTracingTlasInstanceElementSize); + + RHI::BufferScopeAttachmentDescriptor desc; + desc.m_attachmentId = attachmentId; + desc.m_bufferViewDescriptor = bufferViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::DontCare; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Write); + } + + // probe data + { + AZ::RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeDataImageAttachmentId(); + if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId) == false) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(attachmentId, diffuseProbeGrid->GetProbeDataImage()); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import DiffuseProbeGrid probe data buffer with error %d", result); + } + + RHI::ImageScopeAttachmentDescriptor desc; + desc.m_attachmentId = attachmentId; + desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDataImageViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read); + } + } + } + } + + void DiffuseProbeGridVisualizationPreparePass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context) + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + // the DiffuseProbeGrid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs + // (see ValidateSetImageView() in ShaderResourceGroupData.cpp) + diffuseProbeGrid->UpdateVisualizationPrepareSrg(m_shader, m_srgLayout); + diffuseProbeGrid->GetVisualizationPrepareSrg()->Compile(); + } + } + + void DiffuseProbeGridVisualizationPreparePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) + { + RHI::CommandList* commandList = context.GetCommandList(); + + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetVisualizationPrepareSrg()->GetRHIShaderResourceGroup(); + commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup); + + RHI::DispatchItem dispatchItem; + dispatchItem.m_arguments = m_dispatchArgs; + dispatchItem.m_pipelineState = m_pipelineState; + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = diffuseProbeGrid->GetTotalProbeCount(); + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = 1; + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1; + + commandList->Submit(dispatchItem); + } + } + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.h new file mode 100644 index 0000000000..5e86a606aa --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.h @@ -0,0 +1,52 @@ +/* + * 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 Render + { + //! This pass updates the DiffuseProbeGrid visualization TLAS instances buffer + class DiffuseProbeGridVisualizationPreparePass final + : public RPI::RenderPass + { + public: + AZ_RPI_PASS(DiffuseProbeGridVisualizationPreparePass); + + AZ_RTTI(DiffuseProbeGridVisualizationPreparePass, "{33BD769D-378B-4142-8C11-6A2ADA2BB095}", Pass); + AZ_CLASS_ALLOCATOR(DiffuseProbeGridVisualizationPreparePass, SystemAllocator, 0); + + //! Creates a DiffuseProbeGridVisualizationPreparePass + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + ~DiffuseProbeGridVisualizationPreparePass() = default; + + private: + explicit DiffuseProbeGridVisualizationPreparePass(const RPI::PassDescriptor& descriptor); + + void LoadShader(); + bool ShouldUpdate(const AZStd::shared_ptr& diffuseProbeGrid) const; + + // Pass overrides + bool IsEnabled() const override; + void FrameBeginInternal(FramePrepareParams params) override; + void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; + void CompileResources(const RHI::FrameGraphCompileContext& context) override; + void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; + + // shader + Data::Instance m_shader; + const RHI::PipelineState* m_pipelineState = nullptr; + RHI::Ptr m_srgLayout; + RHI::DispatchDirect m_dispatchArgs; + }; + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.cpp new file mode 100644 index 0000000000..69c033f76c --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.cpp @@ -0,0 +1,300 @@ +/* + * 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 +#include + +namespace AZ +{ + namespace Render + { + RPI::Ptr DiffuseProbeGridVisualizationRayTracingPass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew DiffuseProbeGridVisualizationRayTracingPass(descriptor); + return AZStd::move(pass); + } + + DiffuseProbeGridVisualizationRayTracingPass::DiffuseProbeGridVisualizationRayTracingPass(const RPI::PassDescriptor& descriptor) + : RPI::RenderPass(descriptor) + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + if (device->GetFeatures().m_rayTracing == false || !AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED) + { + // raytracing or GI is not supported on this platform + SetEnabled(false); + } + } + + void DiffuseProbeGridVisualizationRayTracingPass::CreateRayTracingPipelineState() + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + + // load the ray tracing shader + // Note: the shader may not be available on all platforms + AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracing.azshader"; + m_rayTracingShader = RPI::LoadCriticalShader(shaderFilePath); + if (m_rayTracingShader == nullptr) + { + return; + } + + auto shaderVariant = m_rayTracingShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); + RHI::PipelineStateDescriptorForRayTracing rayGenerationShaderDescriptor; + shaderVariant.ConfigurePipelineState(rayGenerationShaderDescriptor); + + // closest hit shader + AZStd::string closestHitShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingClosestHit.azshader"; + m_closestHitShader = RPI::LoadCriticalShader(closestHitShaderFilePath); + + auto closestHitShaderVariant = m_closestHitShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); + RHI::PipelineStateDescriptorForRayTracing closestHitShaderDescriptor; + closestHitShaderVariant.ConfigurePipelineState(closestHitShaderDescriptor); + + // miss shader + AZStd::string missShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingMiss.azshader"; + m_missShader = RPI::LoadCriticalShader(missShaderFilePath); + + auto missShaderVariant = m_missShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); + RHI::PipelineStateDescriptorForRayTracing missShaderDescriptor; + missShaderVariant.ConfigurePipelineState(missShaderDescriptor); + + // global pipeline state and Srg + m_globalPipelineState = m_rayTracingShader->AcquirePipelineState(rayGenerationShaderDescriptor); + AZ_Assert(m_globalPipelineState, "Failed to acquire ray tracing global pipeline state"); + + m_globalSrgLayout = m_rayTracingShader->FindShaderResourceGroupLayout(Name{ "RayTracingGlobalSrg" }); + AZ_Assert(m_globalSrgLayout != nullptr, "Failed to find RayTracingGlobalSrg layout for shader [%s]", shaderFilePath.c_str()); + + // build the ray tracing pipeline state descriptor + RHI::RayTracingPipelineStateDescriptor descriptor; + descriptor.Build() + ->PipelineState(m_globalPipelineState.get()) + ->MaxPayloadSize(64) + ->MaxAttributeSize(32) + ->MaxRecursionDepth(2) + ->ShaderLibrary(rayGenerationShaderDescriptor) + ->RayGenerationShaderName(AZ::Name("RayGen")) + ->ShaderLibrary(missShaderDescriptor) + ->MissShaderName(AZ::Name("Miss")) + ->ShaderLibrary(closestHitShaderDescriptor) + ->ClosestHitShaderName(AZ::Name("ClosestHit")) + ->HitGroup(AZ::Name("HitGroup")) + ->ClosestHitShaderName(AZ::Name("ClosestHit")); + + // create the ray tracing pipeline state object + m_rayTracingPipelineState = RHI::Factory::Get().CreateRayTracingPipelineState(); + m_rayTracingPipelineState->Init(*device.get(), &descriptor); + } + + bool DiffuseProbeGridVisualizationRayTracingPass::IsEnabled() const + { + if (!RenderPass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (diffuseProbeGridFeatureProcessor) + { + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (diffuseProbeGrid->GetVisualizationEnabled()) + { + return true; + } + } + } + + return false; + } + + void DiffuseProbeGridVisualizationRayTracingPass::FrameBeginInternal(FramePrepareParams params) + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + if (!m_initialized) + { + CreateRayTracingPipelineState(); + m_initialized = true; + } + + if (!m_rayTracingShaderTable) + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + RHI::RayTracingBufferPools& rayTracingBufferPools = diffuseProbeGridFeatureProcessor->GetVisualizationBufferPools(); + + m_rayTracingShaderTable = RHI::Factory::Get().CreateRayTracingShaderTable(); + m_rayTracingShaderTable->Init(*device.get(), rayTracingBufferPools); + + AZStd::shared_ptr descriptor = AZStd::make_shared(); + + // build the ray tracing shader table descriptor + descriptor->Build(AZ::Name("RayTracingShaderTable"), m_rayTracingPipelineState) + ->RayGenerationRecord(AZ::Name("RayGen")) + ->MissRecord(AZ::Name("Miss")) + ->HitGroupRecord(AZ::Name("HitGroup")) + ; + + m_rayTracingShaderTable->Build(descriptor); + } + + RenderPass::FrameBeginInternal(params); + } + + void DiffuseProbeGridVisualizationRayTracingPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) + { + RenderPass::SetupFrameGraphDependencies(frameGraph); + + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!diffuseProbeGrid->GetVisualizationEnabled()) + { + continue; + } + + // TLAS + { + AZ::RHI::AttachmentId tlasAttachmentId = diffuseProbeGrid->GetProbeVisualizationTlasAttachmentId(); + const RHI::Ptr& visualizationTlasBuffer = diffuseProbeGrid->GetVisualizationTlas()->GetTlasBuffer(); + if (visualizationTlasBuffer) + { + if (!frameGraph.GetAttachmentDatabase().IsAttachmentValid(tlasAttachmentId)) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(tlasAttachmentId, visualizationTlasBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import ray tracing TLAS buffer with error %d", result); + } + + uint32_t tlasBufferByteCount = aznumeric_cast(visualizationTlasBuffer->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor tlasBufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tlasBufferByteCount); + + RHI::BufferScopeAttachmentDescriptor desc; + desc.m_attachmentId = tlasAttachmentId; + desc.m_bufferViewDescriptor = tlasBufferViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite); + } + } + + // probe irradiance + { + RHI::ImageScopeAttachmentDescriptor desc; + desc.m_attachmentId = diffuseProbeGrid->GetIrradianceImageAttachmentId(); + desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeIrradianceImageViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read); + } + + // probe distance + { + RHI::ImageScopeAttachmentDescriptor desc; + desc.m_attachmentId = diffuseProbeGrid->GetDistanceImageAttachmentId(); + desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDistanceImageViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read); + } + + // probe data + { + RHI::ImageScopeAttachmentDescriptor desc; + desc.m_attachmentId = diffuseProbeGrid->GetProbeDataImageAttachmentId(); + desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDataImageViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read); + } + } + + // retrieve the visualization image size, this will determine the number of rays to cast + RPI::Ptr visualizationImageAttachment = m_ownedAttachments[0]; + AZ_Assert(visualizationImageAttachment.get(), "Invalid DiffuseProbeGrid Visualization image"); + + m_outputAttachmentSize = visualizationImageAttachment->GetTransientImageDescriptor().m_imageDescriptor.m_size; + } + + void DiffuseProbeGridVisualizationRayTracingPass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context) + { + const RHI::ImageView* outputImageView = context.GetImageView(GetOutputBinding(0).m_attachment->GetAttachmentId()); + AZ_Assert(outputImageView, "Failed to retrieve output ImageView"); + + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!diffuseProbeGrid->GetVisualizationEnabled()) + { + continue; + } + + // the DiffuseProbeGridVisualization Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader + // inputs (see line ValidateSetImageView() in ShaderResourceGroupData.cpp) + diffuseProbeGrid->UpdateVisualizationRayTraceSrg(m_rayTracingShader, m_globalSrgLayout, outputImageView); + diffuseProbeGrid->GetVisualizationRayTraceSrg()->Compile(); + } + } + + void DiffuseProbeGridVisualizationRayTracingPass::BuildCommandListInternal([[maybe_unused]] const RHI::FrameGraphExecuteContext& context) + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + const AZStd::vector& views = m_pipeline->GetViews(RPI::PipelineViewTag{ "MainCamera" }); + if (views.empty()) + { + return; + } + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!diffuseProbeGrid->GetVisualizationEnabled()) + { + continue; + } + + const RHI::ShaderResourceGroup* shaderResourceGroups[] = { + diffuseProbeGrid->GetVisualizationRayTraceSrg()->GetRHIShaderResourceGroup(), + views[0]->GetRHIShaderResourceGroup() + }; + + RHI::DispatchRaysItem dispatchRaysItem; + dispatchRaysItem.m_width = m_outputAttachmentSize.m_width; + dispatchRaysItem.m_height = m_outputAttachmentSize.m_height; + dispatchRaysItem.m_depth = 1; + dispatchRaysItem.m_rayTracingPipelineState = m_rayTracingPipelineState.get(); + dispatchRaysItem.m_rayTracingShaderTable = m_rayTracingShaderTable.get(); + dispatchRaysItem.m_shaderResourceGroupCount = RHI::ArraySize(shaderResourceGroups); + dispatchRaysItem.m_shaderResourceGroups = shaderResourceGroups; + dispatchRaysItem.m_globalPipelineState = m_globalPipelineState.get(); + + // submit the DispatchRays item + context.GetCommandList()->Submit(dispatchRaysItem); + } + } + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.h new file mode 100644 index 0000000000..c2e5ecf3de --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.h @@ -0,0 +1,67 @@ +/* + * 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 + +namespace AZ +{ + namespace Render + { + //! Ray tracing shader that generates the probe visualization image for a DiffuseProbeGrid + class DiffuseProbeGridVisualizationRayTracingPass final + : public RPI::RenderPass + { + public: + AZ_RPI_PASS(DiffuseProbeGridVisualizationRayTracingPass); + + AZ_RTTI(DiffuseProbeGridVisualizationRayTracingPass, "{CDFB5C03-08D1-4FCA-8B63-2F8326E0DF1D}", RPI::RenderPass); + AZ_CLASS_ALLOCATOR(DiffuseProbeGridVisualizationRayTracingPass, SystemAllocator, 0); + + //! Creates a DiffuseProbeGridVisualizationRayTracingPass + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + ~DiffuseProbeGridVisualizationRayTracingPass() = default; + + private: + explicit DiffuseProbeGridVisualizationRayTracingPass(const RPI::PassDescriptor& descriptor); + + void CreateRayTracingPipelineState(); + + // Scope producer functions + void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; + void CompileResources(const RHI::FrameGraphCompileContext& context) override; + void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; + + // Pass overrides + bool IsEnabled() const override; + void FrameBeginInternal(FramePrepareParams params) override; + + // ray tracing shader and pipeline state + Data::Instance m_rayTracingShader; + Data::Instance m_missShader; + Data::Instance m_closestHitShader; + RHI::Ptr m_rayTracingPipelineState; + + // ray tracing shader table + RHI::Ptr m_rayTracingShaderTable; + + // current size of output attachment, updated every frame + RHI::Size m_outputAttachmentSize; + + // ray tracing global shader resource group layout and pipeline state + RHI::Ptr m_globalSrgLayout; + RHI::ConstPtr m_globalPipelineState; + + bool m_initialized = false; + }; + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h index d098fca35a..dce340807d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h @@ -24,6 +24,8 @@ namespace AZ static const uint32_t RayTracingSceneSrgBindingSlot = 1; static const uint32_t RayTracingMaterialSrgBindingSlot = 2; + static const uint32_t RayTracingTlasInstanceElementSize = 64; + enum class RayTracingSubMeshBufferFlags : uint32_t { None = 0, diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index 1ec6402b3e..6ba0ed1165 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -140,6 +140,14 @@ set(FILES Source/DiffuseGlobalIllumination/DiffuseProbeGridTextureReadback.h Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.h + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.cpp + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.h + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.cpp + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.h + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.cpp + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.h + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.cpp Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.h Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.cpp Source/DisplayMapper/AcesOutputTransformPass.cpp diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h index cd58ee359f..ce12d12162 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h @@ -182,6 +182,7 @@ namespace AZ //! Returns the TLAS RHI buffer virtual const RHI::Ptr GetTlasBuffer() const = 0; + virtual const RHI::Ptr GetTlasInstancesBuffer() const = 0; private: // Platform API diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingBufferPools.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingBufferPools.h index 288a83b4da..6b3e2a4abd 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingBufferPools.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingBufferPools.h @@ -46,7 +46,7 @@ namespace AZ virtual RHI::BufferBindFlags GetShaderTableBufferBindFlags() const { return RHI::BufferBindFlags::ShaderRead | RHI::BufferBindFlags::CopyRead | RHI::BufferBindFlags::RayTracingShaderTable; } virtual RHI::BufferBindFlags GetScratchBufferBindFlags() const { return RHI::BufferBindFlags::ShaderReadWrite | RHI::BufferBindFlags::RayTracingScratchBuffer; } virtual RHI::BufferBindFlags GetBlasBufferBindFlags() const { return RHI::BufferBindFlags::ShaderReadWrite | RHI::BufferBindFlags::RayTracingAccelerationStructure; } - virtual RHI::BufferBindFlags GetTlasInstancesBufferBindFlags() const { return RHI::BufferBindFlags::ShaderRead; } + virtual RHI::BufferBindFlags GetTlasInstancesBufferBindFlags() const { return RHI::BufferBindFlags::ShaderReadWrite; } virtual RHI::BufferBindFlags GetTlasBufferBindFlags() const { return RHI::BufferBindFlags::RayTracingAccelerationStructure; } private: diff --git a/Gems/Atom/RHI/Code/Source/RHI/RayTracingBufferPools.cpp b/Gems/Atom/RHI/Code/Source/RHI/RayTracingBufferPools.cpp index 3ef2ba05ac..7899d9b5d0 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RayTracingBufferPools.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RayTracingBufferPools.cpp @@ -97,7 +97,7 @@ namespace AZ // create TLAS Instances buffer pool { RHI::BufferPoolDescriptor bufferPoolDesc; - bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host; + bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device; bufferPoolDesc.m_bindFlags = GetTlasInstancesBufferBindFlags(); m_tlasInstancesBufferPool = RHI::Factory::Get().CreateBufferPool(); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp index c28c5e4db5..a91f995671 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp @@ -54,7 +54,7 @@ namespace AZ // create instances buffer buffers.m_tlasInstancesBuffer = RHI::Factory::Get().CreateBuffer(); AZ::RHI::BufferDescriptor tlasInstancesBufferDescriptor; - tlasInstancesBufferDescriptor.m_bindFlags = RHI::BufferBindFlags::ShaderRead; + tlasInstancesBufferDescriptor.m_bindFlags = RHI::BufferBindFlags::ShaderReadWrite; tlasInstancesBufferDescriptor.m_byteCount = instanceDescsSizeInBytes; tlasInstancesBufferDescriptor.m_alignment = D3D12_RAYTRACING_INSTANCE_DESCS_BYTE_ALIGNMENT; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.h index accc43ec92..41aad8cf87 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.h @@ -40,7 +40,8 @@ namespace AZ const TlasBuffers& GetBuffers() const { return m_buffers[m_currentBufferIndex]; } // RHI::RayTracingTlas overrides... - virtual const RHI::Ptr GetTlasBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasBuffer; } + const RHI::Ptr GetTlasBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasBuffer; } + const RHI::Ptr GetTlasInstancesBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasInstancesBuffer; } private: RayTracingTlas() = default; diff --git a/Gems/Atom/RHI/Null/Code/Source/RHI/RayTracingTlas.h b/Gems/Atom/RHI/Null/Code/Source/RHI/RayTracingTlas.h index 7bb0316230..a3e5d8c558 100644 --- a/Gems/Atom/RHI/Null/Code/Source/RHI/RayTracingTlas.h +++ b/Gems/Atom/RHI/Null/Code/Source/RHI/RayTracingTlas.h @@ -26,7 +26,8 @@ namespace AZ static RHI::Ptr Create(); // RHI::RayTracingTlas overrides... - virtual const RHI::Ptr GetTlasBuffer() const override { return nullptr; } + const RHI::Ptr GetTlasBuffer() const override { return nullptr; } + const RHI::Ptr GetTlasInstancesBuffer() const override { return nullptr; } private: RayTracingTlas() = default; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandList.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandList.cpp index c1d87b0211..6211adf35c 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandList.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandList.cpp @@ -970,6 +970,26 @@ namespace AZ const VkAccelerationStructureBuildRangeInfoKHR& offsetInfo = tlasBuffers.m_offsetInfo; const VkAccelerationStructureBuildRangeInfoKHR* pOffsetInfo = &offsetInfo; vkCmdBuildAccelerationStructuresKHR(GetNativeCommandBuffer(), 1, &tlasBuffers.m_buildInfo, &pOffsetInfo); + + // we need a pipeline barrier on VK_ACCESS_ACCELERATION_STRUCTURE (both read and write) in case we are building + // multiple TLAS objects in a command list + VkMemoryBarrier memoryBarrier = {}; + memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + memoryBarrier.pNext = nullptr; + memoryBarrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + memoryBarrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + + vkCmdPipelineBarrier( + GetNativeCommandBuffer(), + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + 0, + 1, + &memoryBarrier, + 0, + nullptr, + 0, + nullptr); } void CommandList::ClearImage(const ResourceClearRequest& request) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingBufferPools.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingBufferPools.h index a7547c7106..0ae3b37c50 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingBufferPools.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingBufferPools.h @@ -24,8 +24,8 @@ namespace AZ static RHI::Ptr Create() { return aznew RayTracingBufferPools; } protected: - virtual RHI::BufferBindFlags GetShaderTableBufferBindFlags() const override { return RHI::BufferBindFlags::CopyRead | RHI::BufferBindFlags::RayTracingShaderTable; } - virtual RHI::BufferBindFlags GetTlasInstancesBufferBindFlags() const override { return RHI::BufferBindFlags::ShaderRead | RHI::BufferBindFlags::RayTracingAccelerationStructure; } + RHI::BufferBindFlags GetShaderTableBufferBindFlags() const override { return RHI::BufferBindFlags::CopyRead | RHI::BufferBindFlags::RayTracingShaderTable; } + RHI::BufferBindFlags GetTlasInstancesBufferBindFlags() const override { return RHI::BufferBindFlags::ShaderReadWrite | RHI::BufferBindFlags::RayTracingAccelerationStructure; } private: RayTracingBufferPools() = default; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp index 08b933c96b..b081e3f82d 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp @@ -60,7 +60,7 @@ namespace AZ // create instances buffer buffers.m_tlasInstancesBuffer = RHI::Factory::Get().CreateBuffer(); AZ::RHI::BufferDescriptor tlasInstancesBufferDescriptor; - tlasInstancesBufferDescriptor.m_bindFlags = RHI::BufferBindFlags::ShaderRead | RHI::BufferBindFlags::RayTracingAccelerationStructure; + tlasInstancesBufferDescriptor.m_bindFlags = RHI::BufferBindFlags::ShaderReadWrite | RHI::BufferBindFlags::RayTracingAccelerationStructure; tlasInstancesBufferDescriptor.m_byteCount = instanceDescsSizeInBytes; AZ::RHI::BufferInitRequest tlasInstancesBufferRequest; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.h index 96d5f8f5f6..55fcf481af 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.h @@ -43,7 +43,8 @@ namespace AZ const TlasBuffers& GetBuffers() const { return m_buffers[m_currentBufferIndex]; } // RHI::RayTracingTlas overrides... - virtual const RHI::Ptr GetTlasBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasBuffer; } + const RHI::Ptr GetTlasBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasBuffer; } + const RHI::Ptr GetTlasInstancesBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasInstancesBuffer; } private: RayTracingTlas() = default; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderOptionGroupLayout.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderOptionGroupLayout.h index 396b6d50f0..27c8fff001 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderOptionGroupLayout.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderOptionGroupLayout.h @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -44,6 +45,12 @@ namespace AZ bool m_bakeEmptyAsDefault = false; }; + //! Creates a list of shader option values that can be used to construct a ShaderOptionDescriptor. + ShaderOptionValues CreateEnumShaderOptionValues(AZStd::span enumNames); + ShaderOptionValues CreateEnumShaderOptionValues(AZStd::initializer_list enumNames); + ShaderOptionValues CreateBoolShaderOptionValues(); + ShaderOptionValues CreateIntRangeShaderOptionValues(uint32_t min, uint32_t max); + //! Describes a shader option to the ShaderOptionGroupLayout class. Maps a shader option //! to a set of bits in a mask in order to facilitate packing values into a mask to //! form a ShaderKey. @@ -62,15 +69,16 @@ namespace AZ //! @param optionType Type hint for the option - bool, enum, integer range, etc. //! @param bitOffset Bit offset must match the ShaderOptionGroupLayout where this Option will be added //! @param order The order (rank) of the shader option. Must be unique within a group. Lower order is higher priority. - //! @param nameIndexList List of valid (valueName, value) pairs for this Option + //! @param nameIndexList List of valid (valueName, value) pairs for this Option. See "Create*ShaderOptionValues" utility functions above. //! @param defaultValue Default value name, which must also be in the nameIndexList. In the cases where the list //! defines a range (IntegerRange for instance) defaultValue must be within the range instead. + //! If omitted, the first entry in @nameIndexList will be used. ShaderOptionDescriptor(const Name& name, const ShaderOptionType& optionType, uint32_t bitOffset, uint32_t order, - const AZStd::vector& nameIndexList, - const Name& defaultValue); + const ShaderOptionValues& nameIndexList, + const Name& defaultValue = {}); AZ_DEFAULT_COPY_MOVE(ShaderOptionDescriptor); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderOptionTypes.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderOptionTypes.h index e8be930a22..427f70890c 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderOptionTypes.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderOptionTypes.h @@ -18,6 +18,7 @@ namespace AZ using ShaderOptionIndex = RHI::Handle; //!< ShaderOption index in the group layout using ShaderOptionValue = RHI::Handle; //!< Numerical representation for a single value in the ShaderOption using ShaderOptionValuePair = AZStd::pair; //!< Provides a string representation for a ShaderOptionValue + using ShaderOptionValues = AZStd::vector; //!< List of possible values for a shader option enum class ShaderOptionType : uint32_t { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderOptionGroupLayout.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderOptionGroupLayout.cpp index 7e9f62e560..17f5faec98 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderOptionGroupLayout.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderOptionGroupLayout.cpp @@ -35,6 +35,35 @@ namespace AZ default: return ""; } } + + ShaderOptionValues CreateEnumShaderOptionValues(AZStd::span enumNames) + { + ShaderOptionValues values; + values.reserve(enumNames.size()); + for (size_t i = 0; i < enumNames.size(); ++i) + { + values.emplace_back(Name{enumNames[i]}, i); + } + return values; + } + + ShaderOptionValues CreateEnumShaderOptionValues(AZStd::initializer_list enumNames) + { + return CreateEnumShaderOptionValues(AZStd::span(enumNames.begin(), enumNames.end())); + } + + ShaderOptionValues CreateBoolShaderOptionValues() + { + return CreateEnumShaderOptionValues({"False", "True"}); + } + + ShaderOptionValues CreateIntRangeShaderOptionValues(uint32_t min, uint32_t max) + { + AZStd::vector intOptionRange; + intOptionRange.push_back({Name{AZStd::string::format("%u", min)}, RPI::ShaderOptionValue{min}}); + intOptionRange.push_back({Name{AZStd::string::format("%u", max)}, RPI::ShaderOptionValue{max}}); + return intOptionRange; + } void ShaderOptionGroupHints::Reflect(ReflectContext* context) { @@ -90,7 +119,7 @@ namespace AZ const ShaderOptionType& optionType, uint32_t bitOffset, uint32_t order, - const AZStd::vector& nameIndexList, + const ShaderOptionValues& nameIndexList, const Name& defaultValue) : m_name{name} @@ -102,6 +131,11 @@ namespace AZ for (auto pair : nameIndexList) { // Registers the pair in the lookup table AddValue(pair.first, pair.second); + + if (m_defaultValue.IsEmpty()) + { + m_defaultValue = pair.first; + } } uint32_t numValues = (m_type == ShaderOptionType::IntegerRange) ? (m_maxValue.GetIndex() - m_minValue.GetIndex() + 1) : (uint32_t) nameIndexList.size(); diff --git a/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp index 5016f8303e..15f66916a6 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp @@ -70,18 +70,9 @@ namespace UnitTest AZ::RPI::Ptr CreateCommonTestShaderOptionsLayout() { - AZStd::vector boolOptionValues; - boolOptionValues.push_back({Name("False"), RPI::ShaderOptionValue(0)}); - boolOptionValues.push_back({Name("True"), RPI::ShaderOptionValue(1)}); - - AZStd::vector intRangeOptionValues; - intRangeOptionValues.push_back({Name("0"), RPI::ShaderOptionValue(0)}); - intRangeOptionValues.push_back({Name("15"), RPI::ShaderOptionValue(15)}); - - AZStd::vector qualityOptionValues; - qualityOptionValues.push_back({Name("Quality::Low"), RPI::ShaderOptionValue(0)}); - qualityOptionValues.push_back({Name("Quality::Medium"), RPI::ShaderOptionValue(1)}); - qualityOptionValues.push_back({Name("Quality::High"), RPI::ShaderOptionValue(2)}); + AZStd::vector boolOptionValues = CreateBoolShaderOptionValues(); + AZStd::vector intRangeOptionValues = CreateIntRangeShaderOptionValues(0, 15); + AZStd::vector qualityOptionValues = CreateEnumShaderOptionValues({"Quality::Low", "Quality::Medium", "Quality::High"}); AZ::RPI::Ptr shaderOptions = RPI::ShaderOptionGroupLayout::Create(); shaderOptions->AddShaderOption(ShaderOptionDescriptor{Name{"o_bool"}, ShaderOptionType::Boolean, 0, 0, boolOptionValues, Name{"False"}}); diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp index 3373646c6e..08049f3393 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp @@ -127,9 +127,7 @@ namespace UnitTest { using namespace AZ::RPI; - AZStd::vector boolOptionValues; - boolOptionValues.push_back({Name("False"), RPI::ShaderOptionValue(0)}); - boolOptionValues.push_back({Name("True"), RPI::ShaderOptionValue(1)}); + AZStd::vector boolOptionValues = CreateBoolShaderOptionValues(); AZ::RPI::Ptr shaderOptions = RPI::ShaderOptionGroupLayout::Create(); shaderOptions->AddShaderOption(ShaderOptionDescriptor{Name{"o_optionA"}, ShaderOptionType::Boolean, 0, 0, boolOptionValues, Name{"False"}}); @@ -138,7 +136,6 @@ namespace UnitTest shaderOptions->Finalize(); Data::Asset materialTypeAsset; - //Data::Asset materialAsset; // Note we don't actually need any properties or functors in the material type. We just need to set up some sample data // structures that we can pass to the functors below, especially the shader with shader options. diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp index 569f8f6df0..02b78d5fd2 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp @@ -389,18 +389,9 @@ namespace UnitTest Ptr CreateTestOptionsLayout() { - AZStd::vector enumOptionValues; - enumOptionValues.push_back({Name("Low"), RPI::ShaderOptionValue(0)}); - enumOptionValues.push_back({Name("Med"), RPI::ShaderOptionValue(1)}); - enumOptionValues.push_back({Name("High"), RPI::ShaderOptionValue(2)}); - - AZStd::vector boolOptionValues; - boolOptionValues.push_back({Name("False"), RPI::ShaderOptionValue(0)}); - boolOptionValues.push_back({Name("True"), RPI::ShaderOptionValue(1)}); - - AZStd::vector rangeOptionValues; - rangeOptionValues.push_back({Name("1"), RPI::ShaderOptionValue(1)}); - rangeOptionValues.push_back({Name("10"), RPI::ShaderOptionValue(10)}); + AZStd::vector enumOptionValues = CreateEnumShaderOptionValues({"Low", "Med", "High"}); + AZStd::vector boolOptionValues = CreateBoolShaderOptionValues(); + AZStd::vector rangeOptionValues = CreateIntRangeShaderOptionValues(1, 10); Ptr shaderOptions = ShaderOptionGroupLayout::Create(); uint32_t order = 0; diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp index 382ab4e149..0fbbcf76c3 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp @@ -103,18 +103,9 @@ namespace UnitTest m_testMaterialSrgLayout = CreateCommonTestMaterialSrgLayout(); - AZStd::vector boolOptionValues; - boolOptionValues.push_back({Name{"False"}, RPI::ShaderOptionValue{0}}); - boolOptionValues.push_back({Name{"True"}, RPI::ShaderOptionValue{1}}); - - AZStd::vector enumOptionValues; - enumOptionValues.push_back({Name{"Low"}, RPI::ShaderOptionValue{0}}); - enumOptionValues.push_back({Name{"Med"}, RPI::ShaderOptionValue{1}}); - enumOptionValues.push_back({Name{"High"}, RPI::ShaderOptionValue{2}}); - - AZStd::vector intOptionRange; - intOptionRange.push_back({Name{"0"}, RPI::ShaderOptionValue{0}}); - intOptionRange.push_back({Name{"8"}, RPI::ShaderOptionValue{8}}); + AZStd::vector boolOptionValues = CreateBoolShaderOptionValues(); + AZStd::vector enumOptionValues = CreateEnumShaderOptionValues({"Low", "Med", "High"}); + AZStd::vector intOptionRange = CreateIntRangeShaderOptionValues(0, 8); m_testShaderOptionsLayout = ShaderOptionGroupLayout::Create(); uint32_t order = 0; @@ -977,9 +968,7 @@ namespace UnitTest { // Create shaders... - AZStd::vector boolOptionValues; - boolOptionValues.push_back({Name("False"), RPI::ShaderOptionValue(0)}); - boolOptionValues.push_back({Name("True"), RPI::ShaderOptionValue(1)}); + AZStd::vector boolOptionValues = CreateBoolShaderOptionValues(); Ptr optionsForShaderA = ShaderOptionGroupLayout::Create(); optionsForShaderA->AddShaderOption(ShaderOptionDescriptor{Name{"o_globalOption_inBothShaders"}, ShaderOptionType::Boolean, 0, 0, boolOptionValues, Name{"False"}}); diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp index 206073e96a..948a56f557 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp @@ -289,10 +289,7 @@ namespace UnitTest m_testMaterialSrgLayout->AddShaderInput(RHI::ShaderInputImageDescriptor{ Name{ "m_image" }, RHI::ShaderInputImageAccess::Read, RHI::ShaderInputImageType::Image2D, 1, 1 }); EXPECT_TRUE(m_testMaterialSrgLayout->Finalize()); - AZStd::vector optionValues; - optionValues.push_back({Name("Low"), RPI::ShaderOptionValue(0)}); - optionValues.push_back({Name("Med"), RPI::ShaderOptionValue(1)}); - optionValues.push_back({Name("High"), RPI::ShaderOptionValue(2)}); + AZStd::vector optionValues = CreateEnumShaderOptionValues({"Low", "Med", "High"}); Ptr shaderOptions = ShaderOptionGroupLayout::Create(); uint32_t order = 0; @@ -703,10 +700,7 @@ namespace UnitTest { // Set up the shaders... - AZStd::vector optionValues; - optionValues.push_back({Name("Low"), RPI::ShaderOptionValue(0)}); - optionValues.push_back({Name("Med"), RPI::ShaderOptionValue(1)}); - optionValues.push_back({Name("High"), RPI::ShaderOptionValue(2)}); + AZStd::vector optionValues = CreateEnumShaderOptionValues({"Low", "Med", "High"}); Ptr shaderOptions = ShaderOptionGroupLayout::Create(); uint32_t order = 0; @@ -1072,10 +1066,7 @@ namespace UnitTest { // Setup the shader... - AZStd::vector optionValues; - optionValues.push_back({ Name("Low"), RPI::ShaderOptionValue(0) }); - optionValues.push_back({ Name("Med"), RPI::ShaderOptionValue(1) }); - optionValues.push_back({ Name("High"), RPI::ShaderOptionValue(2) }); + AZStd::vector optionValues = CreateEnumShaderOptionValues({"Low", "Med", "High"}); uint32_t order = 0; @@ -1402,9 +1393,7 @@ namespace UnitTest layeredMaterialSrgLayout->AddShaderInput(RHI::ShaderInputConstantDescriptor{ Name{ "m_blendFactor" }, 4, 4, 0 }); layeredMaterialSrgLayout->Finalize(); - AZStd::vector boolOptionValues; - boolOptionValues.push_back({Name("False"), RPI::ShaderOptionValue(0)}); - boolOptionValues.push_back({Name("True"), RPI::ShaderOptionValue(1)}); + AZStd::vector boolOptionValues = CreateBoolShaderOptionValues(); Ptr shaderOptionsLayout = ShaderOptionGroupLayout::Create(); uint32_t order = 0; shaderOptionsLayout->AddShaderOption(ShaderOptionDescriptor{Name{"o_layer2_clearCoat_enable"}, ShaderOptionType::Boolean, 0, order++, boolOptionValues, Name{"False"}}); diff --git a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp index 81d773d8c0..cbdb99a008 100644 --- a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp @@ -976,14 +976,14 @@ namespace UnitTest EXPECT_EQ(uvStreamTangentBitmask.GetFullTangentBitmask(), 0x70000F51); } - // - // +----+ - // / /| - // +----+ | - // | | + - // | |/ - // +----+ - // + /* + +----+ + / /| + +----+ | + | | + + | |/ + +----+ + */ static constexpr AZStd::array CubePositions = { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f }; static constexpr AZStd::array CubeIndices = { @@ -993,23 +993,25 @@ namespace UnitTest static constexpr AZStd::array QuadPositions = { -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f }; static constexpr AZStd::array QuadIndices = { uint32_t{ 0 }, 2, 1, 1, 2, 3 }; - // This class creates a Model with one LOD, whose mesh contains 2 planes. Plane 1 is in the XY plane at Z=-0.5, and - // plane 2 is in the XY plane at Z=0.5. The two planes each have 9 quads which have been triangulated. It only has - // a position and index buffer. - // - // -0.33 - // -1 0.33 1 - // 0.5 *---*---*---* - // \ / \ / \ / \ - // *---*---*---* - // \ / \ / \ / \ - // -0.5 *- *---*---*---* - // \ \ / \ / \ / \ - // *- *---*---*---* - // \ \ \ \ - // *---*---*---* - // \ / \ / \ / \ - // *---*---*---* + /* + This class creates a Model with one LOD, whose mesh contains 2 planes. Plane 1 is in the XY plane at Z=-0.5, and + plane 2 is in the XY plane at Z=0.5. The two planes each have 9 quads which have been triangulated. It only has + a position and index buffer. + + -0.33 + -1 0.33 1 + 0.5 *---*---*---* + \ / \ / \ / \ + *---*---*---* + \ / \ / \ / \ + -0.5 *- *---*---*---* + \ \ / \ / \ / \ + *- *---*---*---* + \ \ \ \ + *---*---*---* + \ / \ / \ / \ + *---*---*---* + */ static constexpr AZStd::array TwoSeparatedPlanesPositions{ -1.0f, -0.333f, -0.5f, -0.333f, -1.0f, -0.5f, -0.333f, -0.333f, -0.5f, 0.333f, -0.333f, -0.5f, 1.0f, -1.0f, -0.5f, 1.0f, -0.333f, -0.5f, 0.333f, -1.0f, -0.5f, 0.333f, 1.0f, -0.5f, 1.0f, 0.333f, -0.5f, 1.0f, 1.0f, -0.5f, diff --git a/Gems/Atom/RPI/Code/Tests/Shader/ShaderTests.cpp b/Gems/Atom/RPI/Code/Tests/Shader/ShaderTests.cpp index 74f79ad80a..4fc5f74f3b 100644 --- a/Gems/Atom/RPI/Code/Tests/Shader/ShaderTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Shader/ShaderTests.cpp @@ -793,16 +793,6 @@ namespace UnitTest EXPECT_FALSE(success); errorMessageFinder.CheckExpectedErrorsFound(); - // Add shader option with an empty default value. - errorMessageFinder.Reset(); - errorMessageFinder.AddExpectedErrorMessage("invalid default value"); - AZStd::vector list5; - list5.push_back({ Name("0"), RPI::ShaderOptionValue(0) }); // 1+ bit - list5.push_back({ Name("1"), RPI::ShaderOptionValue(1) }); // ... - success = shaderOptionGroupLayout->AddShaderOption(AZ::RPI::ShaderOptionDescriptor{ Name{"Invalid"}, intRangeType, 16, order++, list5, Name() }); - EXPECT_FALSE(success); - errorMessageFinder.CheckExpectedErrorsFound(); - // Add shader option with an invalid default int value. errorMessageFinder.Reset(); errorMessageFinder.AddExpectedErrorMessage("invalid default value"); @@ -886,6 +876,18 @@ namespace UnitTest EXPECT_FALSE(shaderOptionGroupLayout->FindShaderOptionIndex(Name{ "Invalid" }).IsValid()); } + + TEST_F(ShaderTests, ImplicitDefaultValue) + { + // Add shader option with no default value. + + RPI::Ptr shaderOptionGroupLayout = RPI::ShaderOptionGroupLayout::Create(); + + AZStd::vector values = AZ::RPI::CreateEnumShaderOptionValues({"A", "B", "C"}); + bool success = shaderOptionGroupLayout->AddShaderOption(AZ::RPI::ShaderOptionDescriptor{ Name{"NoDefaultSpecified"}, RPI::ShaderOptionType::Enumeration, 0, 0, values }); + EXPECT_TRUE(success); + EXPECT_STREQ("A", shaderOptionGroupLayout->GetShaderOptions().back().GetDefaultValue().GetCStr()); + } TEST_F(ShaderTests, ShaderOptionGroupTest) { @@ -1666,20 +1668,21 @@ namespace UnitTest EXPECT_FALSE(result7.IsFullyBaked()); EXPECT_EQ(result7.GetStableId().GetIndex(), stableId7); - // All searches so far found exactly the node we were looking for - // The next couple of searches will not find the requested node - // and will instead default to its parent, up the tree to the root - // - // [] [Root] - // / \ - // [Color] [Teal] [Fuchsia] - // / \ - // [Quality] [Sublime] [Auto] - // / - // [NumberSamples] [50] - // / \ - // [Raytracing] [On] [Off] - + /* + All searches so far found exactly the node we were looking for + The next couple of searches will not find the requested node + and will instead default to its parent, up the tree to the root + + [] [Root] + / \ + [Color] [Teal] [Fuchsia] + / \ + [Quality] [Sublime] [Auto] + / + [NumberSamples] [50] + / \ + [Raytracing] [On] [Off] + */ // ---------------------------------------- // [Quality::Poor] diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index 06a9f65ec1..016bc5c5e2 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -111,7 +111,7 @@ namespace AtomToolsFramework AZStd::unique_ptr m_styleManager; - //! Local user settings are used to store material browser tree expansion state + //! Local user settings are used to store asset browser tree expansion state AZ::UserSettingsProvider m_localUserSettings; //! Are local settings loaded diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h index bf18d36c2c..cb64d23cd0 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocument.h @@ -7,8 +7,9 @@ */ #pragma once -#include #include +#include +#include namespace AtomToolsFramework { @@ -17,6 +18,7 @@ namespace AtomToolsFramework */ class AtomToolsDocument : public AtomToolsDocumentRequestBus::Handler + , private AzToolsFramework::AssetSystemBus::Handler { public: AZ_RTTI(AtomToolsDocument, "{8992DF74-88EC-438C-B280-6E71D4C0880B}"); @@ -28,10 +30,8 @@ namespace AtomToolsFramework const AZ::Uuid& GetId() const; - //////////////////////////////////////////////////////////////////////// - // AtomToolsDocumentRequestBus::Handler implementation + // AtomToolsDocumentRequestBus::Handler overrides... AZStd::string_view GetAbsolutePath() const override; - AZStd::string_view GetRelativePath() const override; const AZStd::any& GetPropertyValue(const AZ::Name& propertyId) const override; const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyId) const override; bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; @@ -51,21 +51,67 @@ namespace AtomToolsFramework bool Redo() override; bool BeginEdit() override; bool EndEdit() override; - //////////////////////////////////////////////////////////////////////// protected: + virtual void Clear(); - // Unique id of this document + virtual bool OpenSucceeded(); + virtual bool OpenFailed(); + + virtual bool SaveSucceeded(); + virtual bool SaveFailed(); + + //! Record state that needs to be restored after a document is reopened. + //! This can be overridden to record additional data. + virtual bool ReopenRecordState(); + + //! Restore state that was recorded prior to document being reloaded. + //! This can be overridden to restore additional data. + virtual bool ReopenRestoreState(); + + //! The unique id of this document, used for all bus notifications and requests. AZ::Uuid m_id = AZ::Uuid::CreateRandom(); - // Relative path to the material source file - AZStd::string m_relativePath; - - // Absolute path to the material source file + //! The absolute path to the document source file. AZStd::string m_absolutePath; + //! The normalized, absolute path where the document will be saved. + AZStd::string m_savePathNormalized; + AZStd::any m_invalidValue; AtomToolsFramework::DynamicProperty m_invalidProperty; + + //! This contains absolute paths of other source files that affect this document. + //! If any of the source files in this container are modified, the document system is notified to reload this document. + AZStd::unordered_set m_sourceDependencies; + + //! If this flag is true then the next source file change notification for this document will be ignored. + bool m_ignoreSourceFileChangeToSelf = false; + + // Variables needed for tracking the undo and redo state of this document + + // Function to be bound for undo and redo + using UndoRedoFunction = AZStd::function; + + // A pair of functions, where first is the undo operation and second is the redo operation + using UndoRedoFunctionPair = AZStd::pair; + + // Container for all of the active undo and redo functions and state + using UndoRedoHistory = AZStd::vector; + + // Container of undo commands + UndoRedoHistory m_undoHistory; + UndoRedoHistory m_undoHistoryBeforeReopen; + + // The current position in the undo redo history + int m_undoHistoryIndex = {}; + int m_undoHistoryIndexBeforeReopen = {}; + + //! Add new undo redo command functions at the current position in the undo history. + void AddUndoRedoHistory(const UndoRedoFunction& undoCommand, const UndoRedoFunction& redoCommand); + + // AzToolsFramework::AssetSystemBus::Handler overrides... + void SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid sourceUUID) override; }; } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h index 6a21a8a2df..b6b3f65110 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h @@ -25,9 +25,6 @@ namespace AtomToolsFramework //! Get absolute path of document virtual AZStd::string_view GetAbsolutePath() const = 0; - //! Get relative path of document - virtual AZStd::string_view GetRelativePath() const = 0; - //! Return property value //! If the document is not open or the id can't be found, an invalid value is returned instead. virtual const AZStd::any& GetPropertyValue(const AZ::Name& propertyFullName) const = 0; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h index 68e5e38cbd..5af0fcc845 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h @@ -111,7 +111,7 @@ namespace AtomToolsFramework AZStd::string GetDescription() const; AZStd::vector> GetEnumValues() const; - // Handles changes from the ReflectedPropertyEditor and sends notification to the material document. + // Handles changes from the ReflectedPropertyEditor and sends notification. AZ::u32 OnDataChanged() const; template diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp index 1e2c685c3c..84638eefc4 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocument.cpp @@ -6,8 +6,10 @@ * */ +#include #include #include +#include namespace AtomToolsFramework { @@ -19,6 +21,7 @@ namespace AtomToolsFramework AtomToolsDocument::~AtomToolsDocument() { + AzToolsFramework::AssetSystemBus::Handler::BusDisconnect(); AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); AtomToolsDocumentRequestBus::Handler::BusDisconnect(); } @@ -33,11 +36,6 @@ namespace AtomToolsFramework return m_absolutePath; } - AZStd::string_view AtomToolsDocument::GetRelativePath() const - { - return m_relativePath; - } - const AZStd::any& AtomToolsDocument::GetPropertyValue([[maybe_unused]] const AZ::Name& propertyId) const { AZ_UNUSED(propertyId); @@ -66,49 +64,144 @@ namespace AtomToolsFramework AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); } - bool AtomToolsDocument::Open([[maybe_unused]] AZStd::string_view loadPath) + bool AtomToolsDocument::Open(AZStd::string_view loadPath) { - AZ_UNUSED(loadPath); - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); - return false; + Clear(); + + m_absolutePath = loadPath; + if (!AzFramework::StringFunc::Path::Normalize(m_absolutePath)) + { + AZ_Error("AtomToolsDocument", false, "Document path could not be normalized: '%s'.", m_absolutePath.c_str()); + return OpenFailed(); + } + + if (AzFramework::StringFunc::Path::IsRelative(m_absolutePath.c_str())) + { + AZ_Error("AtomToolsDocument", false, "Document path must be absolute: '%s'.", m_absolutePath.c_str()); + return OpenFailed(); + } + + return true; } bool AtomToolsDocument::Reopen() { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); - return false; + if (!ReopenRecordState()) + { + return false; + } + + const auto loadPath = m_absolutePath; + if (!Open(loadPath)) + { + return false; + } + + if (!ReopenRestoreState()) + { + return false; + } + + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); + return true; } bool AtomToolsDocument::Save() { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); - return false; + m_savePathNormalized = m_absolutePath; + if (!AzFramework::StringFunc::Path::Normalize(m_savePathNormalized)) + { + AZ_Error("AtomToolsDocument", false, "Document save path could not be normalized: '%s'.", m_savePathNormalized.c_str()); + return SaveFailed(); + } + + if (!IsOpen()) + { + AZ_Error("AtomToolsDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); + return SaveFailed(); + } + + if (!IsSavable()) + { + AZ_Error("AtomToolsDocument", false, "Document type can not be saved: '%s'.", m_absolutePath.c_str()); + return SaveFailed(); + } + + return true; } - bool AtomToolsDocument::SaveAsCopy([[maybe_unused]] AZStd::string_view savePath) + bool AtomToolsDocument::SaveAsCopy(AZStd::string_view savePath) { - AZ_UNUSED(savePath); - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); - return false; + m_savePathNormalized = savePath; + if (!AzFramework::StringFunc::Path::Normalize(m_savePathNormalized)) + { + AZ_Error("AtomToolsDocument", false, "Document save path could not be normalized: '%s'.", m_savePathNormalized.c_str()); + return SaveFailed(); + } + + if (!IsOpen()) + { + AZ_Error("AtomToolsDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); + return SaveFailed(); + } + + if (!IsSavable()) + { + AZ_Error("AtomToolsDocument", false, "Document type can not be saved: '%s'.", m_absolutePath.c_str()); + return SaveFailed(); + } + + return true; } - - bool AtomToolsDocument::SaveAsChild([[maybe_unused]] AZStd::string_view savePath) + bool AtomToolsDocument::SaveAsChild(AZStd::string_view savePath) { - AZ_UNUSED(savePath); - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); - return false; + m_savePathNormalized = savePath; + if (!AzFramework::StringFunc::Path::Normalize(m_savePathNormalized)) + { + AZ_Error("AtomToolsDocument", false, "Document save path could not be normalized: '%s'.", m_savePathNormalized.c_str()); + return SaveFailed(); + } + + if (!IsOpen()) + { + AZ_Error("AtomToolsDocument", false, "Document is not open to be saved: '%s'.", m_absolutePath.c_str()); + return SaveFailed(); + } + + if (m_absolutePath == m_savePathNormalized || m_sourceDependencies.find(m_savePathNormalized) != m_sourceDependencies.end()) + { + AZ_Error("AtomToolsDocument", false, "Document can not be saved over a dependancy: '%s'.", m_savePathNormalized.c_str()); + return SaveFailed(); + } + + return true; } bool AtomToolsDocument::Close() { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); - return false; + if (!IsOpen()) + { + AZ_Error("AtomToolsDocument", false, "Document is not open."); + return false; + } + + AZ_TracePrintf("AtomToolsDocument", "Document closed: '%s'.\n", m_absolutePath.c_str()); + + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id); + + // Clearing after notification so paths are still available + Clear(); + return true; } bool AtomToolsDocument::IsOpen() const { - return false; + return !m_id.IsNull() && !m_absolutePath.empty(); } bool AtomToolsDocument::IsModified() const @@ -123,23 +216,41 @@ namespace AtomToolsFramework bool AtomToolsDocument::CanUndo() const { - return false; + // Undo will only be allowed if something has been recorded and we're not at the beginning of history + return IsOpen() && !m_undoHistory.empty() && m_undoHistoryIndex > 0; } bool AtomToolsDocument::CanRedo() const { - return false; + // Redo will only be allowed if something has been recorded and we're not at the end of history + return IsOpen() && !m_undoHistory.empty() && m_undoHistoryIndex < m_undoHistory.size(); } bool AtomToolsDocument::Undo() { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + if (CanUndo()) + { + // The history index is one beyond the last executed command. Decrement the index then execute undo. + m_undoHistory[--m_undoHistoryIndex].first(); + AZ_TracePrintf("AtomToolsDocument", "Document undo: '%s'.\n", m_absolutePath.c_str()); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); + return true; + } return false; } bool AtomToolsDocument::Redo() { - AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); + if (CanRedo()) + { + // Execute the current redo command then move the history index to the next position. + m_undoHistory[m_undoHistoryIndex++].second(); + AZ_TracePrintf("AtomToolsDocument", "Document redo: '%s'.\n", m_absolutePath.c_str()); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); + return true; + } return false; } @@ -154,4 +265,107 @@ namespace AtomToolsFramework AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__); return false; } + + void AtomToolsDocument::Clear() + { + AzToolsFramework::AssetSystemBus::Handler::BusDisconnect(); + + m_absolutePath.clear(); + m_sourceDependencies.clear(); + m_ignoreSourceFileChangeToSelf = {}; + m_undoHistory.clear(); + m_undoHistoryIndex = {}; + } + + bool AtomToolsDocument::OpenSucceeded() + { + AZ_TracePrintf("AtomToolsDocument", "Document opened: '%s'.\n", m_absolutePath.c_str()); + AzToolsFramework::AssetSystemBus::Handler::BusConnect(); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); + return true; + } + + bool AtomToolsDocument::OpenFailed() + { + AZ_TracePrintf("AtomToolsDocument", "Document could not opened: '%s'.\n", m_absolutePath.c_str()); + Clear(); + return false; + } + + bool AtomToolsDocument::SaveSucceeded() + { + m_ignoreSourceFileChangeToSelf = true; + + AZ_TracePrintf("AtomToolsDocument", "Document saved: '%s'.\n", m_savePathNormalized.c_str()); + + // Auto add or checkout saved file + AzToolsFramework::SourceControlCommandBus::Broadcast( + &AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, m_savePathNormalized.c_str(), true, + [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); + + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); + return true; + } + + bool AtomToolsDocument::SaveFailed() + { + AZ_TracePrintf("AtomToolsDocument", "Document not saved: '%s'.\n", m_savePathNormalized.c_str()); + return false; + } + + bool AtomToolsDocument::ReopenRecordState() + { + m_undoHistoryBeforeReopen = m_undoHistory; + m_undoHistoryIndexBeforeReopen = m_undoHistoryIndex; + return true; + } + + bool AtomToolsDocument::ReopenRestoreState() + { + m_undoHistory = m_undoHistoryBeforeReopen; + m_undoHistoryIndex = m_undoHistoryIndexBeforeReopen; + m_undoHistoryBeforeReopen = {}; + m_undoHistoryIndexBeforeReopen = {}; + return true; + } + + void AtomToolsDocument::AddUndoRedoHistory(const UndoRedoFunction& undoCommand, const UndoRedoFunction& redoCommand) + { + // Wipe any state beyond the current history index + m_undoHistory.erase(m_undoHistory.begin() + m_undoHistoryIndex, m_undoHistory.end()); + + // Add undo and redo operations using functions that capture state and restore it when executed + m_undoHistory.emplace_back(undoCommand, redoCommand); + + // Assign the index to the end of history + m_undoHistoryIndex = aznumeric_cast(m_undoHistory.size()); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); + } + + void AtomToolsDocument::SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid sourceUUID) + { + const auto sourcePath = AZ::RPI::AssetUtils::ResolvePathReference(scanFolder, relativePath); + + if (m_absolutePath == sourcePath) + { + // ignore notifications caused by saving the open document + if (!m_ignoreSourceFileChangeToSelf) + { + AZ_TracePrintf("AtomToolsDocument", "Document changed externally: '%s'.\n", m_absolutePath.c_str()); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); + } + m_ignoreSourceFileChangeToSelf = false; + } + else if (m_sourceDependencies.find(sourcePath) != m_sourceDependencies.end()) + { + AZ_TracePrintf("AtomToolsDocument", "Document dependency changed: '%s'.\n", m_absolutePath.c_str()); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); + } + } + } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp index d554c68451..b5a3f5322c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -77,7 +77,6 @@ namespace AtomToolsFramework ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "atomtools") ->Event("GetAbsolutePath", &AtomToolsDocumentRequestBus::Events::GetAbsolutePath) - ->Event("GetRelativePath", &AtomToolsDocumentRequestBus::Events::GetRelativePath) ->Event("GetPropertyValue", &AtomToolsDocumentRequestBus::Events::GetPropertyValue) ->Event("SetPropertyValue", &AtomToolsDocumentRequestBus::Events::SetPropertyValue) ->Event("Open", &AtomToolsDocumentRequestBus::Events::Open) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h index 58470e3582..5c7454e5c7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h @@ -24,7 +24,7 @@ AZ_POP_DISABLE_WARNING namespace AtomToolsFramework { - //! AtomToolsDocumentSystemComponent is the central component of the Material Editor Core gem + //! AtomToolsDocumentSystemComponent is the central component for managing documents class AtomToolsDocumentSystemComponent : public AZ::Component , private AtomToolsDocumentNotificationBus::Handler diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRendererCaptureState.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRendererCaptureState.h index 74195ab396..55f0507014 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRendererCaptureState.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRendererCaptureState.h @@ -14,7 +14,7 @@ namespace AtomToolsFramework { - //! PreviewRendererCaptureState renders a thumbnail to a pixmap and notifies MaterialOrModelThumbnail once finished + //! PreviewRendererCaptureState renders a preview to an image class PreviewRendererCaptureState final : public PreviewRendererState , public AZ::TickBus::Handler @@ -31,7 +31,7 @@ namespace AtomToolsFramework //! AZ::Render::FrameCaptureNotificationBus::Handler overrides... void OnCaptureFinished(AZ::Render::FrameCaptureResult result, const AZStd::string& info) override; - //! This is necessary to suspend capture to allow a frame for Material and Mesh components to assign materials + //! This is necessary to suspend capture until preview scene is ready int m_ticksToCapture = 1; }; } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index c441762710..283b7a8a7f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -12,16 +12,11 @@ #include #include #include -#include -#include -#include #include #include #include #include #include -#include -#include #include namespace MaterialEditor @@ -30,14 +25,12 @@ namespace MaterialEditor : AtomToolsFramework::AtomToolsDocument() { MaterialDocumentRequestBus::Handler::BusConnect(m_id); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id); } MaterialDocument::~MaterialDocument() { - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); MaterialDocumentRequestBus::Handler::BusDisconnect(); - Clear(); + AZ::TickBus::Handler::BusDisconnect(); } AZ::Data::Asset MaterialDocument::GetAsset() const @@ -62,19 +55,16 @@ namespace MaterialEditor const AZStd::any& MaterialDocument::GetPropertyValue(const AZ::Name& propertyId) const { - using namespace AZ; - using namespace RPI; - if (!IsOpen()) { - AZ_Error("MaterialDocument", false, "Material document is not open."); + AZ_Error("MaterialDocument", false, "Document is not open."); return m_invalidValue; } const auto it = m_properties.find(propertyId); if (it == m_properties.end()) { - AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyId.GetCStr()); + AZ_Error("MaterialDocument", false, "Document property could not be found: '%s'.", propertyId.GetCStr()); return m_invalidValue; } @@ -86,14 +76,14 @@ namespace MaterialEditor { if (!IsOpen()) { - AZ_Error("MaterialDocument", false, "Material document is not open."); + AZ_Error("MaterialDocument", false, "Document is not open."); return m_invalidProperty; } const auto it = m_properties.find(propertyId); if (it == m_properties.end()) { - AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyId.GetCStr()); + AZ_Error("MaterialDocument", false, "Document property could not be found: '%s'.", propertyId.GetCStr()); return m_invalidProperty; } @@ -105,14 +95,14 @@ namespace MaterialEditor { if (!IsOpen()) { - AZ_Error("MaterialDocument", false, "Material document is not open."); + AZ_Error("MaterialDocument", false, "Document is not open."); return false; } const auto it = m_propertyGroupVisibility.find(propertyGroupFullName); if (it == m_propertyGroupVisibility.end()) { - AZ_Error("MaterialDocument", false, "Material document property group could not be found: '%s'.", propertyGroupFullName.GetCStr()); + AZ_Error("MaterialDocument", false, "Document property group could not be found: '%s'.", propertyGroupFullName.GetCStr()); return false; } @@ -121,25 +111,21 @@ namespace MaterialEditor void MaterialDocument::SetPropertyValue(const AZ::Name& propertyId, const AZStd::any& value) { - using namespace AZ; - using namespace RPI; - if (!IsOpen()) { - AZ_Error("MaterialDocument", false, "Material document is not open."); + AZ_Error("MaterialDocument", false, "Document is not open."); return; } const auto it = m_properties.find(propertyId); if (it == m_properties.end()) { - AZ_Error("MaterialDocument", false, "Material document property could not be found: '%s'.", propertyId.GetCStr()); + AZ_Error("MaterialDocument", false, "Document property could not be found: '%s'.", propertyId.GetCStr()); return; } // This first converts to an acceptable runtime type in case the value came from script - const AZ::RPI::MaterialPropertyValue propertyValue = - AtomToolsFramework::ConvertToRuntimeType(value); + const AZ::RPI::MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(value); AtomToolsFramework::DynamicProperty& property = it->second; property.SetValue(AtomToolsFramework::ConvertToEditableType(propertyValue)); @@ -149,108 +135,53 @@ namespace MaterialEditor { if (m_materialInstance->SetPropertyValue(propertyIndex, propertyValue)) { - MaterialPropertyFlags dirtyFlags = m_materialInstance->GetPropertyDirtyFlags(); + AZ::RPI::MaterialPropertyFlags dirtyFlags = m_materialInstance->GetPropertyDirtyFlags(); Recompile(); EditorMaterialFunctorResult result = RunEditorMaterialFunctors(dirtyFlags); - for (const Name& changedPropertyGroupName : result.m_updatedPropertyGroups) + for (const AZ::Name& changedPropertyGroupName : result.m_updatedPropertyGroups) { - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyGroupVisibilityChanged, m_id, changedPropertyGroupName, IsPropertyGroupVisible(changedPropertyGroupName)); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyGroupVisibilityChanged, m_id, + changedPropertyGroupName, IsPropertyGroupVisible(changedPropertyGroupName)); } - for (const Name& changedPropertyName : result.m_updatedProperties) + for (const AZ::Name& changedPropertyName : result.m_updatedProperties) { - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyConfigModified, m_id, GetProperty(changedPropertyName)); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyConfigModified, m_id, + GetProperty(changedPropertyName)); } } } - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyValueModified, m_id, property); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id); - } - - bool MaterialDocument::Open(AZStd::string_view loadPath) - { - if (!OpenInternal(loadPath)) - { - Clear(); - AZ_Error("MaterialDocument", false, "Material document could not be opened: '%s'.", loadPath.data()); - return false; - } - - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); - return true; - } - - bool MaterialDocument::Reopen() - { - // Store history and property changes that should be reapplied after reload - auto undoHistoryToRestore = m_undoHistory; - auto undoHistoryIndexToRestore = m_undoHistoryIndex; - PropertyValueMap propertyValuesToRestore; - for (const auto& propertyPair : m_properties) - { - const AtomToolsFramework::DynamicProperty& property = propertyPair.second; - if (!AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue)) - { - propertyValuesToRestore[property.GetId()] = property.GetValue(); - } - } - - // Reopen the same document - const AZStd::string loadPath = m_absolutePath; - if (!OpenInternal(loadPath)) - { - Clear(); - return false; - } - - RestorePropertyValues(propertyValuesToRestore); - AZStd::swap(undoHistoryToRestore, m_undoHistory); - AZStd::swap(undoHistoryIndexToRestore, m_undoHistoryIndex); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); - return true; + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentPropertyValueModified, m_id, property); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id); } bool MaterialDocument::Save() { - using namespace AZ; - using namespace RPI; - - if (!IsOpen()) + if (!AtomToolsDocument::Save()) { - AZ_Error("MaterialDocument", false, "Material document is not open to be saved: '%s'.", m_absolutePath.c_str()); + // SaveFailed has already been called so just forward the result without additional notifications. + // TODO Replace bool return value with enum for open and save states. return false; } - if (!IsSavable()) - { - AZ_Error("MaterialDocument", false, "Material types can only be saved as a child: '%s'.", m_absolutePath.c_str()); - return false; - } - - // create source data from properties - MaterialSourceData sourceData; + // populate sourceData with modified or overridden properties and save object + AZ::RPI::MaterialSourceData sourceData; sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion(); sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(m_absolutePath, m_materialSourceData.m_materialType); sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(m_absolutePath, m_materialSourceData.m_parentMaterial); - - // populate sourceData with modified or overwritten properties - const bool savedProperties = SavePropertiesToSourceData(m_absolutePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property) - { + auto propertyFilter = [](const AtomToolsFramework::DynamicProperty& property) { return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); - }); + }; - if (!savedProperties) + if (!SaveSourceData(sourceData, propertyFilter)) { - return false; - } - - // write sourceData to .material file - if (!AZ::RPI::JsonUtils::SaveObjectToFile(m_absolutePath, sourceData)) - { - AZ_Error("MaterialDocument", false, "Material document could not be saved: '%s'.", m_absolutePath.c_str()); - return false; + return SaveFailed(); } // after saving, reset to a clean state @@ -262,181 +193,82 @@ namespace MaterialEditor property.SetConfig(propertyConfig); } - // Auto add or checkout saved file - AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - m_absolutePath.c_str(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - - AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", m_absolutePath.data()); - - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); - - m_saveTriggeredInternally = true; - return true; + return SaveSucceeded(); } bool MaterialDocument::SaveAsCopy(AZStd::string_view savePath) { - using namespace AZ; - using namespace RPI; - - if (!IsOpen()) + if (!AtomToolsDocument::SaveAsCopy(savePath)) { - AZ_Error("MaterialDocument", false, "Material document is not open to be saved: '%s'.", m_absolutePath.c_str()); + // SaveFailed has already been called so just forward the result without additional notifications. + // TODO Replace bool return value with enum for open and save states. return false; } - if (!IsSavable()) - { - AZ_Error("MaterialDocument", false, "Material types can only be saved as a child: '%s'.", m_absolutePath.c_str()); - return false; - } - - AZStd::string normalizedSavePath = savePath; - if (!AzFramework::StringFunc::Path::Normalize(normalizedSavePath)) - { - AZ_Error("MaterialDocument", false, "Material document save path could not be normalized: '%s'.", normalizedSavePath.c_str()); - return false; - } - - // create source data from properties - MaterialSourceData sourceData; + // populate sourceData with modified or overridden properties and save object + AZ::RPI::MaterialSourceData sourceData; sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion(); - sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_materialType); - sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_parentMaterial); - - // populate sourceData with modified or overwritten properties - const bool savedProperties = SavePropertiesToSourceData(normalizedSavePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property) - { + sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(m_savePathNormalized, m_materialSourceData.m_materialType); + sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(m_savePathNormalized, m_materialSourceData.m_parentMaterial); + auto propertyFilter = [](const AtomToolsFramework::DynamicProperty& property) { return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue); - }); + }; - if (!savedProperties) + if (!SaveSourceData(sourceData, propertyFilter)) { - return false; + return SaveFailed(); } - // write sourceData to .material file - if (!AZ::RPI::JsonUtils::SaveObjectToFile(normalizedSavePath, sourceData)) - { - AZ_Error("MaterialDocument", false, "Material document could not be saved: '%s'.", normalizedSavePath.c_str()); - return false; - } - - // Auto add or checkout saved file - AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - normalizedSavePath.c_str(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - - AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", normalizedSavePath.c_str()); - - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); - // If the document is saved to a new file we need to reopen the new document to update assets, paths, property deltas. - if (!Open(normalizedSavePath)) + if (!Open(m_savePathNormalized)) { - return false; + return SaveFailed(); } - // Setting flag after reopening becausse it's cleared on open - m_saveTriggeredInternally = true; - return true; + return SaveSucceeded(); } bool MaterialDocument::SaveAsChild(AZStd::string_view savePath) { - using namespace AZ; - using namespace RPI; - - if (!IsOpen()) + if (!AtomToolsDocument::SaveAsChild(savePath)) { - AZ_Error("MaterialDocument", false, "Material document is not open to be saved: '%s'.", m_absolutePath.c_str()); + // SaveFailed has already been called so just forward the result without additional notifications. + // TODO Replace bool return value with enum for open and save states. return false; } - AZStd::string normalizedSavePath = savePath; - if (!AzFramework::StringFunc::Path::Normalize(normalizedSavePath)) - { - AZ_Error("MaterialDocument", false, "Material document save path could not be normalized: '%s'.", normalizedSavePath.c_str()); - return false; - } - - if (m_absolutePath == normalizedSavePath) - { - // ToDo: this should scan the entire hierarchy so we don't overwrite parent's parent, for example - AZ_Error("MaterialDocument", false, "Can't overwrite parent material with a child that depends on it."); - return false; - } - - // create source data from properties - MaterialSourceData sourceData; + // populate sourceData with modified or overridden properties and save object + AZ::RPI::MaterialSourceData sourceData; sourceData.m_materialTypeVersion = m_materialAsset->GetMaterialTypeAsset()->GetVersion(); - sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_materialSourceData.m_materialType); + sourceData.m_materialType = AtomToolsFramework::GetExteralReferencePath(m_savePathNormalized, m_materialSourceData.m_materialType); // Only assign a parent path if the source was a .material - if (AzFramework::StringFunc::Path::IsExtension(m_relativePath.c_str(), MaterialSourceData::Extension)) + if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::MaterialSourceData::Extension)) { - sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(normalizedSavePath, m_absolutePath); + sourceData.m_parentMaterial = AtomToolsFramework::GetExteralReferencePath(m_savePathNormalized, m_absolutePath); } - // populate sourceData with modified properties - const bool savedProperties = SavePropertiesToSourceData(normalizedSavePath, sourceData, [](const AtomToolsFramework::DynamicProperty& property) - { + auto propertyFilter = [](const AtomToolsFramework::DynamicProperty& property) { return !AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_originalValue); - }); + }; - if (!savedProperties) + if (!SaveSourceData(sourceData, propertyFilter)) { - return false; + return SaveFailed(); } - // write sourceData to .material file - if (!AZ::RPI::JsonUtils::SaveObjectToFile(normalizedSavePath, sourceData)) - { - AZ_Error("MaterialDocument", false, "Material document could not be saved: '%s'.", normalizedSavePath.c_str()); - return false; - } - - // Auto add or checkout saved file - AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - normalizedSavePath.c_str(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - - AZ_TracePrintf("MaterialDocument", "Material document saved: '%s'.\n", normalizedSavePath.c_str()); - - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentSaved, m_id); - // If the document is saved to a new file we need to reopen the new document to update assets, paths, property deltas. - if (!Open(normalizedSavePath)) + if (!Open(m_savePathNormalized)) { - return false; + return SaveFailed(); } - // Setting flag after reopening becausse it's cleared on open - m_saveTriggeredInternally = true; - return true; - } - - bool MaterialDocument::Close() - { - using namespace AZ; - using namespace RPI; - - if (!IsOpen()) - { - AZ_Error("MaterialDocument", false, "Material document is not open."); - return false; - } - - AZ_TracePrintf("MaterialDocument", "Material document closed: '%s'.\n", m_absolutePath.c_str()); - - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id); - - // Clearing after notification so paths are still available - Clear(); - return true; + return SaveSucceeded(); } bool MaterialDocument::IsOpen() const { - return !m_absolutePath.empty() && !m_relativePath.empty() && m_materialAsset.IsReady() && m_materialInstance; + return AtomToolsDocument::IsOpen() && m_materialAsset.IsReady() && m_materialInstance; } bool MaterialDocument::IsModified() const @@ -454,44 +286,6 @@ namespace MaterialEditor return AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::MaterialSourceData::Extension); } - bool MaterialDocument::CanUndo() const - { - // Undo will only be allowed if something has been recorded and we're not at the beginning of history - return IsOpen() && !m_undoHistory.empty() && m_undoHistoryIndex > 0; - } - - bool MaterialDocument::CanRedo() const - { - // Redo will only be allowed if something has been recorded and we're not at the end of history - return IsOpen() && !m_undoHistory.empty() && m_undoHistoryIndex < m_undoHistory.size(); - } - - bool MaterialDocument::Undo() - { - if (CanUndo()) - { - // The history index is one beyond the last executed command. Decrement the index then execute undo. - m_undoHistory[--m_undoHistoryIndex].first(); - AZ_TracePrintf("MaterialDocument", "Material document undo: '%s'.\n", m_absolutePath.c_str()); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); - return true; - } - return false; - } - - bool MaterialDocument::Redo() - { - if (CanRedo()) - { - // Execute the current redo command then move the history index to the next position. - m_undoHistory[m_undoHistoryIndex++].second(); - AZ_TracePrintf("MaterialDocument", "Material document redo: '%s'.\n", m_absolutePath.c_str()); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); - return true; - } - return false; - } - bool MaterialDocument::BeginEdit() { // Save the current properties as a momento for undo before any changes are applied @@ -524,17 +318,9 @@ namespace MaterialEditor if (!propertyValuesForUndo.empty() && !propertyValuesForRedo.empty()) { - // Wipe any state beyond the current history index - m_undoHistory.erase(m_undoHistory.begin() + m_undoHistoryIndex, m_undoHistory.end()); - - // Add undo and redo operations using lambdas that will capture property state and restore it when executed - m_undoHistory.emplace_back( + AddUndoRedoHistory( [this, propertyValuesForUndo]() { RestorePropertyValues(propertyValuesForUndo); }, [this, propertyValuesForRedo]() { RestorePropertyValues(propertyValuesForRedo); }); - - // Assign the index to the end of history - m_undoHistoryIndex = aznumeric_cast(m_undoHistory.size()); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentUndoStateChanged, m_id); } m_propertyValuesBeforeEdit.clear(); @@ -553,52 +339,25 @@ namespace MaterialEditor } } - void MaterialDocument::SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid sourceUUID) + bool MaterialDocument::SaveSourceData(AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const { - const auto sourcePath = AZ::RPI::AssetUtils::ResolvePathReference(scanFolder, relativePath); - - if (m_absolutePath == sourcePath) - { - // ignore notifications caused by saving the open document - if (!m_saveTriggeredInternally) - { - AZ_TracePrintf("MaterialDocument", "Material document changed externally: '%s'.\n", m_absolutePath.c_str()); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( - &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); - } - m_saveTriggeredInternally = false; - } - else if (m_sourceDependencies.find(sourcePath) != m_sourceDependencies.end()) - { - AZ_TracePrintf("MaterialDocument", "Material document dependency changed: '%s'.\n", m_absolutePath.c_str()); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( - &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); - } - } - - bool MaterialDocument::SavePropertiesToSourceData( - const AZStd::string& exportPath, AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const - { - using namespace AZ; - using namespace RPI; - - bool result = true; + bool addPropertiesResult = true; // populate sourceData with properties that meet the filter - m_materialTypeSourceData.EnumerateProperties([&](const AZStd::string& propertyIdContext, const auto& propertyDefinition) { + m_materialTypeSourceData.EnumerateProperties([&, this](const AZStd::string& propertyIdContext, const auto& propertyDefinition) { - Name propertyId{propertyIdContext + propertyDefinition->GetName()}; + AZ::Name propertyId{propertyIdContext + propertyDefinition->GetName()}; const auto it = m_properties.find(propertyId); if (it != m_properties.end() && propertyFilter(it->second)) { - MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(it->second.GetValue()); + AZ::RPI::MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(it->second.GetValue()); if (propertyValue.IsValid()) { - if (!AtomToolsFramework::ConvertToExportFormat(exportPath, propertyId, *propertyDefinition, propertyValue)) + if (!AtomToolsFramework::ConvertToExportFormat(m_savePathNormalized, propertyId, *propertyDefinition, propertyValue)) { - AZ_Error("MaterialDocument", false, "Material document property could not be converted: '%s' in '%s'.", propertyId.GetCStr(), m_absolutePath.c_str()); - result = false; + AZ_Error("MaterialDocument", false, "Document property could not be converted: '%s' in '%s'.", propertyId.GetCStr(), m_absolutePath.c_str()); + addPropertiesResult = false; return false; } @@ -610,55 +369,36 @@ namespace MaterialEditor return true; }); - return result; + if (!addPropertiesResult) + { + AZ_Error("MaterialDocument", false, "Document properties could not be saved: '%s'.", m_savePathNormalized.c_str()); + return false; + } + + if (!AZ::RPI::JsonUtils::SaveObjectToFile(m_savePathNormalized, sourceData)) + { + AZ_Error("MaterialDocument", false, "Document could not be saved: '%s'.", m_savePathNormalized.c_str()); + return false; + } + + return true; } - bool MaterialDocument::OpenInternal(AZStd::string_view loadPath) + bool MaterialDocument::Open(AZStd::string_view loadPath) { - using namespace AZ; - using namespace RPI; - - Clear(); - - m_absolutePath = loadPath; - if (!AzFramework::StringFunc::Path::Normalize(m_absolutePath)) + if (!AtomToolsDocument::Open(loadPath)) { - AZ_Error("MaterialDocument", false, "Material document path could not be normalized: '%s'.", m_absolutePath.c_str()); - return false; - } - - if (AzFramework::StringFunc::Path::IsRelative(m_absolutePath.c_str())) - { - AZ_Error("MaterialDocument", false, "Material document path must be absolute: '%s'.", m_absolutePath.c_str()); - return false; - } - - bool result = false; - Data::AssetInfo sourceAssetInfo; - AZStd::string watchFolder; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, - m_absolutePath.c_str(), sourceAssetInfo, watchFolder); - if (!result) - { - AZ_Error("MaterialDocument", false, "Could not find source material: '%s'.", m_absolutePath.c_str()); - return false; - } - - m_relativePath = sourceAssetInfo.m_relativePath; - if (!AzFramework::StringFunc::Path::Normalize(m_relativePath)) - { - AZ_Error("MaterialDocument", false, "Material document path could not be normalized: '%s'.", m_relativePath.c_str()); return false; } // The material document and inspector are constructed from source data - if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), MaterialSourceData::Extension)) + if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::MaterialSourceData::Extension)) { // Load the material source data so that we can check properties and create a material asset from it if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_absolutePath, m_materialSourceData)) { AZ_Error("MaterialDocument", false, "Material source data could not be loaded: '%s'.", m_absolutePath.c_str()); - return false; + return OpenFailed(); } // We always need the absolute path for the material type and parent material to load source data and resolving @@ -666,33 +406,34 @@ namespace MaterialEditor if (!m_materialSourceData.m_parentMaterial.empty()) { m_materialSourceData.m_parentMaterial = - AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_parentMaterial); + AZ::RPI::AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_parentMaterial); } if (!m_materialSourceData.m_materialType.empty()) { - m_materialSourceData.m_materialType = AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_materialType); + m_materialSourceData.m_materialType = + AZ::RPI::AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_materialType); } // Load the material type source data which provides the layout and default values of all of the properties - auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(m_materialSourceData.m_materialType); + auto materialTypeOutcome = AZ::RPI::MaterialUtils::LoadMaterialTypeSourceData(m_materialSourceData.m_materialType); if (!materialTypeOutcome.IsSuccess()) { AZ_Error("MaterialDocument", false, "Material type source data could not be loaded: '%s'.", m_materialSourceData.m_materialType.c_str()); - return false; + return OpenFailed(); } m_materialTypeSourceData = materialTypeOutcome.TakeValue(); } - else if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), MaterialTypeSourceData::Extension)) + else if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::MaterialTypeSourceData::Extension)) { // A material document can be created or loaded from material or material type source data. If we are attempting to load // material type source data then the material source data object can be created just by referencing the document path as the // material type path. - auto materialTypeOutcome = MaterialUtils::LoadMaterialTypeSourceData(m_absolutePath); + auto materialTypeOutcome = AZ::RPI::MaterialUtils::LoadMaterialTypeSourceData(m_absolutePath); if (!materialTypeOutcome.IsSuccess()) { AZ_Error("MaterialDocument", false, "Material type source data could not be loaded: '%s'.", m_absolutePath.c_str()); - return false; + return OpenFailed(); } m_materialTypeSourceData = materialTypeOutcome.TakeValue(); @@ -702,8 +443,8 @@ namespace MaterialEditor } else { - AZ_Error("MaterialDocument", false, "Material document extension not supported: '%s'.", m_absolutePath.c_str()); - return false; + AZ_Error("MaterialDocument", false, "Document extension not supported: '%s'.", m_absolutePath.c_str()); + return OpenFailed(); } const bool elevateWarnings = false; @@ -714,44 +455,44 @@ namespace MaterialEditor // we can create the asset dynamically from the source data. // Long term, the material document should not be concerned with assets at all. The viewport window should be the // only thing concerned with assets or instances. - auto materialAssetResult = - m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, elevateWarnings, &m_sourceDependencies); + auto materialAssetResult = m_materialSourceData.CreateMaterialAssetFromSourceData( + AZ::Uuid::CreateRandom(), m_absolutePath, elevateWarnings, &m_sourceDependencies); if (!materialAssetResult) { AZ_Error("MaterialDocument", false, "Material asset could not be created from source data: '%s'.", m_absolutePath.c_str()); - return false; + return OpenFailed(); } m_materialAsset = materialAssetResult.GetValue(); if (!m_materialAsset.IsReady()) { AZ_Error("MaterialDocument", false, "Material asset is not ready: '%s'.", m_absolutePath.c_str()); - return false; + return OpenFailed(); } const auto& materialTypeAsset = m_materialAsset->GetMaterialTypeAsset(); if (!materialTypeAsset.IsReady()) { AZ_Error("MaterialDocument", false, "Material type asset is not ready: '%s'.", m_absolutePath.c_str()); - return false; + return OpenFailed(); } AZStd::span parentPropertyValues = materialTypeAsset->GetDefaultPropertyValues(); - AZ::Data::Asset parentMaterialAsset; + AZ::Data::Asset parentMaterialAsset; if (!m_materialSourceData.m_parentMaterial.empty()) { AZ::RPI::MaterialSourceData parentMaterialSourceData; if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_materialSourceData.m_parentMaterial, parentMaterialSourceData)) { AZ_Error("MaterialDocument", false, "Material parent source data could not be loaded for: '%s'.", m_materialSourceData.m_parentMaterial.c_str()); - return false; + return OpenFailed(); } - const auto parentMaterialAssetIdResult = AssetUtils::MakeAssetId(m_materialSourceData.m_parentMaterial, 0); + const auto parentMaterialAssetIdResult = AZ::RPI::AssetUtils::MakeAssetId(m_materialSourceData.m_parentMaterial, 0); if (!parentMaterialAssetIdResult) { AZ_Error("MaterialDocument", false, "Material parent asset ID could not be created: '%s'.", m_materialSourceData.m_parentMaterial.c_str()); - return false; + return OpenFailed(); } auto parentMaterialAssetResult = parentMaterialSourceData.CreateMaterialAssetFromSourceData( @@ -759,7 +500,7 @@ namespace MaterialEditor if (!parentMaterialAssetResult) { AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", m_materialSourceData.m_parentMaterial.c_str()); - return false; + return OpenFailed(); } parentMaterialAsset = parentMaterialAssetResult.GetValue(); @@ -767,11 +508,11 @@ namespace MaterialEditor } // Creating a material from a material asset will fail if a texture is referenced but not loaded - m_materialInstance = Material::Create(m_materialAsset); + m_materialInstance = AZ::RPI::Material::Create(m_materialAsset); if (!m_materialInstance) { AZ_Error("MaterialDocument", false, "Material instance could not be created: '%s'.", m_absolutePath.c_str()); - return false; + return OpenFailed(); } // Pipeline State Object changes are always allowed in the material editor because it only runs on developer systems @@ -781,7 +522,7 @@ namespace MaterialEditor // Populate the property map from a combination of source data and assets // Assets must still be used for now because they contain the final accumulated value after all other materials // in the hierarchy are applied - m_materialTypeSourceData.EnumeratePropertyGroups([this, &parentPropertyValues](const AZStd::string& propertyIdContext, const MaterialTypeSourceData::PropertyGroup* propertyGroup) + m_materialTypeSourceData.EnumeratePropertyGroups([this, &parentPropertyValues](const AZStd::string& propertyIdContext, const AZ::RPI::MaterialTypeSourceData::PropertyGroup* propertyGroup) { AtomToolsFramework::DynamicPropertyConfig propertyConfig; @@ -813,7 +554,7 @@ namespace MaterialEditor // Populate the property group visibility map // TODO: Support populating the Material Editor with nested property groups, not just the top level. - for (const AZStd::unique_ptr& propertyGroup : m_materialTypeSourceData.GetPropertyLayout().m_propertyGroups) + for (const AZStd::unique_ptr& propertyGroup : m_materialTypeSourceData.GetPropertyLayout().m_propertyGroups) { m_propertyGroupVisibility[AZ::Name{propertyGroup->GetName()}] = true; } @@ -856,15 +597,15 @@ namespace MaterialEditor m_properties[propertyConfig.m_id] = AtomToolsFramework::DynamicProperty(propertyConfig); //Add UV name customization properties - const RPI::MaterialUvNameMap& uvNameMap = materialTypeAsset->GetUvNameMap(); - for (const RPI::UvNamePair& uvNamePair : uvNameMap) + const AZ::RPI::MaterialUvNameMap& uvNameMap = materialTypeAsset->GetUvNameMap(); + for (const AZ::RPI::UvNamePair& uvNamePair : uvNameMap) { const AZStd::string shaderInput = uvNamePair.m_shaderInput.ToString(); const AZStd::string uvName = uvNamePair.m_uvName.GetStringView(); propertyConfig = {}; propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::String; - propertyConfig.m_id = MaterialPropertyId(UvGroupName, shaderInput); + propertyConfig.m_id = AZ::RPI::MaterialPropertyId(UvGroupName, shaderInput); propertyConfig.m_name = shaderInput; propertyConfig.m_displayName = shaderInput; propertyConfig.m_groupName = "UV Sets"; @@ -878,15 +619,15 @@ namespace MaterialEditor } // Add material functors that are in the top-level functors list. - const MaterialFunctorSourceData::EditorContext editorContext = - MaterialFunctorSourceData::EditorContext(m_materialSourceData.m_materialType, m_materialAsset->GetMaterialPropertiesLayout()); - for (Ptr functorData : m_materialTypeSourceData.m_materialFunctorSourceData) + const AZ::RPI::MaterialFunctorSourceData::EditorContext editorContext = + AZ::RPI::MaterialFunctorSourceData::EditorContext(m_materialSourceData.m_materialType, m_materialAsset->GetMaterialPropertiesLayout()); + for (AZ::RPI::Ptr functorData : m_materialTypeSourceData.m_materialFunctorSourceData) { - MaterialFunctorSourceData::FunctorResult result2 = functorData->CreateFunctor(editorContext); + AZ::RPI::MaterialFunctorSourceData::FunctorResult result2 = functorData->CreateFunctor(editorContext); if (result2.IsSuccess()) { - Ptr& functor = result2.GetValue(); + AZ::RPI::Ptr& functor = result2.GetValue(); if (functor != nullptr) { m_editorFunctors.push_back(functor); @@ -895,24 +636,24 @@ namespace MaterialEditor else { AZ_Error("MaterialDocument", false, "Material functors were not created: '%s'.", m_absolutePath.c_str()); - return false; + return OpenFailed(); } } // Add any material functors that are located inside each property group. bool enumerateResult = m_materialTypeSourceData.EnumeratePropertyGroups( - [this](const AZStd::string&, const MaterialTypeSourceData::PropertyGroup* propertyGroup) + [this](const AZStd::string&, const AZ::RPI::MaterialTypeSourceData::PropertyGroup* propertyGroup) { - const MaterialFunctorSourceData::EditorContext editorContext = MaterialFunctorSourceData::EditorContext( + const AZ::RPI::MaterialFunctorSourceData::EditorContext editorContext = AZ::RPI::MaterialFunctorSourceData::EditorContext( m_materialSourceData.m_materialType, m_materialAsset->GetMaterialPropertiesLayout()); - for (Ptr functorData : propertyGroup->GetFunctors()) + for (AZ::RPI::Ptr functorData : propertyGroup->GetFunctors()) { - MaterialFunctorSourceData::FunctorResult result = functorData->CreateFunctor(editorContext); + AZ::RPI::MaterialFunctorSourceData::FunctorResult result = functorData->CreateFunctor(editorContext); if (result.IsSuccess()) { - Ptr& functor = result.GetValue(); + AZ::RPI::Ptr& functor = result.GetValue(); if (functor != nullptr) { m_editorFunctors.push_back(functor); @@ -930,18 +671,35 @@ namespace MaterialEditor if (!enumerateResult) { - return false; + return OpenFailed(); } AZ::RPI::MaterialPropertyFlags dirtyFlags; dirtyFlags.set(); // Mark all properties as dirty since we just loaded the material and need to initialize property visibility RunEditorMaterialFunctors(dirtyFlags); - // Connecting to bus to monitor external changes - AzToolsFramework::AssetSystemBus::Handler::BusConnect(); + return OpenSucceeded(); + } - AZ_TracePrintf("MaterialDocument", "Material document opened: '%s'.\n", m_absolutePath.c_str()); - return true; + bool MaterialDocument::ReopenRecordState() + { + m_propertyValuesBeforeReopen.clear(); + for (const auto& propertyPair : m_properties) + { + const AtomToolsFramework::DynamicProperty& property = propertyPair.second; + if (!AtomToolsFramework::ArePropertyValuesEqual(property.GetValue(), property.GetConfig().m_parentValue)) + { + m_propertyValuesBeforeReopen[property.GetId()] = property.GetValue(); + } + } + return AtomToolsDocument::ReopenRecordState(); + } + + bool MaterialDocument::ReopenRestoreState() + { + RestorePropertyValues(m_propertyValuesBeforeReopen); + m_propertyValuesBeforeReopen.clear(); + return AtomToolsDocument::ReopenRestoreState(); } void MaterialDocument::Recompile() @@ -955,23 +713,18 @@ namespace MaterialEditor void MaterialDocument::Clear() { + AtomToolsFramework::AtomToolsDocument::Clear(); + AZ::TickBus::Handler::BusDisconnect(); - AzToolsFramework::AssetSystemBus::Handler::BusDisconnect(); m_materialAsset = {}; m_materialInstance = {}; - m_absolutePath.clear(); - m_relativePath.clear(); - m_sourceDependencies.clear(); - m_saveTriggeredInternally = {}; m_compilePending = {}; m_properties.clear(); m_editorFunctors.clear(); m_materialTypeSourceData = AZ::RPI::MaterialTypeSourceData(); m_materialSourceData = AZ::RPI::MaterialSourceData(); m_propertyValuesBeforeEdit.clear(); - m_undoHistory.clear(); - m_undoHistoryIndex = {}; } void MaterialDocument::RestorePropertyValues(const PropertyValueMap& propertyValues) @@ -1040,5 +793,4 @@ namespace MaterialEditor return result; } - } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index c975824e22..b03d0943fa 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -28,7 +27,6 @@ namespace MaterialEditor : public AtomToolsFramework::AtomToolsDocument , public MaterialDocumentRequestBus::Handler , private AZ::TickBus::Handler - , private AzToolsFramework::AssetSystemBus::Handler { public: AZ_RTTI(MaterialDocument, "{DBA269AE-892B-415C-8FA1-166B94B0E045}"); @@ -38,37 +36,26 @@ namespace MaterialEditor MaterialDocument(); virtual ~MaterialDocument(); - //////////////////////////////////////////////////////////////////////// - // AtomToolsFramework::AtomToolsDocument - //////////////////////////////////////////////////////////////////////// + // AtomToolsFramework::AtomToolsDocument overrides... const AZStd::any& GetPropertyValue(const AZ::Name& propertyId) const override; const AtomToolsFramework::DynamicProperty& GetProperty(const AZ::Name& propertyId) const override; bool IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const override; void SetPropertyValue(const AZ::Name& propertyId, const AZStd::any& value) override; bool Open(AZStd::string_view loadPath) override; - bool Reopen() override; bool Save() override; bool SaveAsCopy(AZStd::string_view savePath) override; bool SaveAsChild(AZStd::string_view savePath) override; - bool Close() override; bool IsOpen() const override; bool IsModified() const override; bool IsSavable() const override; - bool CanUndo() const override; - bool CanRedo() const override; - bool Undo() override; - bool Redo() override; bool BeginEdit() override; bool EndEdit() override; - //////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// - // MaterialDocumentRequestBus::Handler implementation + // MaterialDocumentRequestBus::Handler overrides... AZ::Data::Asset GetAsset() const override; AZ::Data::Instance GetInstance() const override; const AZ::RPI::MaterialSourceData* GetMaterialSourceData() const override; const AZ::RPI::MaterialTypeSourceData* GetMaterialTypeSourceData() const override; - //////////////////////////////////////////////////////////////////////// private: @@ -84,34 +71,19 @@ namespace MaterialEditor // Map of document's property group visibility flags using PropertyGroupVisibilityMap = AZStd::unordered_map; - // Function to be bound for undo and redo - using UndoRedoFunction = AZStd::function; - - // A pair of functions, where first is the undo operation and second is the redo operation - using UndoRedoFunctionPair = AZStd::pair; - - // Container for all of the active undo and redo functions and state - using UndoRedoHistory = AZStd::vector; - - //////////////////////////////////////////////////////////////////////// - // AZ::TickBus interface implementation + // AZ::TickBus overrides... void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - //////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AzToolsFramework::AssetSystemBus::Handler overrides... - void SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid sourceUUID) override; - ////////////////////////////////////////////////////////////////////////// + bool SaveSourceData(AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const; - bool SavePropertiesToSourceData( - const AZStd::string& exportPath, AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const; + // AtomToolsFramework::AtomToolsDocument overrides... + void Clear() override; - bool OpenInternal(AZStd::string_view loadPath); + bool ReopenRecordState() override; + bool ReopenRestoreState() override; void Recompile(); - void Clear(); - void RestorePropertyValues(const PropertyValueMap& propertyValues); struct EditorMaterialFunctorResult @@ -131,12 +103,6 @@ namespace MaterialEditor // Material instance being edited AZ::Data::Instance m_materialInstance; - // Set of assets that can trigger a document reload - AZStd::unordered_set m_sourceDependencies; - - // Track if document saved itself last to skip external modification notification - bool m_saveTriggeredInternally = false; - // If material instance value(s) were modified, do we need to recompile on next tick? bool m_compilePending = false; @@ -155,19 +121,10 @@ namespace MaterialEditor // Source data for material AZ::RPI::MaterialSourceData m_materialSourceData; - // Variables needed for tracking the undo and redo state of this document - // State of property values prior to an edit, used for restoration during undo PropertyValueMap m_propertyValuesBeforeEdit; - // Container of undo commands - UndoRedoHistory m_undoHistory; - - // The current position in the undo redo history - int m_undoHistoryIndex = 0; - - AZStd::any m_invalidValue; - - AtomToolsFramework::DynamicProperty m_invalidProperty; + // State of property values prior to reopen + PropertyValueMap m_propertyValuesBeforeReopen; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp index b2f1cdc9c1..f25d83556d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp @@ -170,11 +170,14 @@ namespace MaterialEditor { m_lightingPresetAssets[info.m_assetId] = { info.m_assetId, info.m_assetType }; AZ::Data::AssetBus::MultiHandler::BusConnect(info.m_assetId); + return; } - else if (AZ::StringFunc::EndsWith(info.m_relativePath.c_str(), ".modelpreset.azasset")) + + if (AZ::StringFunc::EndsWith(info.m_relativePath.c_str(), ".modelpreset.azasset")) { m_modelPresetAssets[info.m_assetId] = { info.m_assetId, info.m_assetType }; AZ::Data::AssetBus::MultiHandler::BusConnect(info.m_assetId); + return; } }; @@ -436,24 +439,20 @@ namespace MaterialEditor auto ReloadLightingAndModelPresets = [this, &assetId](AZ::Data::AssetCatalogRequests* assetCatalogRequests) { AZ::Data::AssetInfo assetInfo = assetCatalogRequests->GetAssetInfoById(assetId); - AZ::Data::Asset* modifiedPresetAsset{}; if (AZ::StringFunc::EndsWith(assetInfo.m_relativePath.c_str(), ".lightingpreset.azasset")) { m_lightingPresetAssets[assetInfo.m_assetId] = { assetInfo.m_assetId, assetInfo.m_assetType }; + m_lightingPresetAssets[assetInfo.m_assetId].QueueLoad(); AZ::Data::AssetBus::MultiHandler::BusConnect(assetInfo.m_assetId); - modifiedPresetAsset = &m_lightingPresetAssets[assetInfo.m_assetId]; - } - else if (AzFramework::StringFunc::EndsWith(assetInfo.m_relativePath.c_str(), ".modelpreset.azasset")) - { - m_modelPresetAssets[assetInfo.m_assetId] = { assetInfo.m_assetId, assetInfo.m_assetType }; - AZ::Data::AssetBus::MultiHandler::BusConnect(assetInfo.m_assetId); - modifiedPresetAsset = &m_modelPresetAssets[assetInfo.m_assetId]; + return; } - // Queue a load on the changed asset - if (modifiedPresetAsset != nullptr) + if (AzFramework::StringFunc::EndsWith(assetInfo.m_relativePath.c_str(), ".modelpreset.azasset")) { - modifiedPresetAsset->QueueLoad(); + m_modelPresetAssets[assetInfo.m_assetId] = { assetInfo.m_assetId, assetInfo.m_assetType }; + m_modelPresetAssets[assetInfo.m_assetId].QueueLoad(); + AZ::Data::AssetBus::MultiHandler::BusConnect(assetInfo.m_assetId); + return; } }; AZ::Data::AssetCatalogRequestBus::Broadcast(AZStd::move(ReloadLightingAndModelPresets)); @@ -470,11 +469,14 @@ namespace MaterialEditor { AZ::Data::AssetBus::MultiHandler::BusDisconnect(assetInfo.m_assetId); m_lightingPresetAssets.erase(assetId); + return; } + if (AZ::StringFunc::EndsWith(assetInfo.m_relativePath.c_str(), ".modelpreset.azasset")) { AZ::Data::AssetBus::MultiHandler::BusDisconnect(assetInfo.m_assetId); m_modelPresetAssets.erase(assetId); + return; } } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h index a4cd2b7616..690e8add86 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h @@ -19,8 +19,7 @@ namespace MaterialEditor { - //! Provides controls for viewing and editing a material document settings. - //! The settings can be divided into cards, with each one showing a subset of properties. + //! Provides controls for viewing and editing document settings. class MaterialInspector : public AtomToolsFramework::InspectorWidget , public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h index 464a55aa7f..ad4629550f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h @@ -21,8 +21,7 @@ namespace MaterialEditor { - //! Provides controls for viewing and editing a material document settings. - //! The settings can be divided into cards, with each one showing a subset of properties. + //! Provides controls for viewing and editing lighting and model preset settings. class ViewportSettingsInspector : public AtomToolsFramework::InspectorWidget , private AzToolsFramework::IPropertyEditorNotify diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp index 2b7767635e..99a3aea347 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.cpp @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include namespace ShaderManagementConsole @@ -20,28 +18,32 @@ namespace ShaderManagementConsole : AtomToolsFramework::AtomToolsDocument() { ShaderManagementConsoleDocumentRequestBus::Handler::BusConnect(m_id); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentCreated, m_id); } ShaderManagementConsoleDocument::~ShaderManagementConsoleDocument() { - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDestroyed, m_id); ShaderManagementConsoleDocumentRequestBus::Handler::BusDisconnect(); - Clear(); } - size_t ShaderManagementConsoleDocument::GetShaderOptionCount() const + void ShaderManagementConsoleDocument::SetShaderVariantListSourceData(const AZ::RPI::ShaderVariantListSourceData& sourceData) { - auto layout = m_shaderAsset->GetShaderOptionGroupLayout(); - auto& shaderOptionDescriptors = layout->GetShaderOptions(); - return shaderOptionDescriptors.size(); + m_shaderVariantListSourceData = sourceData; + AZStd::string shaderPath = m_shaderVariantListSourceData.m_shaderFilePath; + AzFramework::StringFunc::Path::ReplaceExtension(shaderPath, AZ::RPI::ShaderAsset::Extension); + + m_shaderAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath(shaderPath.c_str()); + if (!m_shaderAsset) + { + AZ_Error("ShaderManagementConsoleDocument", false, "Could not load shader asset: %s.", shaderPath.c_str()); + } + + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentModified, m_id); } - const AZ::RPI::ShaderOptionDescriptor& ShaderManagementConsoleDocument::GetShaderOptionDescriptor(size_t index) const + const AZ::RPI::ShaderVariantListSourceData& ShaderManagementConsoleDocument::GetShaderVariantListSourceData() const { - auto layout = m_shaderAsset->GetShaderOptionGroupLayout(); - auto& shaderOptionDescriptors = layout->GetShaderOptions(); - return shaderOptionDescriptors[index]; + return m_shaderVariantListSourceData; } size_t ShaderManagementConsoleDocument::GetShaderVariantCount() const @@ -54,92 +56,121 @@ namespace ShaderManagementConsole return m_shaderVariantListSourceData.m_shaderVariants[index]; } - bool ShaderManagementConsoleDocument::Open(AZStd::string_view loadPath) + size_t ShaderManagementConsoleDocument::GetShaderOptionCount() const { - Clear(); - - m_absolutePath = loadPath; - if (!AzFramework::StringFunc::Path::Normalize(m_absolutePath)) + if (IsOpen()) { - AZ_Error("ShaderManagementConsoleDocument", false, "Document path could not be normalized: '%s'.", m_absolutePath.c_str()); - return false; + const auto& layout = m_shaderAsset->GetShaderOptionGroupLayout(); + const auto& shaderOptionDescriptors = layout->GetShaderOptions(); + return shaderOptionDescriptors.size(); } - - if (AzFramework::StringFunc::Path::IsRelative(m_absolutePath.c_str())) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Document path must be absolute: '%s'.", m_absolutePath.c_str()); - return false; - } - - if (AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) - { - // Load the shader config data and create a shader config asset from it - if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_absolutePath, m_shaderVariantListSourceData)) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Failed loading shader variant list data: '%s.'", m_absolutePath.c_str()); - return false; - } - } - - bool result = false; - AZ::Data::AssetInfo sourceAssetInfo; - AZStd::string watchFolder; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult( - result, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, m_absolutePath.c_str(), sourceAssetInfo, - watchFolder); - if (!result) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Could not find source data: '%s'.", m_absolutePath.c_str()); - return false; - } - - m_relativePath = m_shaderVariantListSourceData.m_shaderFilePath; - if (!AzFramework::StringFunc::Path::Normalize(m_relativePath)) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Shader path could not be normalized: '%s'.", m_relativePath.c_str()); - return false; - } - - AZStd::string shaderPath = m_relativePath; - AzFramework::StringFunc::Path::ReplaceExtension(shaderPath, AZ::RPI::ShaderAsset::Extension); - - m_shaderAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath(shaderPath.c_str()); - if (!m_shaderAsset) - { - AZ_Error("ShaderManagementConsoleDocument", false, "Could not load shader asset: %s.", shaderPath.c_str()); - return false; - } - - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentOpened, m_id); - - AZ_TracePrintf("ShaderManagementConsoleDocument", "Document opened: '%s'\n", m_absolutePath.c_str()); - return true; + return 0; } - bool ShaderManagementConsoleDocument::Close() + const AZ::RPI::ShaderOptionDescriptor& ShaderManagementConsoleDocument::GetShaderOptionDescriptor(size_t index) const { - if (!IsOpen()) + if (IsOpen()) + { + const auto& layout = m_shaderAsset->GetShaderOptionGroupLayout(); + const auto& shaderOptionDescriptors = layout->GetShaderOptions(); + return shaderOptionDescriptors.at(index); + } + return m_invalidDescriptor; + } + + bool ShaderManagementConsoleDocument::Open(AZStd::string_view loadPath) + { + if (!AtomToolsDocument::Open(loadPath)) { - AZ_Error("ShaderManagementConsoleDocument", false, "Document is not open"); return false; } - Clear(); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentClosed, m_id); - AZ_TracePrintf("ShaderManagementConsoleDocument", "Document closed\n"); - return true; + if (!AzFramework::StringFunc::Path::IsExtension(m_absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension)) + { + AZ_Error("ShaderManagementConsoleDocument", false, "Document extension is not supported: '%s.'", m_absolutePath.c_str()); + return OpenFailed(); + } + + // Load the shader config data and create a shader config asset from it + AZ::RPI::ShaderVariantListSourceData sourceData; + if (!AZ::RPI::JsonUtils::LoadObjectFromFile(m_absolutePath, sourceData)) + { + AZ_Error("ShaderManagementConsoleDocument", false, "Failed loading shader variant list data: '%s.'", m_absolutePath.c_str()); + return OpenFailed(); + } + + SetShaderVariantListSourceData(sourceData); + return IsOpen() ? OpenSucceeded() : OpenFailed(); + } + + bool ShaderManagementConsoleDocument::Save() + { + if (!AtomToolsDocument::Save()) + { + // SaveFailed has already been called so just forward the result without additional notifications. + // TODO Replace bool return value with enum for open and save states. + return false; + } + + return SaveSourceData(); + } + + bool ShaderManagementConsoleDocument::SaveAsCopy(AZStd::string_view savePath) + { + if (!AtomToolsDocument::SaveAsCopy(savePath)) + { + // SaveFailed has already been called so just forward the result without additional notifications. + // TODO Replace bool return value with enum for open and save states. + return false; + } + + return SaveSourceData(); + } + + bool ShaderManagementConsoleDocument::SaveAsChild(AZStd::string_view savePath) + { + if (!AtomToolsDocument::SaveAsChild(savePath)) + { + // SaveFailed has already been called so just forward the result without additional notifications. + // TODO Replace bool return value with enum for open and save states. + return false; + } + + return SaveSourceData(); } bool ShaderManagementConsoleDocument::IsOpen() const { - return !m_absolutePath.empty() && !m_relativePath.empty(); + return AtomToolsDocument::IsOpen() && m_shaderAsset.IsReady(); + } + + bool ShaderManagementConsoleDocument::IsModified() const + { + return false; + } + + bool ShaderManagementConsoleDocument::IsSavable() const + { + return true; } void ShaderManagementConsoleDocument::Clear() { - m_absolutePath.clear(); - m_relativePath.clear(); + AtomToolsFramework::AtomToolsDocument::Clear(); + m_shaderVariantListSourceData = {}; m_shaderAsset = {}; } + + bool ShaderManagementConsoleDocument::SaveSourceData() + { + if (!AZ::RPI::JsonUtils::SaveObjectToFile(m_savePathNormalized, m_shaderVariantListSourceData)) + { + AZ_Error("ShaderManagementConsoleDocument", false, "Document could not be saved: '%s'.", m_savePathNormalized.c_str()); + return SaveFailed(); + } + + m_absolutePath = m_savePathNormalized; + return SaveSucceeded(); + } } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h index bd51616f7a..4ad951e463 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocument.h @@ -29,40 +29,37 @@ namespace ShaderManagementConsole AZ_DISABLE_COPY(ShaderManagementConsoleDocument); ShaderManagementConsoleDocument(); - virtual ~ShaderManagementConsoleDocument(); + ~ShaderManagementConsoleDocument(); - //////////////////////////////////////////////////////////////////////// - // AtomToolsFramework::AtomToolsDocument - //////////////////////////////////////////////////////////////////////// + // AtomToolsFramework::AtomToolsDocument overrides... bool Open(AZStd::string_view loadPath) override; - bool Close() override; + bool Save() override; + bool SaveAsCopy(AZStd::string_view savePath) override; + bool SaveAsChild(AZStd::string_view savePath) override; bool IsOpen() const override; - //////////////////////////////////////////////////////////////////////// + bool IsModified() const override; + bool IsSavable() const override; - //////////////////////////////////////////////////////////////////////// - // ShaderManagementConsoleDocumentRequestBus::Handler implementation - size_t GetShaderOptionCount() const override; - const AZ::RPI::ShaderOptionDescriptor& GetShaderOptionDescriptor(size_t index) const override; + // ShaderManagementConsoleDocumentRequestBus::Handler overridfes... + void SetShaderVariantListSourceData(const AZ::RPI::ShaderVariantListSourceData& sourceData) override; + const AZ::RPI::ShaderVariantListSourceData& GetShaderVariantListSourceData() const override; size_t GetShaderVariantCount() const override; const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const override; - //////////////////////////////////////////////////////////////////////// + size_t GetShaderOptionCount() const override; + const AZ::RPI::ShaderOptionDescriptor& GetShaderOptionDescriptor(size_t index) const override; private: - // Function to be bound for undo and redo - using UndoRedoFunction = AZStd::function; + // AtomToolsFramework::AtomToolsDocument overrides... + void Clear() override; - // A pair of functions, where first is the undo operation and second is the redo operation - using UndoRedoFunctionPair = AZStd::pair; - - // Container for all of the active undo and redo functions and state - using UndoRedoHistory = AZStd::vector; - - void Clear(); + bool SaveSourceData(); // Source data for shader variant list AZ::RPI::ShaderVariantListSourceData m_shaderVariantListSourceData; // Shader asset for the corresponding shader variant list AZ::Data::Asset m_shaderAsset; + + AZ::RPI::ShaderOptionDescriptor m_invalidDescriptor; }; } // namespace ShaderManagementConsole diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentRequestBus.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentRequestBus.h index d0e6aea5b9..e58ee34ed1 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentRequestBus.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentRequestBus.h @@ -23,17 +23,23 @@ namespace ShaderManagementConsole static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; typedef AZ::Uuid BusIdType; - //! Get the number of options - virtual size_t GetShaderOptionCount() const = 0; + //! Set the shader variant list + virtual void SetShaderVariantListSourceData(const AZ::RPI::ShaderVariantListSourceData& sourceData) = 0; - //! Get the descriptor for the shader option at the specified index - virtual const AZ::RPI::ShaderOptionDescriptor& GetShaderOptionDescriptor(size_t index) const = 0; + //! Get the shader variant list + virtual const AZ::RPI::ShaderVariantListSourceData& GetShaderVariantListSourceData() const = 0; //! Get the number of shader variants virtual size_t GetShaderVariantCount() const = 0; //! Get the information for the shader variant at the specified index virtual const AZ::RPI::ShaderVariantListSourceData::VariantInfo& GetShaderVariantInfo(size_t index) const = 0; + + //! Get the number of options + virtual size_t GetShaderOptionCount() const = 0; + + //! Get the descriptor for the shader option at the specified index + virtual const AZ::RPI::ShaderOptionDescriptor& GetShaderOptionDescriptor(size_t index) const = 0; }; using ShaderManagementConsoleDocumentRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp index ba8038319b..aa0c378ff0 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/ShaderManagementConsoleApplication.cpp @@ -84,6 +84,8 @@ namespace ShaderManagementConsole ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole") + ->Event("SetShaderVariantListSourceData", &ShaderManagementConsoleDocumentRequestBus::Events::SetShaderVariantListSourceData) + ->Event("GetShaderVariantListSourceData", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantListSourceData) ->Event("GetShaderOptionCount", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionCount) ->Event("GetShaderOptionDescriptor", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderOptionDescriptor) ->Event("GetShaderVariantCount", &ShaderManagementConsoleDocumentRequestBus::Events::GetShaderVariantCount) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp index f4672d670e..04a8a71191 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Window/ShaderManagementConsoleWindow.cpp @@ -61,8 +61,6 @@ namespace ShaderManagementConsole m_actionNew->setEnabled(false); m_actionSaveAsChild->setVisible(false); m_actionSaveAsChild->setEnabled(false); - m_actionSaveAll->setVisible(false); - m_actionSaveAll->setEnabled(false); OnDocumentOpened(AZ::Uuid::CreateNull()); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentConstants.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentConstants.h index 91c4e2bcf4..32d77c1c3a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentConstants.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentConstants.h @@ -20,5 +20,6 @@ namespace AZ static constexpr float DefaultDiffuseProbeGridViewBias = 0.2f; static constexpr float DefaultDiffuseProbeGridNormalBias = 0.1f; static constexpr DiffuseProbeGridNumRaysPerProbe DefaultDiffuseProbeGridNumRaysPerProbe = DiffuseProbeGridNumRaysPerProbe::NumRaysPerProbe_288; + static constexpr float DefaultVisualizationSphereRadius = 0.5f; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.cpp index 8c8b29a053..9aa58c1082 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.cpp @@ -34,7 +34,7 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(2) // Added NumRaysPerProbe setting + ->Version(3) // Added probe visualization ->Field("ProbeSpacing", &DiffuseProbeGridComponentConfig::m_probeSpacing) ->Field("Extents", &DiffuseProbeGridComponentConfig::m_extents) ->Field("AmbientMultiplier", &DiffuseProbeGridComponentConfig::m_ambientMultiplier) @@ -49,6 +49,9 @@ namespace AZ ->Field("BakedIrradianceTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedIrradianceTextureAsset) ->Field("BakedDistanceTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedDistanceTextureAsset) ->Field("BakedProbeDataTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedProbeDataTextureAsset) + ->Field("VisualizationEnabled", &DiffuseProbeGridComponentConfig::m_visualizationEnabled) + ->Field("VisualizationShowInactiveProbes", &DiffuseProbeGridComponentConfig::m_visualizationShowInactiveProbes) + ->Field("VisualizationSphereRadius", &DiffuseProbeGridComponentConfig::m_visualizationSphereRadius) ; } } @@ -140,6 +143,9 @@ namespace AZ m_featureProcessor->SetViewBias(m_handle, m_configuration.m_viewBias); m_featureProcessor->SetNormalBias(m_handle, m_configuration.m_normalBias); m_featureProcessor->SetNumRaysPerProbe(m_handle, m_configuration.m_numRaysPerProbe); + m_featureProcessor->SetVisualizationEnabled(m_handle, m_configuration.m_visualizationEnabled); + m_featureProcessor->SetVisualizationShowInactiveProbes(m_handle, m_configuration.m_visualizationShowInactiveProbes); + m_featureProcessor->SetVisualizationSphereRadius(m_handle, m_configuration.m_visualizationSphereRadius); // load the baked texture assets, but only if they are all valid if (m_configuration.m_bakedIrradianceTextureAsset.GetId().IsValid() && @@ -356,6 +362,39 @@ namespace AZ m_configuration.m_runtimeMode = runtimeMode; } + void DiffuseProbeGridComponentController::SetVisualizationEnabled(bool visualizationEnabled) + { + if (!m_featureProcessor) + { + return; + } + + m_configuration.m_visualizationEnabled = visualizationEnabled; + m_featureProcessor->SetVisualizationEnabled(m_handle, m_configuration.m_visualizationEnabled); + } + + void DiffuseProbeGridComponentController::SetVisualizationShowInactiveProbes(bool visualizationShowInactiveProbes) + { + if (!m_featureProcessor) + { + return; + } + + m_configuration.m_visualizationShowInactiveProbes = visualizationShowInactiveProbes; + m_featureProcessor->SetVisualizationShowInactiveProbes(m_handle, m_configuration.m_visualizationShowInactiveProbes); + } + + void DiffuseProbeGridComponentController::SetVisualizationSphereRadius(float visualizationSphereRadius) + { + if (!m_featureProcessor) + { + return; + } + + m_configuration.m_visualizationSphereRadius = visualizationSphereRadius; + m_featureProcessor->SetVisualizationSphereRadius(m_handle, m_configuration.m_visualizationSphereRadius); + } + void DiffuseProbeGridComponentController::BakeTextures(DiffuseProbeGridBakeTexturesCallback callback) { if (!m_featureProcessor) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.h index 8f84954b2c..44cab5fc32 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.h @@ -48,6 +48,10 @@ namespace AZ Data::Asset m_bakedDistanceTextureAsset; Data::Asset m_bakedProbeDataTextureAsset; + bool m_visualizationEnabled = false; + bool m_visualizationShowInactiveProbes = false; + float m_visualizationSphereRadius = DefaultVisualizationSphereRadius; + AZ::u64 m_entityId{ EntityId::InvalidEntityId }; }; @@ -102,6 +106,9 @@ namespace AZ void SetNumRaysPerProbe(const DiffuseProbeGridNumRaysPerProbe& numRaysPerProbe); void SetEditorMode(DiffuseProbeGridMode editorMode); void SetRuntimeMode(DiffuseProbeGridMode runtimeMode); + void SetVisualizationEnabled(bool visualizationEnabled); + void SetVisualizationShowInactiveProbes(bool visualizationShowInactiveProbes); + void SetVisualizationSphereRadius(float visualizationSphereRadius); // Bake the diffuse probe grid textures to assets void BakeTextures(DiffuseProbeGridBakeTexturesCallback callback); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp index 6588b18636..dd4ffd25e6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp @@ -43,6 +43,9 @@ namespace AZ ->Field("numRaysPerProbe", &EditorDiffuseProbeGridComponent::m_numRaysPerProbe) ->Field("editorMode", &EditorDiffuseProbeGridComponent::m_editorMode) ->Field("runtimeMode", &EditorDiffuseProbeGridComponent::m_runtimeMode) + ->Field("showVisualization", &EditorDiffuseProbeGridComponent::m_showVisualization) + ->Field("showInactiveProbes", &EditorDiffuseProbeGridComponent::m_showInactiveProbes) + ->Field("visualizationSphereRadius", &EditorDiffuseProbeGridComponent::m_visualizationSphereRadius) ; if (AZ::EditContext* editContext = serializeContext->GetEditContext()) @@ -94,10 +97,22 @@ namespace AZ ->Attribute(Edit::Attributes::Step, 0.1f) ->Attribute(Edit::Attributes::Min, 0.0f) ->Attribute(Edit::Attributes::Max, 1.0f) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorDiffuseProbeGridComponent::m_numRaysPerProbe, "Number of Rays Per Probe", "Number of rays cast by each probe to detect lighting in its surroundings") + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorDiffuseProbeGridComponent::m_numRaysPerProbe, "Number of Rays Per Probe", "Number of rays cast by each probe to detect lighting in its surroundings") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnNumRaysPerProbeChanged) ->Attribute(AZ::Edit::Attributes::EnumValues, &EditorDiffuseProbeGridComponent::GetNumRaysPerProbeEnumList) - ->ClassElement(AZ::Edit::ClassElements::EditorData, "Grid mode") + ->ClassElement(AZ::Edit::ClassElements::Group, "Visualization") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &EditorDiffuseProbeGridComponent::m_showVisualization, "Show Visualization", "Show the probe grid visualization") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnShowVisualizationChanged) + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &EditorDiffuseProbeGridComponent::m_showInactiveProbes, "Show Inactive Probes", "Show inactive probes in the probe grid visualization") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnShowInactiveProbesChanged) + ->DataElement(AZ::Edit::UIHandlers::Slider, &EditorDiffuseProbeGridComponent::m_visualizationSphereRadius, "Visualization Sphere Radius", "Radius of the spheres in the probe grid visualization") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnVisualizationSphereRadiusChanged) + ->Attribute(Edit::Attributes::Decimals, 2) + ->Attribute(Edit::Attributes::Step, 0.25f) + ->Attribute(Edit::Attributes::Min, 0.25f) + ->Attribute(Edit::Attributes::Max, 2.0f) + ->ClassElement(AZ::Edit::ClassElements::Group, "Grid mode") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(Edit::UIHandlers::ComboBox, &EditorDiffuseProbeGridComponent::m_editorMode, "Editor Mode", "Controls whether the editor uses RealTime or Baked diffuse GI. RealTime requires a ray-tracing capable GPU. Auto-Select will fallback to Baked if ray-tracing is not available") ->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnModeChangeValidate) @@ -350,6 +365,24 @@ namespace AZ return AZ::Edit::PropertyRefreshLevels::None; } + AZ::u32 EditorDiffuseProbeGridComponent::OnShowVisualizationChanged() + { + m_controller.SetVisualizationEnabled(m_showVisualization); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::u32 EditorDiffuseProbeGridComponent::OnShowInactiveProbesChanged() + { + m_controller.SetVisualizationShowInactiveProbes(m_showInactiveProbes); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::u32 EditorDiffuseProbeGridComponent::OnVisualizationSphereRadiusChanged() + { + m_controller.SetVisualizationSphereRadius(m_visualizationSphereRadius); + return AZ::Edit::PropertyRefreshLevels::None; + } + AZ::Outcome EditorDiffuseProbeGridComponent::OnModeChangeValidate([[maybe_unused]] void* newValue, [[maybe_unused]] const AZ::Uuid& valueType) { DiffuseProbeGridMode newMode = (*(reinterpret_cast(newValue))); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.h index c7832902a8..2b3d4dfe0e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.h @@ -69,6 +69,9 @@ namespace AZ AZ::u32 OnNumRaysPerProbeChanged(); AZ::u32 OnEditorModeChanged(); AZ::u32 OnRuntimeModeChanged(); + AZ::u32 OnShowVisualizationChanged(); + AZ::u32 OnShowInactiveProbesChanged(); + AZ::u32 OnVisualizationSphereRadiusChanged(); AZ::Outcome OnModeChangeValidate(void* newValue, const AZ::Uuid& valueType); // Button handler @@ -85,6 +88,9 @@ namespace AZ DiffuseProbeGridNumRaysPerProbe m_numRaysPerProbe = DefaultDiffuseProbeGridNumRaysPerProbe; DiffuseProbeGridMode m_editorMode = DiffuseProbeGridMode::RealTime; DiffuseProbeGridMode m_runtimeMode = DiffuseProbeGridMode::RealTime; + bool m_showVisualization = false; + bool m_showInactiveProbes = false; + float m_visualizationSphereRadius = DefaultVisualizationSphereRadius; // flags bool m_editorModeSet = false; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SurfaceData/SurfaceDataMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SurfaceData/SurfaceDataMeshComponent.cpp index 862e3599a3..71e880fdef 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SurfaceData/SurfaceDataMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SurfaceData/SurfaceDataMeshComponent.cpp @@ -95,6 +95,7 @@ namespace SurfaceData m_refresh = false; // Update the cached mesh data and bounds, then register the surface data provider + AssignSurfaceTagWeights(m_configuration.m_tags, 1.0f, m_newPointWeights); UpdateMeshData(); } @@ -115,7 +116,7 @@ namespace SurfaceData // Clear the cached mesh data { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::unique_lock lock(m_cacheMutex); m_meshAssetData = {}; m_meshBounds = AZ::Aabb::CreateNull(); m_meshWorldTM = AZ::Transform::CreateIdentity(); @@ -145,7 +146,7 @@ namespace SurfaceData bool SurfaceDataMeshComponent::DoRayTrace(const AZ::Vector3& inPosition, AZ::Vector3& outPosition, AZ::Vector3& outNormal) const { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::shared_lock lock(m_cacheMutex); // test AABB as first pass to claim the point const AZ::Vector3 testPosition = AZ::Vector3( @@ -181,8 +182,8 @@ namespace SurfaceData point.m_entityId = GetEntityId(); point.m_position = hitPosition; point.m_normal = hitNormal; - AddMaxValueForMasks(point.m_masks, m_configuration.m_tags, 1.0f); - surfacePointList.push_back(point); + point.m_masks = m_newPointWeights; + surfacePointList.push_back(AZStd::move(point)); } } @@ -235,7 +236,7 @@ namespace SurfaceData bool meshValidAfterUpdate = false; { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::unique_lock lock(m_cacheMutex); meshValidBeforeUpdate = (m_meshAssetData.GetAs() != nullptr) && (m_meshBounds.IsValid()); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SurfaceData/SurfaceDataMeshComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SurfaceData/SurfaceDataMeshComponent.h index 92536f9523..758bb1ee99 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SurfaceData/SurfaceDataMeshComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SurfaceData/SurfaceDataMeshComponent.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -96,11 +97,12 @@ namespace SurfaceData // cached data AZStd::atomic_bool m_refresh{ false }; - mutable AZStd::recursive_mutex m_cacheMutex; + mutable AZStd::shared_mutex m_cacheMutex; AZ::Data::Asset m_meshAssetData; AZ::Transform m_meshWorldTM = AZ::Transform::CreateIdentity(); AZ::Transform m_meshWorldTMInverse = AZ::Transform::CreateIdentity(); AZ::Vector3 m_meshNonUniformScale = AZ::Vector3::CreateOne(); AZ::Aabb m_meshBounds = AZ::Aabb::CreateNull(); + SurfaceTagWeightMap m_newPointWeights; }; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp index 23e5d25824..7f909e0e5f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp @@ -1634,19 +1634,19 @@ namespace MCommon AZ::Vector3 vertices[7]; /* - // 4 - // / \ - // / \ - // / \ - // / \ - // / \ - // 5-----6 2-----3 - // | | - // | | - // | | - // | | - // | | - // 0---------1 + 4 + / \ + / \ + / \ + / \ + / \ + 5-----6 2-----3 + | | + | | + | | + | | + | | + 0---------1 */ // construct the arrow vertices vertices[0] = center + AZ::Vector3(-right * trailWidthHalf - forward * trailLengh) * scale; @@ -1744,19 +1744,19 @@ namespace MCommon AZ::Vector3 oldLeft, oldRight; /* - // 4 - // / \ - // / \ - // / \ - // / \ - // / \ - // 5-----6 2-----3 - // | | - // | | - // | | - // | | - // | | - // 0-------1 + 4 + / \ + / \ + / \ + / \ + / \ + 5-----6 2-----3 + | | + | | + | | + | | + | | + 0-------1 */ // construct the arrow vertices vertices[0] = center + (-right * trailWidthHalf - forward * trailLength) * scale; diff --git a/Gems/EMotionFX/Code/Tests/AutoSkeletonLODTests.cpp b/Gems/EMotionFX/Code/Tests/AutoSkeletonLODTests.cpp index 726aa664f0..d445bc62e0 100644 --- a/Gems/EMotionFX/Code/Tests/AutoSkeletonLODTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AutoSkeletonLODTests.cpp @@ -31,23 +31,25 @@ namespace EMotionFX class AutoSkeletonLODActor : public SimpleJointChainActor { - // This creates an Actor with following hierarchy. - // The numbers are the joint indices. - // - // 5 - // / - // / - // 0-----1-----2-----3-----4 - // \ - // \ - // 6 - // - // 7 (a node with skinned mesh) - // - // The mesh is on node 7, which is also a root node, just like joint number 0. - // We (fake) skin the first six joints to the mesh of node 7. - // Our test will actually skin to only a selection of these first seven joints. - // We then test which joints get disabled and which not. + /* + This creates an Actor with following hierarchy. + The numbers are the joint indices. + + 5 + / + / + 0-----1-----2-----3-----4 + \ + \ + 6 + + 7 (a node with skinned mesh) + + The mesh is on node 7, which is also a root node, just like joint number 0. + We (fake) skin the first six joints to the mesh of node 7. + Our test will actually skin to only a selection of these first seven joints. + We then test which joints get disabled and which not. + */ public: explicit AutoSkeletonLODActor(AZ::u32 numSubMeshJoints) : SimpleJointChainActor(5) diff --git a/Gems/EMotionFX/Code/Tests/BlendSpaceTests.cpp b/Gems/EMotionFX/Code/Tests/BlendSpaceTests.cpp index b2f6f49d8f..ce8387f150 100644 --- a/Gems/EMotionFX/Code/Tests/BlendSpaceTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendSpaceTests.cpp @@ -254,19 +254,21 @@ namespace EMotionFX EXPECT_EQ(motions.size(), 4); EXPECT_EQ(uniqueData->m_triangles.size(), 2); - // run 2 * - // |\ - // | \ - // | \ - // | \ - // | \ - // forward 1 * * 3 Strafe - // | / - // | / - // | / - // | / - // |/ - // idle 0 * + /* + run 2 * + |\ + | \ + | \ + | \ + | \ + forward 1 * * 3 Strafe + | / + | / + | / + | / + |/ + idle 0 * + */ EXPECT_EQ(uniqueData->m_triangles[0], BlendSpace2DNode::Triangle(1, 0, 3)); EXPECT_EQ(uniqueData->m_triangles[1], BlendSpace2DNode::Triangle(2, 1, 3)); } diff --git a/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp b/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp index 09a4e46b84..cc3e3c344a 100644 --- a/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp +++ b/Gems/EMotionFX/Code/Tests/NonUniformMotionDataTests.cpp @@ -285,12 +285,14 @@ namespace EMotionFX numRemoved = motionData.ReduceSamples(reduceSettings); EXPECT_EQ(motionData.GetNumFloatSamples(0), 2); EXPECT_EQ(numRemoved, 9); - - // Set the sample in the middle to 1.0 and the rest to 0. - // - // /\ - // / \ - // ---------------------/ \--------------------- + + /* + Set the sample in the middle to 1.0 and the rest to 0. + + /\ + / \ + ---------------------/ \--------------------- + */ motionData.AllocateFloatSamples(0, 11); for (size_t i = 0; i < motionData.GetNumFloatSamples(0); ++i) { @@ -301,12 +303,14 @@ namespace EMotionFX numRemoved = motionData.ReduceSamples(reduceSettings); EXPECT_EQ(motionData.GetNumFloatSamples(0), 5); EXPECT_EQ(numRemoved, 6); - - // Make a bump of 2 frames. - // - // /------\ - // / \ - // ---------------------/ \--------------- + + /* + Make a bump of 2 frames. + + /------\ + / \ + ---------------------/ \--------------- + */ motionData.AllocateFloatSamples(0, 11); for (size_t i = 0; i < motionData.GetNumFloatSamples(0); ++i) { @@ -398,11 +402,13 @@ namespace EMotionFX EXPECT_EQ(motionData.GetNumJointRotationSamples(0), 0); EXPECT_EQ(numRemoved, 11); - // Set the sample in the middle to 1.0 and the rest to 0. - // - // /\ - // / \ - // ---------------------/ \--------------------- + /* + Set the sample in the middle to 1.0 and the rest to 0. + + /\ + / \ + ---------------------/ \--------------------- + */ motionData.AllocateJointRotationSamples(0, 11); for (size_t i = 0; i < motionData.GetNumJointRotationSamples(0); ++i) { @@ -413,12 +419,14 @@ namespace EMotionFX numRemoved = motionData.ReduceSamples(reduceSettings); EXPECT_EQ(motionData.GetNumJointRotationSamples(0), 5); EXPECT_EQ(numRemoved, 6); - - // Make a bump of 2 frames. - // - // /------\ - // / \ - // ---------------------/ \--------------- + + /* + Make a bump of 2 frames. + + /------\ + / \ + ---------------------/ \--------------- + */ motionData.AllocateJointRotationSamples(0, 11); for (size_t i = 0; i < motionData.GetNumJointRotationSamples(0); ++i) { @@ -509,11 +517,13 @@ namespace EMotionFX EXPECT_EQ(motionData.GetNumJointPositionSamples(0), 0); EXPECT_EQ(numRemoved, 11); - // Set the sample in the middle to 1.0 and the rest to 0. - // - // /\ - // / \ - // ---------------------/ \--------------------- + /* + Set the sample in the middle to 1.0 and the rest to 0. + + /\ + / \ + ---------------------/ \--------------------- + */ motionData.AllocateJointPositionSamples(0, 11); for (size_t i = 0; i < motionData.GetNumJointPositionSamples(0); ++i) { @@ -525,11 +535,13 @@ namespace EMotionFX EXPECT_EQ(motionData.GetNumJointPositionSamples(0), 5); EXPECT_EQ(numRemoved, 6); - // Make a bump of 2 frames. - // - // /------\ - // / \ - // ---------------------/ \--------------- + /* + Make a bump of 2 frames. + + /------\ + / \ + ---------------------/ \--------------- + */ motionData.AllocateJointPositionSamples(0, 11); for (size_t i = 0; i < motionData.GetNumJointPositionSamples(0); ++i) { diff --git a/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStateMainMenu.inl b/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStateMainMenu.inl index 98147756f4..9f61c32175 100644 --- a/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStateMainMenu.inl +++ b/Gems/GameStateSamples/Code/Include/GameStateSamples/GameStateMainMenu.inl @@ -277,7 +277,7 @@ namespace GameStateSamples bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (usePrefabSystemForLevels) { diff --git a/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramGroup.h b/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramGroup.h index b3c7e0e7d8..e3c923d9d9 100644 --- a/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramGroup.h +++ b/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramGroup.h @@ -36,6 +36,8 @@ namespace ImGui::LYImGuiUtils void SetHistogramBinCount(int count) { m_histogramBinCount = count; } + ImGui::LYImGuiUtils::HistogramContainer* FindContainerByName(const char* name); + //! Needs to be public for l-value access for ImGui::MenuItem() bool m_show = true; diff --git a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp index ecc97682de..e92d93798d 100644 --- a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp +++ b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp @@ -267,7 +267,7 @@ namespace ImGui bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (usePrefabSystemForLevels) { diff --git a/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramGroup.cpp b/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramGroup.cpp index 62e8eb7b33..2534475712 100644 --- a/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramGroup.cpp +++ b/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramGroup.cpp @@ -77,6 +77,17 @@ namespace ImGui::LYImGuiUtils } } } + + ImGui::LYImGuiUtils::HistogramContainer* HistogramGroup::FindContainerByName(const char* name) + { + const auto iterator = m_histogramIndexByName.find(name); + if (iterator != m_histogramIndexByName.end()) + { + return &m_histograms[iterator->second]; + } + + return nullptr; + } } // namespace ImGui::LYImGuiUtils #endif // IMGUI_ENABLED diff --git a/Gems/LmbrCentral/Code/Source/Builders/LevelBuilder/LevelBuilderComponent.cpp b/Gems/LmbrCentral/Code/Source/Builders/LevelBuilder/LevelBuilderComponent.cpp index 7e6fc54830..880a994f5a 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/LevelBuilder/LevelBuilderComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/LevelBuilder/LevelBuilderComponent.cpp @@ -17,7 +17,7 @@ namespace LevelBuilder { bool usePrefabSystemForLevels = false; AzFramework::ApplicationRequests::Bus::BroadcastResult( - usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled); + usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); // No need to build level.pak files when using the prefab system. if (usePrefabSystemForLevels) diff --git a/Gems/LmbrCentral/Code/Source/Shape/TubeShape.cpp b/Gems/LmbrCentral/Code/Source/Shape/TubeShape.cpp index 68198c491a..6dc6bf3f18 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/TubeShape.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/TubeShape.cpp @@ -328,18 +328,19 @@ namespace LmbrCentral sides, capSegments, vertices); } } - - /// Generates vertices and indices for a tube shape - /// Split into two stages: - /// - Generate vertex positions - /// - Generate indices (faces) - /// Heres a rough diagram of how it is built: - /// ____________ - /// /_|__|__|__|_\ - /// \_|__|__|__|_/ - /// - A single vertex at each end of the tube - /// - Angled end cap segments - /// - Middle segments + /* + Generates vertices and indices for a tube shape + Split into two stages: + - Generate vertex positions + - Generate indices (faces) + Heres a rough diagram of how it is built: + ____________ + /_|__|__|__|_\ + \_|__|__|__|_/ + - A single vertex at each end of the tube + - Angled end cap segments + - Middle segments + */ void GenerateSolidTubeMesh( const AZ::SplinePtr& spline, const SplineAttribute& variableRadius, const float radius, const AZ::u32 capSegments, const AZ::u32 sides, diff --git a/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/CameraController_AutomaticDemo.scriptcanvas b/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/CameraController_AutomaticDemo.scriptcanvas new file mode 100644 index 0000000000..8569d7686b --- /dev/null +++ b/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/CameraController_AutomaticDemo.scriptcanvas @@ -0,0 +1,4255 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "ScriptCanvasData", + "ClassData": { + "m_scriptCanvas": { + "Id": { + "id": 1874297699023155003 + }, + "Name": "CameraController", + "Components": { + "Component_[18372998151874304809]": { + "$type": "EditorGraph", + "Id": 18372998151874304809, + "m_graphData": { + "m_nodes": [ + { + "Id": { + "id": 58688970296996 + }, + "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{Transform(double )}* RotationXDegreesTraits >)", + "Components": { + "Component_[11367256627712525407]": { + "$type": "(NodeFunctionGenericMultiReturn)<{Transform(double )}* RotationXDegreesTraits >", + "Id": 11367256627712525407, + "Slots": [ + { + "id": { + "m_id": "{DC131C25-5C2C-482D-96A1-88542026DF75}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{A4D7609D-9560-43D5-9FDE-36242CE35B48}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{22458849-F990-4D8A-94B2-03D8F3878E19}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number: Degrees", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{24EDA641-DBF3-41A8-8D47-60A3D83E3F23}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Transform", + "DisplayDataType": { + "m_type": 7 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": -15.0, + "label": "Number: Degrees" + } + ], + "Initialized": true + } + } + }, + { + "Id": { + "id": 58624545787556 + }, + "Name": "SC-Node(OperatorMul)", + "Components": { + "Component_[11451129070958096728]": { + "$type": "OperatorMul", + "Id": 11451129070958096728, + "Slots": [ + { + "id": { + "m_id": "{3180019C-C78A-456E-B3E2-F1601B4A629A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{A4F4074B-5E3B-4A5B-A7F7-AC2E4AAA0939}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{B2F820AB-9377-4A47-AD2C-03D76C6E4024}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Transform", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 7 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{5509933D-93A5-483E-B7B5-FDD637C997DA}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Transform", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 7 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{96271AD4-A2BB-4597-B78F-8053F0200C3D}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Result", + "toolTip": "The result of the specified operation", + "DisplayDataType": { + "m_type": 7 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 7 + }, + "isNullPointer": false, + "$type": "Transform", + "value": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ], + "Rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "Scale": 1.0 + }, + "label": "Transform" + }, + { + "scriptCanvasType": { + "m_type": 7 + }, + "isNullPointer": false, + "$type": "Transform", + "value": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ], + "Rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "Scale": 1.0 + }, + "label": "Transform" + } + ] + } + } + }, + { + "Id": { + "id": 58667495460516 + }, + "Name": "EBusEventHandler", + "Components": { + "Component_[12391893846605096594]": { + "$type": "EBusEventHandler", + "Id": 12391893846605096594, + "Slots": [ + { + "id": { + "m_id": "{47B8793A-68B3-4DF7-B485-98CF8625EE94}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Connect", + "toolTip": "Connect this event handler to the specified entity.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{75D0B671-F876-4383-B3AE-414B37AD0638}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Disconnect", + "toolTip": "Disconnect this event handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{03259091-B08D-4118-9AA3-053FD63AD6F7}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnConnected", + "toolTip": "Signaled when a connection has taken place.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{7C2E17C2-C3A1-4CB1-9AE6-521C4DD0D780}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnDisconnected", + "toolTip": "Signaled when this event handler is disconnected.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{9EB40EA9-0799-4FFF-9816-D6BEE9302D56}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnFailure", + "toolTip": "Signaled when it is not possible to connect this handler.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{02148868-388F-44F0-9E3A-C31601701F3B}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{1D2C5717-17A6-401F-BBF6-08EF84870CD3}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ScriptTimePoint", + "DisplayDataType": { + "m_type": 4, + "m_azType": "{4C0F6AD4-0D4F-4354-AD4A-0C01E948245C}" + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{8965578E-A29D-4468-B12B-9D4E4F814641}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ExecutionSlot:OnTick", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{53E6F39B-30C2-4828-83A4-A286E22DD18D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Number", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{909B60CC-693B-4DC9-9BC2-65B1D9373B5A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ExecutionSlot:GetTickOrder", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Result: Number" + } + ], + "m_eventMap": [ + { + "Key": { + "Value": 1502188240 + }, + "Value": { + "m_eventName": "OnTick", + "m_eventId": { + "Value": 1502188240 + }, + "m_eventSlotId": { + "m_id": "{8965578E-A29D-4468-B12B-9D4E4F814641}" + }, + "m_parameterSlotIds": [ + { + "m_id": "{02148868-388F-44F0-9E3A-C31601701F3B}" + }, + { + "m_id": "{1D2C5717-17A6-401F-BBF6-08EF84870CD3}" + } + ], + "m_numExpectedArguments": 2 + } + }, + { + "Key": { + "Value": 1890826333 + }, + "Value": { + "m_eventName": "GetTickOrder", + "m_eventId": { + "Value": 1890826333 + }, + "m_eventSlotId": { + "m_id": "{909B60CC-693B-4DC9-9BC2-65B1D9373B5A}" + }, + "m_resultSlotId": { + "m_id": "{53E6F39B-30C2-4828-83A4-A286E22DD18D}" + } + } + } + ], + "m_ebusName": "TickBus", + "m_busId": { + "Value": 1209186864 + } + } + } + }, + { + "Id": { + "id": 58633135722148 + }, + "Name": "SC-Node(OperatorMul)", + "Components": { + "Component_[13427352953117170385]": { + "$type": "OperatorMul", + "Id": 13427352953117170385, + "Slots": [ + { + "id": { + "m_id": "{B6D38C30-7BB4-4549-AFFA-C5A52AE9796E}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{86D20026-0D06-4DFB-B3CD-9BE5038B8121}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{F9E6233F-EAFB-43F5-A10D-96A3A41763A7}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Number", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{9D3D613C-ABE4-4028-A1CC-22E6E036376C}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Number", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{C0EA31C9-71C6-4CCF-A31B-33E7385C78D0}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Result", + "toolTip": "The result of the specified operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 1.0, + "label": "Number" + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": -90.0, + "label": "Number" + } + ] + } + } + }, + { + "Id": { + "id": 214400860662419 + }, + "Name": "SC Node(GetVariable)", + "Components": { + "Component_[1359072869693534631]": { + "$type": "GetVariableNode", + "Id": 1359072869693534631, + "Slots": [ + { + "id": { + "m_id": "{7500DE86-7349-4213-B3D6-F2872EDF15A6}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled sends the property referenced by this node to a Data Output slot", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8C8D3DD7-F821-42F4-AF51-5D976133DAE4}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after the referenced property has been pushed to the Data Output slot", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{5E4734A2-3CAF-4E29-AC72-5689FF1FD619}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "m_variableId": { + "m_id": "{0620A309-A152-4CF3-BF76-284115B30780}" + }, + "m_variableDataOutSlotId": { + "m_id": "{5E4734A2-3CAF-4E29-AC72-5689FF1FD619}" + } + } + } + }, + { + "Id": { + "id": 58577301147300 + }, + "Name": "SC-Node(OperatorMul)", + "Components": { + "Component_[14055904483179664364]": { + "$type": "OperatorMul", + "Id": 14055904483179664364, + "Slots": [ + { + "id": { + "m_id": "{F5BE2CBC-3CA3-44BD-B7D4-71D9CAC023B3}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{4CD5D25E-73DA-4936-89E9-8F0A7946DED1}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{2F0B4FC7-0B48-42A9-8073-8493E9F1D2E5}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Number", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{67B729E8-73F9-4B97-A67C-C986E874BD01}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Number", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{785A9BC8-8F65-4DFE-8809-7C8E937A8D8B}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Result", + "toolTip": "The result of the specified operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 1.0, + "label": "Number" + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 1.0, + "label": "Number" + } + ] + } + } + }, + { + "Id": { + "id": 58581596114596 + }, + "Name": "SC-Node(OperatorMul)", + "Components": { + "Component_[14210959117790557692]": { + "$type": "OperatorMul", + "Id": 14210959117790557692, + "Slots": [ + { + "id": { + "m_id": "{374AA17F-7CC0-4808-8269-6CC4F64579C3}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{1E111259-19D2-4180-81A1-F648F79B004D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{E7D6A002-7522-4915-BCCB-89A29E3D5582}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Transform", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 7 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{0ABC384E-FBE6-40F8-B5C3-7652B814102C}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Transform", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 7 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{7DA1EC3E-277C-4DDA-94FD-EF2EC66CD272}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Result", + "toolTip": "The result of the specified operation", + "DisplayDataType": { + "m_type": 7 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 7 + }, + "isNullPointer": false, + "$type": "Transform", + "value": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ], + "Rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "Scale": 1.0 + }, + "label": "Transform" + }, + { + "scriptCanvasType": { + "m_type": 7 + }, + "isNullPointer": false, + "$type": "Transform", + "value": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ], + "Rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "Scale": 1.0 + }, + "label": "Transform" + } + ] + } + } + }, + { + "Id": { + "id": 213241219492499 + }, + "Name": "SC-Node(OperatorAdd)", + "Components": { + "Component_[14948826965328970882]": { + "$type": "OperatorAdd", + "Id": 14948826965328970882, + "Slots": [ + { + "id": { + "m_id": "{56805D2B-0C98-4145-80FB-AA1DCB16CF1A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{008FCEC7-3E86-4249-A736-F158EFDB0EFA}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{DB849F77-66D0-4D64-A45F-122F93E1E80C}" + }, + "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": "Number", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{CA8ABF3F-BF80-4A8B-A2B2-A1D2C16278C1}" + }, + "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": "Number", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{53895246-F759-4328-AABB-D26E49E5208D}" + }, + "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": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Number" + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Number" + } + ] + } + } + }, + { + "Id": { + "id": 58628840754852 + }, + "Name": "SC-Node(SetWorldTM)", + "Components": { + "Component_[15733030521963116718]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 15733030521963116718, + "Slots": [ + { + "id": { + "m_id": "{785CBBEE-E704-4049-A180-8E99E3E1E1F2}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{A7826FF9-C3B2-4E28-815D-9B07A6EE0949}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Transform: 1", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{6BB59597-64B4-458F-9C96-B3E0DA73279A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{44A7845D-724A-4BB6-99F1-12B2E7979D93}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "Transform" + }, + { + "scriptCanvasType": { + "m_type": 7 + }, + "isNullPointer": false, + "$type": "Transform", + "value": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ], + "Rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "Scale": 1.0 + }, + "label": "Transform: 1" + } + ], + "methodType": 0, + "methodName": "SetWorldTM", + "className": "TransformBus", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{785CBBEE-E704-4049-A180-8E99E3E1E1F2}" + }, + { + "m_id": "{A7826FF9-C3B2-4E28-815D-9B07A6EE0949}" + } + ], + "prettyClassName": "TransformBus" + } + } + }, + { + "Id": { + "id": 239870016727699 + }, + "Name": "SC-Node(OperatorMul)", + "Components": { + "Component_[3092852928531574536]": { + "$type": "OperatorMul", + "Id": 3092852928531574536, + "Slots": [ + { + "id": { + "m_id": "{FEFF67A1-C89B-447E-80D4-CD94CB0C8AD7}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{7E5D8673-F03A-4134-87DE-88AD13A74C29}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8A243C9C-0D69-4753-B28B-A8D2FAC5D508}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Number", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{3F3F3DD6-124E-48A8-8373-6666900D8177}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Number", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{DFD1DE7E-B470-43F6-A6CF-E9E572D0C075}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Result", + "toolTip": "The result of the specified operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 1.0, + "label": "Number" + }, + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 10.0, + "label": "Number" + } + ] + } + } + }, + { + "Id": { + "id": 58654610558628 + }, + "Name": "SC Node(SetVariable)", + "Components": { + "Component_[5081311661452231726]": { + "$type": "SetVariableNode", + "Id": 5081311661452231726, + "Slots": [ + { + "id": { + "m_id": "{F32F9B01-14B4-4DC3-AE0E-9E233DE5E941}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled sends the variable referenced by this node to a Data Output slot", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{47175A2C-5EE4-4C48-8CC1-8F2C84D36FE5}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after the referenced variable has been pushed to the Data Output slot", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{B22A0453-9715-46C7-A766-9536020AB59F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{1B58C71B-3AB9-4D90-A8D5-164A20B083DA}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Number" + } + ], + "m_variableId": { + "m_id": "{0620A309-A152-4CF3-BF76-284115B30780}" + }, + "m_variableDataInSlotId": { + "m_id": "{B22A0453-9715-46C7-A766-9536020AB59F}" + }, + "m_variableDataOutSlotId": { + "m_id": "{1B58C71B-3AB9-4D90-A8D5-164A20B083DA}" + } + } + } + }, + { + "Id": { + "id": 58671790427812 + }, + "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{Transform(Vector3 )}* FromTranslationTraits >)", + "Components": { + "Component_[5185507574364590308]": { + "$type": "(NodeFunctionGenericMultiReturn)<{Transform(Vector3 )}* FromTranslationTraits >", + "Id": 5185507574364590308, + "Slots": [ + { + "id": { + "m_id": "{991F134E-88CC-423B-93C9-FFE9A9406739}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{FACA9011-E0FC-413E-B8AE-136D7DD2BD14}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{210001FC-BDC8-4E41-9990-6F42A0368833}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Vector3: Translation", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{49236CAF-226C-4F65-9C1D-92436010232D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Transform", + "DisplayDataType": { + "m_type": 7 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + -0.6499999761581421, + -4.699999809265137, + 0.699999988079071 + ], + "label": "Vector3: Translation" + } + ], + "Initialized": true + } + } + }, + { + "Id": { + "id": 58590186049188 + }, + "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{Transform(double )}* RotationZDegreesTraits >)", + "Components": { + "Component_[5714854897173958925]": { + "$type": "(NodeFunctionGenericMultiReturn)<{Transform(double )}* RotationZDegreesTraits >", + "Id": 5714854897173958925, + "Slots": [ + { + "id": { + "m_id": "{4B28D8A2-7F6C-4EB1-A7D5-EA68FB783B52}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{A6D81A02-E3CB-44FC-80E6-61D8AB732ACC}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{694A218A-8047-4981-BF62-726AF9BCB3C6}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number: Degrees", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{065D3BDE-D0B8-4F84-82EB-8B48779A80CA}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Transform", + "DisplayDataType": { + "m_type": 7 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Number: Degrees" + } + ], + "Initialized": true + } + } + }, + { + "Id": { + "id": 58607365918372 + }, + "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{Transform(Vector3 )}* FromTranslationTraits >)", + "Components": { + "Component_[6151602155863937217]": { + "$type": "(NodeFunctionGenericMultiReturn)<{Transform(Vector3 )}* FromTranslationTraits >", + "Id": 6151602155863937217, + "Slots": [ + { + "id": { + "m_id": "{AC5F0607-97E7-4EF4-A4A1-7CE21E42A484}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{5F03F883-BFAC-424C-BB04-334B68B845FC}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{E00A1E12-1D89-42EC-939B-284B1D6B4EAE}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Vector3: Translation", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{F84430FF-A436-459B-B849-6456573B85E7}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Transform", + "DisplayDataType": { + "m_type": 7 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Vector3: Translation" + } + ], + "Initialized": true + } + } + }, + { + "Id": { + "id": 58663200493220 + }, + "Name": "SC-Node(GetWorldTranslation)", + "Components": { + "Component_[7931832476506096485]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 7931832476506096485, + "Slots": [ + { + "id": { + "m_id": "{D2B68C1A-14D8-45DE-8AED-DDB02B925B24}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{94D7F295-34CD-42AC-AD7B-65B8407F2CF4}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{0A0BFDE6-2029-414E-8A8F-41DF60F9C348}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{2FAA43A0-BC0B-428B-B0BF-AFDDFDEA474C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Vector3", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 653853330958 + }, + "label": "EntityID: 0" + } + ], + "methodType": 0, + "methodName": "GetWorldTranslation", + "className": "TransformBus", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{D2B68C1A-14D8-45DE-8AED-DDB02B925B24}" + } + ], + "prettyClassName": "TransformBus" + } + } + }, + { + "Id": { + "id": 58594481016484 + }, + "Name": "SC Node(GetVariable)", + "Components": { + "Component_[8136131668650391163]": { + "$type": "GetVariableNode", + "Id": 8136131668650391163, + "Slots": [ + { + "id": { + "m_id": "{09256706-E7A2-47C3-ACE0-3BE7D80E34FD}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled sends the property referenced by this node to a Data Output slot", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{1ACC7F53-E81A-4721-9AC8-5C1A33C8BE96}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after the referenced property has been pushed to the Data Output slot", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{4972DD3B-D554-47B7-816B-CBCF67697ABA}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "m_variableId": { + "m_id": "{0620A309-A152-4CF3-BF76-284115B30780}" + }, + "m_variableDataOutSlotId": { + "m_id": "{4972DD3B-D554-47B7-816B-CBCF67697ABA}" + } + } + } + }, + { + "Id": { + "id": 58658905525924 + }, + "Name": "SC-Node(OperatorMul)", + "Components": { + "Component_[8240456843039210842]": { + "$type": "OperatorMul", + "Id": 8240456843039210842, + "Slots": [ + { + "id": { + "m_id": "{472B1FB5-766E-4F47-9955-B655857BE135}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{1ACBC12A-7FB1-4ADF-92BC-56B0DCE8CFAD}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{73F9A12E-8255-4C5E-89A8-B2F837C29AF6}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Transform", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 7 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{89EA50A0-3CD4-46D6-8404-534EDB8C94EE}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Transform", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 7 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{A56467EC-4D3B-4CBE-847D-E5367BEFF26C}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "OperatorType": "Multiply", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 7 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Result", + "toolTip": "The result of the specified operation", + "DisplayDataType": { + "m_type": 7 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 7 + }, + "isNullPointer": false, + "$type": "Transform", + "value": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ], + "Rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "Scale": 1.0 + }, + "label": "Transform" + }, + { + "scriptCanvasType": { + "m_type": 7 + }, + "isNullPointer": false, + "$type": "Transform", + "value": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ], + "Rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "Scale": 1.0 + }, + "label": "Transform" + } + ] + } + } + } + ], + "m_connections": [ + { + "Id": { + "id": 58706150166180 + }, + "Name": "srcEndpoint=(Get Variable: Out), destEndpoint=(RotationZDegrees: In)", + "Components": { + "Component_[553961487450147653]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 553961487450147653, + "sourceEndpoint": { + "nodeId": { + "id": 58594481016484 + }, + "slotId": { + "m_id": "{1ACC7F53-E81A-4721-9AC8-5C1A33C8BE96}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58590186049188 + }, + "slotId": { + "m_id": "{4B28D8A2-7F6C-4EB1-A7D5-EA68FB783B52}" + } + } + } + } + }, + { + "Id": { + "id": 58710445133476 + }, + "Name": "srcEndpoint=(Get Variable: Number), destEndpoint=(RotationZDegrees: Number: Degrees)", + "Components": { + "Component_[8946072267986857913]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 8946072267986857913, + "sourceEndpoint": { + "nodeId": { + "id": 58594481016484 + }, + "slotId": { + "m_id": "{4972DD3B-D554-47B7-816B-CBCF67697ABA}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58590186049188 + }, + "slotId": { + "m_id": "{694A218A-8047-4981-BF62-726AF9BCB3C6}" + } + } + } + } + }, + { + "Id": { + "id": 58714740100772 + }, + "Name": "srcEndpoint=(Multiply (*): Out), destEndpoint=(SetWorldTM: In)", + "Components": { + "Component_[3188243497734984899]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 3188243497734984899, + "sourceEndpoint": { + "nodeId": { + "id": 58581596114596 + }, + "slotId": { + "m_id": "{1E111259-19D2-4180-81A1-F648F79B004D}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58628840754852 + }, + "slotId": { + "m_id": "{6BB59597-64B4-458F-9C96-B3E0DA73279A}" + } + } + } + } + }, + { + "Id": { + "id": 58719035068068 + }, + "Name": "srcEndpoint=(Multiply (*): Result), destEndpoint=(SetWorldTM: Transform: 1)", + "Components": { + "Component_[16154630012362343924]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 16154630012362343924, + "sourceEndpoint": { + "nodeId": { + "id": 58581596114596 + }, + "slotId": { + "m_id": "{7DA1EC3E-277C-4DDA-94FD-EF2EC66CD272}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58628840754852 + }, + "slotId": { + "m_id": "{A7826FF9-C3B2-4E28-815D-9B07A6EE0949}" + } + } + } + } + }, + { + "Id": { + "id": 58723330035364 + }, + "Name": "srcEndpoint=(GetWorldTranslation: Result: Vector3), destEndpoint=(FromTranslation: Vector3: Translation)", + "Components": { + "Component_[12394822413729075366]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 12394822413729075366, + "sourceEndpoint": { + "nodeId": { + "id": 58663200493220 + }, + "slotId": { + "m_id": "{2FAA43A0-BC0B-428B-B0BF-AFDDFDEA474C}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58607365918372 + }, + "slotId": { + "m_id": "{E00A1E12-1D89-42EC-939B-284B1D6B4EAE}" + } + } + } + } + }, + { + "Id": { + "id": 58727625002660 + }, + "Name": "srcEndpoint=(GetWorldTranslation: Out), destEndpoint=(FromTranslation: In)", + "Components": { + "Component_[4243880791484280857]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 4243880791484280857, + "sourceEndpoint": { + "nodeId": { + "id": 58663200493220 + }, + "slotId": { + "m_id": "{0A0BFDE6-2029-414E-8A8F-41DF60F9C348}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58607365918372 + }, + "slotId": { + "m_id": "{AC5F0607-97E7-4EF4-A4A1-7CE21E42A484}" + } + } + } + } + }, + { + "Id": { + "id": 58731919969956 + }, + "Name": "srcEndpoint=(FromTranslation: Out), destEndpoint=(GetWorldTranslation: In)", + "Components": { + "Component_[1519056228570549771]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 1519056228570549771, + "sourceEndpoint": { + "nodeId": { + "id": 58671790427812 + }, + "slotId": { + "m_id": "{FACA9011-E0FC-413E-B8AE-136D7DD2BD14}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58663200493220 + }, + "slotId": { + "m_id": "{94D7F295-34CD-42AC-AD7B-65B8407F2CF4}" + } + } + } + } + }, + { + "Id": { + "id": 58736214937252 + }, + "Name": "srcEndpoint=(Multiply (*): Out), destEndpoint=(Multiply (*): In)", + "Components": { + "Component_[6232453632040220382]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 6232453632040220382, + "sourceEndpoint": { + "nodeId": { + "id": 58624545787556 + }, + "slotId": { + "m_id": "{A4F4074B-5E3B-4A5B-A7F7-AC2E4AAA0939}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58581596114596 + }, + "slotId": { + "m_id": "{374AA17F-7CC0-4808-8269-6CC4F64579C3}" + } + } + } + } + }, + { + "Id": { + "id": 58740509904548 + }, + "Name": "srcEndpoint=(Multiply (*): Result), destEndpoint=(Multiply (*): Transform)", + "Components": { + "Component_[7007808555566524915]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 7007808555566524915, + "sourceEndpoint": { + "nodeId": { + "id": 58624545787556 + }, + "slotId": { + "m_id": "{96271AD4-A2BB-4597-B78F-8053F0200C3D}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58581596114596 + }, + "slotId": { + "m_id": "{E7D6A002-7522-4915-BCCB-89A29E3D5582}" + } + } + } + } + }, + { + "Id": { + "id": 58753394806436 + }, + "Name": "srcEndpoint=(TickBus Handler: Number), destEndpoint=(Multiply (*): Value)", + "Components": { + "Component_[1087668963814879388]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 1087668963814879388, + "sourceEndpoint": { + "nodeId": { + "id": 58667495460516 + }, + "slotId": { + "m_id": "{02148868-388F-44F0-9E3A-C31601701F3B}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58577301147300 + }, + "slotId": { + "m_id": "{67B729E8-73F9-4B97-A67C-C986E874BD01}" + } + } + } + } + }, + { + "Id": { + "id": 58783459577508 + }, + "Name": "srcEndpoint=(Set Variable: Out), destEndpoint=(Get Variable: In)", + "Components": { + "Component_[5808096905671825435]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 5808096905671825435, + "sourceEndpoint": { + "nodeId": { + "id": 58654610558628 + }, + "slotId": { + "m_id": "{47175A2C-5EE4-4C48-8CC1-8F2C84D36FE5}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58594481016484 + }, + "slotId": { + "m_id": "{09256706-E7A2-47C3-ACE0-3BE7D80E34FD}" + } + } + } + } + }, + { + "Id": { + "id": 58787754544804 + }, + "Name": "srcEndpoint=(Multiply (*): Result), destEndpoint=(Multiply (*): Value)", + "Components": { + "Component_[11775794502882233004]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 11775794502882233004, + "sourceEndpoint": { + "nodeId": { + "id": 58577301147300 + }, + "slotId": { + "m_id": "{785A9BC8-8F65-4DFE-8809-7C8E937A8D8B}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58633135722148 + }, + "slotId": { + "m_id": "{F9E6233F-EAFB-43F5-A10D-96A3A41763A7}" + } + } + } + } + }, + { + "Id": { + "id": 58792049512100 + }, + "Name": "srcEndpoint=(Multiply (*): Out), destEndpoint=(Multiply (*): In)", + "Components": { + "Component_[80299809090156725]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 80299809090156725, + "sourceEndpoint": { + "nodeId": { + "id": 58577301147300 + }, + "slotId": { + "m_id": "{4CD5D25E-73DA-4936-89E9-8F0A7946DED1}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58633135722148 + }, + "slotId": { + "m_id": "{B6D38C30-7BB4-4549-AFFA-C5A52AE9796E}" + } + } + } + } + }, + { + "Id": { + "id": 58800639446692 + }, + "Name": "srcEndpoint=(FromTranslation: Result: Transform), destEndpoint=(Multiply (*): Transform)", + "Components": { + "Component_[7632901123910891973]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 7632901123910891973, + "sourceEndpoint": { + "nodeId": { + "id": 58671790427812 + }, + "slotId": { + "m_id": "{49236CAF-226C-4F65-9C1D-92436010232D}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58581596114596 + }, + "slotId": { + "m_id": "{0ABC384E-FBE6-40F8-B5C3-7652B814102C}" + } + } + } + } + }, + { + "Id": { + "id": 58804934413988 + }, + "Name": "srcEndpoint=(RotationZDegrees: Out), destEndpoint=(RotationXDegrees: In)", + "Components": { + "Component_[10139510177917176292]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 10139510177917176292, + "sourceEndpoint": { + "nodeId": { + "id": 58590186049188 + }, + "slotId": { + "m_id": "{A6D81A02-E3CB-44FC-80E6-61D8AB732ACC}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58688970296996 + }, + "slotId": { + "m_id": "{DC131C25-5C2C-482D-96A1-88542026DF75}" + } + } + } + } + }, + { + "Id": { + "id": 58809229381284 + }, + "Name": "srcEndpoint=(RotationXDegrees: Out), destEndpoint=(FromTranslation: In)", + "Components": { + "Component_[14430114494626818296]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14430114494626818296, + "sourceEndpoint": { + "nodeId": { + "id": 58688970296996 + }, + "slotId": { + "m_id": "{A4D7609D-9560-43D5-9FDE-36242CE35B48}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58671790427812 + }, + "slotId": { + "m_id": "{991F134E-88CC-423B-93C9-FFE9A9406739}" + } + } + } + } + }, + { + "Id": { + "id": 58813524348580 + }, + "Name": "srcEndpoint=(FromTranslation: Result: Transform), destEndpoint=(Multiply (*): Value)", + "Components": { + "Component_[4673903760365810060]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 4673903760365810060, + "sourceEndpoint": { + "nodeId": { + "id": 58607365918372 + }, + "slotId": { + "m_id": "{F84430FF-A436-459B-B849-6456573B85E7}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58658905525924 + }, + "slotId": { + "m_id": "{73F9A12E-8255-4C5E-89A8-B2F837C29AF6}" + } + } + } + } + }, + { + "Id": { + "id": 58817819315876 + }, + "Name": "srcEndpoint=(Multiply (*): Result), destEndpoint=(Multiply (*): Transform)", + "Components": { + "Component_[8661784838702007417]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 8661784838702007417, + "sourceEndpoint": { + "nodeId": { + "id": 58658905525924 + }, + "slotId": { + "m_id": "{A56467EC-4D3B-4CBE-847D-E5367BEFF26C}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58624545787556 + }, + "slotId": { + "m_id": "{B2F820AB-9377-4A47-AD2C-03D76C6E4024}" + } + } + } + } + }, + { + "Id": { + "id": 58822114283172 + }, + "Name": "srcEndpoint=(FromTranslation: Out), destEndpoint=(Multiply (*): In)", + "Components": { + "Component_[268387562422533755]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 268387562422533755, + "sourceEndpoint": { + "nodeId": { + "id": 58607365918372 + }, + "slotId": { + "m_id": "{5F03F883-BFAC-424C-BB04-334B68B845FC}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58658905525924 + }, + "slotId": { + "m_id": "{472B1FB5-766E-4F47-9955-B655857BE135}" + } + } + } + } + }, + { + "Id": { + "id": 58826409250468 + }, + "Name": "srcEndpoint=(Multiply (*): Out), destEndpoint=(Multiply (*): In)", + "Components": { + "Component_[3775912189287118250]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 3775912189287118250, + "sourceEndpoint": { + "nodeId": { + "id": 58658905525924 + }, + "slotId": { + "m_id": "{1ACBC12A-7FB1-4ADF-92BC-56B0DCE8CFAD}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58624545787556 + }, + "slotId": { + "m_id": "{3180019C-C78A-456E-B3E2-F1601B4A629A}" + } + } + } + } + }, + { + "Id": { + "id": 58830704217764 + }, + "Name": "srcEndpoint=(RotationZDegrees: Result: Transform), destEndpoint=(Multiply (*): Transform)", + "Components": { + "Component_[2967942488527008121]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 2967942488527008121, + "sourceEndpoint": { + "nodeId": { + "id": 58590186049188 + }, + "slotId": { + "m_id": "{065D3BDE-D0B8-4F84-82EB-8B48779A80CA}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58658905525924 + }, + "slotId": { + "m_id": "{89EA50A0-3CD4-46D6-8404-534EDB8C94EE}" + } + } + } + } + }, + { + "Id": { + "id": 58834999185060 + }, + "Name": "srcEndpoint=(RotationXDegrees: Result: Transform), destEndpoint=(Multiply (*): Transform)", + "Components": { + "Component_[191558726927551301]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 191558726927551301, + "sourceEndpoint": { + "nodeId": { + "id": 58688970296996 + }, + "slotId": { + "m_id": "{24EDA641-DBF3-41A8-8D47-60A3D83E3F23}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58624545787556 + }, + "slotId": { + "m_id": "{5509933D-93A5-483E-B7B5-FDD637C997DA}" + } + } + } + } + }, + { + "Id": { + "id": 164626484669075 + }, + "Name": "srcEndpoint=(: ), destEndpoint=(: )", + "Components": { + "Component_[14524450253664706586]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14524450253664706586, + "sourceEndpoint": { + "nodeId": { + "id": 58667495460516 + }, + "slotId": { + "m_id": "{8965578E-A29D-4468-B12B-9D4E4F814641}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58577301147300 + }, + "slotId": { + "m_id": "{F5BE2CBC-3CA3-44BD-B7D4-71D9CAC023B3}" + } + } + } + } + }, + { + "Id": { + "id": 214778817784467 + }, + "Name": "srcEndpoint=(TickBus Handler: ExecutionSlot:OnTick), destEndpoint=(Get Variable: In)", + "Components": { + "Component_[7779223725351419178]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 7779223725351419178, + "sourceEndpoint": { + "nodeId": { + "id": 58667495460516 + }, + "slotId": { + "m_id": "{8965578E-A29D-4468-B12B-9D4E4F814641}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 214400860662419 + }, + "slotId": { + "m_id": "{7500DE86-7349-4213-B3D6-F2872EDF15A6}" + } + } + } + } + }, + { + "Id": { + "id": 216011473398419 + }, + "Name": "srcEndpoint=(Get Variable: Number), destEndpoint=(Add (+): Value)", + "Components": { + "Component_[16293929363603149316]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 16293929363603149316, + "sourceEndpoint": { + "nodeId": { + "id": 214400860662419 + }, + "slotId": { + "m_id": "{5E4734A2-3CAF-4E29-AC72-5689FF1FD619}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 213241219492499 + }, + "slotId": { + "m_id": "{DB849F77-66D0-4D64-A45F-122F93E1E80C}" + } + } + } + } + }, + { + "Id": { + "id": 217330028358291 + }, + "Name": "srcEndpoint=(Add (+): Out), destEndpoint=(Set Variable: In)", + "Components": { + "Component_[13732207464069515508]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 13732207464069515508, + "sourceEndpoint": { + "nodeId": { + "id": 213241219492499 + }, + "slotId": { + "m_id": "{008FCEC7-3E86-4249-A736-F158EFDB0EFA}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58654610558628 + }, + "slotId": { + "m_id": "{F32F9B01-14B4-4DC3-AE0E-9E233DE5E941}" + } + } + } + } + }, + { + "Id": { + "id": 217626381101715 + }, + "Name": "srcEndpoint=(Add (+): Result), destEndpoint=(Set Variable: Number)", + "Components": { + "Component_[7103679238250108573]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 7103679238250108573, + "sourceEndpoint": { + "nodeId": { + "id": 213241219492499 + }, + "slotId": { + "m_id": "{53895246-F759-4328-AABB-D26E49E5208D}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 58654610558628 + }, + "slotId": { + "m_id": "{B22A0453-9715-46C7-A766-9536020AB59F}" + } + } + } + } + }, + { + "Id": { + "id": 240698945415827 + }, + "Name": "srcEndpoint=(Get Variable: Out), destEndpoint=(Multiply (*): In)", + "Components": { + "Component_[12012899230680400379]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 12012899230680400379, + "sourceEndpoint": { + "nodeId": { + "id": 214400860662419 + }, + "slotId": { + "m_id": "{8C8D3DD7-F821-42F4-AF51-5D976133DAE4}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 239870016727699 + }, + "slotId": { + "m_id": "{FEFF67A1-C89B-447E-80D4-CD94CB0C8AD7}" + } + } + } + } + }, + { + "Id": { + "id": 241158506916499 + }, + "Name": "srcEndpoint=(TickBus Handler: Number), destEndpoint=(Multiply (*): Value)", + "Components": { + "Component_[6729356013537587652]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 6729356013537587652, + "sourceEndpoint": { + "nodeId": { + "id": 58667495460516 + }, + "slotId": { + "m_id": "{02148868-388F-44F0-9E3A-C31601701F3B}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 239870016727699 + }, + "slotId": { + "m_id": "{8A243C9C-0D69-4753-B28B-A8D2FAC5D508}" + } + } + } + } + }, + { + "Id": { + "id": 241845701683859 + }, + "Name": "srcEndpoint=(Multiply (*): Out), destEndpoint=(Add (+): In)", + "Components": { + "Component_[1977054835666987502]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 1977054835666987502, + "sourceEndpoint": { + "nodeId": { + "id": 239870016727699 + }, + "slotId": { + "m_id": "{7E5D8673-F03A-4134-87DE-88AD13A74C29}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 213241219492499 + }, + "slotId": { + "m_id": "{56805D2B-0C98-4145-80FB-AA1DCB16CF1A}" + } + } + } + } + }, + { + "Id": { + "id": 242150644361875 + }, + "Name": "srcEndpoint=(Multiply (*): Result), destEndpoint=(Add (+): Number)", + "Components": { + "Component_[4687422202712804034]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 4687422202712804034, + "sourceEndpoint": { + "nodeId": { + "id": 239870016727699 + }, + "slotId": { + "m_id": "{DFD1DE7E-B470-43F6-A6CF-E9E572D0C075}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 213241219492499 + }, + "slotId": { + "m_id": "{CA8ABF3F-BF80-4A8B-A2B2-A1D2C16278C1}" + } + } + } + } + } + ] + }, + "m_assetType": "{3E2AC8CD-713F-453E-967F-29517F331784}", + "versionData": { + "_grammarVersion": 1, + "_runtimeVersion": 1, + "_fileVersion": 1 + }, + "m_variableCounter": 3, + "GraphCanvasData": [ + { + "Key": { + "id": 58577301147300 + }, + "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": [ + -40.0, + 180.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{EB1D5C50-BE43-4D5B-95CA-72BB2444355C}" + } + } + } + }, + { + "Key": { + "id": 58581596114596 + }, + "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": [ + 3540.0, + 580.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{A3A4908C-0B83-483F-831F-248D6AB79C29}" + } + } + } + }, + { + "Key": { + "id": 58590186049188 + }, + "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": [ + 2120.0, + 160.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{FED059CE-0252-49B1-8138-209A60BA8DA5}" + } + } + } + }, + { + "Key": { + "id": 58594481016484 + }, + "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": [ + 1820.0, + 160.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".getVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{4F7B87C1-4C5D-4B00-87F1-E742C7F9B0BB}" + } + } + } + }, + { + "Key": { + "id": 58607365918372 + }, + "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": [ + 2120.0, + 660.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{D8112E71-9789-4C0C-8366-B4F92D91986F}" + } + } + } + }, + { + "Key": { + "id": 58624545787556 + }, + "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": [ + 3180.0, + 360.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{297AAB81-3421-4A7B-8699-ECA4FF4DB2F3}" + } + } + } + }, + { + "Key": { + "id": 58628840754852 + }, + "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": [ + 3860.0, + 580.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{71F019FA-B307-4644-BB23-7869C6FEC456}" + } + } + } + }, + { + "Key": { + "id": 58633135722148 + }, + "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": [ + 300.0, + 180.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{3B2FC30A-C96E-4D45-8FB8-D93213E40656}" + } + } + } + }, + { + "Key": { + "id": 58654610558628 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "SetVariableNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 1300.0, + 480.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".setVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{6FF025AC-1B80-46F9-8827-C1C42EC3C298}" + } + } + } + }, + { + "Key": { + "id": 58658905525924 + }, + "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": [ + 2800.0, + 140.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{145EFCDE-FC2F-4B18-AF2D-B6952DC734BA}" + } + } + } + }, + { + "Key": { + "id": 58663200493220 + }, + "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": [ + 1680.0, + 660.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{B9601350-A96F-498A-AF35-F2D8374142F8}" + } + } + } + }, + { + "Key": { + "id": 58667495460516 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -480.0, + 500.0 + ] + }, + "{9E81C95F-89C0-4476-8E82-63CCC4E52E04}": { + "$type": "EBusHandlerNodeDescriptorSaveData", + "EventIds": [ + { + "Value": 1502188240 + } + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{A4513B84-5371-4B5E-8D78-6D5B2A9856D0}" + } + } + } + }, + { + "Key": { + "id": 58671790427812 + }, + "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": [ + 1980.0, + 500.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{9414796E-C664-46D2-99AD-506FBDFA6D56}" + } + } + } + }, + { + "Key": { + "id": 58688970296996 + }, + "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": [ + 2120.0, + 320.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{484503BE-9628-4885-A608-445A99D2768D}" + } + } + } + }, + { + "Key": { + "id": 213241219492499 + }, + "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": [ + 940.0, + 520.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{D8706C3B-F5F1-42A9-8717-81AA7769955D}" + } + } + } + }, + { + "Key": { + "id": 214400860662419 + }, + "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": [ + 100.0, + 540.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".getVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{1D7795F6-7D30-4BD9-80E1-7E2525FA859A}" + } + } + } + }, + { + "Key": { + "id": 239870016727699 + }, + "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": [ + 480.0, + 700.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{591ECD3E-51E5-4452-B8F0-91EEC22334EC}" + } + } + } + }, + { + "Key": { + "id": 1874297699023155003 + }, + "Value": { + "ComponentData": { + "{5F84B500-8C45-40D1-8EFC-A5306B241444}": { + "$type": "SceneComponentSaveData", + "ViewParams": { + "Scale": 0.6141249999999999, + "AnchorX": -615.5098876953125, + "AnchorY": -29.309993743896484 + } + } + } + } + } + ], + "StatisticsHelper": { + "InstanceCounter": [ + { + "Key": 1244476766431948410, + "Value": 1 + }, + { + "Key": 5842117451819972883, + "Value": 1 + }, + { + "Key": 11545666372999204726, + "Value": 2 + }, + { + "Key": 12702286953450386850, + "Value": 6 + }, + { + "Key": 12777283451032324504, + "Value": 2 + }, + { + "Key": 13282221058690490956, + "Value": 1 + }, + { + "Key": 13774516556399355685, + "Value": 1 + }, + { + "Key": 13774516556865812506, + "Value": 1 + }, + { + "Key": 16634824409549490771, + "Value": 1 + }, + { + "Key": 17750282321150628137, + "Value": 1 + } + ] + } + }, + "Component_[5106629331029292502]": { + "$type": "EditorGraphVariableManagerComponent", + "Id": 5106629331029292502, + "m_variableData": { + "m_nameVariableMap": [ + { + "Key": { + "m_id": "{0620A309-A152-4CF3-BF76-284115B30780}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0 + }, + "VariableId": { + "m_id": "{0620A309-A152-4CF3-BF76-284115B30780}" + }, + "VariableName": "RotateCamZ" + } + }, + { + "Key": { + "m_id": "{6A2D4F20-5402-4283-8799-EB8DEABD6369}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.1 + }, + "VariableId": { + "m_id": "{6A2D4F20-5402-4283-8799-EB8DEABD6369}" + }, + "VariableName": "JoystickDeadzone" + } + }, + { + "Key": { + "m_id": "{7062B1EE-2A8A-4E1D-8275-9DA1C5927FF0}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0 + }, + "VariableId": { + "m_id": "{7062B1EE-2A8A-4E1D-8275-9DA1C5927FF0}" + }, + "VariableName": "JoystickRight_X" + } + }, + { + "Key": { + "m_id": "{8E040B94-3374-4228-8020-577BB7C70EE7}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0 + }, + "VariableId": { + "m_id": "{8E040B94-3374-4228-8020-577BB7C70EE7}" + }, + "VariableName": "MoveX" + } + }, + { + "Key": { + "m_id": "{BF2919BD-19B4-4738-AC3A-81857D5204E4}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0 + }, + "VariableId": { + "m_id": "{BF2919BD-19B4-4738-AC3A-81857D5204E4}" + }, + "VariableName": "MoveY" + } + } + ] + }, + "CopiedVariableRemapping": [ + { + "Key": { + "m_id": "{5EB17E58-0B4E-451D-A1CE-0E7C272CBDEC}" + }, + "Value": { + "m_id": "{BF2919BD-19B4-4738-AC3A-81857D5204E4}" + } + }, + { + "Key": { + "m_id": "{B48E5726-A7FF-42A8-84D2-CF43ABBD1EDC}" + }, + "Value": { + "m_id": "{8E040B94-3374-4228-8020-577BB7C70EE7}" + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/CharacterController_AutomaticDemo.scriptcanvas b/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/CharacterController_AutomaticDemo.scriptcanvas new file mode 100644 index 0000000000..3582708516 --- /dev/null +++ b/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/CharacterController_AutomaticDemo.scriptcanvas @@ -0,0 +1,6387 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "ScriptCanvasData", + "ClassData": { + "m_scriptCanvas": { + "Id": { + "id": 3794495145504990811 + }, + "Name": "CharacterController", + "Components": { + "Component_[9391142200043061739]": { + "$type": "{4D755CA9-AB92-462C-B24F-0B3376F19967} Graph", + "Id": 9391142200043061739, + "m_graphData": { + "m_nodes": [ + { + "Id": { + "id": 246132492243092 + }, + "Name": "SC-Node(InputHandlerNodeableNode)", + "Components": { + "Component_[10263047381934993123]": { + "$type": "InputHandlerNodeableNode", + "Id": 10263047381934993123, + "Slots": [ + { + "id": { + "m_id": "{223DB32E-54FF-41B5-978E-289EA97C1A1C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Connect Event", + "toolTip": "Connect to input event name as defined in an input binding asset.", + "DisplayGroup": { + "Value": 2173756817 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{56FD98EC-6A1B-4738-898D-8B3B345315D5}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Event Name", + "toolTip": "Event name as defined in an input binding asset. Example 'Fireball'.", + "DisplayGroup": { + "Value": 2173756817 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{889B7C99-BD3C-4599-B0B4-C79A882B0395}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "On Connect Event", + "toolTip": "Connect to input event name as defined in an input binding asset.", + "DisplayGroup": { + "Value": 2173756817 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{C0E40FC8-0D14-4FFD-B8EE-6423B5059AF0}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Pressed", + "toolTip": "Signaled when the input event begins.", + "DisplayGroup": { + "Value": 458537082 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{C88462F2-E947-4525-9DBB-AE9B3851B2DB}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "value", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 458537082 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{12DA88AD-8B23-45AF-991D-456F32377083}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Held", + "toolTip": "Signaled while the input event is active.", + "DisplayGroup": { + "Value": 308119761 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{60393886-46EF-4B82-9009-9B4D9954255B}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Released", + "toolTip": "Signaled when the input event ends.", + "DisplayGroup": { + "Value": 4215628054 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 5 + }, + "isNullPointer": false, + "$type": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9} AZStd::string", + "value": "MoveX", + "label": "Event Name" + } + ], + "slotExecutionMap": { + "ins": [ + { + "_slotId": { + "m_id": "{223DB32E-54FF-41B5-978E-289EA97C1A1C}" + }, + "_inputs": [ + { + "_slotId": { + "m_id": "{56FD98EC-6A1B-4738-898D-8B3B345315D5}" + } + } + ], + "_outs": [ + { + "_slotId": { + "m_id": "{889B7C99-BD3C-4599-B0B4-C79A882B0395}" + }, + "_name": "On Connect Event", + "_interfaceSourceId": "{1B000000-0000-0000-0000-B376C2010000}" + } + ], + "_interfaceSourceId": "{00000000-0000-0000-4082-B80FBB000000}" + } + ], + "latents": [ + { + "_slotId": { + "m_id": "{C0E40FC8-0D14-4FFD-B8EE-6423B5059AF0}" + }, + "_name": "Pressed", + "_outputs": [ + { + "_slotId": { + "m_id": "{C88462F2-E947-4525-9DBB-AE9B3851B2DB}" + } + } + ], + "_interfaceSourceId": "{00000000-0000-0000-4082-B80FBB000000}" + }, + { + "_slotId": { + "m_id": "{12DA88AD-8B23-45AF-991D-456F32377083}" + }, + "_name": "Held", + "_outputs": [ + { + "_slotId": { + "m_id": "{C88462F2-E947-4525-9DBB-AE9B3851B2DB}" + } + } + ], + "_interfaceSourceId": "{00000000-0000-0000-4082-B80FBB000000}" + }, + { + "_slotId": { + "m_id": "{60393886-46EF-4B82-9009-9B4D9954255B}" + }, + "_name": "Released", + "_outputs": [ + { + "_slotId": { + "m_id": "{C88462F2-E947-4525-9DBB-AE9B3851B2DB}" + } + } + ], + "_interfaceSourceId": "{1B000000-0000-0000-0000-B376C2010000}" + } + ] + } + } + } + }, + { + "Id": { + "id": 246089542570132 + }, + "Name": "SC-Node(ConvertQuaternionToEulerDegrees)", + "Components": { + "Component_[12205034688404220919]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 12205034688404220919, + "Slots": [ + { + "id": { + "m_id": "{A96CFD2A-531E-4330-B991-F27754DB21B4}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Quaternion: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{CC9077E4-E835-4CAE-90EB-2B5FF8BA8F07}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{1286BE0C-88F5-4C0A-ADD6-EEE94AEA78A3}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{79FE68CC-45CC-4F5D-87A7-94B9144A3598}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Euler Angle", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 6 + }, + "isNullPointer": false, + "$type": "Quaternion", + "value": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "label": "Quaternion" + } + ], + "methodType": 2, + "methodName": "ConvertQuaternionToEulerDegrees", + "className": "MathUtils", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{A96CFD2A-531E-4330-B991-F27754DB21B4}" + } + ], + "prettyClassName": "MathUtils" + } + } + }, + { + "Id": { + "id": 246136787210388 + }, + "Name": "SC-Node(ConvertQuaternionToEulerDegrees)", + "Components": { + "Component_[12205034688404220919]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 12205034688404220919, + "Slots": [ + { + "id": { + "m_id": "{A96CFD2A-531E-4330-B991-F27754DB21B4}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Quaternion: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{CC9077E4-E835-4CAE-90EB-2B5FF8BA8F07}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{1286BE0C-88F5-4C0A-ADD6-EEE94AEA78A3}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{79FE68CC-45CC-4F5D-87A7-94B9144A3598}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Euler Angle", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 6 + }, + "isNullPointer": false, + "$type": "Quaternion", + "value": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "label": "Quaternion" + } + ], + "methodType": 2, + "methodName": "ConvertQuaternionToEulerDegrees", + "className": "MathUtils", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{A96CFD2A-531E-4330-B991-F27754DB21B4}" + } + ], + "prettyClassName": "MathUtils" + } + } + }, + { + "Id": { + "id": 246093837537428 + }, + "Name": "EBusEventHandler", + "Components": { + "Component_[12391893846605096594]": { + "$type": "EBusEventHandler", + "Id": 12391893846605096594, + "Slots": [ + { + "id": { + "m_id": "{47B8793A-68B3-4DF7-B485-98CF8625EE94}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Connect", + "toolTip": "Connect this event handler to the specified entity.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{75D0B671-F876-4383-B3AE-414B37AD0638}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Disconnect", + "toolTip": "Disconnect this event handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{03259091-B08D-4118-9AA3-053FD63AD6F7}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnConnected", + "toolTip": "Signaled when a connection has taken place.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{7C2E17C2-C3A1-4CB1-9AE6-521C4DD0D780}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnDisconnected", + "toolTip": "Signaled when this event handler is disconnected.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{9EB40EA9-0799-4FFF-9816-D6BEE9302D56}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnFailure", + "toolTip": "Signaled when it is not possible to connect this handler.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{02148868-388F-44F0-9E3A-C31601701F3B}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{1D2C5717-17A6-401F-BBF6-08EF84870CD3}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ScriptTimePoint", + "DisplayDataType": { + "m_type": 4, + "m_azType": "{4C0F6AD4-0D4F-4354-AD4A-0C01E948245C}" + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{8965578E-A29D-4468-B12B-9D4E4F814641}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ExecutionSlot:OnTick", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{53E6F39B-30C2-4828-83A4-A286E22DD18D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Number", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{909B60CC-693B-4DC9-9BC2-65B1D9373B5A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ExecutionSlot:GetTickOrder", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Result: Number" + } + ], + "m_eventMap": [ + { + "Key": { + "Value": 1502188240 + }, + "Value": { + "m_eventName": "OnTick", + "m_eventId": { + "Value": 1502188240 + }, + "m_eventSlotId": { + "m_id": "{8965578E-A29D-4468-B12B-9D4E4F814641}" + }, + "m_parameterSlotIds": [ + { + "m_id": "{02148868-388F-44F0-9E3A-C31601701F3B}" + }, + { + "m_id": "{1D2C5717-17A6-401F-BBF6-08EF84870CD3}" + } + ], + "m_numExpectedArguments": 2 + } + }, + { + "Key": { + "Value": 1890826333 + }, + "Value": { + "m_eventName": "GetTickOrder", + "m_eventId": { + "Value": 1890826333 + }, + "m_eventSlotId": { + "m_id": "{909B60CC-693B-4DC9-9BC2-65B1D9373B5A}" + }, + "m_resultSlotId": { + "m_id": "{53E6F39B-30C2-4828-83A4-A286E22DD18D}" + } + } + } + ], + "m_ebusName": "TickBus", + "m_busId": { + "Value": 1209186864 + } + } + } + }, + { + "Id": { + "id": 246128197275796 + }, + "Name": "SC-Node(SetNamedParameterVector3)", + "Components": { + "Component_[12793834298003501509]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 12793834298003501509, + "Slots": [ + { + "id": { + "m_id": "{25F29FBA-7B7B-44FA-869A-48167AE73CD8}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{DB4C82E4-77C5-4CCF-960E-FFB36CE6A930}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "String: 1", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{04958BE6-8525-49CA-9130-8CECD0BE43B3}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Vector3: 2", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{5D58862C-5682-4497-A994-F240120E8E62}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8F6FD0FC-11E5-49DD-A7D6-0AC0351E2DCA}" + }, + "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": 5 + }, + "isNullPointer": false, + "$type": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9} AZStd::string", + "value": "GoalFacingDir", + "label": "Name" + }, + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Value" + } + ], + "methodType": 0, + "methodName": "SetNamedParameterVector3", + "className": "AnimGraphComponentRequestBus", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{25F29FBA-7B7B-44FA-869A-48167AE73CD8}" + }, + { + "m_id": "{DB4C82E4-77C5-4CCF-960E-FFB36CE6A930}" + }, + { + "m_id": "{04958BE6-8525-49CA-9130-8CECD0BE43B3}" + } + ], + "prettyClassName": "AnimGraphComponentRequestBus" + } + } + }, + { + "Id": { + "id": 246171146948756 + }, + "Name": "SC-Node(SetNamedParameterVector3)", + "Components": { + "Component_[12793834298003501509]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 12793834298003501509, + "Slots": [ + { + "id": { + "m_id": "{25F29FBA-7B7B-44FA-869A-48167AE73CD8}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{DB4C82E4-77C5-4CCF-960E-FFB36CE6A930}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "String: 1", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{04958BE6-8525-49CA-9130-8CECD0BE43B3}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Vector3: 2", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{5D58862C-5682-4497-A994-F240120E8E62}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8F6FD0FC-11E5-49DD-A7D6-0AC0351E2DCA}" + }, + "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": 5 + }, + "isNullPointer": false, + "$type": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9} AZStd::string", + "value": "GoalPos", + "label": "Name" + }, + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Value" + } + ], + "methodType": 0, + "methodName": "SetNamedParameterVector3", + "className": "AnimGraphComponentRequestBus", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{25F29FBA-7B7B-44FA-869A-48167AE73CD8}" + }, + { + "m_id": "{DB4C82E4-77C5-4CCF-960E-FFB36CE6A930}" + }, + { + "m_id": "{04958BE6-8525-49CA-9130-8CECD0BE43B3}" + } + ], + "prettyClassName": "AnimGraphComponentRequestBus" + } + } + }, + { + "Id": { + "id": 246184031850644 + }, + "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{Quaternion(double )}* RotationZDegreesTraits >)", + "Components": { + "Component_[13432280424019746829]": { + "$type": "(NodeFunctionGenericMultiReturn)<{Quaternion(double )}* RotationZDegreesTraits >", + "Id": 13432280424019746829, + "Slots": [ + { + "id": { + "m_id": "{424CC5BD-ACB0-4F1E-9700-DE29DE2F908E}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{6D35C87C-35B1-49F2-9FE6-2FE2991AAB8D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{E2E3C0BC-56A7-4504-BEFA-1F1673DE7B0E}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Degrees", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{C2F9543A-928E-4405-A269-D8F952D227DB}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result", + "DisplayDataType": { + "m_type": 6 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Degrees" + } + ], + "Initialized": true + } + } + }, + { + "Id": { + "id": 246149672112276 + }, + "Name": "SC-Node(DrawTextAtLocation)", + "Components": { + "Component_[13698618923081442893]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 13698618923081442893, + "Slots": [ + { + "id": { + "m_id": "{C1270538-1843-4392-B23C-12747DD40B15}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Vector3: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{BE55072D-9B52-484A-BAB6-6847B191F6FA}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "String: 1", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{3DB3F6B0-8401-4068-9ACE-7EEA6717A748}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Color: 2", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{89BAE0A0-D8B2-4150-BFC2-69BACAF0D141}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number: 3", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{31C53E9E-3EE2-4476-A4C3-4966FDA539CC}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{E3D18BB2-B5F4-4AFD-8902-91124330D9E2}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Position" + }, + { + "scriptCanvasType": { + "m_type": 5 + }, + "isNullPointer": false, + "$type": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9} AZStd::string", + "value": "Goal", + "label": "Text" + }, + { + "scriptCanvasType": { + "m_type": 12 + }, + "isNullPointer": false, + "$type": "Color", + "value": [ + 1.0, + 0.0, + 0.0, + 1.0 + ], + "label": "Color" + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Duration" + } + ], + "NodeDisabledFlag": 1, + "methodType": 0, + "methodName": "DrawTextAtLocation", + "className": "DebugDrawRequestBus", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{C1270538-1843-4392-B23C-12747DD40B15}" + }, + { + "m_id": "{BE55072D-9B52-484A-BAB6-6847B191F6FA}" + }, + { + "m_id": "{3DB3F6B0-8401-4068-9ACE-7EEA6717A748}" + }, + { + "m_id": "{89BAE0A0-D8B2-4150-BFC2-69BACAF0D141}" + } + ], + "prettyClassName": "DebugDrawRequestBus" + } + } + }, + { + "Id": { + "id": 246098132504724 + }, + "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{Quaternion(double )}* RotationZDegreesTraits >)", + "Components": { + "Component_[15296836612744061228]": { + "$type": "(NodeFunctionGenericMultiReturn)<{Quaternion(double )}* RotationZDegreesTraits >", + "Id": 15296836612744061228, + "Slots": [ + { + "id": { + "m_id": "{C9C41693-0E85-429F-B9CF-87102B7AF399}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{DFA7AD12-D253-4B55-95BF-EBD79C9F0986}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{5076FEE2-72A1-4E2C-8FAF-649186F6F022}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Degrees", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{59A7EF4E-857E-4F2B-9466-37FE3C783EF9}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result", + "DisplayDataType": { + "m_type": 6 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Degrees" + } + ], + "Initialized": true + } + } + }, + { + "Id": { + "id": 246106722439316 + }, + "Name": "SC-Node(OperatorAdd)", + "Components": { + "Component_[16975947039966203662]": { + "$type": "OperatorAdd", + "Id": 16975947039966203662, + "Slots": [ + { + "id": { + "m_id": "{1AD1DED1-EDE6-4FAF-B3B6-FB5B26F1B294}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{E8BA15CB-A2B1-4824-92D6-2A71EEBF0378}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{FBF48C32-3CCB-47CA-BC9E-45567BF1B269}" + }, + "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": "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": "{C59084D6-69B9-464E-B6C9-910F69509779}" + }, + "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": "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": "{B87A6F0B-DE2B-4E9E-9C44-D18F1B8706E4}" + }, + "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": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Vector3" + } + ] + } + } + }, + { + "Id": { + "id": 246085247602836 + }, + "Name": "SC-Node(Print)", + "Components": { + "Component_[17915522105314128859]": { + "$type": "Print", + "Id": 17915522105314128859, + "Slots": [ + { + "id": { + "m_id": "{9FEBBB50-0F94-4781-9B51-88CAA867EC16}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "Input signal", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{3F92B8A4-0A0C-4120-B947-9A64BE38855F}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Value", + "toolTip": "Value which replaces instances of {Value} in the resulting string.", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1015031923 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{CFDEBA73-CAD5-4A66-ACD1-4080334CEED1}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Value" + } + ], + "NodeDisabledFlag": 1, + "m_format": "MoveX {Value}", + "m_arrayBindingMap": [ + { + "Key": 1, + "Value": { + "m_id": "{3F92B8A4-0A0C-4120-B947-9A64BE38855F}" + } + } + ], + "m_unresolvedString": [ + "MoveX ", + {} + ], + "m_formatSlotMap": { + "Value": { + "m_id": "{3F92B8A4-0A0C-4120-B947-9A64BE38855F}" + } + } + } + } + }, + { + "Id": { + "id": 246192621785236 + }, + "Name": "SC-Node(Print)", + "Components": { + "Component_[17915522105314128859]": { + "$type": "Print", + "Id": 17915522105314128859, + "Slots": [ + { + "id": { + "m_id": "{9FEBBB50-0F94-4781-9B51-88CAA867EC16}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "Input signal", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{3F92B8A4-0A0C-4120-B947-9A64BE38855F}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Value", + "toolTip": "Value which replaces instances of {Value} in the resulting string.", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1015031923 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{CFDEBA73-CAD5-4A66-ACD1-4080334CEED1}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Value" + } + ], + "NodeDisabledFlag": 1, + "m_format": "MoveY {Value}", + "m_arrayBindingMap": [ + { + "Key": 1, + "Value": { + "m_id": "{3F92B8A4-0A0C-4120-B947-9A64BE38855F}" + } + } + ], + "m_unresolvedString": [ + "MoveY ", + {} + ], + "m_formatSlotMap": { + "Value": { + "m_id": "{3F92B8A4-0A0C-4120-B947-9A64BE38855F}" + } + } + } + } + }, + { + "Id": { + "id": 246080952635540 + }, + "Name": "SC-Node(ExtractProperty)", + "Components": { + "Component_[18182473127226221453]": { + "$type": "ExtractProperty", + "Id": 18182473127226221453, + "Slots": [ + { + "id": { + "m_id": "{B85B623A-CACB-4B96-98DB-E4F289AA01D4}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled assigns property values using the supplied source input", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{E6DBA835-98FA-4ADB-8F87-15604C8D3FD3}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after all property haves have been pushed to the output slots", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8F09882E-A82E-481D-9FBD-FED706BEFB7C}" + }, + "DynamicTypeOverride": 1, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Source", + "toolTip": "The value on which to extract properties from.", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{10C2FAA6-AA90-4D62-97FB-1C6C81BA6AB2}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "X", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{7FAB654B-42B6-4402-91F8-7AD3AB651DE1}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Y", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{E7EB179B-BACB-44DB-B2D1-D5D4788D80D8}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Z", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Source" + } + ], + "m_dataType": { + "m_type": 8 + }, + "m_propertyAccounts": [ + { + "m_propertySlotId": { + "m_id": "{10C2FAA6-AA90-4D62-97FB-1C6C81BA6AB2}" + }, + "m_propertyType": { + "m_type": 3 + }, + "m_propertyName": "x" + }, + { + "m_propertySlotId": { + "m_id": "{7FAB654B-42B6-4402-91F8-7AD3AB651DE1}" + }, + "m_propertyType": { + "m_type": 3 + }, + "m_propertyName": "y" + }, + { + "m_propertySlotId": { + "m_id": "{E7EB179B-BACB-44DB-B2D1-D5D4788D80D8}" + }, + "m_propertyType": { + "m_type": 3 + }, + "m_propertyName": "z" + } + ] + } + } + }, + { + "Id": { + "id": 246102427472020 + }, + "Name": "SC-Node(DrawSphereAtLocation)", + "Components": { + "Component_[217512573203327123]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 217512573203327123, + "Slots": [ + { + "id": { + "m_id": "{67CBBEE3-F9B5-472E-8A3E-A82996CDA2D1}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Vector3: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{0C39ADAF-7C3F-465C-A61F-54FD9E06B6F6}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number: 1", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{3D43E30E-F93C-4463-AF83-60B68E277D51}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Color: 2", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{12524268-7E71-44A0-B2E2-FAB3465AF3C8}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number: 3", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{9B026749-1D6E-4F69-9F20-777A510FD7C4}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{063DEA47-18F0-45C9-B2D6-BB6767B769DE}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Position" + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.1, + "label": "Radius" + }, + { + "scriptCanvasType": { + "m_type": 12 + }, + "isNullPointer": false, + "$type": "Color", + "value": [ + 1.0, + 0.0, + 0.0, + 1.0 + ], + "label": "Color" + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Duration" + } + ], + "NodeDisabledFlag": 1, + "methodType": 0, + "methodName": "DrawSphereAtLocation", + "className": "DebugDrawRequestBus", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{67CBBEE3-F9B5-472E-8A3E-A82996CDA2D1}" + }, + { + "m_id": "{0C39ADAF-7C3F-465C-A61F-54FD9E06B6F6}" + }, + { + "m_id": "{3D43E30E-F93C-4463-AF83-60B68E277D51}" + }, + { + "m_id": "{12524268-7E71-44A0-B2E2-FAB3465AF3C8}" + } + ], + "prettyClassName": "DebugDrawRequestBus" + } + } + }, + { + "Id": { + "id": 246145377144980 + }, + "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{Vector3(Quaternion Vector3 )}* RotateVector3Traits >)", + "Components": { + "Component_[2974676320576034178]": { + "$type": "(NodeFunctionGenericMultiReturn)<{Vector3(Quaternion Vector3 )}* RotateVector3Traits >", + "Id": 2974676320576034178, + "Slots": [ + { + "id": { + "m_id": "{9704DF19-1C22-4E87-B461-EBA5E86CA68C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{C49165F2-9484-4E70-874F-4FD821B83AB0}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{6F45F01E-F700-4594-98F0-A02A5BE00617}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Quaternion", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{50A0D858-774F-4379-8B02-C178E5327BE9}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Vector", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{099EF8F5-DE6F-45FC-9AA6-716996AAB7C6}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 6 + }, + "isNullPointer": false, + "$type": "Quaternion", + "value": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "label": "Quaternion" + }, + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 1.0, + 0.0 + ], + "label": "Vector" + } + ], + "Initialized": true + } + } + }, + { + "Id": { + "id": 246166851981460 + }, + "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{Vector3(Quaternion Vector3 )}* RotateVector3Traits >)", + "Components": { + "Component_[2974676320576034178]": { + "$type": "(NodeFunctionGenericMultiReturn)<{Vector3(Quaternion Vector3 )}* RotateVector3Traits >", + "Id": 2974676320576034178, + "Slots": [ + { + "id": { + "m_id": "{9704DF19-1C22-4E87-B461-EBA5E86CA68C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{C49165F2-9484-4E70-874F-4FD821B83AB0}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{6F45F01E-F700-4594-98F0-A02A5BE00617}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Quaternion", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{50A0D858-774F-4379-8B02-C178E5327BE9}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Vector", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{099EF8F5-DE6F-45FC-9AA6-716996AAB7C6}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 6 + }, + "isNullPointer": false, + "$type": "Quaternion", + "value": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "label": "Quaternion" + }, + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 1.0, + 0.0 + ], + "label": "Vector" + } + ], + "Initialized": true + } + } + }, + { + "Id": { + "id": 246076657668244 + }, + "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{Vector3(Quaternion Vector3 )}* RotateVector3Traits >)", + "Components": { + "Component_[3881104967231448701]": { + "$type": "(NodeFunctionGenericMultiReturn)<{Vector3(Quaternion Vector3 )}* RotateVector3Traits >", + "Id": 3881104967231448701, + "Slots": [ + { + "id": { + "m_id": "{8C5BE0B0-13CC-43A5-8F44-9C282B3E4D60}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8D7093BA-E37A-48D7-ABB6-8D3960A60BF0}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{72351E0C-D3F5-4181-90CB-8A4E0557A978}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Quaternion", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{B46DDF66-DA5E-474C-A740-5472FBBF285A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Vector", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{879125AE-8729-465D-A3E3-1DAF6B9C84C7}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 6 + }, + "isNullPointer": false, + "$type": "Quaternion", + "value": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "label": "Quaternion" + }, + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Vector" + } + ], + "Initialized": true + } + } + }, + { + "Id": { + "id": 246153967079572 + }, + "Name": "SC-Node((NodeFunctionGenericMultiReturn)<{Vector3(double double double )}* FromValuesTraits >)", + "Components": { + "Component_[4092504572586685068]": { + "$type": "(NodeFunctionGenericMultiReturn)<{Vector3(double double double )}* FromValuesTraits >", + "Id": 4092504572586685068, + "Slots": [ + { + "id": { + "m_id": "{7A425E1D-C67F-42D7-8377-124FDDCCD02B}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{2EAFCACB-BC3D-4748-86F6-E2037A7CF487}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8FACA5C3-ED4D-4DC2-8E6A-28AE1B340BE7}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "X", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{A01573D8-5F5D-404B-A5BC-193480C65F28}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Y", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{0F6AB874-B298-4425-B142-017E8B7F0501}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Z", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{5029C117-20D4-4CE1-9097-FBBC98B4F457}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "X" + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Y" + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Z" + } + ], + "Initialized": true + } + } + }, + { + "Id": { + "id": 246162557014164 + }, + "Name": "SC Node(SetVariable)", + "Components": { + "Component_[4132372868512871966]": { + "$type": "SetVariableNode", + "Id": 4132372868512871966, + "Slots": [ + { + "id": { + "m_id": "{F83C85A3-77E5-4B09-8FE2-32127A1C6EDE}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled sends the variable referenced by this node to a Data Output slot", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{457D8C40-3373-4DA9-8186-C33DBFA2397F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after the referenced variable has been pushed to the Data Output slot", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{AFAC9742-D20E-4094-8720-7E4582FE7761}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{954FC5E5-8838-4ABF-8C6E-B6B100C7BD20}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Number" + } + ], + "m_variableId": { + "m_id": "{5EB17E58-0B4E-451D-A1CE-0E7C272CBDEC}" + }, + "m_variableDataInSlotId": { + "m_id": "{AFAC9742-D20E-4094-8720-7E4582FE7761}" + }, + "m_variableDataOutSlotId": { + "m_id": "{954FC5E5-8838-4ABF-8C6E-B6B100C7BD20}" + } + } + } + }, + { + "Id": { + "id": 246119607341204 + }, + "Name": "SC Node(SetVariable)", + "Components": { + "Component_[4132372868512871966]": { + "$type": "SetVariableNode", + "Id": 4132372868512871966, + "Slots": [ + { + "id": { + "m_id": "{F83C85A3-77E5-4B09-8FE2-32127A1C6EDE}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled sends the variable referenced by this node to a Data Output slot", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{457D8C40-3373-4DA9-8186-C33DBFA2397F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after the referenced variable has been pushed to the Data Output slot", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{AFAC9742-D20E-4094-8720-7E4582FE7761}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{954FC5E5-8838-4ABF-8C6E-B6B100C7BD20}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Number" + } + ], + "m_variableId": { + "m_id": "{B48E5726-A7FF-42A8-84D2-CF43ABBD1EDC}" + }, + "m_variableDataInSlotId": { + "m_id": "{AFAC9742-D20E-4094-8720-7E4582FE7761}" + }, + "m_variableDataOutSlotId": { + "m_id": "{954FC5E5-8838-4ABF-8C6E-B6B100C7BD20}" + } + } + } + }, + { + "Id": { + "id": 246175441916052 + }, + "Name": "SC Node(GetVariable)", + "Components": { + "Component_[5278854140649584684]": { + "$type": "GetVariableNode", + "Id": 5278854140649584684, + "Slots": [ + { + "id": { + "m_id": "{17B5B6FD-B942-4C0C-847E-3891BA11743B}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled sends the property referenced by this node to a Data Output slot", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{613E9634-0EEC-43EE-A680-94724628BEAB}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after the referenced property has been pushed to the Data Output slot", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{D44E36FC-7879-4E15-B0AA-0E9F866D2A5C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "m_variableId": { + "m_id": "{B48E5726-A7FF-42A8-84D2-CF43ABBD1EDC}" + }, + "m_variableDataOutSlotId": { + "m_id": "{D44E36FC-7879-4E15-B0AA-0E9F866D2A5C}" + } + } + } + }, + { + "Id": { + "id": 246068067733652 + }, + "Name": "SC-Node(GetWorldTranslation)", + "Components": { + "Component_[6584501548902644902]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 6584501548902644902, + "Slots": [ + { + "id": { + "m_id": "{72B594D3-36EA-4390-A1E3-E8B296D3CC68}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{5AAE80BB-C549-4D61-AC36-57FF33A0F9B9}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{D6245737-F70E-431A-8DB2-D187634B6859}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{EBC733B4-A0E0-4772-888E-082AF8BA2FFF}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Vector3", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 2901262558 + }, + "label": "Source" + } + ], + "methodType": 0, + "methodName": "GetWorldTranslation", + "className": "TransformBus", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{72B594D3-36EA-4390-A1E3-E8B296D3CC68}" + } + ], + "prettyClassName": "TransformBus" + } + } + }, + { + "Id": { + "id": 246115312373908 + }, + "Name": "SC-Node(InputHandlerNodeableNode)", + "Components": { + "Component_[6810487525300205505]": { + "$type": "InputHandlerNodeableNode", + "Id": 6810487525300205505, + "Slots": [ + { + "id": { + "m_id": "{59344FA8-1BCE-4323-B7ED-963439BB3D43}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Connect Event", + "toolTip": "Connect to input event name as defined in an input binding asset.", + "DisplayGroup": { + "Value": 2173756817 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{DBEB7EFF-188D-498B-A0C7-62A6A379E121}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Event Name", + "toolTip": "Event name as defined in an input binding asset. Example 'Fireball'.", + "DisplayGroup": { + "Value": 2173756817 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{ABD24CF7-E97C-41E9-8AC3-EC4C586DDBFC}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "On Connect Event", + "toolTip": "Connect to input event name as defined in an input binding asset.", + "DisplayGroup": { + "Value": 2173756817 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{DD88EDED-AD61-4BD4-9A2A-2A8F7339CD66}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Pressed", + "toolTip": "Signaled when the input event begins.", + "DisplayGroup": { + "Value": 458537082 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{CDB5418B-2ECA-421E-827E-44835EF28954}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "value", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 458537082 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{C20E41AE-74BA-4E93-B278-841E4F3848DD}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Held", + "toolTip": "Signaled while the input event is active.", + "DisplayGroup": { + "Value": 308119761 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{001FCBA0-A022-47DB-A346-782286DA3DE5}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Released", + "toolTip": "Signaled when the input event ends.", + "DisplayGroup": { + "Value": 4215628054 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 5 + }, + "isNullPointer": false, + "$type": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9} AZStd::string", + "value": "MoveY", + "label": "Event Name" + } + ], + "slotExecutionMap": { + "ins": [ + { + "_slotId": { + "m_id": "{59344FA8-1BCE-4323-B7ED-963439BB3D43}" + }, + "_inputs": [ + { + "_slotId": { + "m_id": "{DBEB7EFF-188D-498B-A0C7-62A6A379E121}" + } + } + ], + "_outs": [ + { + "_slotId": { + "m_id": "{ABD24CF7-E97C-41E9-8AC3-EC4C586DDBFC}" + }, + "_name": "On Connect Event" + } + ], + "_interfaceSourceId": "{8087B80F-BB00-0000-0241-25E7FC7F0000}" + } + ], + "latents": [ + { + "_slotId": { + "m_id": "{DD88EDED-AD61-4BD4-9A2A-2A8F7339CD66}" + }, + "_name": "Pressed", + "_outputs": [ + { + "_slotId": { + "m_id": "{CDB5418B-2ECA-421E-827E-44835EF28954}" + } + } + ], + "_interfaceSourceId": "{8087B80F-BB00-0000-0241-25E7FC7F0000}" + }, + { + "_slotId": { + "m_id": "{C20E41AE-74BA-4E93-B278-841E4F3848DD}" + }, + "_name": "Held", + "_outputs": [ + { + "_slotId": { + "m_id": "{CDB5418B-2ECA-421E-827E-44835EF28954}" + } + } + ], + "_interfaceSourceId": "{8087B80F-BB00-0000-0241-25E7FC7F0000}" + }, + { + "_slotId": { + "m_id": "{001FCBA0-A022-47DB-A346-782286DA3DE5}" + }, + "_name": "Released", + "_outputs": [ + { + "_slotId": { + "m_id": "{CDB5418B-2ECA-421E-827E-44835EF28954}" + } + } + ] + } + ] + } + } + } + }, + { + "Id": { + "id": 246072362700948 + }, + "Name": "SC Node(GetVariable)", + "Components": { + "Component_[7093473538212812857]": { + "$type": "GetVariableNode", + "Id": 7093473538212812857, + "Slots": [ + { + "id": { + "m_id": "{276F5B6E-2FC8-4EFF-A161-2548BC0E0885}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled sends the property referenced by this node to a Data Output slot", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{6D512DCD-4CA6-421F-9C23-214E4A757D5F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after the referenced property has been pushed to the Data Output slot", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{68E66FCE-1DF4-445A-9DD5-7D06D3A3146D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "m_variableId": { + "m_id": "{5EB17E58-0B4E-451D-A1CE-0E7C272CBDEC}" + }, + "m_variableDataOutSlotId": { + "m_id": "{68E66FCE-1DF4-445A-9DD5-7D06D3A3146D}" + } + } + } + }, + { + "Id": { + "id": 246179736883348 + }, + "Name": "EBusEventHandler", + "Components": { + "Component_[7486482846458186344]": { + "$type": "EBusEventHandler", + "Id": 7486482846458186344, + "Slots": [ + { + "id": { + "m_id": "{ACA820F7-7515-4904-AB73-975DE0723CBE}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Connect", + "toolTip": "Connect this event handler to the specified entity.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{DAA6A799-AB8F-448D-92CD-F431D4A9424C}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Disconnect", + "toolTip": "Disconnect this event handler.", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{1E01CC28-0CD3-4E29-9AF5-F51958FBEB44}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnConnected", + "toolTip": "Signaled when a connection has taken place.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{A9AF6E0E-6D77-45C4-9720-CF4F488243ED}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnDisconnected", + "toolTip": "Signaled when this event handler is disconnected.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{4D7CF661-9343-4A44-8095-AFC33096AB20}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "OnFailure", + "toolTip": "Signaled when it is not possible to connect this handler.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{96E803E6-7979-48B7-B473-21D317FC97BD}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Source", + "toolTip": "ID used to connect on a specific Event address (Type: EntityId)", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{8449A9CC-591E-40CD-8122-CDA20BCD226D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID", + "DisplayDataType": { + "m_type": 1 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{FC0FCD21-DA19-4674-9F8C-D79960777B1E}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "ExecutionSlot:OnEntityActivated", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + }, + "IsLatent": true + }, + { + "id": { + "m_id": "{24D001AB-332B-41B2-B2AA-AF7D6418DB8F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID", + "DisplayDataType": { + "m_type": 1 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{3DE59EA1-6365-458A-8806-D42BA4B79F07}" + }, + "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": "{FC0FCD21-DA19-4674-9F8C-D79960777B1E}" + }, + "m_parameterSlotIds": [ + { + "m_id": "{8449A9CC-591E-40CD-8122-CDA20BCD226D}" + } + ], + "m_numExpectedArguments": 1 + } + }, + { + "Key": { + "Value": 4273369222 + }, + "Value": { + "m_eventName": "OnEntityDeactivated", + "m_eventId": { + "Value": 4273369222 + }, + "m_eventSlotId": { + "m_id": "{3DE59EA1-6365-458A-8806-D42BA4B79F07}" + }, + "m_parameterSlotIds": [ + { + "m_id": "{24D001AB-332B-41B2-B2AA-AF7D6418DB8F}" + } + ], + "m_numExpectedArguments": 1 + } + } + ], + "m_ebusName": "EntityBus", + "m_busId": { + "Value": 3358774020 + } + } + } + }, + { + "Id": { + "id": 246188326817940 + }, + "Name": "SC-Node(GetWorldRotationQuaternion)", + "Components": { + "Component_[9629672380141390157]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 9629672380141390157, + "Slots": [ + { + "id": { + "m_id": "{C9D6C354-CB4F-40E3-892E-19D7940A9399}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{6BCB6E4B-E9C5-4D6E-A4AF-C2C76271E115}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{E7F58DBD-3882-43D3-B44F-D2E68E5E7098}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{81953E27-7B51-462D-9AB8-B122F33A7391}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Quaternion", + "DisplayDataType": { + "m_type": 6 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 623788559886 + }, + "label": "Source" + } + ], + "methodType": 0, + "methodName": "GetWorldRotationQuaternion", + "className": "TransformBus", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{C9D6C354-CB4F-40E3-892E-19D7940A9399}" + } + ], + "prettyClassName": "TransformBus" + } + } + }, + { + "Id": { + "id": 246141082177684 + }, + "Name": "SC-Node(GetWorldRotationQuaternion)", + "Components": { + "Component_[9629672380141390157]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 9629672380141390157, + "Slots": [ + { + "id": { + "m_id": "{C9D6C354-CB4F-40E3-892E-19D7940A9399}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityID: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{6BCB6E4B-E9C5-4D6E-A4AF-C2C76271E115}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{E7F58DBD-3882-43D3-B44F-D2E68E5E7098}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{81953E27-7B51-462D-9AB8-B122F33A7391}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Result: Quaternion", + "DisplayDataType": { + "m_type": 6 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 653853330958 + }, + "label": "Source" + } + ], + "methodType": 0, + "methodName": "GetWorldRotationQuaternion", + "className": "TransformBus", + "resultSlotIDs": [ + {} + ], + "inputSlots": [ + { + "m_id": "{C9D6C354-CB4F-40E3-892E-19D7940A9399}" + } + ], + "prettyClassName": "TransformBus" + } + } + }, + { + "Id": { + "id": 246158262046868 + }, + "Name": "SC-Node(ExtractProperty)", + "Components": { + "Component_[973963568861268593]": { + "$type": "ExtractProperty", + "Id": 973963568861268593, + "Slots": [ + { + "id": { + "m_id": "{A6542FE6-CFED-4033-AC3A-64614B1BF141}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled assigns property values using the supplied source input", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{3EB4F651-DA08-45E5-94FE-432A8FC45914}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after all property haves have been pushed to the output slots", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{E14C7719-5419-444C-BCDF-23BFDFD40DA4}" + }, + "DynamicTypeOverride": 1, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Source", + "toolTip": "The value on which to extract properties from.", + "DisplayDataType": { + "m_type": 8 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{663DD576-8088-485C-AFFE-DCB0FCAEE679}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "X", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{DB27CBA5-2F04-44AD-A73E-A3772236908A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Y", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{B138BB48-9B60-4DE3-8DF0-DCC17D0D6358}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Z", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 8 + }, + "isNullPointer": false, + "$type": "Vector3", + "value": [ + 0.0, + 0.0, + 0.0 + ], + "label": "Source" + } + ], + "m_dataType": { + "m_type": 8 + }, + "m_propertyAccounts": [ + { + "m_propertySlotId": { + "m_id": "{663DD576-8088-485C-AFFE-DCB0FCAEE679}" + }, + "m_propertyType": { + "m_type": 3 + }, + "m_propertyName": "x" + }, + { + "m_propertySlotId": { + "m_id": "{DB27CBA5-2F04-44AD-A73E-A3772236908A}" + }, + "m_propertyType": { + "m_type": 3 + }, + "m_propertyName": "y" + }, + { + "m_propertySlotId": { + "m_id": "{B138BB48-9B60-4DE3-8DF0-DCC17D0D6358}" + }, + "m_propertyType": { + "m_type": 3 + }, + "m_propertyName": "z" + } + ] + } + } + } + ], + "m_connections": [ + { + "Id": { + "id": 246196916752532 + }, + "Name": "srcEndpoint=(EntityBus Handler: ExecutionSlot:OnEntityActivated), destEndpoint=(InputHandler: Connect Event)", + "Components": { + "Component_[8456523383292490588]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 8456523383292490588, + "sourceEndpoint": { + "nodeId": { + "id": 246179736883348 + }, + "slotId": { + "m_id": "{FC0FCD21-DA19-4674-9F8C-D79960777B1E}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246132492243092 + }, + "slotId": { + "m_id": "{223DB32E-54FF-41B5-978E-289EA97C1A1C}" + } + } + } + } + }, + { + "Id": { + "id": 246201211719828 + }, + "Name": "srcEndpoint=(EntityBus Handler: ExecutionSlot:OnEntityActivated), destEndpoint=(InputHandler: Connect Event)", + "Components": { + "Component_[12635346401763282235]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 12635346401763282235, + "sourceEndpoint": { + "nodeId": { + "id": 246179736883348 + }, + "slotId": { + "m_id": "{FC0FCD21-DA19-4674-9F8C-D79960777B1E}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246115312373908 + }, + "slotId": { + "m_id": "{59344FA8-1BCE-4323-B7ED-963439BB3D43}" + } + } + } + } + }, + { + "Id": { + "id": 246205506687124 + }, + "Name": "srcEndpoint=(InputHandler: value), destEndpoint=(Set Variable: Number)", + "Components": { + "Component_[12090259056249954518]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 12090259056249954518, + "sourceEndpoint": { + "nodeId": { + "id": 246132492243092 + }, + "slotId": { + "m_id": "{C88462F2-E947-4525-9DBB-AE9B3851B2DB}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246119607341204 + }, + "slotId": { + "m_id": "{AFAC9742-D20E-4094-8720-7E4582FE7761}" + } + } + } + } + }, + { + "Id": { + "id": 246209801654420 + }, + "Name": "srcEndpoint=(InputHandler: Held), destEndpoint=(Set Variable: In)", + "Components": { + "Component_[10496578309013320974]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 10496578309013320974, + "sourceEndpoint": { + "nodeId": { + "id": 246132492243092 + }, + "slotId": { + "m_id": "{12DA88AD-8B23-45AF-991D-456F32377083}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246119607341204 + }, + "slotId": { + "m_id": "{F83C85A3-77E5-4B09-8FE2-32127A1C6EDE}" + } + } + } + } + }, + { + "Id": { + "id": 246214096621716 + }, + "Name": "srcEndpoint=(Set Variable: Out), destEndpoint=(Print: In)", + "Components": { + "Component_[5484696725367231856]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 5484696725367231856, + "sourceEndpoint": { + "nodeId": { + "id": 246119607341204 + }, + "slotId": { + "m_id": "{457D8C40-3373-4DA9-8186-C33DBFA2397F}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246085247602836 + }, + "slotId": { + "m_id": "{9FEBBB50-0F94-4781-9B51-88CAA867EC16}" + } + } + } + } + }, + { + "Id": { + "id": 246218391589012 + }, + "Name": "srcEndpoint=(Set Variable: Number), destEndpoint=(Print: Value)", + "Components": { + "Component_[14254771563627471531]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14254771563627471531, + "sourceEndpoint": { + "nodeId": { + "id": 246119607341204 + }, + "slotId": { + "m_id": "{954FC5E5-8838-4ABF-8C6E-B6B100C7BD20}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246085247602836 + }, + "slotId": { + "m_id": "{3F92B8A4-0A0C-4120-B947-9A64BE38855F}" + } + } + } + } + }, + { + "Id": { + "id": 246222686556308 + }, + "Name": "srcEndpoint=(Set Variable: Out), destEndpoint=(Print: In)", + "Components": { + "Component_[4813008405212019270]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 4813008405212019270, + "sourceEndpoint": { + "nodeId": { + "id": 246162557014164 + }, + "slotId": { + "m_id": "{457D8C40-3373-4DA9-8186-C33DBFA2397F}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246192621785236 + }, + "slotId": { + "m_id": "{9FEBBB50-0F94-4781-9B51-88CAA867EC16}" + } + } + } + } + }, + { + "Id": { + "id": 246226981523604 + }, + "Name": "srcEndpoint=(Set Variable: Number), destEndpoint=(Print: Value)", + "Components": { + "Component_[7843206400486067015]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 7843206400486067015, + "sourceEndpoint": { + "nodeId": { + "id": 246162557014164 + }, + "slotId": { + "m_id": "{954FC5E5-8838-4ABF-8C6E-B6B100C7BD20}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246192621785236 + }, + "slotId": { + "m_id": "{3F92B8A4-0A0C-4120-B947-9A64BE38855F}" + } + } + } + } + }, + { + "Id": { + "id": 246231276490900 + }, + "Name": "srcEndpoint=(InputHandler: Held), destEndpoint=(Set Variable: In)", + "Components": { + "Component_[6686521440104763914]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 6686521440104763914, + "sourceEndpoint": { + "nodeId": { + "id": 246115312373908 + }, + "slotId": { + "m_id": "{C20E41AE-74BA-4E93-B278-841E4F3848DD}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246162557014164 + }, + "slotId": { + "m_id": "{F83C85A3-77E5-4B09-8FE2-32127A1C6EDE}" + } + } + } + } + }, + { + "Id": { + "id": 246235571458196 + }, + "Name": "srcEndpoint=(InputHandler: value), destEndpoint=(Set Variable: Number)", + "Components": { + "Component_[9188879004341290744]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 9188879004341290744, + "sourceEndpoint": { + "nodeId": { + "id": 246115312373908 + }, + "slotId": { + "m_id": "{CDB5418B-2ECA-421E-827E-44835EF28954}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246162557014164 + }, + "slotId": { + "m_id": "{AFAC9742-D20E-4094-8720-7E4582FE7761}" + } + } + } + } + }, + { + "Id": { + "id": 246239866425492 + }, + "Name": "srcEndpoint=(Get Variable: Out), destEndpoint=(Get Variable: In)", + "Components": { + "Component_[11528425355392281835]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 11528425355392281835, + "sourceEndpoint": { + "nodeId": { + "id": 246175441916052 + }, + "slotId": { + "m_id": "{613E9634-0EEC-43EE-A680-94724628BEAB}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246072362700948 + }, + "slotId": { + "m_id": "{276F5B6E-2FC8-4EFF-A161-2548BC0E0885}" + } + } + } + } + }, + { + "Id": { + "id": 246244161392788 + }, + "Name": "srcEndpoint=(GetWorldRotationQuaternion: Result: Quaternion), destEndpoint=(ConvertQuaternionToEulerDegrees: Quaternion: 0)", + "Components": { + "Component_[12030435265785289825]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 12030435265785289825, + "sourceEndpoint": { + "nodeId": { + "id": 246188326817940 + }, + "slotId": { + "m_id": "{81953E27-7B51-462D-9AB8-B122F33A7391}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246136787210388 + }, + "slotId": { + "m_id": "{A96CFD2A-531E-4330-B991-F27754DB21B4}" + } + } + } + } + }, + { + "Id": { + "id": 246248456360084 + }, + "Name": "srcEndpoint=(GetWorldRotationQuaternion: Out), destEndpoint=(ConvertQuaternionToEulerDegrees: In)", + "Components": { + "Component_[9017349526511387231]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 9017349526511387231, + "sourceEndpoint": { + "nodeId": { + "id": 246188326817940 + }, + "slotId": { + "m_id": "{E7F58DBD-3882-43D3-B44F-D2E68E5E7098}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246136787210388 + }, + "slotId": { + "m_id": "{CC9077E4-E835-4CAE-90EB-2B5FF8BA8F07}" + } + } + } + } + }, + { + "Id": { + "id": 246252751327380 + }, + "Name": "srcEndpoint=(GetWorldRotationQuaternion: Out), destEndpoint=(ConvertQuaternionToEulerDegrees: In)", + "Components": { + "Component_[13772266509420181725]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 13772266509420181725, + "sourceEndpoint": { + "nodeId": { + "id": 246141082177684 + }, + "slotId": { + "m_id": "{E7F58DBD-3882-43D3-B44F-D2E68E5E7098}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246089542570132 + }, + "slotId": { + "m_id": "{CC9077E4-E835-4CAE-90EB-2B5FF8BA8F07}" + } + } + } + } + }, + { + "Id": { + "id": 246257046294676 + }, + "Name": "srcEndpoint=(GetWorldRotationQuaternion: Result: Quaternion), destEndpoint=(ConvertQuaternionToEulerDegrees: Quaternion: 0)", + "Components": { + "Component_[11761142503816878011]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 11761142503816878011, + "sourceEndpoint": { + "nodeId": { + "id": 246141082177684 + }, + "slotId": { + "m_id": "{81953E27-7B51-462D-9AB8-B122F33A7391}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246089542570132 + }, + "slotId": { + "m_id": "{A96CFD2A-531E-4330-B991-F27754DB21B4}" + } + } + } + } + }, + { + "Id": { + "id": 246261341261972 + }, + "Name": "srcEndpoint=(GetWorldTranslation: Result: Vector3), destEndpoint=(Add (+): Value)", + "Components": { + "Component_[11437964710666113038]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 11437964710666113038, + "sourceEndpoint": { + "nodeId": { + "id": 246068067733652 + }, + "slotId": { + "m_id": "{EBC733B4-A0E0-4772-888E-082AF8BA2FFF}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246106722439316 + }, + "slotId": { + "m_id": "{C59084D6-69B9-464E-B6C9-910F69509779}" + } + } + } + } + }, + { + "Id": { + "id": 246265636229268 + }, + "Name": "srcEndpoint=(Add (+): Out), destEndpoint=(SetNamedParameterVector3: In)", + "Components": { + "Component_[12246932468136989673]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 12246932468136989673, + "sourceEndpoint": { + "nodeId": { + "id": 246106722439316 + }, + "slotId": { + "m_id": "{E8BA15CB-A2B1-4824-92D6-2A71EEBF0378}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246171146948756 + }, + "slotId": { + "m_id": "{5D58862C-5682-4497-A994-F240120E8E62}" + } + } + } + } + }, + { + "Id": { + "id": 246269931196564 + }, + "Name": "srcEndpoint=(SetNamedParameterVector3: Out), destEndpoint=(DrawSphereAtLocation: In)", + "Components": { + "Component_[14273979275766531928]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14273979275766531928, + "sourceEndpoint": { + "nodeId": { + "id": 246171146948756 + }, + "slotId": { + "m_id": "{8F6FD0FC-11E5-49DD-A7D6-0AC0351E2DCA}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246102427472020 + }, + "slotId": { + "m_id": "{9B026749-1D6E-4F69-9F20-777A510FD7C4}" + } + } + } + } + }, + { + "Id": { + "id": 246282816098452 + }, + "Name": "srcEndpoint=(RotateVector3: Result), destEndpoint=(DrawRayEntityToDirection: Vector3: 1)", + "Components": { + "Component_[2134692939135952702]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 2134692939135952702, + "sourceEndpoint": { + "nodeId": { + "id": 246166851981460 + }, + "slotId": { + "m_id": "{099EF8F5-DE6F-45FC-9AA6-716996AAB7C6}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246123902308500 + }, + "slotId": { + "m_id": "{1ADF8F5A-62E9-41F0-B5BA-A53FA4D60311}" + } + } + } + } + }, + { + "Id": { + "id": 246287111065748 + }, + "Name": "srcEndpoint=(DrawSphereAtLocation: Out), destEndpoint=(DrawTextAtLocation: In)", + "Components": { + "Component_[5472516653628902263]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 5472516653628902263, + "sourceEndpoint": { + "nodeId": { + "id": 246102427472020 + }, + "slotId": { + "m_id": "{063DEA47-18F0-45C9-B2D6-BB6767B769DE}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246149672112276 + }, + "slotId": { + "m_id": "{31C53E9E-3EE2-4476-A4C3-4966FDA539CC}" + } + } + } + } + }, + { + "Id": { + "id": 246291406033044 + }, + "Name": "srcEndpoint=(Add (+): Result), destEndpoint=(SetNamedParameterVector3: Vector3: 2)", + "Components": { + "Component_[1844199703114757013]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 1844199703114757013, + "sourceEndpoint": { + "nodeId": { + "id": 246106722439316 + }, + "slotId": { + "m_id": "{B87A6F0B-DE2B-4E9E-9C44-D18F1B8706E4}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246171146948756 + }, + "slotId": { + "m_id": "{04958BE6-8525-49CA-9130-8CECD0BE43B3}" + } + } + } + } + }, + { + "Id": { + "id": 246295701000340 + }, + "Name": "srcEndpoint=(Add (+): Result), destEndpoint=(DrawSphereAtLocation: Vector3: 0)", + "Components": { + "Component_[2568324937444780316]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 2568324937444780316, + "sourceEndpoint": { + "nodeId": { + "id": 246106722439316 + }, + "slotId": { + "m_id": "{B87A6F0B-DE2B-4E9E-9C44-D18F1B8706E4}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246102427472020 + }, + "slotId": { + "m_id": "{67CBBEE3-F9B5-472E-8A3E-A82996CDA2D1}" + } + } + } + } + }, + { + "Id": { + "id": 246299995967636 + }, + "Name": "srcEndpoint=(Add (+): Result), destEndpoint=(DrawTextAtLocation: Vector3: 0)", + "Components": { + "Component_[14096020408718838099]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14096020408718838099, + "sourceEndpoint": { + "nodeId": { + "id": 246106722439316 + }, + "slotId": { + "m_id": "{B87A6F0B-DE2B-4E9E-9C44-D18F1B8706E4}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246149672112276 + }, + "slotId": { + "m_id": "{C1270538-1843-4392-B23C-12747DD40B15}" + } + } + } + } + }, + { + "Id": { + "id": 246304290934932 + }, + "Name": "srcEndpoint=(RotateVector3: Result), destEndpoint=(SetNamedParameterVector3: Vector3: 2)", + "Components": { + "Component_[16993908198950428448]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 16993908198950428448, + "sourceEndpoint": { + "nodeId": { + "id": 246145377144980 + }, + "slotId": { + "m_id": "{099EF8F5-DE6F-45FC-9AA6-716996AAB7C6}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246128197275796 + }, + "slotId": { + "m_id": "{04958BE6-8525-49CA-9130-8CECD0BE43B3}" + } + } + } + } + }, + { + "Id": { + "id": 246308585902228 + }, + "Name": "srcEndpoint=(RotateVector3: Result), destEndpoint=(DrawRayEntityToDirection: Vector3: 1)", + "Components": { + "Component_[8785804684259133429]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 8785804684259133429, + "sourceEndpoint": { + "nodeId": { + "id": 246145377144980 + }, + "slotId": { + "m_id": "{099EF8F5-DE6F-45FC-9AA6-716996AAB7C6}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246111017406612 + }, + "slotId": { + "m_id": "{1ADF8F5A-62E9-41F0-B5BA-A53FA4D60311}" + } + } + } + } + }, + { + "Id": { + "id": 246312880869524 + }, + "Name": "srcEndpoint=(ConvertQuaternionToEulerDegrees: Euler Angle), destEndpoint=(Extract Properties: Source)", + "Components": { + "Component_[9719260768879508209]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 9719260768879508209, + "sourceEndpoint": { + "nodeId": { + "id": 246136787210388 + }, + "slotId": { + "m_id": "{79FE68CC-45CC-4F5D-87A7-94B9144A3598}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246080952635540 + }, + "slotId": { + "m_id": "{8F09882E-A82E-481D-9FBD-FED706BEFB7C}" + } + } + } + } + }, + { + "Id": { + "id": 246317175836820 + }, + "Name": "srcEndpoint=(RotateVector3: Out), destEndpoint=(SetNamedParameterVector3: In)", + "Components": { + "Component_[14742201364563474463]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14742201364563474463, + "sourceEndpoint": { + "nodeId": { + "id": 246145377144980 + }, + "slotId": { + "m_id": "{C49165F2-9484-4E70-874F-4FD821B83AB0}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246128197275796 + }, + "slotId": { + "m_id": "{5D58862C-5682-4497-A994-F240120E8E62}" + } + } + } + } + }, + { + "Id": { + "id": 246321470804116 + }, + "Name": "srcEndpoint=(ConvertQuaternionToEulerDegrees: Out), destEndpoint=(Extract Properties: In)", + "Components": { + "Component_[3599648585598226717]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 3599648585598226717, + "sourceEndpoint": { + "nodeId": { + "id": 246136787210388 + }, + "slotId": { + "m_id": "{1286BE0C-88F5-4C0A-ADD6-EEE94AEA78A3}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246080952635540 + }, + "slotId": { + "m_id": "{B85B623A-CACB-4B96-98DB-E4F289AA01D4}" + } + } + } + } + }, + { + "Id": { + "id": 246325765771412 + }, + "Name": "srcEndpoint=(TickBus Handler: ExecutionSlot:OnTick), destEndpoint=(Get Variable: In)", + "Components": { + "Component_[10064893477852139475]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 10064893477852139475, + "sourceEndpoint": { + "nodeId": { + "id": 246093837537428 + }, + "slotId": { + "m_id": "{8965578E-A29D-4468-B12B-9D4E4F814641}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246175441916052 + }, + "slotId": { + "m_id": "{17B5B6FD-B942-4C0C-847E-3891BA11743B}" + } + } + } + } + }, + { + "Id": { + "id": 246330060738708 + }, + "Name": "srcEndpoint=(ConvertQuaternionToEulerDegrees: Euler Angle), destEndpoint=(Extract Properties: Source)", + "Components": { + "Component_[15688788304938115651]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 15688788304938115651, + "sourceEndpoint": { + "nodeId": { + "id": 246089542570132 + }, + "slotId": { + "m_id": "{79FE68CC-45CC-4F5D-87A7-94B9144A3598}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246158262046868 + }, + "slotId": { + "m_id": "{E14C7719-5419-444C-BCDF-23BFDFD40DA4}" + } + } + } + } + }, + { + "Id": { + "id": 246334355706004 + }, + "Name": "srcEndpoint=(ConvertQuaternionToEulerDegrees: Out), destEndpoint=(Extract Properties: In)", + "Components": { + "Component_[18268274144592574791]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 18268274144592574791, + "sourceEndpoint": { + "nodeId": { + "id": 246089542570132 + }, + "slotId": { + "m_id": "{1286BE0C-88F5-4C0A-ADD6-EEE94AEA78A3}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246158262046868 + }, + "slotId": { + "m_id": "{A6542FE6-CFED-4033-AC3A-64614B1BF141}" + } + } + } + } + }, + { + "Id": { + "id": 246338650673300 + }, + "Name": "srcEndpoint=(Get Variable: Out), destEndpoint=(FromValues: In)", + "Components": { + "Component_[10607947307671971003]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 10607947307671971003, + "sourceEndpoint": { + "nodeId": { + "id": 246072362700948 + }, + "slotId": { + "m_id": "{6D512DCD-4CA6-421F-9C23-214E4A757D5F}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246153967079572 + }, + "slotId": { + "m_id": "{7A425E1D-C67F-42D7-8377-124FDDCCD02B}" + } + } + } + } + }, + { + "Id": { + "id": 246342945640596 + }, + "Name": "srcEndpoint=(Get Variable: Number), destEndpoint=(FromValues: X)", + "Components": { + "Component_[6093226963465581941]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 6093226963465581941, + "sourceEndpoint": { + "nodeId": { + "id": 246175441916052 + }, + "slotId": { + "m_id": "{D44E36FC-7879-4E15-B0AA-0E9F866D2A5C}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246153967079572 + }, + "slotId": { + "m_id": "{8FACA5C3-ED4D-4DC2-8E6A-28AE1B340BE7}" + } + } + } + } + }, + { + "Id": { + "id": 246347240607892 + }, + "Name": "srcEndpoint=(Get Variable: Number), destEndpoint=(FromValues: Y)", + "Components": { + "Component_[9930139812119100083]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 9930139812119100083, + "sourceEndpoint": { + "nodeId": { + "id": 246072362700948 + }, + "slotId": { + "m_id": "{68E66FCE-1DF4-445A-9DD5-7D06D3A3146D}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246153967079572 + }, + "slotId": { + "m_id": "{A01573D8-5F5D-404B-A5BC-193480C65F28}" + } + } + } + } + }, + { + "Id": { + "id": 246351535575188 + }, + "Name": "srcEndpoint=(FromValues: Out), destEndpoint=(GetWorldRotationQuaternion: In)", + "Components": { + "Component_[13049608142141105699]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 13049608142141105699, + "sourceEndpoint": { + "nodeId": { + "id": 246153967079572 + }, + "slotId": { + "m_id": "{2EAFCACB-BC3D-4748-86F6-E2037A7CF487}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246141082177684 + }, + "slotId": { + "m_id": "{6BCB6E4B-E9C5-4D6E-A4AF-C2C76271E115}" + } + } + } + } + }, + { + "Id": { + "id": 246355830542484 + }, + "Name": "srcEndpoint=(Extract Properties: Out), destEndpoint=(RotationZDegrees: In)", + "Components": { + "Component_[2074083843557420377]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 2074083843557420377, + "sourceEndpoint": { + "nodeId": { + "id": 246158262046868 + }, + "slotId": { + "m_id": "{3EB4F651-DA08-45E5-94FE-432A8FC45914}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246098132504724 + }, + "slotId": { + "m_id": "{C9C41693-0E85-429F-B9CF-87102B7AF399}" + } + } + } + } + }, + { + "Id": { + "id": 246360125509780 + }, + "Name": "srcEndpoint=(RotationZDegrees: Result), destEndpoint=(RotateVector3: Quaternion)", + "Components": { + "Component_[10610503423712691047]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 10610503423712691047, + "sourceEndpoint": { + "nodeId": { + "id": 246098132504724 + }, + "slotId": { + "m_id": "{59A7EF4E-857E-4F2B-9466-37FE3C783EF9}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246166851981460 + }, + "slotId": { + "m_id": "{6F45F01E-F700-4594-98F0-A02A5BE00617}" + } + } + } + } + }, + { + "Id": { + "id": 246364420477076 + }, + "Name": "srcEndpoint=(RotationZDegrees: Out), destEndpoint=(RotateVector3: In)", + "Components": { + "Component_[14370414046864144573]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 14370414046864144573, + "sourceEndpoint": { + "nodeId": { + "id": 246098132504724 + }, + "slotId": { + "m_id": "{DFA7AD12-D253-4B55-95BF-EBD79C9F0986}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246166851981460 + }, + "slotId": { + "m_id": "{9704DF19-1C22-4E87-B461-EBA5E86CA68C}" + } + } + } + } + }, + { + "Id": { + "id": 246368715444372 + }, + "Name": "srcEndpoint=(Extract Properties: Out), destEndpoint=(RotationZDegrees: In)", + "Components": { + "Component_[1859237677254936695]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 1859237677254936695, + "sourceEndpoint": { + "nodeId": { + "id": 246080952635540 + }, + "slotId": { + "m_id": "{E6DBA835-98FA-4ADB-8F87-15604C8D3FD3}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246184031850644 + }, + "slotId": { + "m_id": "{424CC5BD-ACB0-4F1E-9700-DE29DE2F908E}" + } + } + } + } + }, + { + "Id": { + "id": 246373010411668 + }, + "Name": "srcEndpoint=(RotationZDegrees: Out), destEndpoint=(RotateVector3: In)", + "Components": { + "Component_[5790169301321537787]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 5790169301321537787, + "sourceEndpoint": { + "nodeId": { + "id": 246184031850644 + }, + "slotId": { + "m_id": "{6D35C87C-35B1-49F2-9FE6-2FE2991AAB8D}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246145377144980 + }, + "slotId": { + "m_id": "{9704DF19-1C22-4E87-B461-EBA5E86CA68C}" + } + } + } + } + }, + { + "Id": { + "id": 246377305378964 + }, + "Name": "srcEndpoint=(RotationZDegrees: Result), destEndpoint=(RotateVector3: Quaternion)", + "Components": { + "Component_[9113874641309049506]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 9113874641309049506, + "sourceEndpoint": { + "nodeId": { + "id": 246184031850644 + }, + "slotId": { + "m_id": "{C2F9543A-928E-4405-A269-D8F952D227DB}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246145377144980 + }, + "slotId": { + "m_id": "{6F45F01E-F700-4594-98F0-A02A5BE00617}" + } + } + } + } + }, + { + "Id": { + "id": 246381600346260 + }, + "Name": "srcEndpoint=(Extract Properties: Z), destEndpoint=(RotationZDegrees: Degrees)", + "Components": { + "Component_[16079074013127612900]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 16079074013127612900, + "sourceEndpoint": { + "nodeId": { + "id": 246080952635540 + }, + "slotId": { + "m_id": "{E7EB179B-BACB-44DB-B2D1-D5D4788D80D8}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246184031850644 + }, + "slotId": { + "m_id": "{E2E3C0BC-56A7-4504-BEFA-1F1673DE7B0E}" + } + } + } + } + }, + { + "Id": { + "id": 246385895313556 + }, + "Name": "srcEndpoint=(Extract Properties: Z), destEndpoint=(RotationZDegrees: Degrees)", + "Components": { + "Component_[324913126273692816]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 324913126273692816, + "sourceEndpoint": { + "nodeId": { + "id": 246158262046868 + }, + "slotId": { + "m_id": "{B138BB48-9B60-4DE3-8DF0-DCC17D0D6358}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246098132504724 + }, + "slotId": { + "m_id": "{5076FEE2-72A1-4E2C-8FAF-649186F6F022}" + } + } + } + } + }, + { + "Id": { + "id": 246394485248148 + }, + "Name": "srcEndpoint=(FromValues: Result), destEndpoint=(RotateVector3: Vector)", + "Components": { + "Component_[8522346125520723525]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 8522346125520723525, + "sourceEndpoint": { + "nodeId": { + "id": 246153967079572 + }, + "slotId": { + "m_id": "{5029C117-20D4-4CE1-9097-FBBC98B4F457}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246076657668244 + }, + "slotId": { + "m_id": "{B46DDF66-DA5E-474C-A740-5472FBBF285A}" + } + } + } + } + }, + { + "Id": { + "id": 246398780215444 + }, + "Name": "srcEndpoint=(RotationZDegrees: Result), destEndpoint=(RotateVector3: Quaternion)", + "Components": { + "Component_[16701501001610934713]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 16701501001610934713, + "sourceEndpoint": { + "nodeId": { + "id": 246184031850644 + }, + "slotId": { + "m_id": "{C2F9543A-928E-4405-A269-D8F952D227DB}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246076657668244 + }, + "slotId": { + "m_id": "{72351E0C-D3F5-4181-90CB-8A4E0557A978}" + } + } + } + } + }, + { + "Id": { + "id": 246407370150036 + }, + "Name": "srcEndpoint=(RotateVector3: Result), destEndpoint=(Add (+): Vector3)", + "Components": { + "Component_[725702429325335637]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 725702429325335637, + "sourceEndpoint": { + "nodeId": { + "id": 246076657668244 + }, + "slotId": { + "m_id": "{879125AE-8729-465D-A3E3-1DAF6B9C84C7}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246106722439316 + }, + "slotId": { + "m_id": "{FBF48C32-3CCB-47CA-BC9E-45567BF1B269}" + } + } + } + } + }, + { + "Id": { + "id": 246411665117332 + }, + "Name": "srcEndpoint=(RotateVector3: Out), destEndpoint=(GetWorldTranslation: In)", + "Components": { + "Component_[18297619570874862126]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 18297619570874862126, + "sourceEndpoint": { + "nodeId": { + "id": 246076657668244 + }, + "slotId": { + "m_id": "{8D7093BA-E37A-48D7-ABB6-8D3960A60BF0}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246068067733652 + }, + "slotId": { + "m_id": "{5AAE80BB-C549-4D61-AC36-57FF33A0F9B9}" + } + } + } + } + }, + { + "Id": { + "id": 246415960084628 + }, + "Name": "srcEndpoint=(GetWorldTranslation: Out), destEndpoint=(Add (+): In)", + "Components": { + "Component_[5276081108224246554]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 5276081108224246554, + "sourceEndpoint": { + "nodeId": { + "id": 246068067733652 + }, + "slotId": { + "m_id": "{D6245737-F70E-431A-8DB2-D187634B6859}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246106722439316 + }, + "slotId": { + "m_id": "{1AD1DED1-EDE6-4FAF-B3B6-FB5B26F1B294}" + } + } + } + } + }, + { + "Id": { + "id": 201379649551848 + }, + "Name": "srcEndpoint=(SetNamedParameterVector3: Out), destEndpoint=(RotateVector3: In)", + "Components": { + "Component_[203700470042535327]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 203700470042535327, + "sourceEndpoint": { + "nodeId": { + "id": 246128197275796 + }, + "slotId": { + "m_id": "{8F6FD0FC-11E5-49DD-A7D6-0AC0351E2DCA}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246076657668244 + }, + "slotId": { + "m_id": "{8C5BE0B0-13CC-43A5-8F44-9C282B3E4D60}" + } + } + } + } + }, + { + "Id": { + "id": 202487751114216 + }, + "Name": "srcEndpoint=(RotateVector3: Out), destEndpoint=(GetWorldRotationQuaternion: In)", + "Components": { + "Component_[1253233322229674061]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 1253233322229674061, + "sourceEndpoint": { + "nodeId": { + "id": 246166851981460 + }, + "slotId": { + "m_id": "{C49165F2-9484-4E70-874F-4FD821B83AB0}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 246188326817940 + }, + "slotId": { + "m_id": "{6BCB6E4B-E9C5-4D6E-A4AF-C2C76271E115}" + } + } + } + } + } + ] + }, + "m_assetType": "{3E2AC8CD-713F-453E-967F-29517F331784}", + "versionData": { + "_grammarVersion": 1, + "_runtimeVersion": 1, + "_fileVersion": 1 + }, + "m_variableCounter": 3, + "GraphCanvasData": [ + { + "Key": { + "id": 246068067733652 + }, + "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": [ + 4540.0, + 2340.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{2FF9E28B-794F-4595-B6CD-F3894076C6E7}" + } + } + } + }, + { + "Key": { + "id": 246072362700948 + }, + "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": [ + 740.0, + 1760.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".getVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{507C10BA-288C-4E68-AEFB-949E4EDA039B}" + } + } + } + }, + { + "Key": { + "id": 246076657668244 + }, + "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": [ + 4200.0, + 2500.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{4BF9A06C-7D50-4FF3-9A4C-55C44FA8F7EF}" + } + } + } + }, + { + "Key": { + "id": 246080952635540 + }, + "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": [ + 1300.0, + 2580.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{4DED46A4-C20B-43F8-A242-8A379685D4F4}" + } + } + } + }, + { + "Key": { + "id": 246085247602836 + }, + "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": [ + 860.0, + -20.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{504E5761-0540-481C-98F1-7C473F7FAD1B}" + } + } + } + }, + { + "Key": { + "id": 246089542570132 + }, + "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": [ + 1980.0, + 1200.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{C7970815-CCB0-4FE2-874D-09968D0C09A5}" + } + } + } + }, + { + "Key": { + "id": 246093837537428 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -160.0, + 1840.0 + ] + }, + "{9E81C95F-89C0-4476-8E82-63CCC4E52E04}": { + "$type": "EBusHandlerNodeDescriptorSaveData", + "EventIds": [ + { + "Value": 1502188240 + } + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{4BD96082-9121-41AC-9C04-7EED59FF8183}" + } + } + } + }, + { + "Key": { + "id": 246098132504724 + }, + "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": [ + 2780.0, + 1240.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{8A15E090-E8AA-4A1E-ABC2-161955729668}" + } + } + } + }, + { + "Key": { + "id": 246102427472020 + }, + "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": [ + 6080.0, + 2280.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{7CCBB240-958D-4A7F-AAB2-C538251C427D}" + } + } + } + }, + { + "Key": { + "id": 246106722439316 + }, + "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": [ + 5140.0, + 2340.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{11DD29F2-0432-479B-AA6A-D1A0A40A6A44}" + } + } + } + }, + { + "Key": { + "id": 246115312373908 + }, + "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": [ + -160.0, + 280.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{CEFD1956-B60A-4727-BEEF-A31E5D712BBF}" + } + } + } + }, + { + "Key": { + "id": 246119607341204 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "SetVariableNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 440.0, + 0.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".setVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{A6009AED-C3E9-4891-8FB8-E7778CB5A9B5}" + } + } + } + }, + { + "Key": { + "id": 246128197275796 + }, + "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": [ + 2840.0, + 2580.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{039ADCFA-B370-4150-96A0-D404A8784B5A}" + } + } + } + }, + { + "Key": { + "id": 246132492243092 + }, + "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": [ + -160.0, + -100.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{E129EEFF-892C-4C5A-86F2-DB349E0BEB1E}" + } + } + } + }, + { + "Key": { + "id": 246136787210388 + }, + "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": [ + 860.0, + 2580.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{181C9959-F9CE-4E83-A28F-34A6122A5FBD}" + } + } + } + }, + { + "Key": { + "id": 246141082177684 + }, + "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": [ + 1540.0, + 1200.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{1F571FC4-D31A-45B9-912B-553620D3BD9D}" + } + } + } + }, + { + "Key": { + "id": 246145377144980 + }, + "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": [ + 2040.0, + 2580.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{92D9C6D1-1261-4404-8F47-B372687FAC49}" + } + } + } + }, + { + "Key": { + "id": 246149672112276 + }, + "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": [ + 6520.0, + 2280.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{86F8827F-9F3C-4A93-89E2-F120EB7DD2AC}" + } + } + } + }, + { + "Key": { + "id": 246153967079572 + }, + "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": [ + 1080.0, + 1740.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{070D096C-3906-46C6-9004-AB47CC3CA321}" + } + } + } + }, + { + "Key": { + "id": 246158262046868 + }, + "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": [ + 2420.0, + 1200.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{A11A84D2-7BF6-4FE1-8C29-E7178CA9AF50}" + } + } + } + }, + { + "Key": { + "id": 246162557014164 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "SetVariableNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 440.0, + 360.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".setVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{5B946F71-A93B-438E-A7B0-27CE24D672B0}" + } + } + } + }, + { + "Key": { + "id": 246166851981460 + }, + "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": [ + 3440.0, + 1120.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{E9D6CBC8-A0AF-48AF-9432-644B01BD8E87}" + } + } + } + }, + { + "Key": { + "id": 246171146948756 + }, + "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": [ + 5740.0, + 2280.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{96C3A2DA-6948-4773-BBF7-E72690F95D27}" + } + } + } + }, + { + "Key": { + "id": 246175441916052 + }, + "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": [ + 500.0, + 1760.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".getVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{C91F684B-BDF4-45B6-8A21-BE01BD0B57E6}" + } + } + } + }, + { + "Key": { + "id": 246179736883348 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -600.0, + 140.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": "{ED62B820-56F3-4907-8297-93FACF11D6C7}" + } + } + } + }, + { + "Key": { + "id": 246184031850644 + }, + "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": [ + 1640.0, + 2620.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{CA7C06D5-1C74-4682-8475-77B4590D1068}" + } + } + } + }, + { + "Key": { + "id": 246188326817940 + }, + "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": [ + 420.0, + 2580.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{40F91617-FB9A-44B0-AB46-7BC49BFA9695}" + } + } + } + }, + { + "Key": { + "id": 246192621785236 + }, + "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": [ + 860.0, + 340.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{25B84E08-7E28-49F4-8D3F-2D5436AD4A59}" + } + } + } + }, + { + "Key": { + "id": 3794495145504990811 + }, + "Value": { + "ComponentData": { + "{5F84B500-8C45-40D1-8EFC-A5306B241444}": { + "$type": "SceneComponentSaveData", + "ViewParams": { + "Scale": 0.41824002620728956, + "AnchorX": 1786.0557861328125, + "AnchorY": 686.2088623046875 + } + } + } + } + } + ], + "StatisticsHelper": { + "InstanceCounter": [ + { + "Key": 1244476766431948410, + "Value": 1 + }, + { + "Key": 5842116761103598202, + "Value": 1 + }, + { + "Key": 5842117451819972883, + "Value": 1 + }, + { + "Key": 5933558821430063196, + "Value": 1 + }, + { + "Key": 7413323401356093379, + "Value": 2 + }, + { + "Key": 8023800818767041160, + "Value": 2 + }, + { + "Key": 8443300848607535552, + "Value": 1 + }, + { + "Key": 10242161751377247902, + "Value": 1 + }, + { + "Key": 10684225535275896474, + "Value": 2 + }, + { + "Key": 12812762535860395237, + "Value": 1 + }, + { + "Key": 13501032720093015244, + "Value": 2 + }, + { + "Key": 13774516225767375488, + "Value": 1 + }, + { + "Key": 13774516226110902316, + "Value": 1 + }, + { + "Key": 13774516341676861545, + "Value": 2 + }, + { + "Key": 13774516555191045853, + "Value": 2 + }, + { + "Key": 13774516556399355685, + "Value": 1 + }, + { + "Key": 14285852892804039565, + "Value": 2 + }, + { + "Key": 14759916521179134347, + "Value": 1 + }, + { + "Key": 18182167487771916815, + "Value": 3 + } + ] + } + }, + "Component_[9726965826837406164]": { + "$type": "EditorGraphVariableManagerComponent", + "Id": 9726965826837406164, + "m_variableData": { + "m_nameVariableMap": [ + { + "Key": { + "m_id": "{5EB17E58-0B4E-451D-A1CE-0E7C272CBDEC}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0 + }, + "VariableId": { + "m_id": "{5EB17E58-0B4E-451D-A1CE-0E7C272CBDEC}" + }, + "VariableName": "MoveY" + } + }, + { + "Key": { + "m_id": "{B48E5726-A7FF-42A8-84D2-CF43ABBD1EDC}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0 + }, + "VariableId": { + "m_id": "{B48E5726-A7FF-42A8-84D2-CF43ABBD1EDC}" + }, + "VariableName": "MoveX" + } + } + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/MotionMatching_AutomaticDemo.animgraph b/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/MotionMatching_AutomaticDemo.animgraph new file mode 100644 index 0000000000..c8633beba2 --- /dev/null +++ b/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/MotionMatching_AutomaticDemo.animgraph @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6476e88fb2bcda44f7ef57d87f2ff7f4d6e3a30f677ad1b7b235c43b3858aa7f +size 39099 diff --git a/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/MotionMatching_AutomaticDemo.ly b/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/MotionMatching_AutomaticDemo.ly new file mode 100644 index 0000000000..592531e632 --- /dev/null +++ b/Gems/MotionMatching/Assets/Levels/MotionMatching_AutomaticDemo/MotionMatching_AutomaticDemo.ly @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:065170c8b2dca1e481b70ed648fc149767e795b0794b6b4b0af3f79054a2f93c +size 11797 diff --git a/Gems/MotionMatching/Assets/MotionMatching.animgraph b/Gems/MotionMatching/Assets/MotionMatching.animgraph index 10707eb6c4..e5656a3d05 100644 --- a/Gems/MotionMatching/Assets/MotionMatching.animgraph +++ b/Gems/MotionMatching/Assets/MotionMatching.animgraph @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:09cc2374b99c219421812ec39b68a350912d44777a50e3078c8cd67e91cc74cf -size 30927 +oid sha256:f974fa29f3542311ee6a4b6fbb92047186c3124b3bd6f88b728646bf9d686c45 +size 39099 diff --git a/Gems/MotionMatching/Assets/MotionMatching.motionset b/Gems/MotionMatching/Assets/MotionMatching.motionset index 276895e3a0..f3f0510e6d 100644 --- a/Gems/MotionMatching/Assets/MotionMatching.motionset +++ b/Gems/MotionMatching/Assets/MotionMatching.motionset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c895a1696f5f37492089ceaef11210d704c1fb7e3dd31305cf4732d63489507 -size 13645 +oid sha256:35bb5b196bc07687004aed1ddff7e3b922f8abe82b0e6b25c88854d9032c6f06 +size 13482 diff --git a/Gems/MotionMatching/Code/Source/Feature.h b/Gems/MotionMatching/Code/Source/Feature.h index 322cf03734..1d33f9b465 100644 --- a/Gems/MotionMatching/Code/Source/Feature.h +++ b/Gems/MotionMatching/Code/Source/Feature.h @@ -98,8 +98,8 @@ namespace EMotionFX::MotionMatching }; virtual float CalculateFrameCost(size_t frameIndex, const FrameCostContext& context) const; - /// Specifies how the feature value differences (residuals), between the input query values - /// and the frames in the motion database that sum up the feature cost, are calculated. + //! Specifies how the feature value differences (residuals), between the input query values + //! and the frames in the motion database that sum up the feature cost, are calculated. enum ResidualType { Absolute, diff --git a/Gems/MotionMatching/preview.png b/Gems/MotionMatching/preview.png index 2979dbb6a4..b3b6192ad5 100644 --- a/Gems/MotionMatching/preview.png +++ b/Gems/MotionMatching/preview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de0e6e480ece5b423222f4feacf56553d73713fe9afea8bbc9a2660a3cd54ec7 -size 1232 +oid sha256:e0f8ffb4980f6cfc34135f4a4b9967293ff34bcdb37019181cb22c6a07067ce8 +size 57461 diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index c0b6758147..c6ac85d314 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -513,7 +513,6 @@ namespace ScriptCanvasEditor m_editorToolbar->AddCustomAction(m_createFunctionOutput); connect(m_createFunctionOutput, &QToolButton::clicked, this, &MainWindow::CreateFunctionOutput); - { m_validateGraphToolButton = new QToolButton(); m_validateGraphToolButton->setToolTip("Will run a validation check on the current graph and report any warnings/errors discovered."); @@ -523,6 +522,18 @@ namespace ScriptCanvasEditor m_editorToolbar->AddCustomAction(m_validateGraphToolButton); + // Screenshot + { + m_takeScreenshot = new QToolButton(); + m_takeScreenshot->setToolTip("Captures a full resolution screenshot of the entire graph or selected nodes into the clipboard"); + m_takeScreenshot->setIcon(QIcon(":/ScriptCanvasEditorResources/Resources/scriptcanvas_screenshot.png")); + m_takeScreenshot->setEnabled(false); + } + + m_editorToolbar->AddCustomAction(m_takeScreenshot); + connect(m_takeScreenshot, &QToolButton::clicked, this, &MainWindow::OnScreenshot); + + connect(m_validateGraphToolButton, &QToolButton::clicked, this, &MainWindow::OnValidateCurrentGraph); m_layout->addWidget(m_editorToolbar); @@ -3211,6 +3222,7 @@ namespace ScriptCanvasEditor m_createFunctionOutput->setEnabled(enabled); m_createFunctionInput->setEnabled(enabled); + m_takeScreenshot->setEnabled(enabled); // File Menu ui->action_Close->setEnabled(enabled); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h index 75c798a0d3..d05792c4ec 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h @@ -648,6 +648,7 @@ namespace ScriptCanvasEditor QToolButton* m_createFunctionInput = nullptr; QToolButton* m_createFunctionOutput = nullptr; + QToolButton* m_takeScreenshot = nullptr; QToolButton* m_createScriptCanvas = nullptr; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Resources/scriptcanvas_screenshot.png b/Gems/ScriptCanvas/Code/Editor/View/Windows/Resources/scriptcanvas_screenshot.png new file mode 100644 index 0000000000..7daa11d945 --- /dev/null +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Resources/scriptcanvas_screenshot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef1d048b1ef82137424b6c346e7f87f156e97402ecc89eca8c0dc0e2b6acc395 +size 400 diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasEditorResources.qrc b/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasEditorResources.qrc index be90d229dc..9244f71ca3 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasEditorResources.qrc +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasEditorResources.qrc @@ -34,6 +34,7 @@ Resources/scriptcanvas_nodes.png Resources/scriptcanvas_outliner.png Resources/scriptcanvas_properties.png + Resources/scriptcanvas_screenshot.png Resources/scriptcanvas_variables.png Resources/settings_icon.png Resources/settings_dropdown_icon.png diff --git a/Gems/SurfaceData/Code/Include/SurfaceData/Utility/SurfaceDataUtility.h b/Gems/SurfaceData/Code/Include/SurfaceData/Utility/SurfaceDataUtility.h index 29b3fac8c7..2a4a39ee3b 100644 --- a/Gems/SurfaceData/Code/Include/SurfaceData/Utility/SurfaceDataUtility.h +++ b/Gems/SurfaceData/Code/Include/SurfaceData/Utility/SurfaceDataUtility.h @@ -88,6 +88,16 @@ namespace SurfaceData const AZ::Vector3& rayStart, const AZ::Vector3& rayEnd, AZ::Vector3& outPosition, AZ::Vector3& outNormal); + AZ_INLINE void AssignSurfaceTagWeights(const SurfaceTagVector& tags, float weight, SurfaceTagWeightMap& weights) + { + weights.clear(); + weights.reserve(tags.size()); + for (auto& tag : tags) + { + weights[tag] = weight; + } + } + AZ_INLINE void AddMaxValueForMasks(SurfaceTagWeightMap& masks, const AZ::Crc32 tag, const float value) { const auto maskItr = masks.find(tag); @@ -166,7 +176,8 @@ namespace SurfaceData } template - AZ_INLINE bool HasMatchingTags(const SurfaceTagWeightMap& sourceTags, const SampleContainer& sampleTags, float valueMin, float valueMax) + AZ_INLINE bool HasMatchingTags( + const SurfaceTagWeightMap& sourceTags, const SampleContainer& sampleTags, float valueMin, float valueMax) { for (const auto& sampleTag : sampleTags) { diff --git a/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.cpp b/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.cpp index d7de299829..dc4e5e6e74 100644 --- a/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.cpp +++ b/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.cpp @@ -132,6 +132,7 @@ namespace SurfaceData Physics::ColliderComponentEventBus::Handler::BusConnect(GetEntityId()); // Update the cached collider data and bounds, then register the surface data provider / modifier + AssignSurfaceTagWeights(m_configuration.m_providerTags, 1.0f, m_newPointWeights); UpdateColliderData(); } @@ -157,7 +158,7 @@ namespace SurfaceData // Clear the cached mesh data { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::unique_lock lock(m_cacheMutex); m_colliderBounds = AZ::Aabb::CreateNull(); } } @@ -184,7 +185,7 @@ namespace SurfaceData bool SurfaceDataColliderComponent::DoRayTrace(const AZ::Vector3& inPosition, bool queryPointOnly, AZ::Vector3& outPosition, AZ::Vector3& outNormal) const { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::shared_lock lock(m_cacheMutex); // test AABB as first pass to claim the point const AZ::Vector3 testPosition = AZ::Vector3( @@ -240,17 +241,14 @@ namespace SurfaceData point.m_entityId = GetEntityId(); point.m_position = hitPosition; point.m_normal = hitNormal; - for (auto& tag : m_configuration.m_providerTags) - { - point.m_masks[tag] = 1.0f; - } - surfacePointList.push_back(point); + point.m_masks = m_newPointWeights; + surfacePointList.push_back(AZStd::move(point)); } } void SurfaceDataColliderComponent::ModifySurfacePoints(SurfacePointList& surfacePointList) const { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::shared_lock lock(m_cacheMutex); if (m_colliderBounds.IsValid() && !m_configuration.m_modifierTags.empty()) { @@ -308,7 +306,7 @@ namespace SurfaceData bool colliderValidAfterUpdate = false; { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::unique_lock lock(m_cacheMutex); colliderValidBeforeUpdate = m_colliderBounds.IsValid(); diff --git a/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.h b/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.h index 43528ecae3..50c84f9519 100644 --- a/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.h +++ b/Gems/SurfaceData/Code/Source/Components/SurfaceDataColliderComponent.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -98,7 +99,8 @@ namespace SurfaceData // cached data AZStd::atomic_bool m_refresh{ false }; - mutable AZStd::recursive_mutex m_cacheMutex; + mutable AZStd::shared_mutex m_cacheMutex; AZ::Aabb m_colliderBounds = AZ::Aabb::CreateNull(); + SurfaceTagWeightMap m_newPointWeights; }; } diff --git a/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.cpp b/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.cpp index a45903498e..682bac150a 100644 --- a/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.cpp +++ b/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.cpp @@ -89,6 +89,7 @@ namespace SurfaceData LmbrCentral::ShapeComponentNotificationsBus::Handler::BusConnect(GetEntityId()); // Update the cached shape data and bounds, then register the surface data provider / modifier + AssignSurfaceTagWeights(m_configuration.m_providerTags, 1.0f, m_newPointWeights); UpdateShapeData(); } @@ -115,7 +116,7 @@ namespace SurfaceData // Clear the cached shape data { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::unique_lock lock(m_cacheMutex); m_shapeBounds = AZ::Aabb::CreateNull(); m_shapeBoundsIsValid = false; } @@ -143,7 +144,7 @@ namespace SurfaceData void SurfaceDataShapeComponent::GetSurfacePoints(const AZ::Vector3& inPosition, SurfacePointList& surfacePointList) const { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::shared_lock lock(m_cacheMutex); if (m_shapeBoundsIsValid) { @@ -158,36 +159,35 @@ namespace SurfaceData point.m_entityId = GetEntityId(); point.m_position = rayOrigin + intersectionDistance * rayDirection; point.m_normal = AZ::Vector3::CreateAxisZ(); - for (auto& tag : m_configuration.m_providerTags) - { - point.m_masks[tag] = 1.0f; - } - surfacePointList.push_back(point); + point.m_masks = m_newPointWeights; + surfacePointList.push_back(AZStd::move(point)); } } } void SurfaceDataShapeComponent::ModifySurfacePoints(SurfacePointList& surfacePointList) const { - AZ_PROFILE_FUNCTION(Entity); - - AZStd::lock_guard lock(m_cacheMutex); + AZStd::shared_lock lock(m_cacheMutex); if (m_shapeBoundsIsValid && !m_configuration.m_modifierTags.empty()) { const AZ::EntityId entityId = GetEntityId(); - for (auto& point : surfacePointList) - { - if (point.m_entityId != entityId && m_shapeBounds.Contains(point.m_position)) + LmbrCentral::ShapeComponentRequestsBus::Event( + GetEntityId(), + [entityId, this, &surfacePointList](LmbrCentral::ShapeComponentRequestsBus::Events* shape) { - bool inside = false; - LmbrCentral::ShapeComponentRequestsBus::EventResult(inside, GetEntityId(), &LmbrCentral::ShapeComponentRequestsBus::Events::IsPointInside, point.m_position); - if (inside) + for (auto& point : surfacePointList) { - AddMaxValueForMasks(point.m_masks, m_configuration.m_modifierTags, 1.0f); + if (point.m_entityId != entityId && m_shapeBounds.Contains(point.m_position)) + { + bool inside = shape->IsPointInside(point.m_position); + if (inside) + { + AddMaxValueForMasks(point.m_masks, m_configuration.m_modifierTags, 1.0f); + } + } } - } - } + }); } } @@ -228,7 +228,7 @@ namespace SurfaceData bool shapeValidAfterUpdate = false; { - AZStd::lock_guard lock(m_cacheMutex); + AZStd::unique_lock lock(m_cacheMutex); shapeValidBeforeUpdate = m_shapeBoundsIsValid; diff --git a/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.h b/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.h index f2c478ed27..59b7950412 100644 --- a/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.h +++ b/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -92,9 +93,10 @@ namespace SurfaceData // cached data AZStd::atomic_bool m_refresh{ false }; - mutable AZStd::recursive_mutex m_cacheMutex; + mutable AZStd::shared_mutex m_cacheMutex; AZ::Aabb m_shapeBounds = AZ::Aabb::CreateNull(); bool m_shapeBoundsIsValid = false; static const float s_rayAABBHeightPadding; + SurfaceTagWeightMap m_newPointWeights; }; } diff --git a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp b/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp index a2a3bc352e..66f282d12b 100644 --- a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp +++ b/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.cpp @@ -181,10 +181,10 @@ namespace SurfaceData void SurfaceDataSystemComponent::GetSurfacePoints(const AZ::Vector3& inPosition, const SurfaceTagVector& desiredTags, SurfacePointList& surfacePointList) const { - const bool hasDesiredTags = HasValidTags(desiredTags); - const bool hasModifierTags = hasDesiredTags && HasMatchingTags(desiredTags, m_registeredModifierTags); + const bool useTagFilters = HasValidTags(desiredTags); + const bool hasModifierTags = useTagFilters && HasMatchingTags(desiredTags, m_registeredModifierTags); - AZStd::lock_guard registrationLock(m_registrationMutex); + AZStd::shared_lock registrationLock(m_registrationMutex); surfacePointList.clear(); @@ -195,7 +195,7 @@ namespace SurfaceData const SurfaceDataRegistryEntry& entry = entryPair.second; if (!entry.m_bounds.IsValid() || AabbContains2D(entry.m_bounds, inPosition)) { - if (!hasDesiredTags || hasModifierTags || HasMatchingTags(desiredTags, entry.m_tags)) + if (!useTagFilters || hasModifierTags || HasMatchingTags(desiredTags, entry.m_tags)) { SurfaceDataProviderRequestBus::Event(entryAddress, &SurfaceDataProviderRequestBus::Events::GetSurfacePoints, inPosition, surfacePointList); } @@ -219,7 +219,12 @@ namespace SurfaceData // same XY coordinates and extremely similar Z values. This produces results that are sorted in decreasing Z order. // Also, this filters out any remaining points that don't match the desired tag list. This can happen when a surface provider // doesn't add a desired tag, and a surface modifier has the *potential* to add it, but then doesn't. - CombineSortAndFilterNeighboringPoints(surfacePointList, hasDesiredTags, desiredTags); + if (useTagFilters) + { + FilterPoints(surfacePointList, desiredTags); + } + + CombineAndSortNeighboringPoints(surfacePointList); } } @@ -248,34 +253,33 @@ namespace SurfaceData void SurfaceDataSystemComponent::GetSurfacePointsFromList( AZStd::span inPositions, const SurfaceTagVector& desiredTags, SurfacePointLists& surfacePointLists) const { - AZStd::lock_guard registrationLock(m_registrationMutex); + AZStd::shared_lock registrationLock(m_registrationMutex); const size_t totalQueryPositions = inPositions.size(); surfacePointLists.clear(); surfacePointLists.resize(totalQueryPositions); - const bool hasDesiredTags = HasValidTags(desiredTags); - const bool hasModifierTags = hasDesiredTags && HasMatchingTags(desiredTags, m_registeredModifierTags); + const bool useTagFilters = HasValidTags(desiredTags); + const bool hasModifierTags = useTagFilters && HasMatchingTags(desiredTags, m_registeredModifierTags); // Loop through each data provider, and query all the points for each one. This allows us to check the tags and the overall // AABB bounds just once per provider, instead of once per point. It also allows for an eventual optimization in which we could // send the list of points directly into each SurfaceDataProvider. - for (const auto& entryPair : m_registeredSurfaceDataProviders) + for (const auto& [providerHandle, provider] : m_registeredSurfaceDataProviders) { - const SurfaceDataRegistryEntry& entry = entryPair.second; - bool alwaysApplies = !entry.m_bounds.IsValid(); + bool hasInfiniteBounds = !provider.m_bounds.IsValid(); - if (!hasDesiredTags || hasModifierTags || HasMatchingTags(desiredTags, entry.m_tags)) + if (!useTagFilters || hasModifierTags || HasMatchingTags(desiredTags, provider.m_tags)) { for (size_t index = 0; index < totalQueryPositions; index++) { - const auto& inPosition = inPositions[index]; - SurfacePointList& surfacePointList = surfacePointLists[index]; - if (alwaysApplies || AabbContains2D(entry.m_bounds, inPosition)) + bool inBounds = hasInfiniteBounds || AabbContains2D(provider.m_bounds, inPositions[index]); + if (inBounds) { SurfaceDataProviderRequestBus::Event( - entryPair.first, &SurfaceDataProviderRequestBus::Events::GetSurfacePoints, inPosition, surfacePointList); + providerHandle, &SurfaceDataProviderRequestBus::Events::GetSurfacePoints, + inPositions[index], surfacePointLists[index]); } } } @@ -289,7 +293,7 @@ namespace SurfaceData for (const auto& entryPair : m_registeredSurfaceDataModifiers) { const SurfaceDataRegistryEntry& entry = entryPair.second; - bool alwaysApplies = !entry.m_bounds.IsValid(); + bool hasInfiniteBounds = !entry.m_bounds.IsValid(); for (size_t index = 0; index < totalQueryPositions; index++) { @@ -297,10 +301,11 @@ namespace SurfaceData SurfacePointList& surfacePointList = surfacePointLists[index]; if (!surfacePointList.empty()) { - if (alwaysApplies || AabbContains2D(entry.m_bounds, inPosition)) + if (hasInfiniteBounds || AabbContains2D(entry.m_bounds, inPosition)) { SurfaceDataModifierRequestBus::Event( - entryPair.first, &SurfaceDataModifierRequestBus::Events::ModifySurfacePoints, surfacePointList); + entryPair.first, &SurfaceDataModifierRequestBus::Events::ModifySurfacePoints, + surfacePointList); } } } @@ -312,88 +317,85 @@ namespace SurfaceData // doesn't add a desired tag, and a surface modifier has the *potential* to add it, but then doesn't. for (auto& surfacePointList : surfacePointLists) { - if (!surfacePointList.empty()) + if (useTagFilters) { - CombineSortAndFilterNeighboringPoints(surfacePointList, hasDesiredTags, desiredTags); + FilterPoints(surfacePointList, desiredTags); } + CombineAndSortNeighboringPoints(surfacePointList); } + } - - - void SurfaceDataSystemComponent::CombineSortAndFilterNeighboringPoints(SurfacePointList& sourcePointList, bool hasDesiredTags, const SurfaceTagVector& desiredTags) const + void SurfaceDataSystemComponent::FilterPoints(SurfacePointList& sourcePointList, const SurfaceTagVector& desiredTags) const { - AZ_PROFILE_FUNCTION(Entity); + // Before sorting and combining, filter out any points that don't match our search tags. + sourcePointList.erase( + AZStd::remove_if( + sourcePointList.begin(), sourcePointList.end(), + [desiredTags](SurfacePoint& point) -> bool + { + return !HasMatchingTags(point.m_masks, desiredTags); + }), + sourcePointList.end()); + } - if (sourcePointList.empty()) + void SurfaceDataSystemComponent::CombineAndSortNeighboringPoints(SurfacePointList& sourcePointList) const + { + // If there's only 0 or 1 point, there is no sorting or combining that needs to happen, so just return. + if (sourcePointList.size() <= 1) { return; } - // Sorting only makes sense if we have two or more points - if (sourcePointList.size() > 1) + // Efficient point consolidation requires the points to be pre-sorted so we are only comparing/combining neighbors. + // Sort XY points together, with decreasing Z. + AZStd::sort(sourcePointList.begin(), sourcePointList.end(), [](const SurfacePoint& a, const SurfacePoint& b) { - //sort by depth/distance before combining points - AZStd::sort(sourcePointList.begin(), sourcePointList.end(), [](const SurfacePoint& a, const SurfacePoint& b) + // Our goal is to have identical XY values sorted adjacent to each other with decreasing Z. + // We sort increasing Y, then increasing X, then decreasing Z, because we need to compare all 3 values for a + // stable sort. The choice of increasing Y first is because we'll often generate the points as ranges of X values within + // ranges of Y values, so this will produce the most usable and expected output sort. + if (a.m_position.GetY() != b.m_position.GetY()) + { + return a.m_position.GetY() < b.m_position.GetY(); + } + if (a.m_position.GetX() != b.m_position.GetX()) + { + return a.m_position.GetX() < b.m_position.GetX(); + } + if (a.m_position.GetZ() != b.m_position.GetZ()) { return a.m_position.GetZ() > b.m_position.GetZ(); - }); - } - - - //efficient point consolidation requires the points to be pre-sorted so we are only comparing/combining neighbors - const size_t sourcePointCount = sourcePointList.size(); - size_t targetPointIndex = 0; - size_t sourcePointIndex = 0; - - m_targetPointList.clear(); - m_targetPointList.reserve(sourcePointCount); - - // Locate the first point that matches our desired tags, if one exists. - for (sourcePointIndex = 0; sourcePointIndex < sourcePointCount; sourcePointIndex++) - { - if (!hasDesiredTags || (HasMatchingTags(sourcePointList[sourcePointIndex].m_masks, desiredTags))) - { - break; - } - } - - if (sourcePointIndex < sourcePointCount) - { - // We found a point that matches our tags, so add it to our target list as the first point. - m_targetPointList.push_back(sourcePointList[sourcePointIndex++]); - - //iterate over subsequent source points for comparison and consolidation with the last added target/unique point - for (; sourcePointIndex < sourcePointCount; ++sourcePointIndex) - { - const auto& sourcePoint = sourcePointList[sourcePointIndex]; - - if (!hasDesiredTags || (HasMatchingTags(sourcePoint.m_masks, desiredTags))) - { - auto& targetPoint = m_targetPointList[targetPointIndex]; - - // [LY-90907] need to add a configurable tolerance for comparison - if (targetPoint.m_position.IsClose(sourcePoint.m_position) && - targetPoint.m_normal.IsClose(sourcePoint.m_normal)) - { - //consolidate points with similar attributes by adding masks to the target point and ignoring the source - AddMaxValueForMasks(targetPoint.m_masks, sourcePoint.m_masks); - continue; - } - - //if the points were too different, we have to add a new target point to compare against - m_targetPointList.push_back(sourcePoint); - ++targetPointIndex; - } } - AZStd::swap(sourcePointList, m_targetPointList); + // If we somehow ended up with two points with identical positions getting generated, use the entity ID as the tiebreaker + // to guarantee a stable sort. We should never have two identical positions generated from the same entity. + return a.m_entityId < b.m_entityId; + }); + + // iterate over subsequent source points for comparison and consolidation with the last added target/unique point + for (auto pointItr = sourcePointList.begin() + 1; pointItr < sourcePointList.end();) + { + auto prevPointItr = pointItr - 1; + + // (Someday we should add a configurable tolerance for comparison) + if (pointItr->m_position.IsClose(prevPointItr->m_position) && pointItr->m_normal.IsClose(prevPointItr->m_normal)) + { + // consolidate points with similar attributes by adding masks/weights to the previous point and deleting this point. + AddMaxValueForMasks(prevPointItr->m_masks, pointItr->m_masks); + + pointItr = sourcePointList.erase(pointItr); + } + else + { + pointItr++; + } } } SurfaceDataRegistryHandle SurfaceDataSystemComponent::RegisterSurfaceDataProviderInternal(const SurfaceDataRegistryEntry& entry) { - AZStd::lock_guard registrationLock(m_registrationMutex); + AZStd::unique_lock registrationLock(m_registrationMutex); SurfaceDataRegistryHandle handle = ++m_registeredSurfaceDataProviderHandleCounter; m_registeredSurfaceDataProviders[handle] = entry; return handle; @@ -401,7 +403,7 @@ namespace SurfaceData SurfaceDataRegistryEntry SurfaceDataSystemComponent::UnregisterSurfaceDataProviderInternal(const SurfaceDataRegistryHandle& handle) { - AZStd::lock_guard registrationLock(m_registrationMutex); + AZStd::unique_lock registrationLock(m_registrationMutex); SurfaceDataRegistryEntry entry; auto entryItr = m_registeredSurfaceDataProviders.find(handle); if (entryItr != m_registeredSurfaceDataProviders.end()) @@ -414,7 +416,7 @@ namespace SurfaceData bool SurfaceDataSystemComponent::UpdateSurfaceDataProviderInternal(const SurfaceDataRegistryHandle& handle, const SurfaceDataRegistryEntry& entry, AZ::Aabb& oldBounds) { - AZStd::lock_guard registrationLock(m_registrationMutex); + AZStd::unique_lock registrationLock(m_registrationMutex); auto entryItr = m_registeredSurfaceDataProviders.find(handle); if (entryItr != m_registeredSurfaceDataProviders.end()) { @@ -427,7 +429,7 @@ namespace SurfaceData SurfaceDataRegistryHandle SurfaceDataSystemComponent::RegisterSurfaceDataModifierInternal(const SurfaceDataRegistryEntry& entry) { - AZStd::lock_guard registrationLock(m_registrationMutex); + AZStd::unique_lock registrationLock(m_registrationMutex); SurfaceDataRegistryHandle handle = ++m_registeredSurfaceDataModifierHandleCounter; m_registeredSurfaceDataModifiers[handle] = entry; m_registeredModifierTags.insert(entry.m_tags.begin(), entry.m_tags.end()); @@ -436,7 +438,7 @@ namespace SurfaceData SurfaceDataRegistryEntry SurfaceDataSystemComponent::UnregisterSurfaceDataModifierInternal(const SurfaceDataRegistryHandle& handle) { - AZStd::lock_guard registrationLock(m_registrationMutex); + AZStd::unique_lock registrationLock(m_registrationMutex); SurfaceDataRegistryEntry entry; auto entryItr = m_registeredSurfaceDataModifiers.find(handle); if (entryItr != m_registeredSurfaceDataModifiers.end()) @@ -449,7 +451,7 @@ namespace SurfaceData bool SurfaceDataSystemComponent::UpdateSurfaceDataModifierInternal(const SurfaceDataRegistryHandle& handle, const SurfaceDataRegistryEntry& entry, AZ::Aabb& oldBounds) { - AZStd::lock_guard registrationLock(m_registrationMutex); + AZStd::unique_lock registrationLock(m_registrationMutex); auto entryItr = m_registeredSurfaceDataModifiers.find(handle); if (entryItr != m_registeredSurfaceDataModifiers.end()) { diff --git a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h b/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h index 8914ee7972..6ec2cab4eb 100644 --- a/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h +++ b/Gems/SurfaceData/Code/Source/SurfaceDataSystemComponent.h @@ -10,6 +10,7 @@ #include #include +#include #include namespace SurfaceData @@ -57,7 +58,8 @@ namespace SurfaceData void RefreshSurfaceData(const AZ::Aabb& dirtyArea) override; private: - void CombineSortAndFilterNeighboringPoints(SurfacePointList& sourcePointList, bool hasDesiredTags, const SurfaceTagVector& desiredTags) const; + void FilterPoints(SurfacePointList& sourcePointList, const SurfaceTagVector& desiredTags) const; + void CombineAndSortNeighboringPoints(SurfacePointList& sourcePointList) const; SurfaceDataRegistryHandle RegisterSurfaceDataProviderInternal(const SurfaceDataRegistryEntry& entry); SurfaceDataRegistryEntry UnregisterSurfaceDataProviderInternal(const SurfaceDataRegistryHandle& handle); @@ -67,7 +69,7 @@ namespace SurfaceData SurfaceDataRegistryEntry UnregisterSurfaceDataModifierInternal(const SurfaceDataRegistryHandle& handle); bool UpdateSurfaceDataModifierInternal(const SurfaceDataRegistryHandle& handle, const SurfaceDataRegistryEntry& entry, AZ::Aabb& oldBounds); - mutable AZStd::recursive_mutex m_registrationMutex; + mutable AZStd::shared_mutex m_registrationMutex; AZStd::unordered_map m_registeredSurfaceDataProviders; AZStd::unordered_map m_registeredSurfaceDataModifiers; SurfaceDataRegistryHandle m_registeredSurfaceDataProviderHandleCounter = InvalidSurfaceDataRegistryHandle; diff --git a/Gems/SurfaceData/Code/Tests/SurfaceDataColliderComponentTest.cpp b/Gems/SurfaceData/Code/Tests/SurfaceDataColliderComponentTest.cpp index b0aa5dd38f..c51ea49f14 100644 --- a/Gems/SurfaceData/Code/Tests/SurfaceDataColliderComponentTest.cpp +++ b/Gems/SurfaceData/Code/Tests/SurfaceDataColliderComponentTest.cpp @@ -93,10 +93,28 @@ namespace UnitTest // Compare two surface points. bool SurfacePointsAreEqual(const SurfaceData::SurfacePoint& lhs, const SurfaceData::SurfacePoint& rhs) { - return (lhs.m_entityId == rhs.m_entityId) - && (lhs.m_position == rhs.m_position) - && (lhs.m_normal == rhs.m_normal) - && (lhs.m_masks == rhs.m_masks); + if ((lhs.m_entityId != rhs.m_entityId) + || (lhs.m_position != rhs.m_position) + || (lhs.m_normal != rhs.m_normal) + || (lhs.m_masks.size() != rhs.m_masks.size())) + { + return false; + } + + for (auto& mask : lhs.m_masks) + { + auto maskEntry = rhs.m_masks.find(mask.first); + if (maskEntry == rhs.m_masks.end()) + { + return false; + } + if (maskEntry->second != mask.second) + { + return false; + } + } + + return true; } // Common test function for testing the "Provider" functionality of the component. diff --git a/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp b/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp index 1d339edc71..2d6d64f65d 100644 --- a/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp +++ b/Gems/SurfaceData/Code/Tests/SurfaceDataTest.cpp @@ -204,30 +204,31 @@ public: m_surfaceDataSystemEntity.reset(); } - bool ValidateRegionListSize(AZ::Aabb bounds, AZ::Vector2 stepSize, const SurfaceData::SurfacePointLists& outputLists) - { - // We expect the output list to contain width * height output entries. - // The right edge of the AABB should be treated as exclusive, so a 4x4 box with 1 step size will produce 16 entries (0, 1, 2, 3 on each dimension), - // but a 4.1 x 4.1 box with 1 step size will produce 25 entries (0, 1, 2, 3, 4 on each dimension). - return (outputLists.size() == aznumeric_cast(ceil(bounds.GetXExtent() * stepSize.GetX()) * ceil(bounds.GetYExtent() * stepSize.GetY()))); - } - void CompareSurfacePointListWithGetSurfacePoints( - SurfaceData::SurfacePointLists surfacePointLists, const SurfaceData::SurfaceTagVector& testTags) + const AZStd::vector& queryPositions, SurfaceData::SurfacePointLists surfacePointLists, + const SurfaceData::SurfaceTagVector& testTags) { - for (auto& pointList : surfacePointLists) + SurfaceData::SurfacePointLists singleQueryPointLists; + + for (auto& queryPosition : queryPositions) { - AZ::Vector3 queryPosition(pointList[0].m_position.GetX(), pointList[0].m_position.GetY(), 16.0f); - SurfaceData::SurfacePointList singleQueryPointList; - + SurfaceData::SurfacePointList tempSingleQueryPointList; SurfaceData::SurfaceDataSystemRequestBus::Broadcast( - &SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePoints, queryPosition, testTags, singleQueryPointList); + &SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePoints, queryPosition, testTags, tempSingleQueryPointList); + singleQueryPointLists.push_back(tempSingleQueryPointList); + } - // Verify the two point lists are the same size, then verify that each point in each list is equal. - ASSERT_EQ(pointList.size(), singleQueryPointList.size()); - for (size_t index = 0; index < pointList.size(); index++) + // Verify the two point lists are the same size, then verify that each point in each list is equal. + ASSERT_EQ(singleQueryPointLists.size(), surfacePointLists.size()); + for (size_t listIndex = 0; listIndex < surfacePointLists.size(); listIndex++) + { + auto& surfacePointList = surfacePointLists[listIndex]; + auto& singleQueryPointList = singleQueryPointLists[listIndex]; + + ASSERT_EQ(singleQueryPointList.size(), surfacePointList.size()); + for (size_t index = 0; index < surfacePointList.size(); index++) { - SurfaceData::SurfacePoint& point1 = pointList[index]; + SurfaceData::SurfacePoint& point1 = surfacePointList[index]; SurfaceData::SurfacePoint& point2 = singleQueryPointList[index]; EXPECT_EQ(point1.m_entityId, point2.m_entityId); @@ -399,8 +400,8 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestAabbOverlaps2D) // Make sure the test produces the correct result. // Also make sure it's correct regardless of which order the boxes are passed in. - EXPECT_TRUE(SurfaceData::AabbOverlaps2D(box1, box2) == testCase.m_overlaps); - EXPECT_TRUE(SurfaceData::AabbOverlaps2D(box2, box1) == testCase.m_overlaps); + EXPECT_EQ(SurfaceData::AabbOverlaps2D(box1, box2), testCase.m_overlaps); + EXPECT_EQ(SurfaceData::AabbOverlaps2D(box2, box1), testCase.m_overlaps); } } @@ -448,9 +449,9 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestAabbContains2D) AZ::Vector3& point = testCase.m_testData[TestCase::POINT]; // Make sure the test produces the correct result. - EXPECT_TRUE(SurfaceData::AabbContains2D(box, point) == testCase.m_contains); + EXPECT_EQ(SurfaceData::AabbContains2D(box, point), testCase.m_contains); // Test the Vector2 version as well. - EXPECT_TRUE(SurfaceData::AabbContains2D(box, AZ::Vector2(point.GetX(), point.GetY())) == testCase.m_contains); + EXPECT_EQ(SurfaceData::AabbContains2D(box, AZ::Vector2(point.GetX(), point.GetY())), testCase.m_contains); } } @@ -482,19 +483,17 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion) &SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePointsFromRegion, regionBounds, stepSize, testTags, availablePointsPerPosition); - EXPECT_TRUE(ValidateRegionListSize(regionBounds, stepSize, availablePointsPerPosition)); - // We expect every entry in the output list to have two surface points, at heights 0 and 4, sorted in // decreasing height order. The masks list should be the same size as the set of masks the provider owns. // We *could* check every mask as well for completeness, but that seems like overkill. for (auto& pointList : availablePointsPerPosition) { - EXPECT_TRUE(pointList.size() == 2); - EXPECT_TRUE(pointList[0].m_position.GetZ() == 4.0f); - EXPECT_TRUE(pointList[1].m_position.GetZ() == 0.0f); + EXPECT_EQ(pointList.size(), 2); + EXPECT_EQ(pointList[0].m_position.GetZ(), 4.0f); + EXPECT_EQ(pointList[1].m_position.GetZ(), 0.0f); for (auto& point : pointList) { - EXPECT_TRUE(point.m_masks.size() == providerTags.size()); + EXPECT_EQ(point.m_masks.size(), providerTags.size()); } } } @@ -520,13 +519,11 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_NoMatchingMas &SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePointsFromRegion, regionBounds, stepSize, testTags, availablePointsPerPosition); - EXPECT_TRUE(ValidateRegionListSize(regionBounds, stepSize, availablePointsPerPosition)); - // We expect every entry in the output list to have no surface points, since the requested mask doesn't match // any of the masks from our mock surface provider. for (auto& queryPosition : availablePointsPerPosition) { - EXPECT_TRUE(queryPosition.size() == 0); + EXPECT_TRUE(queryPosition.empty()); } } @@ -550,13 +547,11 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_NoMatchingReg &SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePointsFromRegion, regionBounds, stepSize, testTags, availablePointsPerPosition); - EXPECT_TRUE(ValidateRegionListSize(regionBounds, stepSize, availablePointsPerPosition)); - // We expect every entry in the output list to have no surface points, since the input points don't overlap with // our surface provider. for (auto& pointList : availablePointsPerPosition) { - EXPECT_TRUE(pointList.size() == 0); + EXPECT_TRUE(pointList.empty()); } } @@ -602,16 +597,17 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_ProviderModif &SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePointsFromRegion, regionBounds, stepSize, testTags, availablePointsPerPosition); - EXPECT_TRUE(ValidateRegionListSize(regionBounds, stepSize, availablePointsPerPosition)); - // We expect every entry in the output list to have two surface points (with heights 0 and 4), // and each point should have both the "test_surface1" and "test_surface2" tag. for (auto& pointList : availablePointsPerPosition) { - EXPECT_TRUE(pointList.size() == 2); + EXPECT_EQ(pointList.size(), 2); + float expectedZ = 4.0f; for (auto& point : pointList) { - EXPECT_TRUE(point.m_masks.size() == 2); + EXPECT_EQ(point.m_position.GetZ(), expectedZ); + EXPECT_EQ(point.m_masks.size(), 2); + expectedZ = (expectedZ == 4.0f) ? 0.0f : 4.0f; } } } @@ -624,7 +620,7 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_SimilarPoints // sets of tags. // Create two mock Surface Providers that covers from (0, 0) - (8, 8) in space, with points spaced 0.25 apart. - // The first has heights 0 and 4, with the tag "surfaceTag1". The second has heights 0.005 and 4.005, with the tag "surfaceTag2". + // The first has heights 0 and 4, with the tag "surfaceTag1". The second has heights 0.0005 and 4.0005, with the tag "surfaceTag2". SurfaceData::SurfaceTagVector provider1Tags = { SurfaceData::SurfaceTag(m_testSurface1Crc) }; MockSurfaceProvider mockProvider1(MockSurfaceProvider::ProviderType::SURFACE_PROVIDER, provider1Tags, AZ::Vector3(0.0f), AZ::Vector3(8.0f), AZ::Vector3(0.25f, 0.25f, 4.0f), @@ -648,16 +644,17 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_SimilarPoints &SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePointsFromRegion, regionBounds, stepSize, testTags, availablePointsPerPosition); - EXPECT_TRUE(ValidateRegionListSize(regionBounds, stepSize, availablePointsPerPosition)); - // We expect every entry in the output list to have two surface points, not four. The two points // should have both surface tags on them. for (auto& pointList : availablePointsPerPosition) { - EXPECT_TRUE(pointList.size() == 2); + EXPECT_EQ(pointList.size(), 2); + float expectedZ = 4.0005f; for (auto& point : pointList) { - EXPECT_TRUE(point.m_masks.size() == 2); + EXPECT_EQ(point.m_position.GetZ(), expectedZ); + EXPECT_EQ(point.m_masks.size(), 2); + expectedZ = (expectedZ == 4.0005f) ? 0.0005f : 4.0005f; } } } @@ -692,16 +689,14 @@ TEST_F(SurfaceDataTestApp, SurfaceData_TestSurfacePointsFromRegion_DissimilarPoi &SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePointsFromRegion, regionBounds, stepSize, testTags, availablePointsPerPosition); - EXPECT_TRUE(ValidateRegionListSize(regionBounds, stepSize, availablePointsPerPosition)); - // We expect every entry in the output list to have four surface points with one tag each, // because the points are far enough apart that they won't merge. for (auto& pointList : availablePointsPerPosition) { - EXPECT_TRUE(pointList.size() == 4); + EXPECT_EQ(pointList.size(), 4); for (auto& point : pointList) { - EXPECT_TRUE(point.m_masks.size() == 1); + EXPECT_EQ(point.m_masks.size(), 1); } } } @@ -727,10 +722,17 @@ TEST_F(SurfaceDataTestApp, SurfaceData_VerifyGetSurfacePointsFromRegionAndGetSur &SurfaceData::SurfaceDataSystemRequestBus::Events::GetSurfacePointsFromRegion, regionBounds, stepSize, providerTags, availablePointsPerPosition); - EXPECT_TRUE(ValidateRegionListSize(regionBounds, stepSize, availablePointsPerPosition)); - // For each point entry returned from GetSurfacePointsFromRegion, call GetSurfacePoints and verify the results match. - CompareSurfacePointListWithGetSurfacePoints(availablePointsPerPosition, providerTags); + AZStd::vector queryPositions; + for (float y = 0.0f; y < 4.0f; y += 1.0f) + { + for (float x = 0.0f; x < 4.0f; x += 1.0f) + { + queryPositions.push_back(AZ::Vector3(x, y, 16.0f)); + } + } + + CompareSurfacePointListWithGetSurfacePoints(queryPositions, availablePointsPerPosition, providerTags); } TEST_F(SurfaceDataTestApp, SurfaceData_VerifyGetSurfacePointsFromListAndGetSurfacePointsMatch) @@ -763,7 +765,7 @@ TEST_F(SurfaceDataTestApp, SurfaceData_VerifyGetSurfacePointsFromListAndGetSurfa EXPECT_EQ(availablePointsPerPosition.size(), 16); // For each point entry returned from GetSurfacePointsFromList, call GetSurfacePoints and verify the results match. - CompareSurfacePointListWithGetSurfacePoints(availablePointsPerPosition, providerTags); + CompareSurfacePointListWithGetSurfacePoints(queryPositions, availablePointsPerPosition, providerTags); } // This uses custom test / benchmark hooks so that we can load LmbrCentral and use Shape components in our unit tests and benchmarks. AZ_UNIT_TEST_HOOK(new UnitTest::SurfaceDataTestEnvironment, UnitTest::SurfaceDataBenchmarkEnvironment); diff --git a/Gems/Terrain/Assets/Passes/TerrainDetailTextureComputePass.pass b/Gems/Terrain/Assets/Passes/TerrainDetailTextureComputePass.pass new file mode 100644 index 0000000000..b880979615 --- /dev/null +++ b/Gems/Terrain/Assets/Passes/TerrainDetailTextureComputePass.pass @@ -0,0 +1,52 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + // Note: all the data here works as placeholders. + "PassTemplate": { + "Name": "TerrainDetailTextureComputePassTemplate", + "PassClass": "TerrainDetailTextureComputePass", + "Slots": [ + { + "Name": "DetailTextureClipmapOutput", + "ShaderInputName": "m_detailTexClipmap", + "SlotType": "Output", + "ScopeAttachmentUsage": "Shader" + } + ], + "ImageAttachments": [ + { + "Name": "DetailTextureClipmap", + "ImageDescriptor": { + "Format": "R32G32B32A32_FLOAT", + "BindFlags": "3", + "SharedQueueMask": "1", + "Size": { + "Width": 1024, + "Height": 1024 + } + } + } + ], + "Connections": [ + { + "LocalSlot": "DetailTextureClipmapOutput", + "AttachmentRef": { + "Pass": "This", + "Attachment": "DetailTextureClipmap" + } + } + ], + "PassData": { + "$type": "Terrain::TerrainDetailTextureComputePassData", + "ShaderAsset": { + "FilePath": "Shaders/Terrain/TerrainDetailTextureComputePass.shader" + }, + "Target Thread Count X": 1024, + "Target Thread Count Y": 1024, + "Target Thread Count Z": 1 + } + } + } +} diff --git a/Gems/Terrain/Assets/Passes/TerrainMacroTextureComputePass.pass b/Gems/Terrain/Assets/Passes/TerrainMacroTextureComputePass.pass new file mode 100644 index 0000000000..ecb31acf69 --- /dev/null +++ b/Gems/Terrain/Assets/Passes/TerrainMacroTextureComputePass.pass @@ -0,0 +1,52 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + // Note: all the data here works as placeholders. + "PassTemplate": { + "Name": "TerrainMacroTextureComputePassTemplate", + "PassClass": "TerrainMacroTextureComputePass", + "Slots": [ + { + "Name": "MacroTextureClipmapOutput", + "ShaderInputName": "m_macroTexClipmap", + "SlotType": "Output", + "ScopeAttachmentUsage": "Shader" + } + ], + "ImageAttachments": [ + { + "Name": "MacroTextureClipmap", + "ImageDescriptor": { + "Format": "R32G32B32A32_FLOAT", + "BindFlags": "3", + "SharedQueueMask": "1", + "Size": { + "Width": 1024, + "Height": 1024 + } + } + } + ], + "Connections": [ + { + "LocalSlot": "MacroTextureClipmapOutput", + "AttachmentRef": { + "Pass": "This", + "Attachment": "MacroTextureClipmap" + } + } + ], + "PassData": { + "$type": "Terrain::TerrainMacroTextureComputePassData", + "ShaderAsset": { + "FilePath": "Shaders/Terrain/TerrainMacroTextureComputePass.shader" + }, + "Target Thread Count X": 1024, + "Target Thread Count Y": 1024, + "Target Thread Count Z": 1 + } + } + } +} diff --git a/Gems/Terrain/Assets/Passes/TerrainPassTemplates.azasset b/Gems/Terrain/Assets/Passes/TerrainPassTemplates.azasset new file mode 100644 index 0000000000..8b20edb6b9 --- /dev/null +++ b/Gems/Terrain/Assets/Passes/TerrainPassTemplates.azasset @@ -0,0 +1,17 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "AssetAliasesSourceData", + "ClassData": { + "AssetPaths": [ + { + "Name": "TerrainDetailTextureComputePassTemplate", + "Path": "Passes/TerrainDetailTextureComputePass.pass" + }, + { + "Name": "TerrainMacroTextureComputePassTemplate", + "Path": "Passes/TerrainMacroTextureComputePass.pass" + } + ] + } +} diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainDetailTextureComputePass.azsl b/Gems/Terrain/Assets/Shaders/Terrain/TerrainDetailTextureComputePass.azsl new file mode 100644 index 0000000000..a982e1aa49 --- /dev/null +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainDetailTextureComputePass.azsl @@ -0,0 +1,18 @@ +/* + * 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 "TerrainDetailTextureComputePassSrg.azsli" + +[numthreads(32,32,1)] +void MainCS( + uint3 dispatchThreadID : SV_DispatchThreadID, + uint3 groupID : SV_GroupID, + uint groupIndex : SV_GroupIndex) +{ + // Simple code to paint the whole image yellow for debug purpose before we actually write clipmap generation code + PassSrg::m_detailTexClipmap[dispatchThreadID.xy].rgba = float4(1.0, 1.0, 0.0, 1.0); +} diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainDetailTextureComputePass.shader b/Gems/Terrain/Assets/Shaders/Terrain/TerrainDetailTextureComputePass.shader new file mode 100644 index 0000000000..6b0488aaaa --- /dev/null +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainDetailTextureComputePass.shader @@ -0,0 +1,14 @@ +{ + "Source": "TerrainDetailTextureComputePass.azsl", + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainCS", + "type": "Compute" + } + ] + } +} diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainDetailTextureComputePassSrg.azsli b/Gems/Terrain/Assets/Shaders/Terrain/TerrainDetailTextureComputePassSrg.azsli new file mode 100644 index 0000000000..aaa67b52da --- /dev/null +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainDetailTextureComputePassSrg.azsli @@ -0,0 +1,16 @@ +/* + * 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 + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + RWTexture2D m_detailTexClipmap; +} diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainMacroTextureComputePass.azsl b/Gems/Terrain/Assets/Shaders/Terrain/TerrainMacroTextureComputePass.azsl new file mode 100644 index 0000000000..287002cf09 --- /dev/null +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainMacroTextureComputePass.azsl @@ -0,0 +1,18 @@ +/* + * 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 "TerrainMacroTextureComputePassSrg.azsli" + +[numthreads(32,32,1)] +void MainCS( + uint3 dispatchThreadID : SV_DispatchThreadID, + uint3 groupID : SV_GroupID, + uint groupIndex : SV_GroupIndex) +{ + // Simple code to paint the whole image magenta for debug purpose before we actually write clipmap generation code + PassSrg::m_macroTexClipmap[dispatchThreadID.xy].rgba = float4(1.0, 0.0, 1.0, 1.0); +} diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainMacroTextureComputePass.shader b/Gems/Terrain/Assets/Shaders/Terrain/TerrainMacroTextureComputePass.shader new file mode 100644 index 0000000000..5e043dea12 --- /dev/null +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainMacroTextureComputePass.shader @@ -0,0 +1,14 @@ +{ + "Source": "TerrainMacroTextureComputePass.azsl", + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainCS", + "type": "Compute" + } + ] + } +} diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainMacroTextureComputePassSrg.azsli b/Gems/Terrain/Assets/Shaders/Terrain/TerrainMacroTextureComputePassSrg.azsli new file mode 100644 index 0000000000..462e5cee34 --- /dev/null +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainMacroTextureComputePassSrg.azsli @@ -0,0 +1,16 @@ +/* + * 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 + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + RWTexture2D m_macroTexClipmap; +} diff --git a/Gems/Terrain/Code/Include/Terrain/Passes/TerrainDetailTextureComputePass.h b/Gems/Terrain/Code/Include/Terrain/Passes/TerrainDetailTextureComputePass.h new file mode 100644 index 0000000000..b7d5138d7f --- /dev/null +++ b/Gems/Terrain/Code/Include/Terrain/Passes/TerrainDetailTextureComputePass.h @@ -0,0 +1,55 @@ +/* + * 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 + +namespace Terrain +{ + class TerrainFeatureProcessor; + + struct TerrainDetailTextureComputePassData + : public AZ::RPI::ComputePassData + { + AZ_RTTI(Terrain::TerrainDetailTextureComputePassData, "{387F7457-16E5-4AA6-8D96-56ED4532CA8D}", AZ::RPI::ComputePassData); + AZ_CLASS_ALLOCATOR(Terrain::TerrainDetailTextureComputePassData, AZ::SystemAllocator, 0); + + TerrainDetailTextureComputePassData() = default; + virtual ~TerrainDetailTextureComputePassData() = default; + + static void Reflect(AZ::ReflectContext* context); + }; + + class TerrainDetailTextureComputePass + : public AZ::RPI::ComputePass + { + AZ_RPI_PASS(TerrainDetailTextureComputePass); + + public: + AZ_RTTI(Terrain::TerrainDetailTextureComputePass, "{69A8207B-3311-4BB1-BD4E-A08B5E0424B5}", AZ::RPI::ComputePass); + AZ_CLASS_ALLOCATOR(Terrain::TerrainDetailTextureComputePass, AZ::SystemAllocator, 0); + virtual ~TerrainDetailTextureComputePass() = default; + + static AZ::RPI::Ptr Create(const AZ::RPI::PassDescriptor& descriptor); + + void SetFeatureProcessor(); + + void CompileResources(const AZ::RHI::FrameGraphCompileContext& context) override; + private: + TerrainDetailTextureComputePass(const AZ::RPI::PassDescriptor& descriptor); + + void BuildCommandListInternal(const AZ::RHI::FrameGraphExecuteContext& context) override; + + TerrainFeatureProcessor* m_terrainFeatureProcessor; + }; +} // namespace AZ::Render diff --git a/Gems/Terrain/Code/Include/Terrain/Passes/TerrainMacroTextureComputePass.h b/Gems/Terrain/Code/Include/Terrain/Passes/TerrainMacroTextureComputePass.h new file mode 100644 index 0000000000..5cadea0706 --- /dev/null +++ b/Gems/Terrain/Code/Include/Terrain/Passes/TerrainMacroTextureComputePass.h @@ -0,0 +1,55 @@ +/* + * 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 + +namespace Terrain +{ + class TerrainFeatureProcessor; + + struct TerrainMacroTextureComputePassData + : public AZ::RPI::ComputePassData + { + AZ_RTTI(Terrain::TerrainMacroTextureComputePassData, "{BB11DACF-AF47-402D-92C6-33C644F6F530}", AZ::RPI::ComputePassData); + AZ_CLASS_ALLOCATOR(Terrain::TerrainMacroTextureComputePassData, AZ::SystemAllocator, 0); + + TerrainMacroTextureComputePassData() = default; + virtual ~TerrainMacroTextureComputePassData() = default; + + static void Reflect(AZ::ReflectContext* context); + }; + + class TerrainMacroTextureComputePass + : public AZ::RPI::ComputePass + { + AZ_RPI_PASS(TerrainMacroTextureComputePass); + + public: + AZ_RTTI(Terrain::TerrainMacroTextureComputePass, "{E493C3D2-D657-49ED-A5B1-A29B2995F6A8}", AZ::RPI::ComputePass); + AZ_CLASS_ALLOCATOR(Terrain::TerrainMacroTextureComputePass, AZ::SystemAllocator, 0); + virtual ~TerrainMacroTextureComputePass() = default; + + static AZ::RPI::Ptr Create(const AZ::RPI::PassDescriptor& descriptor); + + void SetFeatureProcessor(); + + void CompileResources(const AZ::RHI::FrameGraphCompileContext& context) override; + private: + TerrainMacroTextureComputePass(const AZ::RPI::PassDescriptor& descriptor); + + void BuildCommandListInternal(const AZ::RHI::FrameGraphExecuteContext& context) override; + + TerrainFeatureProcessor* m_terrainFeatureProcessor; + }; +} // namespace AZ::Render diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp index 03011db2f3..9a9cb24e4c 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.cpp @@ -177,7 +177,7 @@ namespace Terrain const AZ::Crc32 terrainTag = isHole ? Constants::s_terrainHoleTagCrc : Constants::s_terrainTagCrc; point.m_masks[terrainTag] = 1.0f; - surfacePointList.push_back(point); + surfacePointList.push_back(AZStd::move(point)); } AZ::Aabb TerrainSurfaceDataSystemComponent::GetSurfaceAabb() const diff --git a/Gems/Terrain/Code/Source/Components/TerrainSystemComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainSystemComponent.cpp index 5357ccce32..ae321b37ff 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSystemComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainSystemComponent.cpp @@ -14,6 +14,8 @@ #include #include +#include +#include namespace Terrain { @@ -63,11 +65,33 @@ namespace Terrain // every time an entity is added or removed to a level. If this ever changes, the Terrain System ownership could move into // the level component. m_terrainSystem = new TerrainSystem(); + + auto* passSystem = AZ::RPI::PassSystemInterface::Get(); + AZ_Assert(passSystem, "Cannot get the pass system."); + + // Setup handler for load pass templates mappings + m_loadTemplatesHandler = AZ::RPI::PassSystemInterface::OnReadyLoadTemplatesEvent::Handler([this]() { this->LoadPassTemplateMappings(); }); + passSystem->ConnectEvent(m_loadTemplatesHandler); + + // Register terrain system related passes + passSystem->AddPassCreator(AZ::Name("TerrainDetailTextureComputePass"), &TerrainDetailTextureComputePass::Create); + passSystem->AddPassCreator(AZ::Name("TerrainMacroTextureComputePass"), &TerrainDetailTextureComputePass::Create); } void TerrainSystemComponent::Deactivate() { + m_loadTemplatesHandler.Disconnect(); + delete m_terrainSystem; m_terrainSystem = nullptr; } + + void TerrainSystemComponent::LoadPassTemplateMappings() + { + auto* passSystem = AZ::RPI::PassSystemInterface::Get(); + AZ_Assert(passSystem, "Cannot get the pass system."); + + const char* passTemplatesFile = "Passes/TerrainPassTemplates.azasset"; + passSystem->LoadPassTemplateMappings(passTemplatesFile); + } } diff --git a/Gems/Terrain/Code/Source/Components/TerrainSystemComponent.h b/Gems/Terrain/Code/Source/Components/TerrainSystemComponent.h index b294c0473a..586c9c6be3 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSystemComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainSystemComponent.h @@ -9,6 +9,7 @@ #pragma once #include +#include namespace Terrain { @@ -36,5 +37,11 @@ namespace Terrain //////////////////////////////////////////////////////////////////////// TerrainSystem* m_terrainSystem{ nullptr }; + + private: + //! Used for loading the pass templates of the terrain gem. + AZ::RPI::PassSystemInterface::OnReadyLoadTemplatesEvent::Handler m_loadTemplatesHandler; + + void LoadPassTemplateMappings(); }; } diff --git a/Gems/Terrain/Code/Source/TerrainRaycast/TerrainRaycastContext.cpp b/Gems/Terrain/Code/Source/TerrainRaycast/TerrainRaycastContext.cpp index 1f05c44314..1cc95d4efc 100644 --- a/Gems/Terrain/Code/Source/TerrainRaycast/TerrainRaycastContext.cpp +++ b/Gems/Terrain/Code/Source/TerrainRaycast/TerrainRaycastContext.cpp @@ -35,7 +35,6 @@ namespace inline void FindNearestIntersection(const AZ::Aabb& aabb, const AZ::Vector3& rayStart, const AZ::Vector3& rayDirection, - const AZ::Vector3& rayDirectionReciprocal, AzFramework::RenderGeometry::RayResult& result) { float intersectionT; @@ -43,7 +42,7 @@ namespace AZ::Vector3 intersectionNormal; const int intersectionResult = AZ::Intersect::IntersectRayAABB(rayStart, rayDirection, - rayDirectionReciprocal, + rayDirection.GetReciprocal(), aabb, intersectionT, intersectionEndT, @@ -117,7 +116,6 @@ namespace const AZ::Aabb& aabb, const AZ::Vector3& rayStart, const AZ::Vector3& rayDirection, - const AZ::Vector3& rayDirectionReciprocal, AzFramework::RenderGeometry::RayResult& result) { // Obtain the height values at each corner of the AABB. @@ -132,26 +130,6 @@ namespace point2.SetZ(terrainSystem.GetHeight(point2, AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT)); point3.SetZ(terrainSystem.GetHeight(point3, AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT)); - // Construct a smaller AABB that tightly encloses the four terrain points. - const float refinedMinZ = AZStd::GetMin(AZStd::GetMin(AZStd::GetMin(point0.GetZ(), point1.GetZ()), point2.GetZ()), point3.GetZ()); - const float refinedMaxZ = AZStd::GetMax(AZStd::GetMax(AZStd::GetMax(point0.GetZ(), point1.GetZ()), point2.GetZ()), point3.GetZ()); - const AZ::Vector3 refinedMin(aabbMin.GetX(), aabbMin.GetY(), refinedMinZ); - const AZ::Vector3 refinedMax(aabbMax.GetX(), aabbMax.GetY(), refinedMaxZ); - const AZ::Aabb refinedAABB = AZ::Aabb::CreateFromMinMax(refinedMin, refinedMax); - - // Check for a hit against the refined AABB. - float intersectionT; - float intersectionEndT; - const int intersectionResult = AZ::Intersect::IntersectRayAABB2(rayStart, - rayDirectionReciprocal, - refinedAABB, - intersectionT, - intersectionEndT); - if (intersectionResult == AZ::Intersect::ISECT_RAY_AABB_NONE) - { - return; - } - // Finally, triangulate the four terrain points and check for a hit, // splitting using the top-left -> bottom-right diagonal so to match // the current behavior of the terrain physics and rendering systems. @@ -218,12 +196,10 @@ namespace { // Find the nearest intersection (if any) between the ray and terrain world bounds. // Note that the ray might (and often will) start inside the terrain world bounds. - const AZ::Vector3 rayDirection = rayEnd - rayStart; - const AZ::Vector3 rayDirectionReciprocal = rayDirection.GetReciprocal(); + const AZ::Vector3 rayDirection = (rayEnd - rayStart).GetNormalized(); FindNearestIntersection(terrainWorldBounds, rayStart, rayDirection, - rayDirectionReciprocal, result); if (!result) { @@ -327,7 +303,6 @@ namespace currentVoxel, rayStart, rayDirection, - rayDirectionReciprocal, result); if (result) { diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Passes/TerrainDetailTextureComputePass.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/Passes/TerrainDetailTextureComputePass.cpp new file mode 100644 index 0000000000..0bfbfa134d --- /dev/null +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Passes/TerrainDetailTextureComputePass.cpp @@ -0,0 +1,58 @@ +/* + * 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 + +namespace Terrain +{ + void TerrainDetailTextureComputePassData::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1); + } + } + + AZ::RPI::Ptr TerrainDetailTextureComputePass::Create(const AZ::RPI::PassDescriptor& descriptor) + { + AZ::RPI::Ptr pass = aznew TerrainDetailTextureComputePass(descriptor); + return pass; + } + + TerrainDetailTextureComputePass::TerrainDetailTextureComputePass(const AZ::RPI::PassDescriptor& descriptor) + : AZ::RPI::ComputePass(descriptor) + { + const TerrainDetailTextureComputePass* passData = AZ::RPI::PassUtils::GetPassData(descriptor); + if (passData) + { + // Copy data to pass + + } + } + + void TerrainDetailTextureComputePass::BuildCommandListInternal(const AZ::RHI::FrameGraphExecuteContext& context) + { + ComputePass::BuildCommandListInternal(context); + } + + void TerrainDetailTextureComputePass::SetFeatureProcessor() + { + m_terrainFeatureProcessor = GetRenderPipeline()->GetScene()->GetFeatureProcessor(); + } + + void TerrainDetailTextureComputePass::CompileResources(const AZ::RHI::FrameGraphCompileContext& context) + { + ComputePass::CompileResources(context); + } + +} // namespace Terrain diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Passes/TerrainMacroTextureComputePass.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/Passes/TerrainMacroTextureComputePass.cpp new file mode 100644 index 0000000000..32eb849db3 --- /dev/null +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Passes/TerrainMacroTextureComputePass.cpp @@ -0,0 +1,58 @@ +/* + * 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 + +namespace Terrain +{ + void TerrainMacroTextureComputePassData::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1); + } + } + + AZ::RPI::Ptr TerrainMacroTextureComputePass::Create(const AZ::RPI::PassDescriptor& descriptor) + { + AZ::RPI::Ptr pass = aznew TerrainMacroTextureComputePass(descriptor); + return pass; + } + + TerrainMacroTextureComputePass::TerrainMacroTextureComputePass(const AZ::RPI::PassDescriptor& descriptor) + : AZ::RPI::ComputePass(descriptor) + { + const TerrainMacroTextureComputePass* passData = AZ::RPI::PassUtils::GetPassData(descriptor); + if (passData) + { + // Copy data to pass + + } + } + + void TerrainMacroTextureComputePass::BuildCommandListInternal(const AZ::RHI::FrameGraphExecuteContext& context) + { + ComputePass::BuildCommandListInternal(context); + } + + void TerrainMacroTextureComputePass::SetFeatureProcessor() + { + m_terrainFeatureProcessor = GetRenderPipeline()->GetScene()->GetFeatureProcessor(); + } + + void TerrainMacroTextureComputePass::CompileResources(const AZ::RHI::FrameGraphCompileContext& context) + { + ComputePass::CompileResources(context); + } + +} // namespace Terrain diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp index 17cded8c97..e33f951bb1 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp @@ -6,12 +6,13 @@ * */ +#include +#include #include #include - #include - +#include #include #include #include @@ -21,9 +22,6 @@ #include #include #include - -#include - #include #include @@ -55,6 +53,9 @@ namespace Terrain ->Version(0) ; } + + TerrainDetailTextureComputePassData::Reflect(context); + TerrainMacroTextureComputePassData::Reflect(context); } void TerrainFeatureProcessor::Activate() diff --git a/Gems/Terrain/Code/Tests/TerrainSystemBenchmarks.cpp b/Gems/Terrain/Code/Tests/TerrainSystemBenchmarks.cpp index e54747abcc..6aad3f9568 100644 --- a/Gems/Terrain/Code/Tests/TerrainSystemBenchmarks.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSystemBenchmarks.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -682,6 +683,89 @@ namespace UnitTest ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_GetClosestIntersectionRandom)(benchmark::State& state) + { + // Run the benchmark + const uint32_t numRays = aznumeric_cast(state.range(1)); + RunTerrainApiBenchmark( + state, + [numRays]([[maybe_unused]] float queryResolution, const AZ::Aabb& worldBounds, + [[maybe_unused]] AzFramework::Terrain::TerrainDataRequests::Sampler sampler) + { + // Cast rays starting at random positions above the terrain, + // and ending at a random positions below the terrain. + AZ::SimpleLcgRandom random; + AzFramework::RenderGeometry::RayRequest ray; + AzFramework::RenderGeometry::RayResult result; + for (uint32_t i = 0; i < numRays; ++i) + { + ray.m_startWorldPosition.SetX(worldBounds.GetMin().GetX() + (random.GetRandomFloat() * worldBounds.GetXExtent())); + ray.m_startWorldPosition.SetY(worldBounds.GetMin().GetY() + (random.GetRandomFloat() * worldBounds.GetYExtent())); + ray.m_startWorldPosition.SetZ(worldBounds.GetMax().GetZ()); + ray.m_endWorldPosition.SetX(worldBounds.GetMin().GetX() + (random.GetRandomFloat() * worldBounds.GetXExtent())); + ray.m_endWorldPosition.SetY(worldBounds.GetMin().GetY() + (random.GetRandomFloat() * worldBounds.GetYExtent())); + ray.m_endWorldPosition.SetZ(worldBounds.GetMin().GetZ()); + AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( + result, &AzFramework::Terrain::TerrainDataRequests::GetClosestIntersection, ray); + } + }); + } + + BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_GetClosestIntersectionRandom) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 4096, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 1024, 10, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 10, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 4096, 10, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 1024, 100, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 100, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 4096, 100, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 1024, 1000, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1000, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 4096, 1000, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_GetClosestIntersectionWorstCase)(benchmark::State& state) + { + // Run the benchmark + const uint32_t numRays = aznumeric_cast(state.range(1)); + RunTerrainApiBenchmark( + state, + [numRays]([[maybe_unused]] float queryResolution, const AZ::Aabb& worldBounds, + [[maybe_unused]] AzFramework::Terrain::TerrainDataRequests::Sampler sampler) + { + // Cast rays starting at an upper corner of the terrain world, + // and ending at the opposite top corner of the terrain world, + // traversing the entire grid without finding an intersection. + AzFramework::RenderGeometry::RayRequest ray; + AzFramework::RenderGeometry::RayResult result; + ray.m_startWorldPosition = worldBounds.GetMax(); + ray.m_endWorldPosition = worldBounds.GetMin(); + ray.m_endWorldPosition.SetZ(ray.m_startWorldPosition.GetZ()); + for (uint32_t i = 0; i < numRays; ++i) + { + AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( + result, &AzFramework::Terrain::TerrainDataRequests::GetClosestIntersection, ray); + } + }); + } + + BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_GetClosestIntersectionWorstCase) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 4096, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 1024, 10, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 10, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 4096, 10, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 1024, 100, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 100, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 4096, 100, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 1024, 1000, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1000, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 4096, 1000, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Unit(::benchmark::kMillisecond); #endif } diff --git a/Gems/Terrain/Code/terrain_files.cmake b/Gems/Terrain/Code/terrain_files.cmake index 53a7c6ac6d..cfc7d40cd5 100644 --- a/Gems/Terrain/Code/terrain_files.cmake +++ b/Gems/Terrain/Code/terrain_files.cmake @@ -9,6 +9,8 @@ set(FILES Include/Terrain/Ebuses/TerrainAreaSurfaceRequestBus.h Include/Terrain/TerrainDataConstants.h + Include/Terrain/Passes/TerrainDetailTextureComputePass.h + Include/Terrain/Passes/TerrainMacroTextureComputePass.h Source/Components/TerrainHeightGradientListComponent.cpp Source/Components/TerrainHeightGradientListComponent.h Source/Components/TerrainLayerSpawnerComponent.cpp @@ -39,6 +41,8 @@ set(FILES Source/TerrainRenderer/BindlessImageArrayHandler.h Source/TerrainRenderer/ClipmapBounds.cpp Source/TerrainRenderer/ClipmapBounds.h + Source/TerrainRenderer/Passes/TerrainDetailTextureComputePass.cpp + Source/TerrainRenderer/Passes/TerrainMacroTextureComputePass.cpp Source/TerrainRenderer/TerrainFeatureProcessor.cpp Source/TerrainRenderer/TerrainFeatureProcessor.h Source/TerrainRenderer/TerrainDetailMaterialManager.cpp diff --git a/cmake/Platform/Common/GCC/Configurations_gcc.cmake b/cmake/Platform/Common/GCC/Configurations_gcc.cmake index 9963c62d39..12dd4d7bdd 100644 --- a/cmake/Platform/Common/GCC/Configurations_gcc.cmake +++ b/cmake/Platform/Common/GCC/Configurations_gcc.cmake @@ -34,7 +34,6 @@ ly_append_configurations_options( -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden - -Wall -Werror @@ -45,7 +44,6 @@ ly_append_configurations_options( -Wno-array-bounds -Wno-attributes -Wno-class-memaccess - -Wno-comment -Wno-delete-non-virtual-dtor -Wno-enum-compare -Wno-format-overflow diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index b21d9d832d..3bef8601bc 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -12,6 +12,9 @@ INCREMENTAL_BUILD_SCRIPT_PATH = 'scripts/build/bootstrap/incremental_build_util. EBS_SNAPSHOT_SCRIPT_PATH = 'scripts/build/tools/ebs_snapshot.py' PIPELINE_RETRY_ATTEMPTS = 3 +// Number of minutes of inactivity in all stages of the pipeline to reach the timeout +PIPELINE_TIMEOUT = 60 + EMPTY_JSON = readJSON text: '{}' ENGINE_REPOSITORY_NAME = 'o3de' @@ -753,143 +756,145 @@ def pipelineConfig = {} // Start Pipeline try { - stage('Setup Pipeline') { - node('controller') { - def envVarList = [] - if(isUnix()) { - envVarList.add('IS_UNIX=1') - } - withEnv(envVarList) { - timestamps { - repositoryUrl = scm.getUserRemoteConfigs()[0].getUrl() - // repositoryName is the full repository name - repositoryName = (repositoryUrl =~ /https:\/\/github.com\/(.*)\.git/)[0][1] - env.REPOSITORY_NAME = repositoryName - (projectName, pipelineName) = GetRunningPipelineName(env.JOB_NAME) // env.JOB_NAME is the name of the job given by Jenkins - env.PIPELINE_NAME = pipelineName - if(env.BRANCH_NAME) { - branchName = env.BRANCH_NAME - } else { - branchName = scm.branches[0].name // for non-multibranch pipelines - env.BRANCH_NAME = branchName // so scripts that read this environment have it (e.g. incremental_build_util.py) - } - if(env.CHANGE_TARGET) { - // PR builds - if(BUILD_SNAPSHOTS.contains(env.CHANGE_TARGET)) { - snapshot = env.CHANGE_TARGET - echo "Snapshot for destination branch \"${env.CHANGE_TARGET}\" found." - } else { - snapshot = DEFAULT_BUILD_SNAPSHOT - echo "Snapshot for destination branch \"${env.CHANGE_TARGET}\" does not exist, defaulting to snapshot \"${snapshot}\"" + timeout(time: PIPELINE_TIMEOUT, unit: 'MINUTES', activity: true) { + stage('Setup Pipeline') { + node('controller') { + def envVarList = [] + if(isUnix()) { + envVarList.add('IS_UNIX=1') + } + withEnv(envVarList) { + timestamps { + repositoryUrl = scm.getUserRemoteConfigs()[0].getUrl() + // repositoryName is the full repository name + repositoryName = (repositoryUrl =~ /https:\/\/github.com\/(.*)\.git/)[0][1] + env.REPOSITORY_NAME = repositoryName + (projectName, pipelineName) = GetRunningPipelineName(env.JOB_NAME) // env.JOB_NAME is the name of the job given by Jenkins + env.PIPELINE_NAME = pipelineName + if(env.BRANCH_NAME) { + branchName = env.BRANCH_NAME + } else { + branchName = scm.branches[0].name // for non-multibranch pipelines + env.BRANCH_NAME = branchName // so scripts that read this environment have it (e.g. incremental_build_util.py) } - } else { - // Non-PR builds - pipelineParameters.add(choice(defaultValue: DEFAULT_BUILD_SNAPSHOT, name: 'SNAPSHOT', choices: BUILD_SNAPSHOTS_WITH_EMPTY, description: 'Selects the build snapshot to use. A more diverted snapshot will cause longer build times, but will not cause build failures.')) - snapshot = env.SNAPSHOT - echo "Snapshot \"${snapshot}\" selected." - } - pipelineProperties.add(disableConcurrentBuilds()) + if(env.CHANGE_TARGET) { + // PR builds + if(BUILD_SNAPSHOTS.contains(env.CHANGE_TARGET)) { + snapshot = env.CHANGE_TARGET + echo "Snapshot for destination branch \"${env.CHANGE_TARGET}\" found." + } else { + snapshot = DEFAULT_BUILD_SNAPSHOT + echo "Snapshot for destination branch \"${env.CHANGE_TARGET}\" does not exist, defaulting to snapshot \"${snapshot}\"" + } + } else { + // Non-PR builds + pipelineParameters.add(choice(defaultValue: DEFAULT_BUILD_SNAPSHOT, name: 'SNAPSHOT', choices: BUILD_SNAPSHOTS_WITH_EMPTY, description: 'Selects the build snapshot to use. A more diverted snapshot will cause longer build times, but will not cause build failures.')) + snapshot = env.SNAPSHOT + echo "Snapshot \"${snapshot}\" selected." + } + pipelineProperties.add(disableConcurrentBuilds()) - echo "Running repository: \"${repositoryName}\", pipeline: \"${pipelineName}\", branch: \"${branchName}\", CHANGE_ID: \"${env.CHANGE_ID}\", GIT_COMMMIT: \"${scm.GIT_COMMIT}\"..." + echo "Running repository: \"${repositoryName}\", pipeline: \"${pipelineName}\", branch: \"${branchName}\", CHANGE_ID: \"${env.CHANGE_ID}\", GIT_COMMMIT: \"${scm.GIT_COMMIT}\"..." - CheckoutBootstrapScripts(branchName) + CheckoutBootstrapScripts(branchName) - // Load configs - pipelineConfig = LoadPipelineConfig(pipelineName, branchName) + // Load configs + pipelineConfig = LoadPipelineConfig(pipelineName, branchName) - // Add each platform as a parameter that the user can disable if needed - if (!IsPullRequest(branchName)) { - pipelineParameters.add(stringParam(defaultValue: '', description: 'Filters and overrides the list of jobs to run for each of the below platforms (comma-separated). Can\'t be used during a pull request.', name: 'JOB_LIST_OVERRIDE')) + // Add each platform as a parameter that the user can disable if needed + if (!IsPullRequest(branchName)) { + pipelineParameters.add(stringParam(defaultValue: '', description: 'Filters and overrides the list of jobs to run for each of the below platforms (comma-separated). Can\'t be used during a pull request.', name: 'JOB_LIST_OVERRIDE')) + pipelineConfig.platforms.each { platform -> + pipelineParameters.add(booleanParam(defaultValue: true, description: '', name: platform.key)) + } + } + // Add additional Jenkins parameters pipelineConfig.platforms.each { platform -> - pipelineParameters.add(booleanParam(defaultValue: true, description: '', name: platform.key)) - } - } - // Add additional Jenkins parameters - pipelineConfig.platforms.each { platform -> - platformEnv = platform.value.PIPELINE_ENV - pipelineJenkinsParameters = platformEnv['PIPELINE_JENKINS_PARAMETERS'] ?: [:] - jenkinsParametersToAdd = pipelineJenkinsParameters[pipelineName] ?: [:] - jenkinsParametersToAdd.each{ jenkinsParameter -> - defaultValue = jenkinsParameter['default_value'] - // Use last run's value as default value so we can save values in different Jenkins environment - if (jenkinsParameter['use_last_run_value']?.toBoolean()) { - defaultValue = params."${jenkinsParameter['parameter_name']}" ?: jenkinsParameter['default_value'] - } - switch (jenkinsParameter['parameter_type']) { - case 'string': - pipelineParameters.add(stringParam(defaultValue: defaultValue, - description: jenkinsParameter['description'], - name: jenkinsParameter['parameter_name'] - )) - break - case 'boolean': - pipelineParameters.add(booleanParam(defaultValue: defaultValue, - description: jenkinsParameter['description'], - name: jenkinsParameter['parameter_name'] - )) - break - case 'password': - pipelineParameters.add(password(defaultValue: defaultValue, - description: jenkinsParameter['description'], - name: jenkinsParameter['parameter_name'] - )) - break + platformEnv = platform.value.PIPELINE_ENV + pipelineJenkinsParameters = platformEnv['PIPELINE_JENKINS_PARAMETERS'] ?: [:] + jenkinsParametersToAdd = pipelineJenkinsParameters[pipelineName] ?: [:] + jenkinsParametersToAdd.each{ jenkinsParameter -> + defaultValue = jenkinsParameter['default_value'] + // Use last run's value as default value so we can save values in different Jenkins environment + if (jenkinsParameter['use_last_run_value']?.toBoolean()) { + defaultValue = params."${jenkinsParameter['parameter_name']}" ?: jenkinsParameter['default_value'] + } + switch (jenkinsParameter['parameter_type']) { + case 'string': + pipelineParameters.add(stringParam(defaultValue: defaultValue, + description: jenkinsParameter['description'], + name: jenkinsParameter['parameter_name'] + )) + break + case 'boolean': + pipelineParameters.add(booleanParam(defaultValue: defaultValue, + description: jenkinsParameter['description'], + name: jenkinsParameter['parameter_name'] + )) + break + case 'password': + pipelineParameters.add(password(defaultValue: defaultValue, + description: jenkinsParameter['description'], + name: jenkinsParameter['parameter_name'] + )) + break + } } } - } - pipelineProperties.add(parameters(pipelineParameters.unique())) - properties(pipelineProperties) + pipelineProperties.add(parameters(pipelineParameters.unique())) + properties(pipelineProperties) - // Stash the INCREMENTAL_BUILD_SCRIPT_PATH and EBS_SNAPSHOT_SCRIPT_PATH since all nodes will use it - stash name: 'incremental_build_script', - includes: INCREMENTAL_BUILD_SCRIPT_PATH - if (fileExists(EBS_SNAPSHOT_SCRIPT_PATH)) { - stash name: 'ebs_snapshot_script', - includes: EBS_SNAPSHOT_SCRIPT_PATH + // Stash the INCREMENTAL_BUILD_SCRIPT_PATH and EBS_SNAPSHOT_SCRIPT_PATH since all nodes will use it + stash name: 'incremental_build_script', + includes: INCREMENTAL_BUILD_SCRIPT_PATH + if (fileExists(EBS_SNAPSHOT_SCRIPT_PATH)) { + stash name: 'ebs_snapshot_script', + includes: EBS_SNAPSHOT_SCRIPT_PATH + } } - } + } } } - } - if(env.BUILD_NUMBER == '1' && !IsPullRequest(branchName)) { - // Exit pipeline early on the intial build. This allows Jenkins to load the pipeline for the branch and enables users - // to select build parameters on their first actual build. See https://issues.jenkins.io/browse/JENKINS-41929 - currentBuild.result = 'SUCCESS' - return - } + if(env.BUILD_NUMBER == '1' && !IsPullRequest(branchName)) { + // Exit pipeline early on the intial build. This allows Jenkins to load the pipeline for the branch and enables users + // to select build parameters on their first actual build. See https://issues.jenkins.io/browse/JENKINS-41929 + currentBuild.result = 'SUCCESS' + return + } - def someBuildHappened = false + def someBuildHappened = false - // Build and Post-Build Testing Stage - def buildConfigs = [:] + // Build and Post-Build Testing Stage + def buildConfigs = [:] - // Platform Builds run on EC2 - pipelineConfig.platforms.each { platform -> - platform.value.build_types.each { build_job -> - if (IsJobEnabled(branchName, build_job, pipelineName, platform.key)) { // User can filter jobs, jobs are tagged by pipeline - def envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) - envVars['JENKINS_JOB_NAME'] = env.JOB_NAME // Save original Jenkins job name to JENKINS_JOB_NAME - envVars['JOB_NAME'] = "${branchName}_${platform.key}_${build_job.key}" // backwards compatibility, some scripts rely on this - someBuildHappened = true + // Platform Builds run on EC2 + pipelineConfig.platforms.each { platform -> + platform.value.build_types.each { build_job -> + if (IsJobEnabled(branchName, build_job, pipelineName, platform.key)) { // User can filter jobs, jobs are tagged by pipeline + def envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) + envVars['JENKINS_JOB_NAME'] = env.JOB_NAME // Save original Jenkins job name to JENKINS_JOB_NAME + envVars['JOB_NAME'] = "${branchName}_${platform.key}_${build_job.key}" // backwards compatibility, some scripts rely on this + someBuildHappened = true - buildConfigs["${platform.key} [${build_job.key}]"] = CreateBuildJobs(pipelineConfig, platform, build_job, envVars, branchName, pipelineName, repositoryName, projectName) + buildConfigs["${platform.key} [${build_job.key}]"] = CreateBuildJobs(pipelineConfig, platform, build_job, envVars, branchName, pipelineName, repositoryName, projectName) + } } } - } - timestamps { + timestamps { - stage('Build') { - parallel buildConfigs // Run parallel builds + stage('Build') { + parallel buildConfigs // Run parallel builds + } + + echo 'All builds successful' + } + if (!someBuildHappened) { + currentBuild.result = 'NOT_BUILT' } - - echo 'All builds successful' - } - if (!someBuildHappened) { - currentBuild.result = 'NOT_BUILT' } } catch(Exception e) {