diff --git a/AutomatedTesting/Gem/PythonCoverage/preview.png b/AutomatedTesting/Gem/PythonCoverage/preview.png
index 2f1ed47754..2979dbb6a4 100644
--- a/AutomatedTesting/Gem/PythonCoverage/preview.png
+++ b/AutomatedTesting/Gem/PythonCoverage/preview.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa
-size 41127
+oid sha256:de0e6e480ece5b423222f4feacf56553d73713fe9afea8bbc9a2660a3cd54ec7
+size 1232
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/Gem/PythonTests/Terrain/EditorScripts/Terrain_World_ConfigurationWorks.py b/AutomatedTesting/Gem/PythonTests/Terrain/EditorScripts/Terrain_World_ConfigurationWorks.py
index bb5dcb3bea..41dc6b92af 100644
--- a/AutomatedTesting/Gem/PythonTests/Terrain/EditorScripts/Terrain_World_ConfigurationWorks.py
+++ b/AutomatedTesting/Gem/PythonTests/Terrain/EditorScripts/Terrain_World_ConfigurationWorks.py
@@ -93,7 +93,7 @@ def Terrain_World_ConfigurationWorks():
# 5) Set the base Terrain World values
world_bounds_max = azmath.Vector3(1100.0, 1100.0, 1100.0)
world_bounds_min = azmath.Vector3(10.0, 10.0, 10.0)
- height_query_resolution = azmath.Vector2(1.0, 1.0)
+ height_query_resolution = 1.0
hydra.set_component_property_value(terrain_world_component, "Configuration|World Bounds (Max)", world_bounds_max)
hydra.set_component_property_value(terrain_world_component, "Configuration|World Bounds (Min)", world_bounds_min)
hydra.set_component_property_value(terrain_world_component, "Configuration|Height Query Resolution (m)", height_query_resolution)
@@ -148,7 +148,7 @@ def Terrain_World_ConfigurationWorks():
# 13) Check height value is the expected one when query resolution is changed
testpoint = terrain.TerrainDataRequestBus(bus.Broadcast, 'GetHeightFromFloats', 10.5, 10.5, CLAMP)
- height_query_resolution = azmath.Vector2(0.5, 0.5)
+ height_query_resolution = 0.5
hydra.set_component_property_value(terrain_world_component, "Configuration|Height Query Resolution (m)", height_query_resolution)
general.idle_wait_frames(1)
testpoint2 = terrain.TerrainDataRequestBus(bus.Broadcast, 'GetHeightFromFloats', 10.5, 10.5, CLAMP)
@@ -165,4 +165,3 @@ if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Terrain_World_ConfigurationWorks)
-
diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py
index 0060a3b29a..bedf474387 100644
--- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py
+++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Menus_FileMenuOptions.py
@@ -38,7 +38,7 @@ def Menus_FileMenuOptions_Work():
("Save As",),
("Save Level Statistics",),
("Edit Project Settings",),
- #("Edit Platform Settings",), Temporarily disabled due to https://github.com/o3de/o3de/issues/6604
+ ("Edit Platform Settings",),
("New Project",),
("Open Project",),
("Show Log File",),
diff --git a/AutomatedTesting/Gem/Sponza/preview.png b/AutomatedTesting/Gem/Sponza/preview.png
new file mode 100644
index 0000000000..2979dbb6a4
--- /dev/null
+++ b/AutomatedTesting/Gem/Sponza/preview.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:de0e6e480ece5b423222f4feacf56553d73713fe9afea8bbc9a2660a3cd54ec7
+size 1232
diff --git a/AutomatedTesting/Gem/preview.png b/AutomatedTesting/Gem/preview.png
index 2f1ed47754..2979dbb6a4 100644
--- a/AutomatedTesting/Gem/preview.png
+++ b/AutomatedTesting/Gem/preview.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa
-size 41127
+oid sha256:de0e6e480ece5b423222f4feacf56553d73713fe9afea8bbc9a2660a3cd54ec7
+size 1232
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 3869dfdfcb..70730a4496 100644
--- a/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC_NetLevelEntity.scriptcanvas
+++ b/AutomatedTesting/Levels/Multiplayer/AutoComponent_RPC/AutoComponent_RPC_NetLevelEntity.scriptcanvas
@@ -5,15 +5,120 @@
"ClassData": {
"m_scriptCanvas": {
"Id": {
- "id": 1685762441320719908
+ "id": 7558387155527535988
},
"Name": "AutoComponent_RPC_NetLevelEntity",
"Components": {
"Component_[2936040539888065977]": {
- "$type": "{4D755CA9-AB92-462C-B24F-0B3376F19967} Graph",
+ "$type": "EditorGraph",
"Id": 2936040539888065977,
"m_graphData": {
"m_nodes": [
+ {
+ "Id": {
+ "id": 11993350262154
+ },
+ "Name": "SC-Node(GetAuthorityToClientNoParams_PlayFxEventByEntityId)",
+ "Components": {
+ "Component_[103174496050601676]": {
+ "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method",
+ "Id": 103174496050601676,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{AE2A0AA3-99DD-4DE4-AFEA-7560F078943C}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "EntityId: 0",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DataType": 1
+ },
+ {
+ "id": {
+ "m_id": "{4D460DFD-82A1-4A92-8EAE-D32A96E79FA0}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "In",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{3FD9A3D0-FFAA-475E-89CB-D24EB4FEB952}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Out",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{F120FEE1-448B-4D61-8439-10511C797707}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Event<>",
+ "DisplayDataType": {
+ "m_type": 4,
+ "m_azType": "{F429F985-AF00-529B-8449-16E56694E5F9}"
+ },
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 2
+ },
+ "DataType": 1
+ }
+ ],
+ "Datums": [
+ {
+ "scriptCanvasType": {
+ "m_type": 1
+ },
+ "isNullPointer": false,
+ "$type": "EntityId",
+ "value": {
+ "id": 2901262558
+ },
+ "label": "EntityId: 0"
+ }
+ ],
+ "methodType": 2,
+ "methodName": "GetAuthorityToClientNoParams_PlayFxEventByEntityId",
+ "className": "NetworkTestLevelEntityComponent",
+ "resultSlotIDs": [
+ {}
+ ],
+ "inputSlots": [
+ {
+ "m_id": "{AE2A0AA3-99DD-4DE4-AFEA-7560F078943C}"
+ }
+ ],
+ "prettyClassName": "NetworkTestLevelEntityComponent"
+ }
+ }
+ },
{
"Id": {
"id": 56986727032248
@@ -338,7 +443,7 @@
"isNullPointer": false,
"$type": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9} AZStd::string",
"value": "AutoComponent_RPC_NetLevelEntity: I'm a client playing some superficial fx",
- "label": "Color"
+ "label": "Text"
},
{
"scriptCanvasType": {
@@ -352,7 +457,7 @@
0.0,
1.0
],
- "label": "Color: 2"
+ "label": "Color"
},
{
"scriptCanvasType": {
@@ -361,7 +466,7 @@
"isNullPointer": false,
"$type": "double",
"value": 2.0,
- "label": "Number: 3"
+ "label": "Duration"
}
],
"methodType": 0,
@@ -486,153 +591,6 @@
}
}
},
- {
- "Id": {
- "id": 8318619017825
- },
- "Name": "SC-EventNode(AuthorityToClientNoParams_PlayFx Notify Event)",
- "Components": {
- "Component_[15772128920819427182]": {
- "$type": "AzEventHandler",
- "Id": 15772128920819427182,
- "Slots": [
- {
- "id": {
- "m_id": "{2A42C379-8E3B-46EF-BC63-C1D5395CB583}"
- },
- "contracts": [
- {
- "$type": "SlotTypeContract"
- },
- {
- "$type": "ConnectionLimitContract",
- "limit": 1
- },
- {
- "$type": "RestrictedNodeContract",
- "m_nodeId": {
- "id": 7820402811489
- }
- }
- ],
- "slotName": "Connect",
- "toolTip": "Connect the AZ Event to this AZ Event Handler.",
- "Descriptor": {
- "ConnectionType": 1,
- "SlotType": 1
- }
- },
- {
- "id": {
- "m_id": "{3DB9829E-6088-49B9-A56D-4D1884C679BD}"
- },
- "contracts": [
- {
- "$type": "SlotTypeContract"
- }
- ],
- "slotName": "Disconnect",
- "toolTip": "Disconnect current AZ Event from this AZ Event Handler.",
- "Descriptor": {
- "ConnectionType": 1,
- "SlotType": 1
- }
- },
- {
- "id": {
- "m_id": "{9AC3CF57-B648-4B43-8FCA-8576B6EA350B}"
- },
- "contracts": [
- {
- "$type": "SlotTypeContract"
- }
- ],
- "slotName": "On Connected",
- "toolTip": "Signaled when a connection has taken place.",
- "Descriptor": {
- "ConnectionType": 2,
- "SlotType": 1
- }
- },
- {
- "id": {
- "m_id": "{5FB8D529-6FC6-4543-99B5-5B147EBD7BE6}"
- },
- "contracts": [
- {
- "$type": "SlotTypeContract"
- }
- ],
- "slotName": "On Disconnected",
- "toolTip": "Signaled when this event handler is disconnected.",
- "Descriptor": {
- "ConnectionType": 2,
- "SlotType": 1
- }
- },
- {
- "id": {
- "m_id": "{0481BBFE-D31E-421F-A6C2-8A7AF3012545}"
- },
- "contracts": [
- {
- "$type": "SlotTypeContract"
- }
- ],
- "slotName": "OnEvent",
- "toolTip": "Triggered when the AZ Event invokes Signal() function.",
- "Descriptor": {
- "ConnectionType": 2,
- "SlotType": 1
- },
- "IsLatent": true
- },
- {
- "id": {
- "m_id": "{5F809F1C-ED4E-4391-9E33-AD3B64561A40}"
- },
- "contracts": [
- {
- "$type": "SlotTypeContract"
- },
- {
- "$type": "ConnectionLimitContract",
- "limit": 1
- },
- {
- "$type": "RestrictedNodeContract",
- "m_nodeId": {
- "id": 7820402811489
- }
- }
- ],
- "slotName": "AuthorityToClientNoParams_PlayFx Notify Event",
- "Descriptor": {
- "ConnectionType": 1,
- "SlotType": 2
- },
- "DataType": 1
- }
- ],
- "Datums": [
- {
- "scriptCanvasType": {
- "m_type": 4,
- "m_azType": "{F429F985-AF00-529B-8449-16E56694E5F9}"
- },
- "isNullPointer": true,
- "label": "AuthorityToClientNoParams_PlayFx Notify Event"
- }
- ],
- "m_azEventEntry": {
- "m_eventName": "AuthorityToClientNoParams_PlayFx Notify Event",
- "m_eventSlotId": {
- "m_id": "{5F809F1C-ED4E-4391-9E33-AD3B64561A40}"
- }
- }
- }
- }
- },
{
"Id": {
"id": 56991021999544
@@ -732,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
@@ -868,17 +1019,17 @@
},
{
"Id": {
- "id": 8400576252253
+ "id": 16962627423626
},
"Name": "SC-Node(AuthorityToClientNoParams_PlayFxByEntityId)",
"Components": {
- "Component_[6332803108634970671]": {
+ "Component_[3643560316791874936]": {
"$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method",
- "Id": 6332803108634970671,
+ "Id": 3643560316791874936,
"Slots": [
{
"id": {
- "m_id": "{87B7266B-D7B1-4CAD-9898-4D7F0274DAB0}"
+ "m_id": "{029728DF-0939-4D64-A9A1-3DB4B8AF127E}"
},
"contracts": [
{
@@ -886,7 +1037,7 @@
}
],
"slotName": "Source",
- "toolTip": "The Source containing the NetworkTestPlayerComponentController",
+ "toolTip": "The Source containing the NetworkTestLevelEntityComponentController",
"Descriptor": {
"ConnectionType": 1,
"SlotType": 2
@@ -895,7 +1046,7 @@
},
{
"id": {
- "m_id": "{AB0D7C00-A334-449A-AC56-EA3167AB8900}"
+ "m_id": "{2C322CF8-1A5C-48D4-8CD2-9723E2DD4A4D}"
},
"contracts": [
{
@@ -910,7 +1061,7 @@
},
{
"id": {
- "m_id": "{A52302D6-9DF9-45C2-960D-19BF90A4A931}"
+ "m_id": "{51F7773F-90F9-4465-8A0E-627EFC30E696}"
},
"contracts": [
{
@@ -939,16 +1090,163 @@
],
"methodType": 2,
"methodName": "AuthorityToClientNoParams_PlayFxByEntityId",
- "className": "NetworkTestPlayerComponent",
+ "className": "NetworkTestLevelEntityComponent",
"resultSlotIDs": [
{}
],
"inputSlots": [
{
- "m_id": "{87B7266B-D7B1-4CAD-9898-4D7F0274DAB0}"
+ "m_id": "{029728DF-0939-4D64-A9A1-3DB4B8AF127E}"
}
],
- "prettyClassName": "NetworkTestPlayerComponent"
+ "prettyClassName": "NetworkTestLevelEntityComponent"
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 12482976533898
+ },
+ "Name": "SC-EventNode(AuthorityToClientNoParams_PlayFx Notify Event)",
+ "Components": {
+ "Component_[3959674633056578794]": {
+ "$type": "AzEventHandler",
+ "Id": 3959674633056578794,
+ "Slots": [
+ {
+ "id": {
+ "m_id": "{D9C7482D-62F3-494B-ABD8-DEE1EC423F5B}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ },
+ {
+ "$type": "ConnectionLimitContract",
+ "limit": 1
+ },
+ {
+ "$type": "RestrictedNodeContract",
+ "m_nodeId": {
+ "id": 11993350262154
+ }
+ }
+ ],
+ "slotName": "Connect",
+ "toolTip": "Connect the AZ Event to this AZ Event Handler.",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{79E07161-43E8-46B6-A402-ACEF441621ED}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "Disconnect",
+ "toolTip": "Disconnect current AZ Event from this AZ Event Handler.",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{0DA1B9BC-BAA1-4144-B9A8-C64A3C1EF3B7}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "On Connected",
+ "toolTip": "Signaled when a connection has taken place.",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{F978B3BE-22DC-48EA-B004-D9C7FA7B32E8}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "On Disconnected",
+ "toolTip": "Signaled when this event handler is disconnected.",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ }
+ },
+ {
+ "id": {
+ "m_id": "{27F4E9A2-F450-4519-8358-D13D823DA33F}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ }
+ ],
+ "slotName": "OnEvent",
+ "toolTip": "Triggered when the AZ Event invokes Signal() function.",
+ "Descriptor": {
+ "ConnectionType": 2,
+ "SlotType": 1
+ },
+ "IsLatent": true
+ },
+ {
+ "id": {
+ "m_id": "{3CCA270B-6726-48D0-8523-154B42269D61}"
+ },
+ "contracts": [
+ {
+ "$type": "SlotTypeContract"
+ },
+ {
+ "$type": "ConnectionLimitContract",
+ "limit": 1
+ },
+ {
+ "$type": "RestrictedNodeContract",
+ "m_nodeId": {
+ "id": 11993350262154
+ }
+ }
+ ],
+ "slotName": "AuthorityToClientNoParams_PlayFx Notify Event",
+ "Descriptor": {
+ "ConnectionType": 1,
+ "SlotType": 2
+ },
+ "DataType": 1
+ }
+ ],
+ "Datums": [
+ {
+ "scriptCanvasType": {
+ "m_type": 4,
+ "m_azType": "{F429F985-AF00-529B-8449-16E56694E5F9}"
+ },
+ "isNullPointer": true,
+ "label": "AuthorityToClientNoParams_PlayFx Notify Event"
+ }
+ ],
+ "m_azEventEntry": {
+ "m_eventName": "AuthorityToClientNoParams_PlayFx Notify Event",
+ "m_eventSlotId": {
+ "m_id": "{3CCA270B-6726-48D0-8523-154B42269D61}"
+ }
+ }
}
}
},
@@ -1090,111 +1388,6 @@
}
}
}
- },
- {
- "Id": {
- "id": 7820402811489
- },
- "Name": "SC-Node(GetAuthorityToClientNoParams_PlayFxEventByEntityId)",
- "Components": {
- "Component_[9263945554457190064]": {
- "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method",
- "Id": 9263945554457190064,
- "Slots": [
- {
- "id": {
- "m_id": "{F22A7438-E72F-4757-90D9-99F03C91E10D}"
- },
- "contracts": [
- {
- "$type": "SlotTypeContract"
- }
- ],
- "slotName": "EntityId: 0",
- "Descriptor": {
- "ConnectionType": 1,
- "SlotType": 2
- },
- "DataType": 1
- },
- {
- "id": {
- "m_id": "{510F56FD-6778-4DB8-BDDE-258335431CC6}"
- },
- "contracts": [
- {
- "$type": "SlotTypeContract"
- }
- ],
- "slotName": "In",
- "Descriptor": {
- "ConnectionType": 1,
- "SlotType": 1
- }
- },
- {
- "id": {
- "m_id": "{94C2AF04-6BFA-4E5A-9490-C7479A7AF61E}"
- },
- "contracts": [
- {
- "$type": "SlotTypeContract"
- }
- ],
- "slotName": "Out",
- "Descriptor": {
- "ConnectionType": 2,
- "SlotType": 1
- }
- },
- {
- "id": {
- "m_id": "{9C6DDF96-6BF0-45ED-B15F-2E6C2FF5F886}"
- },
- "contracts": [
- {
- "$type": "SlotTypeContract"
- }
- ],
- "slotName": "Event<>",
- "DisplayDataType": {
- "m_type": 4,
- "m_azType": "{F429F985-AF00-529B-8449-16E56694E5F9}"
- },
- "Descriptor": {
- "ConnectionType": 2,
- "SlotType": 2
- },
- "DataType": 1
- }
- ],
- "Datums": [
- {
- "scriptCanvasType": {
- "m_type": 1
- },
- "isNullPointer": false,
- "$type": "EntityId",
- "value": {
- "id": 2901262558
- },
- "label": "EntityId: 0"
- }
- ],
- "methodType": 2,
- "methodName": "GetAuthorityToClientNoParams_PlayFxEventByEntityId",
- "className": "NetworkTestPlayerComponent",
- "resultSlotIDs": [
- {}
- ],
- "inputSlots": [
- {
- "m_id": "{F22A7438-E72F-4757-90D9-99F03C91E10D}"
- }
- ],
- "prettyClassName": "NetworkTestPlayerComponent"
- }
- }
}
],
"m_connections": [
@@ -1226,62 +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": 9392713697629
- },
- "Name": "srcEndpoint=(Repeater: Action), destEndpoint=(AuthorityToClientNoParams_PlayFxByEntityId: In)",
- "Components": {
- "Component_[17811480012084226596]": {
- "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
- "Id": 17811480012084226596,
- "sourceEndpoint": {
- "nodeId": {
- "id": 56986727032248
- },
- "slotId": {
- "m_id": "{C1CCBA7B-A13B-4FCE-99ED-8FD1A8F72869}"
- }
- },
- "targetEndpoint": {
- "nodeId": {
- "id": 8400576252253
- },
- "slotId": {
- "m_id": "{AB0D7C00-A334-449A-AC56-EA3167AB8900}"
- }
- }
- }
- }
- },
{
"Id": {
"id": 10269167405311
@@ -1366,146 +1503,6 @@
}
}
},
- {
- "Id": {
- "id": 9022993654369
- },
- "Name": "srcEndpoint=(GetAuthorityToClientNoParams_PlayFxEventByEntityId: Event<>), destEndpoint=(AuthorityToClientNoParams_PlayFx Notify Event: AuthorityToClientNoParams_PlayFx Notify Event)",
- "Components": {
- "Component_[4910818715692868417]": {
- "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
- "Id": 4910818715692868417,
- "sourceEndpoint": {
- "nodeId": {
- "id": 7820402811489
- },
- "slotId": {
- "m_id": "{9C6DDF96-6BF0-45ED-B15F-2E6C2FF5F886}"
- }
- },
- "targetEndpoint": {
- "nodeId": {
- "id": 8318619017825
- },
- "slotId": {
- "m_id": "{5F809F1C-ED4E-4391-9E33-AD3B64561A40}"
- }
- }
- }
- }
- },
- {
- "Id": {
- "id": 9078828229217
- },
- "Name": "srcEndpoint=(GetAuthorityToClientNoParams_PlayFxEventByEntityId: Out), destEndpoint=(AuthorityToClientNoParams_PlayFx Notify Event: Connect)",
- "Components": {
- "Component_[16758724763058723803]": {
- "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
- "Id": 16758724763058723803,
- "sourceEndpoint": {
- "nodeId": {
- "id": 7820402811489
- },
- "slotId": {
- "m_id": "{94C2AF04-6BFA-4E5A-9490-C7479A7AF61E}"
- }
- },
- "targetEndpoint": {
- "nodeId": {
- "id": 8318619017825
- },
- "slotId": {
- "m_id": "{2A42C379-8E3B-46EF-BC63-C1D5395CB583}"
- }
- }
- }
- }
- },
- {
- "Id": {
- "id": 9808972669537
- },
- "Name": "srcEndpoint=(TimeDelay: Done), destEndpoint=(GetAuthorityToClientNoParams_PlayFxEventByEntityId: In)",
- "Components": {
- "Component_[597205010205160938]": {
- "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
- "Id": 597205010205160938,
- "sourceEndpoint": {
- "nodeId": {
- "id": 57012496836024
- },
- "slotId": {
- "m_id": "{158B30BE-BD39-40AE-A8A8-F0E5694F0180}"
- }
- },
- "targetEndpoint": {
- "nodeId": {
- "id": 7820402811489
- },
- "slotId": {
- "m_id": "{510F56FD-6778-4DB8-BDDE-258335431CC6}"
- }
- }
- }
- }
- },
- {
- "Id": {
- "id": 10148275085921
- },
- "Name": "srcEndpoint=(AuthorityToClientNoParams_PlayFx Notify Event: OnEvent), destEndpoint=(Print: In)",
- "Components": {
- "Component_[1594149632687531010]": {
- "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
- "Id": 1594149632687531010,
- "sourceEndpoint": {
- "nodeId": {
- "id": 8318619017825
- },
- "slotId": {
- "m_id": "{0481BBFE-D31E-421F-A6C2-8A7AF3012545}"
- }
- },
- "targetEndpoint": {
- "nodeId": {
- "id": 56995316966840
- },
- "slotId": {
- "m_id": "{7CAD6E31-6218-4326-8FFB-0523F545E250}"
- }
- }
- }
- }
- },
- {
- "Id": {
- "id": 10629311423073
- },
- "Name": "srcEndpoint=(AuthorityToClientNoParams_PlayFx Notify Event: OnEvent), destEndpoint=(DrawTextOnEntity: In)",
- "Components": {
- "Component_[17976200298405988971]": {
- "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
- "Id": 17976200298405988971,
- "sourceEndpoint": {
- "nodeId": {
- "id": 8318619017825
- },
- "slotId": {
- "m_id": "{0481BBFE-D31E-421F-A6C2-8A7AF3012545}"
- }
- },
- "targetEndpoint": {
- "nodeId": {
- "id": 57003906901432
- },
- "slotId": {
- "m_id": "{1673B8A0-D4EC-4CC7-8F80-0419BB5560EB}"
- }
- }
- }
- }
- },
{
"Id": {
"id": 42045766425613
@@ -1533,6 +1530,286 @@
}
}
}
+ },
+ {
+ "Id": {
+ "id": 13187351170442
+ },
+ "Name": "srcEndpoint=(GetAuthorityToClientNoParams_PlayFxEventByEntityId: Event<>), destEndpoint=(AuthorityToClientNoParams_PlayFx Notify Event: AuthorityToClientNoParams_PlayFx Notify Event)",
+ "Components": {
+ "Component_[16956267859815935178]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 16956267859815935178,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 11993350262154
+ },
+ "slotId": {
+ "m_id": "{F120FEE1-448B-4D61-8439-10511C797707}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 12482976533898
+ },
+ "slotId": {
+ "m_id": "{3CCA270B-6726-48D0-8523-154B42269D61}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 13243185745290
+ },
+ "Name": "srcEndpoint=(GetAuthorityToClientNoParams_PlayFxEventByEntityId: Out), destEndpoint=(AuthorityToClientNoParams_PlayFx Notify Event: Connect)",
+ "Components": {
+ "Component_[8562287491617113016]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 8562287491617113016,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 11993350262154
+ },
+ "slotId": {
+ "m_id": "{3FD9A3D0-FFAA-475E-89CB-D24EB4FEB952}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 12482976533898
+ },
+ "slotId": {
+ "m_id": "{D9C7482D-62F3-494B-ABD8-DEE1EC423F5B}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 14252503059850
+ },
+ "Name": "srcEndpoint=(TimeDelay: Done), destEndpoint=(GetAuthorityToClientNoParams_PlayFxEventByEntityId: In)",
+ "Components": {
+ "Component_[2852756465133807472]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 2852756465133807472,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 57012496836024
+ },
+ "slotId": {
+ "m_id": "{158B30BE-BD39-40AE-A8A8-F0E5694F0180}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 11993350262154
+ },
+ "slotId": {
+ "m_id": "{4D460DFD-82A1-4A92-8EAE-D32A96E79FA0}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 14690589724042
+ },
+ "Name": "srcEndpoint=(AuthorityToClientNoParams_PlayFx Notify Event: OnEvent), destEndpoint=(DrawTextOnEntity: In)",
+ "Components": {
+ "Component_[5236071663388486964]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 5236071663388486964,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 12482976533898
+ },
+ "slotId": {
+ "m_id": "{27F4E9A2-F450-4519-8358-D13D823DA33F}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 57003906901432
+ },
+ "slotId": {
+ "m_id": "{1673B8A0-D4EC-4CC7-8F80-0419BB5560EB}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 14943992794506
+ },
+ "Name": "srcEndpoint=(AuthorityToClientNoParams_PlayFx Notify Event: OnEvent), destEndpoint=(Print: In)",
+ "Components": {
+ "Component_[3230673372890452861]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 3230673372890452861,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 12482976533898
+ },
+ "slotId": {
+ "m_id": "{27F4E9A2-F450-4519-8358-D13D823DA33F}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 56995316966840
+ },
+ "slotId": {
+ "m_id": "{7CAD6E31-6218-4326-8FFB-0523F545E250}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "Id": {
+ "id": 18109383691658
+ },
+ "Name": "srcEndpoint=(Repeater: Action), destEndpoint=(AuthorityToClientNoParams_PlayFxByEntityId: In)",
+ "Components": {
+ "Component_[12099207352632363628]": {
+ "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection",
+ "Id": 12099207352632363628,
+ "sourceEndpoint": {
+ "nodeId": {
+ "id": 56986727032248
+ },
+ "slotId": {
+ "m_id": "{C1CCBA7B-A13B-4FCE-99ED-8FD1A8F72869}"
+ }
+ },
+ "targetEndpoint": {
+ "nodeId": {
+ "id": 16962627423626
+ },
+ "slotId": {
+ "m_id": "{2C322CF8-1A5C-48D4-8CD2-9723E2DD4A4D}"
+ }
+ }
+ }
+ }
+ },
+ {
+ "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}"
+ }
+ }
+ }
+ }
}
]
},
@@ -1543,37 +1820,6 @@
"_fileVersion": 1
},
"GraphCanvasData": [
- {
- "Key": {
- "id": 7820402811489
- },
- "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,
- 400.0
- ]
- },
- "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
- "$type": "StylingComponentSaveData",
- "SubStyle": ".method"
- },
- "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
- "$type": "PersistentIdComponentSaveData",
- "PersistentId": "{F35F8202-B5EE-4ADD-9FF6-AF214A094266}"
- }
- }
- }
- },
{
"Key": {
"id": 8310662318335
@@ -1607,38 +1853,7 @@
},
{
"Key": {
- "id": 8318619017825
- },
- "Value": {
- "ComponentData": {
- "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
- "$type": "NodeSaveData"
- },
- "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
- "$type": "GeneralNodeTitleComponentSaveData",
- "PaletteOverride": "HandlerNodeTitlePalette"
- },
- "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
- "$type": "GeometrySaveData",
- "Position": [
- 340.0,
- 400.0
- ]
- },
- "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
- "$type": "StylingComponentSaveData",
- "SubStyle": ".azeventhandler"
- },
- "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
- "$type": "PersistentIdComponentSaveData",
- "PersistentId": "{67499699-CA73-48B4-87E0-C66F4A3EA7CB}"
- }
- }
- }
- },
- {
- "Key": {
- "id": 8400576252253
+ "id": 11750998249450
},
"Value": {
"ComponentData": {
@@ -1652,8 +1867,8 @@
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
"$type": "GeometrySaveData",
"Position": [
- 420.0,
- -60.0
+ 100.0,
+ 60.0
]
},
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
@@ -1662,7 +1877,130 @@
},
"{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
"$type": "PersistentIdComponentSaveData",
- "PersistentId": "{2B6329F7-4CE7-4E01-B1A4-1FFCAB2D0B72}"
+ "PersistentId": "{73B270BC-9743-41C1-9E48-0CAB5A63AC97}"
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 11993350262154
+ },
+ "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": [
+ 60.0,
+ 480.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData",
+ "SubStyle": ".method"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{AF658C01-E781-416E-B719-70C171E3FA18}"
+ }
+ }
+ }
+ },
+ {
+ "Key": {
+ "id": 12482976533898
+ },
+ "Value": {
+ "ComponentData": {
+ "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
+ "$type": "NodeSaveData"
+ },
+ "{328FF15C-C302-458F-A43D-E1794DE0904E}": {
+ "$type": "GeneralNodeTitleComponentSaveData",
+ "PaletteOverride": "HandlerNodeTitlePalette"
+ },
+ "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
+ "$type": "GeometrySaveData",
+ "Position": [
+ 520.0,
+ 500.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData",
+ "SubStyle": ".azeventhandler"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{404C56EB-23C4-4AC8-A08A-752725B19703}"
+ }
+ }
+ }
+ },
+ {
+ "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
+ },
+ "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": [
+ 1240.0,
+ 0.0
+ ]
+ },
+ "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
+ "$type": "StylingComponentSaveData",
+ "SubStyle": ".method"
+ },
+ "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
+ "$type": "PersistentIdComponentSaveData",
+ "PersistentId": "{E06094C1-8911-4FB6-9D28-E02B808F1DB1}"
}
}
}
@@ -1683,8 +2021,8 @@
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
"$type": "GeometrySaveData",
"Position": [
- 80.0,
- -60.0
+ 860.0,
+ 0.0
]
},
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
@@ -1743,8 +2081,8 @@
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
"$type": "GeometrySaveData",
"Position": [
- 800.0,
- 260.0
+ 980.0,
+ 400.0
]
},
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
@@ -1773,8 +2111,8 @@
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
"$type": "GeometrySaveData",
"Position": [
- 420.0,
- 100.0
+ 1220.0,
+ 140.0
]
},
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
@@ -1803,8 +2141,8 @@
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
"$type": "GeometrySaveData",
"Position": [
- 800.0,
- 460.0
+ 980.0,
+ 600.0
]
},
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
@@ -1880,15 +2218,16 @@
},
{
"Key": {
- "id": 1685762441320719908
+ "id": 7558387155527535988
},
"Value": {
"ComponentData": {
"{5F84B500-8C45-40D1-8EFC-A5306B241444}": {
"$type": "SceneComponentSaveData",
"ViewParams": {
- "AnchorX": -349.0,
- "AnchorY": 10.0
+ "Scale": 0.9585879578077288,
+ "AnchorX": 488.2181091308594,
+ "AnchorY": -175.25778198242188
}
}
}
@@ -1897,6 +2236,10 @@
],
"StatisticsHelper": {
"InstanceCounter": [
+ {
+ "Key": 435784057388502002,
+ "Value": 1
+ },
{
"Key": 4199610336680704683,
"Value": 1
@@ -1905,16 +2248,20 @@
"Key": 4847610523576971761,
"Value": 1
},
+ {
+ "Key": 5317247366618270757,
+ "Value": 1
+ },
{
"Key": 6462358712820489356,
"Value": 1
},
{
- "Key": 7087687843968394353,
+ "Key": 8065262779685207188,
"Value": 1
},
{
- "Key": 8679770052035517025,
+ "Key": 8452971738487658154,
"Value": 1
},
{
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/AzAssetBrowser/AzAssetBrowserWindow.ui b/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui
index 2cc7c57ccd..e07a5cda95 100644
--- a/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui
+++ b/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.ui
@@ -78,10 +78,7 @@
Qt::ClickFocus
-
-
-
- 3
+ Collapse All
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/QtEditorApplication.h b/Code/Editor/Core/QtEditorApplication.h
index 0d702bf647..28ee8ac14b 100644
--- a/Code/Editor/Core/QtEditorApplication.h
+++ b/Code/Editor/Core/QtEditorApplication.h
@@ -13,7 +13,6 @@
#include
#include
#include
-#include "IEventLoopHook.h"
#include
#include
diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp
index 982f8ba411..480a973282 100644
--- a/Code/Editor/CryEdit.cpp
+++ b/Code/Editor/CryEdit.cpp
@@ -1828,34 +1828,6 @@ bool CCryEditApp::InitInstance()
return true;
}
-void CCryEditApp::RegisterEventLoopHook(IEventLoopHook* pHook)
-{
- pHook->pNextHook = m_pEventLoopHook;
- m_pEventLoopHook = pHook;
-}
-
-void CCryEditApp::UnregisterEventLoopHook(IEventLoopHook* pHookToRemove)
-{
- IEventLoopHook* pPrevious = nullptr;
- for (IEventLoopHook* pHook = m_pEventLoopHook; pHook != nullptr; pHook = pHook->pNextHook)
- {
- if (pHook == pHookToRemove)
- {
- if (pPrevious)
- {
- pPrevious->pNextHook = pHookToRemove->pNextHook;
- }
- else
- {
- m_pEventLoopHook = pHookToRemove->pNextHook;
- }
-
- pHookToRemove->pNextHook = nullptr;
- return;
- }
- }
-}
-
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::LoadFile(QString fileName)
{
diff --git a/Code/Editor/CryEdit.h b/Code/Editor/CryEdit.h
index 48f362003c..f472639dcd 100644
--- a/Code/Editor/CryEdit.h
+++ b/Code/Editor/CryEdit.h
@@ -30,7 +30,6 @@ class CConsoleDialog;
struct mg_connection;
struct mg_request_info;
struct mg_context;
-struct IEventLoopHook;
class QAction;
class MainWindow;
class QSharedMemory;
@@ -153,8 +152,6 @@ public:
int IdleProcessing(bool bBackground);
bool IsWindowInForeground();
void RunInitPythonScript(CEditCommandLineInfo& cmdInfo);
- void RegisterEventLoopHook(IEventLoopHook* pHook);
- void UnregisterEventLoopHook(IEventLoopHook* pHook);
void DisableIdleProcessing() override;
void EnableIdleProcessing() override;
@@ -344,7 +341,6 @@ private:
QString m_lastOpenLevelPath;
CQuickAccessBar* m_pQuickAccessBar = nullptr;
- IEventLoopHook* m_pEventLoopHook = nullptr;
QString m_rootEnginePath;
int m_disableIdleProcessingCounter = 0; //!< Counts requests to disable idle processing. When non-zero, idle processing will be disabled.
diff --git a/Code/Editor/EditorPreferencesPageAWS.cpp b/Code/Editor/EditorPreferencesPageAWS.cpp
index 968969245d..bb57802e47 100644
--- a/Code/Editor/EditorPreferencesPageAWS.cpp
+++ b/Code/Editor/EditorPreferencesPageAWS.cpp
@@ -101,7 +101,7 @@ void CEditorPreferencesPage_AWS::SaveSettingsRegistryFile()
return;
}
- [[maybe_unused]] bool saved{};
+ [[maybe_unused]] bool saved = false;
constexpr auto configurationMode =
AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY;
if (AZ::IO::SystemFile outputFile; outputFile.Open(resolvedPath.data(), configurationMode))
diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp
index 9a9e9f5ad3..7314908580 100644
--- a/Code/Editor/EditorViewportWidget.cpp
+++ b/Code/Editor/EditorViewportWidget.cpp
@@ -586,6 +586,7 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
break;
case eNotify_OnEndLoad:
+ case eNotify_OnEndCreate:
UpdateScene();
SetDefaultCamera();
break;
diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp
index a768861b90..635281aee5 100644
--- a/Code/Editor/GameExporter.cpp
+++ b/Code/Editor/GameExporter.cpp
@@ -317,8 +317,8 @@ void CGameExporter::ExportLevelInfo(const QString& path)
root->setAttr("Name", levelName.toUtf8().data());
auto terrain = AzFramework::Terrain::TerrainDataRequestBus::FindFirstHandler();
const AZ::Aabb terrainAabb = terrain ? terrain->GetTerrainAabb() : AZ::Aabb::CreateFromPoint(AZ::Vector3::CreateZero());
- const AZ::Vector2 terrainGridResolution = terrain ? terrain->GetTerrainHeightQueryResolution() : AZ::Vector2::CreateOne();
- const int compiledHeightmapSize = static_cast(terrainAabb.GetXExtent() / terrainGridResolution.GetX());
+ const float terrainGridResolution = terrain ? terrain->GetTerrainHeightQueryResolution() : 1.0f;
+ const int compiledHeightmapSize = static_cast(terrainAabb.GetXExtent() / terrainGridResolution);
root->setAttr("HeightmapSize", compiledHeightmapSize);
//////////////////////////////////////////////////////////////////////////
diff --git a/Code/Editor/IEditor.h b/Code/Editor/IEditor.h
index da29b00f2d..0de08445b4 100644
--- a/Code/Editor/IEditor.h
+++ b/Code/Editor/IEditor.h
@@ -66,7 +66,6 @@ class IAWSResourceManager;
struct ISystem;
struct IRenderer;
struct AABB;
-struct IEventLoopHook;
struct IErrorReport; // Vladimir@conffx
struct IFileUtil; // Vladimir@conffx
struct IEditorLog; // Vladimir@conffx
@@ -509,11 +508,6 @@ struct IEditor
virtual void SetActiveView(CViewport* viewport) = 0;
virtual struct IEditorFileMonitor* GetFileMonitor() = 0;
- // These are needed for Qt integration:
- virtual void RegisterEventLoopHook(IEventLoopHook* pHook) = 0;
- virtual void UnregisterEventLoopHook(IEventLoopHook* pHook) = 0;
- // ^^^
-
//! QMimeData is used by the Qt clipboard.
//! IMPORTANT: Any QMimeData allocated for the clipboard will be deleted
//! when the editor exists. If a QMimeData is allocated by a different
diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp
index 05b74f3b05..b6a4209948 100644
--- a/Code/Editor/IEditorImpl.cpp
+++ b/Code/Editor/IEditorImpl.cpp
@@ -789,16 +789,6 @@ IEditorFileMonitor* CEditorImpl::GetFileMonitor()
return m_pEditorFileMonitor.get();
}
-void CEditorImpl::RegisterEventLoopHook(IEventLoopHook* pHook)
-{
- CCryEditApp::instance()->RegisterEventLoopHook(pHook);
-}
-
-void CEditorImpl::UnregisterEventLoopHook(IEventLoopHook* pHook)
-{
- CCryEditApp::instance()->UnregisterEventLoopHook(pHook);
-}
-
float CEditorImpl::GetTerrainElevation(float x, float y)
{
float terrainElevation = AzFramework::Terrain::TerrainDataRequests::GetDefaultTerrainHeight();
diff --git a/Code/Editor/IEditorImpl.h b/Code/Editor/IEditorImpl.h
index 5e47a76802..73fcec917d 100644
--- a/Code/Editor/IEditorImpl.h
+++ b/Code/Editor/IEditorImpl.h
@@ -155,8 +155,6 @@ public:
CMusicManager* GetMusicManager() override { return m_pMusicManager; };
IEditorFileMonitor* GetFileMonitor() override;
- void RegisterEventLoopHook(IEventLoopHook* pHook) override;
- void UnregisterEventLoopHook(IEventLoopHook* pHook) override;
IIconManager* GetIconManager() override;
float GetTerrainElevation(float x, float y) override;
Editor::EditorQtApplication* GetEditorQtApplication() override { return m_QtApplication; }
diff --git a/Code/Editor/Include/IEditorClassFactory.h b/Code/Editor/Include/IEditorClassFactory.h
index 6c85192436..82422799cf 100644
--- a/Code/Editor/Include/IEditorClassFactory.h
+++ b/Code/Editor/Include/IEditorClassFactory.h
@@ -135,9 +135,6 @@ struct IClassDesc
//////////////////////////////////////////////////////////////////////////
};
-
-struct IViewPaneClass;
-
struct CRYEDIT_API IEditorClassFactory
{
public:
@@ -149,7 +146,6 @@ public:
virtual IClassDesc* FindClass(const char* pClassName) const = 0;
//! Find class in the factory by class id
virtual IClassDesc* FindClass(const GUID& rClassID) const = 0;
- virtual IViewPaneClass* FindViewPaneClassByTitle(const char* pPaneTitle) const = 0;
virtual void UnregisterClass(const char* pClassName) = 0;
virtual void UnregisterClass(const GUID& rClassID) = 0;
//! Get classes that matching specific requirements.
diff --git a/Code/Editor/Include/IEventLoopHook.h b/Code/Editor/Include/IEventLoopHook.h
deleted file mode 100644
index eaf7bf2d62..0000000000
--- a/Code/Editor/Include/IEventLoopHook.h
+++ /dev/null
@@ -1,24 +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_INCLUDE_IEVENTLOOPHOOK_H
-#define CRYINCLUDE_EDITOR_INCLUDE_IEVENTLOOPHOOK_H
-#pragma once
-
-struct IEventLoopHook
-{
- IEventLoopHook* pNextHook;
-
- IEventLoopHook()
- : pNextHook(0) {}
-
- virtual bool PrePumpMessage() { return false; }
-};
-
-#endif // CRYINCLUDE_EDITOR_INCLUDE_IEVENTLOOPHOOK_H
diff --git a/Code/Editor/Include/IViewPane.h b/Code/Editor/Include/IViewPane.h
deleted file mode 100644
index f2425fb954..0000000000
--- a/Code/Editor/Include/IViewPane.h
+++ /dev/null
@@ -1,74 +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_INCLUDE_IVIEWPANE_H
-#define CRYINCLUDE_EDITOR_INCLUDE_IVIEWPANE_H
-#pragma once
-
-#include "IEditorClassFactory.h"
-
-#include
-
-class QWidget;
-class QRect;
-
-struct IViewPaneClass
- : public IClassDesc
-{
- DEFINE_UUID(0x7E13EC7C, 0xF621, 0x4aeb, 0xB6, 0x42, 0x67, 0xD7, 0x8E, 0xD4, 0x68, 0xF8)
-
- enum EDockingDirection
- {
- DOCK_TOP,
- DOCK_LEFT,
- DOCK_RIGHT,
- DOCK_BOTTOM,
- DOCK_FLOAT,
- };
-
- virtual ~IViewPaneClass() = default;
-
- // Return text for view pane title.
- virtual QString GetPaneTitle() = 0;
-
- // Return the string resource ID for the title's text.
- virtual unsigned int GetPaneTitleID() const = 0;
-
- // Return preferable initial docking position for pane.
- virtual EDockingDirection GetDockingDirection() = 0;
-
- // Initial pane size.
- virtual QRect GetPaneRect() = 0;
-
- // Get Minimal view size
- virtual QSize GetMinSize() { return QSize(0, 0); }
-
- // Return true if only one pane at a time of time view class can be created.
- virtual bool SinglePane() = 0;
-
- // Return true if the view window wants to get ID_IDLE_UPDATE commands.
- virtual bool WantIdleUpdate() = 0;
-
- //////////////////////////////////////////////////////////////////////////
- // IUnknown
- //////////////////////////////////////////////////////////////////////////
- HRESULT STDMETHODCALLTYPE QueryInterface(const IID& riid, void** ppvObj)
- {
- if (riid == __az_uuidof(IViewPaneClass))
- {
- *ppvObj = this;
- return S_OK;
- }
- return E_NOINTERFACE;
- }
- //////////////////////////////////////////////////////////////////////////
-
-};
-
-#endif // CRYINCLUDE_EDITOR_INCLUDE_IVIEWPANE_H
diff --git a/Code/Editor/Lib/Tests/IEditorMock.h b/Code/Editor/Lib/Tests/IEditorMock.h
index 99c05c7f4d..780362cb30 100644
--- a/Code/Editor/Lib/Tests/IEditorMock.h
+++ b/Code/Editor/Lib/Tests/IEditorMock.h
@@ -97,8 +97,6 @@ public:
MOCK_METHOD0(GetActiveView, class CViewport* ());
MOCK_METHOD1(SetActiveView, void(CViewport*));
MOCK_METHOD0(GetFileMonitor, struct IEditorFileMonitor* ());
- MOCK_METHOD1(RegisterEventLoopHook, void(IEventLoopHook* ));
- MOCK_METHOD1(UnregisterEventLoopHook, void(IEventLoopHook* ));
MOCK_CONST_METHOD0(CreateQMimeData, QMimeData* ());
MOCK_CONST_METHOD1(DestroyQMimeData, void(QMimeData*));
MOCK_METHOD0(GetLevelIndependentFileMan, class CLevelIndependentFileMan* ());
diff --git a/Code/Editor/Objects/EntityObject.cpp b/Code/Editor/Objects/EntityObject.cpp
index 450a15766c..0d70d47d7d 100644
--- a/Code/Editor/Objects/EntityObject.cpp
+++ b/Code/Editor/Objects/EntityObject.cpp
@@ -499,14 +499,12 @@ void CEntityObject::AdjustLightProperties(CVarBlockPtr& properties, const char*
pAreaLight->SetHumanName("PlanarLight");
}
- bool bCastShadowLegacy = false; // Backward compatibility for existing shadow casting lights
if (IVariable* pCastShadowVarLegacy = FindVariableInSubBlock(properties, pSubBlockVar, "bCastShadow"))
{
pCastShadowVarLegacy->SetFlags(pCastShadowVarLegacy->GetFlags() | IVariable::UI_INVISIBLE);
const QString zeroPrefix("0");
if (!pCastShadowVarLegacy->GetDisplayValue().startsWith(zeroPrefix))
{
- bCastShadowLegacy = true;
pCastShadowVarLegacy->SetDisplayValue(zeroPrefix);
}
}
diff --git a/Code/Editor/Plugin.cpp b/Code/Editor/Plugin.cpp
index 16c386e31c..fd70cc282d 100644
--- a/Code/Editor/Plugin.cpp
+++ b/Code/Editor/Plugin.cpp
@@ -11,9 +11,6 @@
#include "Plugin.h"
-// Editor
-#include "Include/IViewPane.h"
-
#include
CClassFactory* CClassFactory::s_pInstance = nullptr;
@@ -149,23 +146,6 @@ IClassDesc* CClassFactory::FindClass(const GUID& rClassID) const
return pClassDesc;
}
-IViewPaneClass* CClassFactory::FindViewPaneClassByTitle(const char* pPaneTitle) const
-{
- for (size_t i = 0; i < m_classes.size(); i++)
- {
- IViewPaneClass* viewPane = nullptr;
- IClassDesc* desc = m_classes[i];
- if (SUCCEEDED(desc->QueryInterface(__az_uuidof(IViewPaneClass), (void**)&viewPane)))
- {
- if (QString::compare(viewPane->GetPaneTitle(), pPaneTitle) == 0)
- {
- return viewPane;
- }
- }
- }
- return nullptr;
-}
-
void CClassFactory::UnregisterClass(const char* pClassName)
{
IClassDesc* pClassDesc = FindClass(pClassName);
diff --git a/Code/Editor/Plugin.h b/Code/Editor/Plugin.h
index dd2637f0e9..151586070e 100644
--- a/Code/Editor/Plugin.h
+++ b/Code/Editor/Plugin.h
@@ -32,8 +32,6 @@ public:
IClassDesc* FindClass(const char* className) const;
//! Find class in the factory by class ID
IClassDesc* FindClass(const GUID& rClassID) const;
- //! Find View Pane Class in the factory by pane title
- IViewPaneClass* FindViewPaneClassByTitle(const char* pPaneTitle) const;
void UnregisterClass(const char* pClassName);
void UnregisterClass(const GUID& rClassID);
//! Get classes matching specific requirements ordered alphabetically by name.
@@ -96,10 +94,4 @@ public:
#define REGISTER_CLASS_DESC(ClassDesc) \
CAutoRegisterClassHelper g_AutoRegHelper##ClassDesc(new ClassDesc);
-#define REGISTER_QT_CLASS_DESC(ClassDesc, name, category) \
- CAutoRegisterClassHelper g_AutoRegHelper##ClassDesc(new CQtViewClass(name, category));
-
-#define REGISTER_QT_CLASS_DESC_SYSTEM_ID(ClassDesc, name, category, systemid) \
- CAutoRegisterClassHelper g_AutoRegHelper##ClassDesc(new CQtViewClass(name, category, systemid));
-
#endif // CRYINCLUDE_EDITOR_PLUGIN_H
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp
index ea65cf3e59..c51bfaf04e 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp
+++ b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Android.cpp
@@ -209,12 +209,10 @@ namespace ProjectSettingsTool
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::PackageName))
->Attribute(Attributes::LinkOptional, true)
->Attribute(Attributes::PropertyIdentfier, Identfiers::AndroidPackageName)
- ->Attribute(Attributes::LinkedProperty, Identfiers::IosBundleIdentifer)
->DataElement(Handlers::LinkedLineEdit, &AndroidSettings::m_versionName, "Version Name", "Human readable version number. Used to set the \"android: versionName\" tag in the AndroidManifest.xml and ultimately what will be displayed in the App Store.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IOSVersionNumber))
->Attribute(Attributes::LinkOptional, true)
->Attribute(Attributes::PropertyIdentfier, Identfiers::AndroidVersionName)
- ->Attribute(Attributes::LinkedProperty, Identfiers::IosVersionName)
->DataElement(AZ::Edit::UIHandlers::Default, &AndroidSettings::m_versionNumber, "Version Number", "Internal application version number. Used to set the \"android:versionCode\" tag in the AndroidManifest.xml.")
->Attribute(AZ::Edit::Attributes::Min, 1)
->Attribute(AZ::Edit::Attributes::Max, Validators::maxAndroidVersion)
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Base.cpp b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Base.cpp
index eff524b13e..d011289272 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Base.cpp
+++ b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Base.cpp
@@ -37,19 +37,15 @@ namespace ProjectSettingsTool
->DataElement(Handlers::LinkedLineEdit, &BaseSettings::m_projectName, "Project Name", "The name of the project.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::FileName))
->Attribute(Attributes::PropertyIdentfier, Identfiers::ProjectName)
- ->Attribute(Attributes::LinkedProperty, Identfiers::IosBundleName)
->DataElement(Handlers::LinkedLineEdit, &BaseSettings::m_productName, "Product Name", "The project's user facing name.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IsNotEmpty))
->Attribute(Attributes::PropertyIdentfier, Identfiers::ProductName)
- ->Attribute(Attributes::LinkedProperty, Identfiers::IosDisplayName)
->DataElement(Handlers::LinkedLineEdit, &BaseSettings::m_executableName, "Executable Name", "The project launcher's name.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::FileName))
->Attribute(Attributes::PropertyIdentfier, Identfiers::ExecutableName)
- ->Attribute(Attributes::LinkedProperty, Identfiers::IosExecutableName)
->DataElement(Handlers::QValidatedLineEdit, &BaseSettings::m_projectPath, "Project Path", "The project root folder path .")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::FileNameOrEmpty))
->Attribute(Attributes::PropertyIdentfier, Identfiers::ProductName)
- ->Attribute(Attributes::LinkedProperty, Identfiers::ExecutableName)
->DataElement(Handlers::QValidatedLineEdit, &BaseSettings::m_projectOutputFolder, "Output Folder", "The folder the packed project will be exported to.")
->DataElement(Handlers::QValidatedLineEdit, &BaseSettings::m_codeFolder, "Code Folder (legacy)", "A legacy setting specifing the folder for this project's code.")
;
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Ios.cpp b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Ios.cpp
index fd6aef019e..739a5c94da 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Ios.cpp
+++ b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_Ios.cpp
@@ -262,27 +262,22 @@ namespace ProjectSettingsTool
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(Handlers::LinkedLineEdit, &IosSettings::m_bundleName, "Bundle Name", "The name of the bundle.")
- ->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::FileName))
+ ->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IOSFileName))
->Attribute(Attributes::PropertyIdentfier, Identfiers::IosBundleName)
- ->Attribute(Attributes::LinkedProperty, Identfiers::ProjectName)
->DataElement(Handlers::LinkedLineEdit, &IosSettings::m_bundleDisplayName, "Display Name", "The user visible name of the bundle.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IsNotEmpty))
->Attribute(Attributes::PropertyIdentfier, Identfiers::IosDisplayName)
- ->Attribute(Attributes::LinkedProperty, Identfiers::ProductName)
->DataElement(Handlers::LinkedLineEdit, &IosSettings::m_executableName, "Executable Name", "Name of the bundle's executable file.")
- ->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::FileName))
+ ->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IOSFileName))
->Attribute(Attributes::PropertyIdentfier, Identfiers::IosExecutableName)
- ->Attribute(Attributes::LinkedProperty, Identfiers::ExecutableName)
->DataElement(Handlers::LinkedLineEdit, &IosSettings::m_bundleIdentifier, "Bundle Identifier", "Uniquely identifies the bundle. Should be in reverse-DNS format.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::PackageName))
->Attribute(Attributes::LinkOptional, true)
->Attribute(Attributes::PropertyIdentfier, Identfiers::IosBundleIdentifer)
- ->Attribute(Attributes::LinkedProperty, Identfiers::AndroidPackageName)
->DataElement(Handlers::LinkedLineEdit, &IosSettings::m_versionName, "Version Name", "The release version number string for the app. Displayed in the app store.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IOSVersionNumber))
->Attribute(Attributes::LinkOptional, true)
->Attribute(Attributes::PropertyIdentfier, Identfiers::IosVersionName)
- ->Attribute(Attributes::LinkedProperty, Identfiers::AndroidVersionName)
->DataElement(Handlers::QValidatedLineEdit, &IosSettings::m_versionNumber, "Version Number", "The build version number string for the bundle.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IOSVersionNumber))
->DataElement(AZ::Edit::UIHandlers::ComboBox, &IosSettings::m_developmentRegion, "Development Region", "The default language and region for the app.")
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_common.h b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_common.h
index ab15b2d3cd..ffc9625b53 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_common.h
+++ b/Code/Editor/Plugins/ProjectSettingsTool/PlatformSettings_common.h
@@ -22,7 +22,6 @@ namespace ProjectSettingsTool
static const AZ::Crc32 Obfuscated = AZ_CRC("ObfuscatedText");
// Used as a tooltip and for distinguising linked properties
static const AZ::Crc32 PropertyIdentfier = AZ_CRC("PropertyIdentfier");
- static const AZ::Crc32 LinkedProperty = AZ_CRC("LinkedProperty");
static const AZ::Crc32 DefaultPath = AZ_CRC("DefaultPath");
static const AZ::Crc32 DefaultImagePreview = AZ_CRC("DefaultImagePreview");
static const AZ::Crc32 ObfuscatedText = AZ_CRC("ObfuscatedText");
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/PropertyLinked.cpp b/Code/Editor/Plugins/ProjectSettingsTool/PropertyLinked.cpp
index b48155f1f8..118c11b739 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/PropertyLinked.cpp
+++ b/Code/Editor/Plugins/ProjectSettingsTool/PropertyLinked.cpp
@@ -225,25 +225,6 @@ namespace ProjectSettingsTool
}
}
}
- else if (attrib == Attributes::LinkedProperty)
- {
- AZStd::string linked;
- if (attrValue->Read(linked))
- {
- auto result = m_ctrlToIdentAndLink.find(GUI);
- if (result != m_ctrlToIdentAndLink.end())
- {
- result->second.linkedIdentifier = linked;
- }
- else
- {
- m_ctrlToIdentAndLink.insert(AZStd::pair(GUI, IdentAndLink{ "", linked }));
- m_ctrlInitOrder.push_back(GUI);
- }
-
- GUI->SetLinkTooltip(linked.data());
- }
- }
else
{
GUI->ConsumeAttribute(attrib, attrValue, debugName);
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/Validators.cpp b/Code/Editor/Plugins/ProjectSettingsTool/Validators.cpp
index 4dfc4ee25a..5bf3f5ce67 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/Validators.cpp
+++ b/Code/Editor/Plugins/ProjectSettingsTool/Validators.cpp
@@ -106,6 +106,11 @@ namespace ProjectSettingsTool
return RegularExpressionValidator("[\\w,-]+", name);
}
+ // Returns true if valid iOS file or directory name
+ RetType IOSFileName(const QString& name)
+ {
+ return RegularExpressionValidator("[\\w,-.]+", name);
+ }
RetType FileNameOrEmpty(const QString& name)
{
if (IsNotEmpty(name).first == QValidator::Acceptable)
diff --git a/Code/Editor/Plugins/ProjectSettingsTool/Validators.h b/Code/Editor/Plugins/ProjectSettingsTool/Validators.h
index bd0abb19d6..7cf3498eef 100644
--- a/Code/Editor/Plugins/ProjectSettingsTool/Validators.h
+++ b/Code/Editor/Plugins/ProjectSettingsTool/Validators.h
@@ -24,6 +24,8 @@ namespace ProjectSettingsTool
// Returns true if valid cross platform file or directory name
FunctorValidator::ReturnType FileName(const QString& name);
+ // Returns true if valid iOS file or directory name
+ FunctorValidator::ReturnType IOSFileName(const QString& name);
// Returns true if valid cross platform file or directory name or empty
FunctorValidator::ReturnType FileNameOrEmpty(const QString& name);
// Returns true if string isn't empty
diff --git a/Code/Editor/QtViewPane.h b/Code/Editor/QtViewPane.h
index 194dd8919a..7d7dd04459 100644
--- a/Code/Editor/QtViewPane.h
+++ b/Code/Editor/QtViewPane.h
@@ -13,7 +13,6 @@
#include "IEditor.h"
#include "Include/IEditorClassFactory.h"
-#include "Include/IViewPane.h"
#include "Include/ObjectEvent.h"
#include "Objects/ClassDesc.h"
@@ -107,43 +106,4 @@ public:
}
};
-template
-class CQtViewClass
- : public IViewPaneClass
-{
-public:
- const char* m_name;
- const char* m_category;
- ESystemClassID m_classId;
-
- CQtViewClass(const char* name, const char* category, ESystemClassID classId = ESYSTEM_CLASS_VIEWPANE)
- : m_name(name)
- , m_category(category)
- , m_classId(classId)
- {
- }
-
- ESystemClassID SystemClassID() override { return m_classId; };
- static const GUID& GetClassID()
- {
- return TWidget::GetClassID();
- }
-
- const GUID& ClassID() override
- {
- return GetClassID();
- }
- QString ClassName() override { return m_name; };
- QString Category() override { return m_category; };
-
- QObject* CreateQObject() const override { return new TWidget(); };
- QString GetPaneTitle() override { return m_name; };
- unsigned int GetPaneTitleID() const override { return 0; };
- EDockingDirection GetDockingDirection() override { return DOCK_FLOAT; };
- QRect GetPaneRect() override { return {}; /* KDAB_TODO: ;m_sizeOptions.m_paneRect; */};
- bool SinglePane() override { return false; };
- bool WantIdleUpdate() override { return true; };
- QSize GetMinSize() override { return {}; /*return m_sizeOptions.m_minSize;*/ }
-};
-
#endif // CRYINCLUDE_EDITORCOMMON_QTVIEWPANE_H
diff --git a/Code/Editor/QtViewPaneManager.h b/Code/Editor/QtViewPaneManager.h
index 0515ae726e..5f65958592 100644
--- a/Code/Editor/QtViewPaneManager.h
+++ b/Code/Editor/QtViewPaneManager.h
@@ -269,14 +269,6 @@ bool RegisterQtViewPaneWithName([[maybe_unused]] IEditor* editor, const QString&
return true;
}
-template
-void UnregisterQtViewPane()
-{
- // always close any views that the pane is responsible for before you remove it!
- GetIEditor()->CloseView(CQtViewClass::GetClassID());
- GetIEditor()->GetClassFactory()->UnregisterClass(CQtViewClass::GetClassID());
-}
-
template
TWidget* FindViewPane(const QString& name)
{
diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp
index 9efe846b9e..a3f08a24b2 100644
--- a/Code/Editor/Settings.cpp
+++ b/Code/Editor/Settings.cpp
@@ -1084,7 +1084,7 @@ void SEditorSettings::SaveSettingsRegistryFile()
return;
}
- [[maybe_unused]] bool saved{};
+ [[maybe_unused]] bool saved = false;
constexpr auto configurationMode = AZ::IO::SystemFile::SF_OPEN_CREATE
| AZ::IO::SystemFile::SF_OPEN_CREATE_PATH
| AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY;
diff --git a/Code/Editor/TrackView/2DBezierKeyUIControls.cpp b/Code/Editor/TrackView/2DBezierKeyUIControls.cpp
index 81cd151373..24f2633eb9 100644
--- a/Code/Editor/TrackView/2DBezierKeyUIControls.cpp
+++ b/Code/Editor/TrackView/2DBezierKeyUIControls.cpp
@@ -143,5 +143,3 @@ void C2DBezierKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& se
}
}
}
-
-REGISTER_QT_CLASS_DESC(C2DBezierKeyUIControls, "TrackView.KeyUI.2DBezier", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/AssetBlendKeyUIControls.cpp b/Code/Editor/TrackView/AssetBlendKeyUIControls.cpp
index 038a9d9780..d90f63ee24 100644
--- a/Code/Editor/TrackView/AssetBlendKeyUIControls.cpp
+++ b/Code/Editor/TrackView/AssetBlendKeyUIControls.cpp
@@ -220,5 +220,3 @@ void CAssetBlendKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle&
}
}
}
-
-REGISTER_QT_CLASS_DESC(CAssetBlendKeyUIControls, "TrackView.KeyUI.AssetBlends", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/CaptureKeyUIControls.cpp b/Code/Editor/TrackView/CaptureKeyUIControls.cpp
index e6d88a6cd6..89d55f0a2b 100644
--- a/Code/Editor/TrackView/CaptureKeyUIControls.cpp
+++ b/Code/Editor/TrackView/CaptureKeyUIControls.cpp
@@ -143,5 +143,3 @@ void CCaptureKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& sel
}
}
}
-
-REGISTER_QT_CLASS_DESC(CCaptureKeyUIControls, "TrackView.KeyUI.Capture", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/CommentKeyUIControls.cpp b/Code/Editor/TrackView/CommentKeyUIControls.cpp
index 6b52efd8f1..e4d7183d5e 100644
--- a/Code/Editor/TrackView/CommentKeyUIControls.cpp
+++ b/Code/Editor/TrackView/CommentKeyUIControls.cpp
@@ -169,5 +169,3 @@ void CCommentKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& sel
}
}
}
-
-REGISTER_QT_CLASS_DESC(CCommentKeyUIControls, "TrackView.KeyUI.Comment", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/ConsoleKeyUIControls.cpp b/Code/Editor/TrackView/ConsoleKeyUIControls.cpp
index 7bf23e0b52..f3ed919393 100644
--- a/Code/Editor/TrackView/ConsoleKeyUIControls.cpp
+++ b/Code/Editor/TrackView/ConsoleKeyUIControls.cpp
@@ -118,5 +118,3 @@ void CConsoleKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& sel
}
}
}
-
-REGISTER_QT_CLASS_DESC(CConsoleKeyUIControls, "TrackView.KeyUI.Console", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/EventKeyUIControls.cpp b/Code/Editor/TrackView/EventKeyUIControls.cpp
index 56b16d7c02..b8c737fa6a 100644
--- a/Code/Editor/TrackView/EventKeyUIControls.cpp
+++ b/Code/Editor/TrackView/EventKeyUIControls.cpp
@@ -149,5 +149,3 @@ void CEventKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& selec
}
}
}
-
-REGISTER_QT_CLASS_DESC(CEventKeyUIControls, "TrackView.KeyUI.Event", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/GotoKeyUIControls.cpp b/Code/Editor/TrackView/GotoKeyUIControls.cpp
index c48ce4c5ad..a2767e9d4f 100644
--- a/Code/Editor/TrackView/GotoKeyUIControls.cpp
+++ b/Code/Editor/TrackView/GotoKeyUIControls.cpp
@@ -121,5 +121,3 @@ void CGotoKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& select
}
}
}
-
-REGISTER_QT_CLASS_DESC(CGotoKeyUIControls, "TrackView.KeyUI.Goto", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/ScreenFaderKeyUIControls.cpp b/Code/Editor/TrackView/ScreenFaderKeyUIControls.cpp
index d8b3a2bdf7..b3f971bce0 100644
--- a/Code/Editor/TrackView/ScreenFaderKeyUIControls.cpp
+++ b/Code/Editor/TrackView/ScreenFaderKeyUIControls.cpp
@@ -167,5 +167,3 @@ void CScreenFaderKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle&
}
}
}
-
-REGISTER_QT_CLASS_DESC(CScreenFaderKeyUIControls, "TrackView.KeyUI.ScreenFader", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/SelectKeyUIControls.cpp b/Code/Editor/TrackView/SelectKeyUIControls.cpp
index d12f449c73..81af5f8c8c 100644
--- a/Code/Editor/TrackView/SelectKeyUIControls.cpp
+++ b/Code/Editor/TrackView/SelectKeyUIControls.cpp
@@ -269,5 +269,3 @@ void CSelectKeyUIControls::ResetCameraEntries()
OnCameraAdded(cameraComponentEntities.values[i]);
}
}
-
-REGISTER_QT_CLASS_DESC(CSelectKeyUIControls, "TrackView.KeyUI.Select", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/SequenceKeyUIControls.cpp b/Code/Editor/TrackView/SequenceKeyUIControls.cpp
index 4199563e10..21c654ecc2 100644
--- a/Code/Editor/TrackView/SequenceKeyUIControls.cpp
+++ b/Code/Editor/TrackView/SequenceKeyUIControls.cpp
@@ -215,5 +215,3 @@ void CSequenceKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& se
}
}
}
-
-REGISTER_QT_CLASS_DESC(CSequenceKeyUIControls, "TrackView.KeyUI.Sequence", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/SoundKeyUIControls.cpp b/Code/Editor/TrackView/SoundKeyUIControls.cpp
index f001937e82..2ea41077c4 100644
--- a/Code/Editor/TrackView/SoundKeyUIControls.cpp
+++ b/Code/Editor/TrackView/SoundKeyUIControls.cpp
@@ -127,5 +127,3 @@ void CSoundKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& selec
}
}
}
-
-REGISTER_QT_CLASS_DESC(CSoundKeyUIControls, "TrackView.KeyUI.Sound", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/TimeRangeKeyUIControls.cpp b/Code/Editor/TrackView/TimeRangeKeyUIControls.cpp
index e35c18329b..11e20d854b 100644
--- a/Code/Editor/TrackView/TimeRangeKeyUIControls.cpp
+++ b/Code/Editor/TrackView/TimeRangeKeyUIControls.cpp
@@ -122,5 +122,3 @@ void CTimeRangeKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& s
}
}
}
-
-REGISTER_QT_CLASS_DESC(CTimeRangeKeyUIControls, "TrackView.KeyUI.TimeRange", "TrackViewKeyUI");
diff --git a/Code/Editor/TrackView/TrackEventKeyUIControls.cpp b/Code/Editor/TrackView/TrackEventKeyUIControls.cpp
index 035087733b..835636c080 100644
--- a/Code/Editor/TrackView/TrackEventKeyUIControls.cpp
+++ b/Code/Editor/TrackView/TrackEventKeyUIControls.cpp
@@ -235,5 +235,3 @@ void CTrackEventKeyUIControls::BuildEventDropDown(QString& curEvent, const QStri
}
}
}
-
-REGISTER_QT_CLASS_DESC(CTrackEventKeyUIControls, "TrackView.KeyUI.TrackEvent", "TrackViewKeyUI");
diff --git a/Code/Editor/ViewManager.h b/Code/Editor/ViewManager.h
index 5b84efd197..f67fb19bcb 100644
--- a/Code/Editor/ViewManager.h
+++ b/Code/Editor/ViewManager.h
@@ -17,7 +17,6 @@
#include "Cry_Geo.h"
#include "Viewport.h"
-#include "Include/IViewPane.h"
#include "QtViewPaneManager.h"
// forward declaration.
class CLayoutWnd;
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 5812aae4bb..53cfe243b1 100644
--- a/Code/Editor/editor_lib_files.cmake
+++ b/Code/Editor/editor_lib_files.cmake
@@ -270,7 +270,6 @@ set(FILES
Include/ICommandManager.h
Include/IDisplayViewport.h
Include/IEditorClassFactory.h
- Include/IEventLoopHook.h
Include/IExportManager.h
Include/IGizmoManager.h
Include/IIconManager.h
@@ -281,7 +280,6 @@ set(FILES
Include/IPreferencesPage.h
Include/ISourceControl.h
Include/ITransformManipulator.h
- Include/IViewPane.h
Include/ObjectEvent.h
Util/AffineParts.cpp
Objects/BaseObject.cpp
@@ -315,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
@@ -338,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/AzCore/Asset/AssetJsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp
index 0d28036646..838caf467a 100644
--- a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp
@@ -92,6 +92,12 @@ namespace AZ::Data
result.Combine(resultHint);
}
+ if (SerializedAssetTracker* assetTracker = context.GetMetadata().Find();
+ assetTracker != nullptr && result.GetProcessing() == JSR::Processing::Completed)
+ {
+ assetTracker->AddAsset(*instance);
+ }
+
return context.Report(result,
result.GetProcessing() == JSR::Processing::Completed ? "Successfully stored Asset." : "Failed to store Asset.");
}
diff --git a/Code/Framework/AzCore/AzCore/Debug/Profiler.h b/Code/Framework/AzCore/AzCore/Debug/Profiler.h
index 6b27b35f53..6557743de8 100644
--- a/Code/Framework/AzCore/AzCore/Debug/Profiler.h
+++ b/Code/Framework/AzCore/AzCore/Debug/Profiler.h
@@ -67,8 +67,7 @@ namespace AZ::Debug
Profiler() = default;
virtual ~Profiler() = default;
- // support for the extra macro args (e.g. format strings) will come in a later PR
- virtual void BeginRegion(const Budget* budget, const char* eventName) = 0;
+ virtual void BeginRegion(const Budget* budget, const char* eventName, size_t eventNameArgCount, ...) = 0;
virtual void EndRegion(const Budget* budget) = 0;
};
@@ -76,12 +75,11 @@ namespace AZ::Debug
{
public:
template
- static void BeginRegion([[maybe_unused]] Budget* budget, [[maybe_unused]] const char* eventName, [[maybe_unused]] T const&... args);
-
- static void EndRegion([[maybe_unused]] Budget* budget);
+ static void BeginRegion(Budget* budget, const char* eventName, T const&... args);
+ static void EndRegion(Budget* budget);
template
- ProfileScope(Budget* budget, char const* eventName, T const&... args);
+ ProfileScope(Budget* budget, const char* eventName, T const&... args);
~ProfileScope();
diff --git a/Code/Framework/AzCore/AzCore/Debug/Profiler.inl b/Code/Framework/AzCore/AzCore/Debug/Profiler.inl
index c820639b09..a0917d6130 100644
--- a/Code/Framework/AzCore/AzCore/Debug/Profiler.inl
+++ b/Code/Framework/AzCore/AzCore/Debug/Profiler.inl
@@ -31,10 +31,10 @@ namespace AZ::Debug
if (auto profiler = AZ::Interface::Get(); profiler)
{
- profiler->BeginRegion(budget, eventName);
+ profiler->BeginRegion(budget, eventName, sizeof...(T), args...);
}
}
- #endif // #if !defined(_RELEASE)
+ #endif // !defined(_RELEASE)
}
inline void ProfileScope::EndRegion([[maybe_unused]] Budget* budget)
@@ -55,7 +55,7 @@ namespace AZ::Debug
}
template
- ProfileScope::ProfileScope(Budget* budget, char const* eventName, T const&... args)
+ ProfileScope::ProfileScope(Budget* budget, const char* eventName, T const&... args)
: m_budget{ budget }
{
BeginRegion(budget, eventName, args...);
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp
index 196ce28216..f7e41c0c00 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.cpp
@@ -203,7 +203,7 @@ namespace AZ
JsonSerializationResult::Result JsonMapSerializer::LoadElement(void* outputValue, SerializeContext::IDataContainer* container,
const SerializeContext::ClassElement* pairElement, SerializeContext::IDataContainer* pairContainer,
const SerializeContext::ClassElement* keyElement, const SerializeContext::ClassElement* valueElement,
- const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context)
+ const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context, bool isMultiMap)
{
namespace JSR = JsonSerializationResult;
@@ -231,8 +231,30 @@ namespace AZ
return context.Report(keyResult, "Failed to read key for associative container.");
}
+ void* valueAddress = nullptr;
+ bool keyExists = false;
+
+ // For multimaps, we append values to keys instead updating them.
+ // This is to ensure legacy multimap serialization support.
+ if (!isMultiMap)
+ {
+ auto associativeContainer = container->GetAssociativeContainerInterface();
+ void* existingKeyValuePair = associativeContainer->GetElementByKey(outputValue, keyElement, keyAddress);
+ if (existingKeyValuePair)
+ {
+ valueAddress = pairContainer->GetElementByIndex(existingKeyValuePair, pairElement, 1);
+ expectedSize--;
+ keyExists = true;
+ }
+ }
+
+ // If the key doesn't exist or it's a multimap, we're adding the new element we reserved above.
+ if (!keyExists)
+ {
+ valueAddress = pairContainer->GetElementByIndex(address, pairElement, 1);
+ }
+
// Load value
- void* valueAddress = pairContainer->GetElementByIndex(address, pairElement, 1);
AZ_Assert(valueAddress, "Element reserved for associative container, but unable to retrieve address of the value.");
ContinuationFlags valueLoadFlags = ContinuationFlags::LoadAsNewInstance;
if (valueElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER)
@@ -257,7 +279,18 @@ namespace AZ
}
else
{
- container->StoreElement(outputValue, address);
+ // Even if the key exists, calling StoreElement will not replace the existing key
+ // and will free the temporary address as expected. Checking if the key already
+ // exists and skipping the call to StoreElement if it does, makes the intent more
+ // clear. The end result is the same either way.
+ if (!keyExists)
+ {
+ container->StoreElement(outputValue, address);
+ }
+ else
+ {
+ container->FreeReservedElement(outputValue, address, context.GetSerializeContext());
+ }
if (container->Size(outputValue) != expectedSize)
{
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unavailable,
@@ -430,7 +463,7 @@ namespace AZ
JsonSerializationResult::Result JsonUnorderedMultiMapSerializer::LoadElement(void* outputValue, SerializeContext::IDataContainer* container,
const SerializeContext::ClassElement* pairElement, SerializeContext::IDataContainer* pairContainer,
const SerializeContext::ClassElement* keyElement, const SerializeContext::ClassElement* valueElement,
- const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context)
+ const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context, [[maybe_unused]] bool isMultiMap)
{
namespace JSR = JsonSerializationResult;
@@ -440,7 +473,7 @@ namespace AZ
for (auto& entry : value.GetArray())
{
result.Combine(JsonMapSerializer::LoadElement(outputValue, container, pairElement, pairContainer,
- keyElement, valueElement, key, entry, context));
+ keyElement, valueElement, key, entry, context, true));
if (result.GetProcessing() == JSR::Processing::Halted)
{
return context.Report(result, "Unable to process the key or all values in multi-map.");
@@ -451,7 +484,7 @@ namespace AZ
else if (IsExplicitDefault(value))
{
return JsonMapSerializer::LoadElement(outputValue, container, pairElement, pairContainer,
- keyElement, valueElement, key, value, context);
+ keyElement, valueElement, key, value, context, true);
}
else
{
diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.h
index 937c8389ff..74d7e81ac9 100644
--- a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.h
+++ b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.h
@@ -32,7 +32,7 @@ namespace AZ
virtual JsonSerializationResult::Result LoadElement(void* outputValue, SerializeContext::IDataContainer* container,
const SerializeContext::ClassElement* pairElement, SerializeContext::IDataContainer* pairContainer,
const SerializeContext::ClassElement* keyElement, const SerializeContext::ClassElement* valueElement,
- const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context);
+ const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context, bool isMultiMap = false);
virtual JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context, bool sortResult);
@@ -62,7 +62,7 @@ namespace AZ
JsonSerializationResult::Result LoadElement(void* outputValue, SerializeContext::IDataContainer* container,
const SerializeContext::ClassElement* pairElement, SerializeContext::IDataContainer* pairContainer,
const SerializeContext::ClassElement* keyElement, const SerializeContext::ClassElement* valueElement,
- const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context) override;
+ const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context, bool isMultiMap = false) override;
using JsonMapSerializer::Store;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
diff --git a/Code/Framework/AzCore/Platform/Android/AzCore/std/parallel/internal/thread_Android.cpp b/Code/Framework/AzCore/Platform/Android/AzCore/std/parallel/internal/thread_Android.cpp
index 612296ebba..865d84516f 100644
--- a/Code/Framework/AzCore/Platform/Android/AzCore/std/parallel/internal/thread_Android.cpp
+++ b/Code/Framework/AzCore/Platform/Android/AzCore/std/parallel/internal/thread_Android.cpp
@@ -36,5 +36,12 @@ namespace AZStd
{
pthread_setname_np(tId, name);
}
+
+ uint8_t GetDefaultThreadPriority()
+ {
+ // pthread priority is an integer between >=1 and <=99 (although only range 1<=>32 is guaranteed)
+ // Don't use a scheduling policy value (e.g. SCHED_OTHER or SCHED_FIFO) here.
+ return 1;
+ }
}
}
diff --git a/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/parallel/internal/thread_Apple.cpp b/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/parallel/internal/thread_Apple.cpp
index bc89545faa..c39447b2f2 100644
--- a/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/parallel/internal/thread_Apple.cpp
+++ b/Code/Framework/AzCore/Platform/Common/Apple/AzCore/std/parallel/internal/thread_Apple.cpp
@@ -35,7 +35,7 @@ namespace AZStd
void SetThreadPriority(int priority, pthread_attr_t& attr)
{
- if (priority == -1)
+ if (priority <= -1)
{
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
}
@@ -59,5 +59,18 @@ namespace AZStd
thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)& policyData, 1);
}
}
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Apple pthread -> NSThread quality of service level map
+ // QOS class name | min pthread priority | max pthread priority | comment
+ // QOS_CLASS_USER_INTERACTIVE | 38 | 47 | Per-frame work
+ // QOS_CLASS_USER_INITIATED | 32 | 37 | Asynchronous / Cross frame work
+ // QOS_CLASS_DEFAULT | 21 | 31 | Streaming / Multiple frames deadline
+ // QOS_CLASS_UTILITY | 5 | 20 | Background asset download
+ // QOS_CLASS_BACKGROUN | 0 | 4 | Will be prevented from using whole core.
+ uint8_t GetDefaultThreadPriority()
+ {
+ return 10;
+ }
}
}
diff --git a/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.cpp b/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.cpp
index da5d95b9a4..5ff3b82b3f 100644
--- a/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.cpp
+++ b/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.cpp
@@ -21,6 +21,7 @@ namespace AZStd
void PreCreateSetThreadAffinity(int cpuId, pthread_attr_t& attr);
void SetThreadPriority(int priority, pthread_attr_t& attr);
void PostCreateThread(pthread_t tId, const char * name, int cpuId);
+ uint8_t GetDefaultThreadPriority();
}
namespace Internal
@@ -60,12 +61,13 @@ namespace AZStd
}
else
{
- priority = SCHED_OTHER;
+ priority = Platform::GetDefaultThreadPriority();
}
if (desc->m_name)
{
name = desc->m_name;
}
+ ti->m_name = name;
cpuId = desc->m_cpuId;
pthread_attr_setdetachstate(&attr, desc->m_isJoinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED);
diff --git a/Code/Framework/AzCore/Platform/Linux/AzCore/std/parallel/internal/thread_Linux.cpp b/Code/Framework/AzCore/Platform/Linux/AzCore/std/parallel/internal/thread_Linux.cpp
index 619658057b..10121cc2ed 100644
--- a/Code/Framework/AzCore/Platform/Linux/AzCore/std/parallel/internal/thread_Linux.cpp
+++ b/Code/Framework/AzCore/Platform/Linux/AzCore/std/parallel/internal/thread_Linux.cpp
@@ -55,5 +55,12 @@ namespace AZStd
{
pthread_setname_np(tId, name);
}
+
+ uint8_t GetDefaultThreadPriority()
+ {
+ // pthread priority is an integer between >=1 and <=99 (although only range 1<=>32 is guaranteed)
+ // Don't use a scheduling policy value (e.g. SCHED_OTHER or SCHED_FIFO) here.
+ return 1;
+ }
}
}
diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp
index 7ffe3ffee0..fe97d36f08 100644
--- a/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp
+++ b/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp
@@ -475,7 +475,7 @@ namespace JsonSerializationTests
EXPECT_STRCASEEQ("value_42", worldKey->second.m_value.c_str());
}
- TEST_F(JsonMapSerializerTests, Load_DuplicateKey_EntryIgnored)
+ TEST_F(JsonMapSerializerTests, Load_DuplicateKey_EntryUpdated)
{
using namespace AZ::JsonSerializationResult;
@@ -489,12 +489,12 @@ namespace JsonSerializationTests
StringMap values;
ResultCode result = m_unorderedMapSerializer.Load(&values, azrtti_typeid(&values), *m_jsonDocument, *m_jsonDeserializationContext);
- EXPECT_EQ(Processing::PartialAlter, result.GetProcessing());
- EXPECT_EQ(Outcomes::Unavailable, result.GetOutcome());
+ EXPECT_EQ(Processing::Completed, result.GetProcessing());
+ EXPECT_EQ(Outcomes::Success, result.GetOutcome());
auto entry = values.find("Hello");
ASSERT_NE(values.end(), entry);
- EXPECT_STRCASEEQ("World", entry->second.c_str());
+ EXPECT_EQ("Other", entry->second);
}
TEST_F(JsonMapSerializerTests, Load_DuplicateMultiKey_LoadEverything)
@@ -536,8 +536,8 @@ namespace JsonSerializationTests
ResultCode result = m_unorderedMapSerializer.Load(&values,
azrtti_typeid(&values), *m_jsonDocument, *m_jsonDeserializationContext);
- EXPECT_EQ(Processing::Altered, result.GetProcessing());
- EXPECT_EQ(Outcomes::Unavailable, result.GetOutcome());
+ EXPECT_EQ(Processing::Completed, result.GetProcessing());
+ EXPECT_EQ(Outcomes::Success, result.GetOutcome());
auto entry = values.find("Hello");
ASSERT_NE(values.end(), entry);
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/Physics/ShapeConfiguration.cpp b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp
index db8004d83a..bc38fe78fd 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp
@@ -378,7 +378,7 @@ namespace Physics
m_cachedNativeHeightfield = cachedNativeHeightfield;
}
- AZ::Vector2 HeightfieldShapeConfiguration::GetGridResolution() const
+ const AZ::Vector2& HeightfieldShapeConfiguration::GetGridResolution() const
{
return m_gridResolution;
}
diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h
index bd9d6a6aa7..26af746128 100644
--- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h
+++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h
@@ -221,7 +221,7 @@ namespace Physics
const void* GetCachedNativeHeightfield() const;
void* GetCachedNativeHeightfield();
void SetCachedNativeHeightfield(void* cachedNativeHeightfield);
- AZ::Vector2 GetGridResolution() const;
+ const AZ::Vector2& GetGridResolution() const;
void SetGridResolution(const AZ::Vector2& gridSpacing);
int32_t GetNumColumns() const;
void SetNumColumns(int32_t numColumns);
@@ -235,7 +235,7 @@ namespace Physics
void SetMaxHeightBounds(float maxBounds);
private:
- //! The number of meters between each heightfield sample.
+ //! The number of meters between each heightfield sample in x and y.
AZ::Vector2 m_gridResolution{ 1.0f };
//! The number of columns in the heightfield sample grid.
int32_t m_numColumns{ 0 };
diff --git a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h
index f9ef264ab1..7909a7ec83 100644
--- a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h
+++ b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h
@@ -50,8 +50,8 @@ namespace AzFramework
static AZ::Vector3 GetDefaultTerrainNormal() { return AZ::Vector3::CreateAxisZ(); }
// System-level queries to understand world size and resolution
- virtual AZ::Vector2 GetTerrainHeightQueryResolution() const = 0;
- virtual void SetTerrainHeightQueryResolution(AZ::Vector2 queryResolution) = 0;
+ virtual float GetTerrainHeightQueryResolution() const = 0;
+ virtual void SetTerrainHeightQueryResolution(float queryResolution) = 0;
virtual AZ::Aabb GetTerrainAabb() const = 0;
virtual void SetTerrainAabb(const AZ::Aabb& worldBounds) = 0;
diff --git a/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h b/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h
index f5af0ff486..4b9658eebb 100644
--- a/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h
+++ b/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h
@@ -49,8 +49,8 @@ namespace UnitTest
AzFramework::Terrain::TerrainDataRequestBus::Handler::BusDisconnect();
}
- MOCK_CONST_METHOD0(GetTerrainHeightQueryResolution, AZ::Vector2());
- MOCK_METHOD1(SetTerrainHeightQueryResolution, void(AZ::Vector2));
+ MOCK_CONST_METHOD0(GetTerrainHeightQueryResolution, float());
+ MOCK_METHOD1(SetTerrainHeightQueryResolution, void(float));
MOCK_CONST_METHOD0(GetTerrainAabb, AZ::Aabb());
MOCK_METHOD1(SetTerrainAabb, void(const AZ::Aabb&));
MOCK_CONST_METHOD3(GetHeight, float(const AZ::Vector3&, Sampler, bool*));
diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h
index 865a571d3b..b5251d6e97 100644
--- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h
+++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h
@@ -47,8 +47,6 @@ namespace AzManipulatorTestFramework
virtual void UpdateVisibility() = 0;
//! Sets if sticky select is enabled or not.
virtual void SetStickySelect(bool enabled) = 0;
- //! Gets default Editor Camera Position.
- virtual AZ::Vector3 DefaultEditorCameraPosition() const = 0;
//! Sets if icons are visible in the viewport.
virtual void SetIconsVisible(bool visible) = 0;
//! Sets if helpers are visible in the viewport.
diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h
index f29245bb34..3de54e9e6d 100644
--- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h
+++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h
@@ -10,6 +10,7 @@
#include
#include
+#include
namespace AzFramework
{
@@ -22,7 +23,7 @@ namespace AzManipulatorTestFramework
class ViewportInteraction
: public ViewportInteractionInterface
, public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler
- , public AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler
+ , public UnitTest::ViewportSettingsTestImpl
, private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler
{
public:
@@ -50,19 +51,6 @@ namespace AzManipulatorTestFramework
const AzFramework::ScreenPoint& screenPosition) override;
float DeviceScalingFactor() override;
- // ViewportSettingsRequestBus overrides ...
- bool GridSnappingEnabled() const override;
- float GridSize() const override;
- bool ShowGrid() const override;
- bool AngleSnappingEnabled() const override;
- float AngleStep() const override;
- float ManipulatorLineBoundWidth() const override;
- float ManipulatorCircleBoundWidth() const override;
- bool StickySelectEnabled() const override;
- AZ::Vector3 DefaultEditorCameraPosition() const override;
- bool IconsVisible() const override;
- bool HelpersVisible() const override;
-
// EditorEntityViewportInteractionRequestBus overrides ...
void FindVisibleEntities(AZStd::vector& visibleEntities) override;
@@ -72,12 +60,5 @@ namespace AzManipulatorTestFramework
AzFramework::EntityVisibilityQuery m_entityVisibilityQuery;
AZStd::shared_ptr m_debugDisplayRequests;
AzFramework::CameraState m_cameraState;
- float m_gridSize = 1.0f;
- float m_angularStep = 0.0f;
- bool m_gridSnapping = false;
- bool m_angularSnapping = false;
- bool m_stickySelect = true;
- bool m_iconsVisible = true;
- bool m_helpersVisible = true;
};
} // namespace AzManipulatorTestFramework
diff --git a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp
index b7fd5e2b73..0eac957a0a 100644
--- a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp
+++ b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp
@@ -37,46 +37,6 @@ namespace AzManipulatorTestFramework
return m_cameraState;
}
- bool ViewportInteraction::GridSnappingEnabled() const
- {
- return m_gridSnapping;
- }
-
- float ViewportInteraction::GridSize() const
- {
- return m_gridSize;
- }
-
- bool ViewportInteraction::ShowGrid() const
- {
- return false;
- }
-
- bool ViewportInteraction::AngleSnappingEnabled() const
- {
- return m_angularSnapping;
- }
-
- float ViewportInteraction::AngleStep() const
- {
- return m_angularStep;
- }
-
- float ViewportInteraction::ManipulatorLineBoundWidth() const
- {
- return 0.1f;
- }
-
- float ViewportInteraction::ManipulatorCircleBoundWidth() const
- {
- return 0.1f;
- }
-
- bool ViewportInteraction::StickySelectEnabled() const
- {
- return m_stickySelect;
- }
-
void ViewportInteraction::FindVisibleEntities(AZStd::vector& visibleEntitiesOut)
{
visibleEntitiesOut.assign(m_entityVisibilityQuery.Begin(), m_entityVisibilityQuery.End());
@@ -127,11 +87,6 @@ namespace AzManipulatorTestFramework
m_helpersVisible = visible;
}
- AZ::Vector3 ViewportInteraction::DefaultEditorCameraPosition() const
- {
- return {};
- }
-
void ViewportInteraction::SetGridSize(float size)
{
m_gridSize = size;
@@ -162,14 +117,4 @@ namespace AzManipulatorTestFramework
{
return 1.0f;
}
-
- bool ViewportInteraction::IconsVisible() const
- {
- return m_iconsVisible;
- }
-
- bool ViewportInteraction::HelpersVisible() const
- {
- return m_helpersVisible;
- }
} // namespace AzManipulatorTestFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp
index 50c61e6877..d6faed4b0a 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp
@@ -28,7 +28,7 @@ namespace AzToolsFramework
{
namespace Internal
{
- AZ::JsonSerializationResult::ResultCode JsonIssueReporter(AZStd::string& scratchBuffer,
+ static AZ::JsonSerializationResult::ResultCode JsonIssueReporter(AZStd::string& scratchBuffer,
AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path)
{
namespace JSR = AZ::JsonSerializationResult;
@@ -48,6 +48,66 @@ namespace AzToolsFramework
return result;
}
+
+ static bool StoreInstanceInPrefabDom(
+ const Instance& instance,
+ PrefabDom& prefabDom,
+ AZStd::vector>* referencedAssets,
+ StoreFlags flags)
+ {
+ InstanceEntityIdMapper entityIdMapper;
+ entityIdMapper.SetStoringInstance(instance);
+
+ // Need to store the id mapper as both its type and its base type
+ // Metadata is found by type id and we need access to both types at different levels (Instance, EntityId)
+ AZ::JsonSerializerSettings settings;
+ settings.m_metadata.Add(static_cast(&entityIdMapper));
+ settings.m_metadata.Add(&entityIdMapper);
+ if (referencedAssets)
+ {
+ settings.m_metadata.Add(AZ::Data::SerializedAssetTracker{});
+ }
+
+ if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues)
+ {
+ settings.m_keepDefaults = true;
+ }
+
+ if ((flags & StoreFlags::StoreLinkIds) != StoreFlags::None)
+ {
+ settings.m_metadata.Create();
+ }
+
+ AZStd::string scratchBuffer;
+ auto issueReportingCallback = [&scratchBuffer](
+ AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result,
+ AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode
+ {
+ return Internal::JsonIssueReporter(scratchBuffer, message, result, path);
+ };
+
+ settings.m_reporting = AZStd::move(issueReportingCallback);
+
+ AZ::JsonSerializationResult::ResultCode result =
+ AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings);
+
+ if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted)
+ {
+ AZ_Error(
+ "Prefab", false,
+ "Failed to serialize prefab instance with source path %s. "
+ "Unable to proceed.",
+ instance.GetTemplateSourcePath().c_str());
+
+ return false;
+ }
+
+ if (referencedAssets)
+ {
+ *referencedAssets = AZStd::move(settings.m_metadata.Find()->GetTrackedAssets());
+ }
+ return true;
+ }
}
PrefabDomValueReference FindPrefabDomValue(PrefabDomValue& parentValue, const char* valueName)
@@ -74,49 +134,16 @@ namespace AzToolsFramework
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreFlags flags)
{
- InstanceEntityIdMapper entityIdMapper;
- entityIdMapper.SetStoringInstance(instance);
+ return Internal::StoreInstanceInPrefabDom(instance, prefabDom, nullptr, flags);
+ }
- // Need to store the id mapper as both its type and its base type
- // Meta data is found by type id and we need access to both types at different levels (Instance, EntityId)
- AZ::JsonSerializerSettings settings;
- settings.m_metadata.Add(static_cast(&entityIdMapper));
- settings.m_metadata.Add(&entityIdMapper);
-
- if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues)
- {
- settings.m_keepDefaults = true;
- }
-
- if ((flags & StoreFlags::StoreLinkIds) != StoreFlags::None)
- {
- settings.m_metadata.Create();
- }
-
- AZStd::string scratchBuffer;
- auto issueReportingCallback = [&scratchBuffer]
- (AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result,
- AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode
- {
- return Internal::JsonIssueReporter(scratchBuffer, message, result, path);
- };
-
- settings.m_reporting = AZStd::move(issueReportingCallback);
-
- AZ::JsonSerializationResult::ResultCode result =
- AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings);
-
- if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted)
- {
- AZ_Error("Prefab", false,
- "Failed to serialize prefab instance with source path %s. "
- "Unable to proceed.",
- instance.GetTemplateSourcePath().c_str());
-
- return false;
- }
-
- return true;
+ bool StoreInstanceInPrefabDom(
+ const Instance& instance,
+ PrefabDom& prefabDom,
+ AZStd::vector>& referencedAssets,
+ StoreFlags flags)
+ {
+ return Internal::StoreInstanceInPrefabDom(instance, prefabDom, &referencedAssets, flags);
}
bool StoreEntityInPrefabDomFormat(const AZ::Entity& entity, Instance& owningInstance, PrefabDom& prefabDom, StoreFlags flags)
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h
index 89d1a046e5..e336cf0fca 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.h
@@ -57,14 +57,28 @@ namespace AzToolsFramework
AZ_DEFINE_ENUM_BITWISE_OPERATORS(StoreFlags);
/**
- * Stores a valid Prefab Instance within a Prefab Dom. Useful for generating Templates
- * @param instance The instance to store
- * @param prefabDom The prefabDom that will be used to store the Instance data
- * @param flags Controls behavior such as whether to store default values
- * @return bool on whether the operation succeeded
+ * Stores a valid Prefab Instance within a Prefab Dom. Useful for generating Templates.
+ * @param instance The instance to store.
+ * @param prefabDom The prefabDom that will be used to store the Instance data.
+ * @param flags Controls behavior such as whether to store default values.
+ * @return bool on whether the operation succeeded.
*/
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreFlags flags = StoreFlags::None);
+ /**
+ * Stores a valid Prefab Instance within a Prefab Dom. Useful for generating Templates.
+ * @param instance The instance to store.
+ * @param prefabDom The prefabDom that will be used to store the Instance data.
+ * @param referencedAssets Collect a list of the assets that are referenced during storing.
+ * @param flags Controls behavior such as whether to store default values.
+ * @return bool on whether the operation succeeded.
+ */
+ bool StoreInstanceInPrefabDom(
+ const Instance& instance,
+ PrefabDom& prefabDom,
+ AZStd::vector>& referencedAssets,
+ StoreFlags flags = StoreFlags::None);
+
/**
* Stores a valid entity in Prefab Dom format.
* @param entity The entity to store
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp
index dc5cd299b8..567ccc3619 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.cpp
@@ -6,12 +6,14 @@
*
*/
-#include
#include
#include
+#include
+#include
#include
#include
+#include
#include
namespace AzToolsFramework::Prefab::PrefabConversionUtils
@@ -161,13 +163,10 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
{
return AZ::Failure(AZStd::string::format("Failed to produce the target spawnable '%.*s'.", AZ_STRING_ARG(spawnableName)));
}
-
+
if (loadReferencedAssets)
{
- for (auto& product : context.GetProcessedObjects())
- {
- LoadReferencedAssets(product.GetReferencedAssets());
- }
+ LoadReferencedAssets(spawnableAssetData);
}
auto& spawnableAssetDataAdded = m_spawnableAssets.emplace(spawnableName, spawnableAssetData).first->second;
@@ -213,63 +212,87 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
return m_spawnableAssets;
}
- void InMemorySpawnableAssetContainer::LoadReferencedAssets(AZStd::vector>& referencedAssets)
+ void InMemorySpawnableAssetContainer::LoadReferencedAssets(SpawnableAssetData& spawnable)
{
- // Start our loads on all assets by calling GetAsset from the AssetManager
- for (AZ::Data::Asset& asset : referencedAssets)
+ // Get the referenced assets directly from the product. This is done for two reasons:
+ // 1. Avoids calls to the Asset Manager for assets that are already loaded.
+ // 2. Gets the exact asset to load to avoid issues with assets that don't reload.
+ AZStd::vector*> blockingAssets;
+
+ AZ::SerializeContext* sc = nullptr;
+ AZ::ComponentApplicationBus::BroadcastResult(sc, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
+ AZ_Assert(sc, "Unable to locate Serialize Context while resolving asset references in the in-memory spawnable asset container.");
+
+ for (AZ::Data::Asset& asset : spawnable.m_assets)
{
- if (!asset.GetId().IsValid())
+ auto callback = [&blockingAssets](
+ void* object, const AZ::SerializeContext::ClassData* classData,
+ [[maybe_unused]]const AZ::SerializeContext::ClassElement* elementData) -> bool
{
- AZ_Error("Prefab", false, "Invalid asset found referenced in scene while entering game mode");
- continue;
- }
+ if (classData->m_typeId == AZ::GetAssetClassId())
+ {
+ auto asset = reinterpret_cast*>(object);
- const AZ::Data::AssetLoadBehavior loadBehavior = asset.GetAutoLoadBehavior();
+ if (!asset->GetId().IsValid())
+ {
+ AZ_Error(
+ "Prefab", false,
+ "Invalid asset found referenced in scene while entering game mode. The asset was stored in an instance of %s.",
+ classData->m_name);
+ return false;
+ }
- if (loadBehavior == AZ::Data::AssetLoadBehavior::NoLoad)
- {
- continue;
- }
+ if (asset->GetStatus() != AZ::Data::AssetData::AssetStatus::NotLoaded)
+ {
+ // Already loaded so no need to do anything.
+ return false;
+ }
- AZ::Data::AssetId assetId = asset.GetId();
- AZ::Data::AssetType assetType = asset.GetType();
+ const AZ::Data::AssetLoadBehavior loadBehavior = asset->GetAutoLoadBehavior();
+ if (loadBehavior == AZ::Data::AssetLoadBehavior::NoLoad)
+ {
+ return false;
+ }
- asset = AZ::Data::AssetManager::Instance().GetAsset(assetId, assetType, loadBehavior);
+ if (loadBehavior == AZ::Data::AssetLoadBehavior::PreLoad)
+ {
+ // Only assets that are preloaded need to be waited on.
+ blockingAssets.push_back(asset);
+ }
+ if (!asset->QueueLoad())
+ {
+ AZ_Error(
+ "Prefab", false, "Failed to queue asset '%s' (%s) of type '%s' for loading while entering game mode.",
+ asset->GetHint().c_str(), asset->GetId().ToString>().c_str(),
+ asset->GetType().ToString>().c_str());
+ return false;
+ }
- if (!asset.GetId().IsValid())
- {
- AZ_Error("Prefab", false, "Invalid asset found referenced in scene while entering game mode");
- continue;
- }
+ return false;
+ }
+ return true;
+ };
+
+ AZ::SerializeContext::EnumerateInstanceCallContext enumerationContext(
+ callback, nullptr, sc, AZ::SerializeContext::ENUM_ACCESS_FOR_READ, nullptr);
+ sc->EnumerateInstance(&enumerationContext, asset.GetData(), asset.GetType(), nullptr, nullptr);
}
// For all Preload assets we block until they're ready
// We do this as a separate pass so that we don't interrupt queuing up all other asset loads
- for (AZ::Data::Asset& asset : referencedAssets)
+ for (AZ::Data::Asset* asset : blockingAssets)
{
- if (!asset.GetId().IsValid())
+ asset->BlockUntilLoadComplete();
+
+ if (asset->IsError())
{
- AZ_Error("Prefab", false, "Invalid asset found referenced in scene while entering game mode");
- continue;
- }
-
- const AZ::Data::AssetLoadBehavior loadBehavior = asset.GetAutoLoadBehavior();
-
- if (loadBehavior != AZ::Data::AssetLoadBehavior::PreLoad)
- {
- continue;
- }
-
- asset.BlockUntilLoadComplete();
-
- if (asset.IsError())
- {
- AZ_Error("Prefab", false, "Asset with id %s failed to preload while entering game mode",
- asset.GetId().ToString().c_str());
+ AZ_Error(
+ "Prefab", false, "Asset '%s' (%s) of type '%s' failed to preload while entering game mode", asset->GetHint().c_str(),
+ asset->GetId().ToString>().c_str(),
+ asset->GetType().ToString>().c_str());
continue;
}
}
}
-
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.h
index f567c99b00..6f11976fc9 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.h
@@ -21,7 +21,6 @@ namespace AzToolsFramework::Prefab
namespace AzToolsFramework::Prefab::PrefabConversionUtils
{
-
class InMemorySpawnableAssetContainer
{
public:
@@ -58,8 +57,8 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
const SpawnableAssets& GetAllInMemorySpawnableAssets() const;
private:
- void LoadReferencedAssets(AZStd::vector>& referencedAssets);
-
+ void LoadReferencedAssets(SpawnableAssetData& spawnable);
+
SpawnableAssets m_spawnableAssets;
PrefabConversionUtils::PrefabConversionPipeline m_converter;
AZStd::string_view m_stockProfile;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp
index 230c2226cd..097acbb47c 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp
@@ -53,21 +53,14 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
const PrefabDom& PrefabDocument::GetDom() const
{
- if (m_isDirty)
- {
- m_isDirty = !PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom);
- }
+ RefreshPrefabDom();
return m_dom;
}
PrefabDom&& PrefabDocument::TakeDom()
{
- if (m_isDirty)
- {
- [[maybe_unused]] bool storedSuccessfully = PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom);
- AZ_Assert(storedSuccessfully, "Failed to store Instance '%s' to PrefabDom.", m_name.c_str());
- m_isDirty = false;
- }
+ RefreshPrefabDom();
+
// After the PrefabDom is moved an empty PrefabDom is left behind. This should be reflected in the Instance,
// so reset it so it's empty as well.
m_instance->Reset();
@@ -126,11 +119,13 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
AZStd::vector>& PrefabDocument::GetReferencedAssets()
{
+ RefreshPrefabDom();
return m_referencedAssets;
}
const AZStd::vector>& PrefabDocument::GetReferencedAssets() const
{
+ RefreshPrefabDom();
return m_referencedAssets;
}
@@ -158,4 +153,20 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
return false;
}
}
+
+ void PrefabDocument::RefreshPrefabDom() const
+ {
+ if (m_isDirty)
+ {
+ m_referencedAssets.clear();
+ if (PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom, m_referencedAssets))
+ {
+ m_isDirty = false;
+ }
+ else
+ {
+ AZ_Assert(false, "Failed to store Instance '%s' to PrefabDom.", m_name.c_str());
+ }
+ }
+ }
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h
index 661dba5edf..cff6e8368f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h
@@ -58,11 +58,13 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
private:
bool ConstructInstanceFromPrefabDom(const PrefabDom& prefab);
+ // Marked const so this function can be called from other const functions. It will only operate on mutable variables.
+ void RefreshPrefabDom() const;
mutable PrefabDom m_dom;
AZStd::unique_ptr m_instance;
AZStd::string m_name;
- AZStd::vector> m_referencedAssets;
+ mutable AZStd::vector> m_referencedAssets;
mutable bool m_isDirty{ false };
};
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp
index 93e4ffd3da..45363f4bb5 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp
@@ -80,7 +80,6 @@ namespace AzToolsFramework
EntityOutlinerListModel::EntityOutlinerListModel(QObject* parent)
: QAbstractItemModel(parent)
, m_entitySelectQueue()
- , m_entityExpandQueue()
, m_entityChangeQueue()
, m_entityChangeQueued(false)
, m_entityLayoutQueued(false)
@@ -1275,7 +1274,6 @@ namespace AzToolsFramework
void EntityOutlinerListModel::QueueEntityToExpand(AZ::EntityId entityId, bool expand)
{
m_entityExpansionState[entityId] = expand;
- m_entityExpandQueue.insert(entityId);
QueueEntityUpdate(entityId);
}
@@ -1300,16 +1298,7 @@ namespace AzToolsFramework
{
return;
}
-
- {
- AZ_PROFILE_SCOPE(Editor, "EntityOutlinerListModel::ProcessEntityUpdates:ExpandQueue");
- for (auto entityId : m_entityExpandQueue)
- {
- emit ExpandEntity(entityId, IsExpanded(entityId));
- };
- m_entityExpandQueue.clear();
- }
-
+
{
AZ_PROFILE_SCOPE(Editor, "EntityOutlinerListModel::ProcessEntityUpdates:SelectQueue");
for (auto entityId : m_entitySelectQueue)
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx
index f099ed504a..51d047e81a 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx
@@ -156,7 +156,6 @@ namespace AzToolsFramework
void ProcessEntityUpdates();
Q_SIGNALS:
- void ExpandEntity(const AZ::EntityId& entityId, bool expand);
void SelectEntity(const AZ::EntityId& entityId, bool select);
void EnableSelectionUpdates(bool enable);
void ResetFilter();
@@ -190,7 +189,6 @@ namespace AzToolsFramework
void QueueEntityToExpand(AZ::EntityId entityId, bool expand);
void ProcessEntityInfoResetEnd();
AZStd::unordered_set m_entitySelectQueue;
- AZStd::unordered_set m_entityExpandQueue;
AZStd::unordered_set m_entityChangeQueue;
bool m_entityChangeQueued;
bool m_entityLayoutQueued;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp
index 857fdb5f80..c2bbebb72e 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp
@@ -81,6 +81,61 @@ namespace AzToolsFramework
update();
}
+ void EntityOutlinerTreeView::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles)
+ {
+ AzQtComponents::StyledTreeView::dataChanged(topLeft, bottomRight, roles);
+
+ if (topLeft.isValid() && topLeft.parent() == bottomRight.parent() && topLeft.row() <= bottomRight.row() &&
+ topLeft.column() <= bottomRight.column())
+ {
+ for (int i = topLeft.row(); i <= bottomRight.row(); i++)
+ {
+ auto modelRow = topLeft.sibling(i, EntityOutlinerListModel::ColumnName);
+ if (modelRow.isValid())
+ {
+ checkExpandedState(modelRow);
+ }
+ }
+ }
+ }
+
+ void EntityOutlinerTreeView::rowsInserted(const QModelIndex& parent, int start, int end)
+ {
+ if (parent.isValid())
+ {
+ for (int i = start; i <= end; i++)
+ {
+ auto modelRow = model()->index(i, EntityOutlinerListModel::ColumnName, parent);
+ if (modelRow.isValid())
+ {
+ checkExpandedState(modelRow);
+ recursiveCheckExpandedStates(modelRow);
+ }
+ }
+ }
+ AzQtComponents::StyledTreeView::rowsInserted(parent, start, end);
+ }
+
+ void EntityOutlinerTreeView::recursiveCheckExpandedStates(const QModelIndex& current)
+ {
+ const int rowCount = model()->rowCount(current);
+ for (int i = 0; i < rowCount; i++)
+ {
+ auto modelRow = model()->index(i, EntityOutlinerListModel::ColumnName, current);
+ if (modelRow.isValid())
+ {
+ checkExpandedState(modelRow);
+ recursiveCheckExpandedStates(modelRow);
+ }
+ }
+ }
+
+ void EntityOutlinerTreeView::checkExpandedState(const QModelIndex& current)
+ {
+ const bool expandState = current.data(EntityOutlinerListModel::ExpandedRole).template value();
+ setExpanded(current, expandState);
+ }
+
void EntityOutlinerTreeView::mousePressEvent(QMouseEvent* event)
{
//postponing normal mouse pressed logic until mouse is released or dragged
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx
index 9262da9a73..014bb7bd48 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx
@@ -51,6 +51,10 @@ namespace AzToolsFramework
Q_SIGNALS:
void ItemDropped();
+ protected Q_SLOTS:
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles = QVector()) override;
+ void rowsInserted(const QModelIndex &parent, int start, int end) override;
+
protected:
// Qt overrides
void mousePressEvent(QMouseEvent* event) override;
@@ -75,6 +79,8 @@ namespace AzToolsFramework
void ClearQueuedMouseEvent();
void processQueuedMousePressedEvent(QMouseEvent* event);
+ void recursiveCheckExpandedStates(const QModelIndex& parent);
+ void checkExpandedState(const QModelIndex& current);
void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) override;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
index 31bb067603..52b688543a 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp
@@ -224,7 +224,6 @@ namespace AzToolsFramework
connect(m_gui->m_objectTree, &QTreeView::expanded, this, &EntityOutlinerWidget::OnTreeItemExpanded);
connect(m_gui->m_objectTree, &QTreeView::collapsed, this, &EntityOutlinerWidget::OnTreeItemCollapsed);
connect(m_gui->m_objectTree, &EntityOutlinerTreeView::ItemDropped, this, &EntityOutlinerWidget::OnDropEvent);
- connect(m_listModel, &EntityOutlinerListModel::ExpandEntity, this, &EntityOutlinerWidget::OnExpandEntity);
connect(m_listModel, &EntityOutlinerListModel::SelectEntity, this, &EntityOutlinerWidget::OnSelectEntity);
connect(m_listModel, &EntityOutlinerListModel::EnableSelectionUpdates, this, &EntityOutlinerWidget::OnEnableSelectionUpdates);
connect(m_listModel, &EntityOutlinerListModel::ResetFilter, this, &EntityOutlinerWidget::ClearFilter);
@@ -972,10 +971,6 @@ namespace AzToolsFramework
m_listModel->OnEntityCollapsed(entityId);
}
- void EntityOutlinerWidget::OnExpandEntity(const AZ::EntityId& entityId, bool expand)
- {
- m_gui->m_objectTree->setExpanded(GetIndexFromEntityId(entityId), expand);
- }
void EntityOutlinerWidget::OnSelectEntity(const AZ::EntityId& entityId, bool selected)
{
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx
index e6c42fa64e..38d2e16199 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx
@@ -155,7 +155,6 @@ namespace AzToolsFramework
void OnTreeItemDoubleClicked(const QModelIndex& index);
void OnTreeItemExpanded(const QModelIndex& index);
void OnTreeItemCollapsed(const QModelIndex& index);
- void OnExpandEntity(const AZ::EntityId& entityId, bool expand);
void OnSelectEntity(const AZ::EntityId& entityId, bool selected);
void OnEnableSelectionUpdates(bool enable);
void OnDropEvent();
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp
index cc0018753e..69d6ae82ca 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp
@@ -306,41 +306,37 @@ namespace AzToolsFramework
{
// Only show the close icon if the prefab is expanded.
// This allows the prefab container to be opened if it was collapsed during propagation.
- if (!isExpanded)
+ if (isExpanded)
{
- return;
- }
+ // Use the same color as the background.
+ QColor backgroundColor = m_backgroundColor;
+ if (isSelected)
+ {
+ backgroundColor = m_backgroundSelectedColor;
+ }
+ else if (isHovered)
+ {
+ backgroundColor = m_backgroundHoverColor;
+ }
- // Use the same color as the background.
- QColor backgroundColor = m_backgroundColor;
- if (isSelected)
- {
- backgroundColor = m_backgroundSelectedColor;
- }
- else if (isHovered)
- {
- backgroundColor = m_backgroundHoverColor;
- }
+ // Paint a rect to cover up the expander.
+ QRect rect = QRect(0, 0, 16, 16);
+ rect.translate(option.rect.topLeft() + offset);
+ painter->fillRect(rect, backgroundColor);
- // Paint a rect to cover up the expander.
- QRect rect = QRect(0, 0, 16, 16);
- rect.translate(option.rect.topLeft() + offset);
- painter->fillRect(rect, backgroundColor);
-
- // Paint the icon.
- QIcon closeIcon = QIcon(m_prefabEditCloseIconPath);
- painter->drawPixmap(option.rect.topLeft() + offset, closeIcon.pixmap(iconSize));
+ // Paint the icon.
+ QIcon closeIcon = QIcon(m_prefabEditCloseIconPath);
+ painter->drawPixmap(option.rect.topLeft() + offset, closeIcon.pixmap(iconSize));
+ }
}
else
{
// Only show the edit icon on hover.
- if (!isHovered)
+ if (isHovered)
{
- return;
+ QIcon openIcon = QIcon(m_prefabEditOpenIconPath);
+ painter->drawPixmap(option.rect.topLeft() + offset, openIcon.pixmap(iconSize));
}
-
- QIcon openIcon = QIcon(m_prefabEditOpenIconPath);
- painter->drawPixmap(option.rect.topLeft() + offset, openIcon.pixmap(iconSize));
}
painter->restore();
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp
index 7a9a5a4d7a..6d32145742 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp
@@ -122,7 +122,7 @@ namespace AzToolsFramework
EditorInteractionSystemViewportSelectionRequestBus::Event(
GetEntityContextId(), &EditorInteractionSystemViewportSelection::SetHandler,
- [](const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
+ [](const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique(entityDataCache, viewportEditorModeTracker);
});
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp
index 7f877facb6..dca1da64d8 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp
@@ -90,6 +90,61 @@ namespace UnitTest
return AZStd::string(keyText.toUtf8().data());
}
+ bool ViewportSettingsTestImpl::GridSnappingEnabled() const
+ {
+ return m_gridSnapping;
+ }
+
+ float ViewportSettingsTestImpl::GridSize() const
+ {
+ return m_gridSize;
+ }
+
+ bool ViewportSettingsTestImpl::ShowGrid() const
+ {
+ return false;
+ }
+
+ bool ViewportSettingsTestImpl::AngleSnappingEnabled() const
+ {
+ return m_angularSnapping;
+ }
+
+ float ViewportSettingsTestImpl::AngleStep() const
+ {
+ return m_angularStep;
+ }
+
+ float ViewportSettingsTestImpl::ManipulatorLineBoundWidth() const
+ {
+ return 0.1f;
+ }
+
+ float ViewportSettingsTestImpl::ManipulatorCircleBoundWidth() const
+ {
+ return 0.1f;
+ }
+
+ bool ViewportSettingsTestImpl::StickySelectEnabled() const
+ {
+ return m_stickySelect;
+ }
+
+ bool ViewportSettingsTestImpl::IconsVisible() const
+ {
+ return m_iconsVisible;
+ }
+
+ bool ViewportSettingsTestImpl::HelpersVisible() const
+ {
+ return m_helpersVisible;
+ }
+
+ AZ::Vector3 ViewportSettingsTestImpl::DefaultEditorCameraPosition() const
+ {
+ return {};
+ }
+
bool TestWidget::eventFilter(QObject* watched, QEvent* event)
{
AZ_UNUSED(watched);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h
index 2c60ca914c..e5a655cfee 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h
@@ -91,6 +91,43 @@ namespace UnitTest
/// @param modifiers Optional keyboard modifiers to include during the wheel events, defaults to Qt::NoModifier
AZStd::string QtKeyToAzString(Qt::Key key, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
+ //! Test implementation of the ViewportSettingsRequestBus.
+ //! @note Can be used to customize viewport settings during test execution.
+ class ViewportSettingsTestImpl : public AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler
+ {
+ public:
+ void Connect(const AzFramework::ViewportId viewportId)
+ {
+ AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusConnect(viewportId);
+ }
+
+ void Disconnect()
+ {
+ AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusDisconnect();
+ }
+
+ // ViewportSettingsRequestBus overrides ...
+ bool GridSnappingEnabled() const override;
+ float GridSize() const override;
+ bool ShowGrid() const override;
+ bool AngleSnappingEnabled() const override;
+ float AngleStep() const override;
+ float ManipulatorLineBoundWidth() const override;
+ float ManipulatorCircleBoundWidth() const override;
+ bool StickySelectEnabled() const override;
+ AZ::Vector3 DefaultEditorCameraPosition() const override;
+ bool IconsVisible() const override;
+ bool HelpersVisible() const override;
+
+ float m_gridSize = 1.0f;
+ float m_angularStep = 0.0f;
+ bool m_gridSnapping = false;
+ bool m_angularSnapping = false;
+ bool m_stickySelect = true;
+ bool m_iconsVisible = true;
+ bool m_helpersVisible = true;
+ };
+
/// Test widget to store QActions generated by EditorTransformComponentSelection.
class TestWidget : public QWidget
{
@@ -207,7 +244,7 @@ namespace UnitTest
m_editorActions.Connect();
const auto viewportHandlerBuilder =
- [this](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
+ [this](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
// create the default viewport (handles ComponentMode)
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockEditorViewportIconDisplayInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockEditorViewportIconDisplayInterface.h
new file mode 100644
index 0000000000..be29837b59
--- /dev/null
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockEditorViewportIconDisplayInterface.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+
+#include
+
+namespace UnitTest
+{
+ class MockEditorViewportIconDisplayInterface : public AZ::Interface::Registrar
+ {
+ public:
+ virtual ~MockEditorViewportIconDisplayInterface() = default;
+
+ //! AzToolsFramework::EditorViewportIconDisplayInterface overrides ...
+ MOCK_METHOD1(DrawIcon, void(const DrawParameters&));
+ MOCK_METHOD1(GetOrLoadIconForPath, IconId(AZStd::string_view path));
+ MOCK_METHOD1(GetIconLoadStatus, IconLoadStatus(IconId icon));
+ };
+} // namespace UnitTest
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockEditorVisibleEntityDataCacheInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockEditorVisibleEntityDataCacheInterface.h
new file mode 100644
index 0000000000..4fc35fa9aa
--- /dev/null
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockEditorVisibleEntityDataCacheInterface.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+
+#include
+
+namespace UnitTest
+{
+ class MockEditorVisibleEntityDataCacheInterface : public AzToolsFramework::EditorVisibleEntityDataCacheInterface
+ {
+ using ComponentEntityAccentType = AzToolsFramework::Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType;
+
+ public:
+ virtual ~MockEditorVisibleEntityDataCacheInterface() = default;
+
+ // AzToolsFramework::EditorVisibleEntityDataCacheInterface overrides ...
+ MOCK_CONST_METHOD0(VisibleEntityDataCount, size_t());
+ MOCK_CONST_METHOD1(GetVisibleEntityPosition, AZ::Vector3(size_t));
+ MOCK_CONST_METHOD1(GetVisibleEntityTransform, const AZ::Transform&(size_t));
+ MOCK_CONST_METHOD1(GetVisibleEntityId, AZ::EntityId(size_t));
+ MOCK_CONST_METHOD1(GetVisibleEntityAccent, ComponentEntityAccentType(size_t));
+ MOCK_CONST_METHOD1(IsVisibleEntityLocked, bool(size_t));
+ MOCK_CONST_METHOD1(IsVisibleEntityVisible, bool(size_t));
+ MOCK_CONST_METHOD1(IsVisibleEntitySelected, bool(size_t));
+ MOCK_CONST_METHOD1(IsVisibleEntityIconHidden, bool(size_t));
+ MOCK_CONST_METHOD1(IsVisibleEntityIndividuallySelectableInViewport, bool(size_t));
+ MOCK_CONST_METHOD1(GetVisibleEntityIndexFromId, AZStd::optional(AZ::EntityId entityId));
+ };
+} // namespace UnitTest
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockFocusModeInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockFocusModeInterface.h
new file mode 100644
index 0000000000..7bb5db14c5
--- /dev/null
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/Mocks/MockFocusModeInterface.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+
+#include
+
+namespace UnitTest
+{
+ class MockFocusModeInterface : public AZ::Interface::Registrar
+ {
+ public:
+ virtual ~MockFocusModeInterface() = default;
+
+ // AzToolsFramework::FocusModeInterface overrides ...
+ MOCK_METHOD1(SetFocusRoot, void(AZ::EntityId entityId));
+ MOCK_METHOD1(ClearFocusRoot, void(AzFramework::EntityContextId entityContextId));
+ MOCK_METHOD1(GetFocusRoot, AZ::EntityId(AzFramework::EntityContextId entityContextId));
+ MOCK_METHOD1(GetFocusedEntities, AzToolsFramework::EntityIdList(AzFramework::EntityContextId entityContextId));
+ MOCK_CONST_METHOD1(IsInFocusSubTree, bool(AZ::EntityId entityId));
+ };
+} // namespace UnitTest
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp
index 1541d4678e..4ae22ca899 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp
@@ -21,9 +21,8 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR_IMPL(EditorDefaultSelection, AZ::SystemAllocator, 0)
EditorDefaultSelection::EditorDefaultSelection(
- const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
+ const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
: m_phantomWidget(nullptr)
- , m_entityDataCache(entityDataCache)
, m_viewportEditorModeTracker(viewportEditorModeTracker)
, m_componentModeCollection(viewportEditorModeTracker)
{
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.h
index f44de0d6eb..f940a3e6b2 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.h
@@ -27,7 +27,8 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR_DECL
//! @cond
- EditorDefaultSelection(const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker);
+ EditorDefaultSelection(
+ const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker);
EditorDefaultSelection(const EditorDefaultSelection&) = delete;
EditorDefaultSelection& operator=(const EditorDefaultSelection&) = delete;
virtual ~EditorDefaultSelection();
@@ -85,10 +86,8 @@ namespace AzToolsFramework
QWidget m_phantomWidget; //!< The phantom widget responsible for holding QActions while in ComponentMode.
QWidget* m_phantomOverrideWidget = nullptr; //!< It's possible to override the phantom widget in special circumstances (eg testing).
ComponentModeFramework::ComponentModeCollection m_componentModeCollection; //!< Handles all active ComponentMode types.
- AZStd::unique_ptr m_transformComponentSelection =
- nullptr; //!< Viewport selection (responsible for
- //!< manipulators and transform modifications).
- const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Reference to cached visible EntityData.
+ //! Viewport selection (responsible for manipulators and transform modifications).
+ AZStd::unique_ptr m_transformComponentSelection = nullptr;
//! Mapping between passed ActionOverride (AddActionOverride) and allocated QAction.
struct ActionOverrideMapping
@@ -112,7 +111,7 @@ namespace AzToolsFramework
AZStd::shared_ptr m_manipulatorManager; //!< The default manipulator manager.
ViewportInteraction::MouseInteraction m_currentInteraction; //!< Current mouse interaction to be used for drawing manipulators.
- ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr; //!< Tracker for activating/deactivating viewport editor modes.
-
+ //! Tracker for activating/deactivating viewport editor modes.
+ ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr;
};
} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp
index ace2156d85..9b82129582 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp
@@ -159,7 +159,7 @@ namespace AzToolsFramework
return false;
}
- EditorHelpers::EditorHelpers(const EditorVisibleEntityDataCache* entityDataCache)
+ EditorHelpers::EditorHelpers(const EditorVisibleEntityDataCacheInterface* entityDataCache)
: m_entityDataCache(entityDataCache)
{
m_focusModeInterface = AZ::Interface::Get();
@@ -344,9 +344,19 @@ namespace AzToolsFramework
continue;
}
- int iconTextureId = 0;
- EditorEntityIconComponentRequestBus::EventResult(
- iconTextureId, entityId, &EditorEntityIconComponentRequests::GetEntityIconTextureId);
+ const AZ::Vector3& entityPosition = m_entityDataCache->GetVisibleEntityPosition(entityCacheIndex);
+ const AZ::Vector3 entityCameraVector = entityPosition - cameraState.m_position;
+
+ if (const float directionFromCamera = entityCameraVector.Dot(cameraState.m_forward); directionFromCamera < 0.0f)
+ {
+ continue;
+ }
+
+ const float distanceFromCamera = entityCameraVector.GetLength();
+ if (distanceFromCamera < cameraState.m_nearClip)
+ {
+ continue;
+ }
using ComponentEntityAccentType = Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType;
const AZ::Color iconHighlight = [this, entityCacheIndex]()
@@ -364,13 +374,13 @@ namespace AzToolsFramework
return AZ::Color(1.0f, 1.0f, 1.0f, 1.0f);
}();
- const AZ::Vector3& entityPosition = m_entityDataCache->GetVisibleEntityPosition(entityCacheIndex);
- const float distanceFromCamera = cameraState.m_position.GetDistance(entityPosition);
- const float iconSize = GetIconSize(distanceFromCamera);
+ int iconTextureId = 0;
+ EditorEntityIconComponentRequestBus::EventResult(
+ iconTextureId, entityId, &EditorEntityIconComponentRequestBus::Events::GetEntityIconTextureId);
- editorViewportIconDisplay->DrawIcon({ viewportInfo.m_viewportId, iconTextureId, iconHighlight, entityPosition,
- EditorViewportIconDisplayInterface::CoordinateSpace::WorldSpace,
- AZ::Vector2{ iconSize, iconSize } });
+ editorViewportIconDisplay->DrawIcon(EditorViewportIconDisplayInterface::DrawParameters{
+ viewportInfo.m_viewportId, iconTextureId, iconHighlight, entityPosition,
+ EditorViewportIconDisplayInterface::CoordinateSpace::WorldSpace, AZ::Vector2(GetIconSize(distanceFromCamera)) });
}
}
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h
index 358e6d9117..b21e0b6737 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h
@@ -24,7 +24,7 @@ namespace AzFramework
namespace AzToolsFramework
{
- class EditorVisibleEntityDataCache;
+ class EditorVisibleEntityDataCacheInterface;
class FocusModeInterface;
namespace ViewportInteraction
@@ -64,7 +64,7 @@ namespace AzToolsFramework
//! An EditorVisibleEntityDataCache must be passed to EditorHelpers to allow it to
//! efficiently read entity data without resorting to EBus calls.
- explicit EditorHelpers(const EditorVisibleEntityDataCache* entityDataCache);
+ explicit EditorHelpers(const EditorVisibleEntityDataCacheInterface* entityDataCache);
EditorHelpers(const EditorHelpers&) = delete;
EditorHelpers& operator=(const EditorHelpers&) = delete;
~EditorHelpers() = default;
@@ -103,7 +103,7 @@ namespace AzToolsFramework
AZStd::unique_ptr m_invalidClicks; //!< Display for invalid click behavior.
- const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers.
+ const EditorVisibleEntityDataCacheInterface* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers.
const FocusModeInterface* m_focusModeInterface = nullptr; //!< API to interact with focus mode functionality.
};
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.cpp
index 5d03231aab..17ffa2fdc1 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemComponent.cpp
@@ -84,7 +84,7 @@ namespace AzToolsFramework
void EditorInteractionSystemComponent::SetDefaultHandler()
{
SetHandler(
- [](const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
+ [](const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique(entityDataCache, viewportEditorModeTracker);
});
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h
index 3579460ca0..78fd8d3429 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h
@@ -16,7 +16,7 @@
namespace AzToolsFramework
{
- class EditorVisibleEntityDataCache;
+ class EditorVisibleEntityDataCacheInterface;
class ViewportEditorModeTrackerInterface;
//! Bus to handle all mouse events originating from the viewport.
@@ -34,7 +34,7 @@ namespace AzToolsFramework
//! Alias for factory function to create a new type implementing the ViewportSelectionRequests interface.
using ViewportSelectionRequestsBuilderFn = AZStd::function(
- const EditorVisibleEntityDataCache*, ViewportEditorModeTrackerInterface*)>;
+ const EditorVisibleEntityDataCacheInterface*, ViewportEditorModeTrackerInterface*)>;
//! Interface for system component implementing the ViewportSelectionRequests interface.
//! This interface also includes a setter to set a custom handler also implementing
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.cpp
index 059b265f51..a853a9182d 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.cpp
@@ -17,7 +17,7 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR_IMPL(EditorPickEntitySelection, AZ::SystemAllocator, 0)
EditorPickEntitySelection::EditorPickEntitySelection(
- const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
+ const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
: m_editorHelpers(AZStd::make_unique(entityDataCache))
, m_viewportEditorModeTracker(viewportEditorModeTracker)
{
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h
index 62fa4161b7..f941108ef8 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h
@@ -13,6 +13,7 @@
namespace AzToolsFramework
{
+ class EditorVisibleEntityDataCacheInterface;
class ViewportEditorModeTrackerInterface;
//! Viewport interaction that will handle assigning an entity in the viewport to
@@ -23,7 +24,7 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR_DECL
EditorPickEntitySelection(
- const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker);
+ const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker);
~EditorPickEntitySelection();
private:
@@ -35,6 +36,7 @@ namespace AzToolsFramework
AZStd::unique_ptr m_editorHelpers; //!< Editor visualization of entities (icons, shapes, debug visuals etc).
AZ::EntityId m_hoveredEntityId; //!< What EntityId is the mouse currently hovering over (if any).
AZ::EntityId m_cachedEntityIdUnderCursor; //!< Store the EntityId on each mouse move for use in Display.
- ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr; //!< Tracker for activating/deactivating viewport editor modes.
+ //! Tracker for activating/deactivating viewport editor modes.
+ ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr;
};
} // namespace AzToolsFramework
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
index b14f58fafa..5c5cdcb4b4 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp
@@ -381,7 +381,7 @@ namespace AzToolsFramework
EntityIdContainer& selectedEntityIdsBeforeBoxSelect,
EntityIdContainer& potentialSelectedEntityIds,
EntityIdContainer& potentialDeselectedEntityIds,
- const EditorVisibleEntityDataCache& entityDataCache,
+ const EditorVisibleEntityDataCacheInterface& entityDataCache,
const int viewportId,
const ViewportInteraction::KeyboardModifiers currentKeyboardModifiers,
const ViewportInteraction::KeyboardModifiers& previousKeyboardModifiers)
@@ -958,7 +958,7 @@ namespace AzToolsFramework
// (useful in the context of drawing when we only care about entities we can see)
// note: return the index if it is selectable, nullopt otherwise
static AZStd::optional SelectableInVisibleViewportCache(
- const EditorVisibleEntityDataCache& entityDataCache, const AZ::EntityId entityId)
+ const EditorVisibleEntityDataCacheInterface& entityDataCache, const AZ::EntityId entityId)
{
if (auto entityIndex = entityDataCache.GetVisibleEntityIndexFromId(entityId))
{
@@ -1002,7 +1002,7 @@ namespace AzToolsFramework
}
}
- EditorTransformComponentSelection::EditorTransformComponentSelection(const EditorVisibleEntityDataCache* entityDataCache)
+ EditorTransformComponentSelection::EditorTransformComponentSelection(const EditorVisibleEntityDataCacheInterface* entityDataCache)
: m_entityDataCache(entityDataCache)
{
const AzFramework::EntityContextId entityContextId = GetEntityContextId();
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h
index 7b3ba08894..0465a7920f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h
@@ -34,7 +34,7 @@
namespace AzToolsFramework
{
- class EditorVisibleEntityDataCache;
+ class EditorVisibleEntityDataCacheInterface;
using EntityIdSet = AZStd::unordered_set; //!< Alias for unordered_set of EntityIds.
@@ -167,7 +167,7 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR_DECL
EditorTransformComponentSelection() = default;
- explicit EditorTransformComponentSelection(const EditorVisibleEntityDataCache* entityDataCache);
+ explicit EditorTransformComponentSelection(const EditorVisibleEntityDataCacheInterface* entityDataCache);
EditorTransformComponentSelection(const EditorTransformComponentSelection&) = delete;
EditorTransformComponentSelection& operator=(const EditorTransformComponentSelection&) = delete;
virtual ~EditorTransformComponentSelection();
@@ -325,10 +325,8 @@ namespace AzToolsFramework
AZ::EntityId m_currentEntityIdUnderCursor; //!< Store the EntityId on each mouse move for use in Display.
AZ::EntityId m_editorCameraComponentEntityId; //!< The EditorCameraComponent EntityId if it is set.
EntityIdSet m_selectedEntityIds; //!< Represents the current entities in the selection.
-
- const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< A cache of packed EntityData that can be
- //!< iterated over efficiently without the need
- //!< to make individual EBus calls.
+ //! A cache of packed EntityData that can be iterated over efficiently without the need to make individual EBus calls.
+ const EditorVisibleEntityDataCacheInterface* m_entityDataCache = nullptr;
AZStd::unique_ptr m_editorHelpers; //!< Editor visualization of entities (icons, shapes, debug visuals etc).
EntityIdManipulators m_entityIdManipulators; //!< Mapping from a Manipulator to potentially many EntityIds.
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h
index 4262d334df..44dc570d5a 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h
@@ -20,10 +20,36 @@
namespace AzToolsFramework
{
+ //! Read-only interface for EditorVisibleEntityDataCache to be used by systems that want to efficiently
+ //! query the state of visible entities in the viewport.
+ class EditorVisibleEntityDataCacheInterface
+ {
+ using ComponentEntityAccentType = Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType;
+
+ public:
+ virtual ~EditorVisibleEntityDataCacheInterface() = default;
+
+ virtual size_t VisibleEntityDataCount() const = 0;
+ virtual AZ::Vector3 GetVisibleEntityPosition(size_t index) const = 0;
+ virtual const AZ::Transform& GetVisibleEntityTransform(size_t index) const = 0;
+ virtual AZ::EntityId GetVisibleEntityId(size_t index) const = 0;
+ virtual ComponentEntityAccentType GetVisibleEntityAccent(size_t index) const = 0;
+ virtual bool IsVisibleEntityLocked(size_t index) const = 0;
+ virtual bool IsVisibleEntityVisible(size_t index) const = 0;
+ virtual bool IsVisibleEntitySelected(size_t index) const = 0;
+ virtual bool IsVisibleEntityIconHidden(size_t index) const = 0;
+ //! Returns true if the entity is individually selectable (none of its ancestors are a closed container entity).
+ //! @note It may still be desirable to be able to 'click' an entity that is a descendant of a closed container
+ //! to select the container itself, not the individual entity.
+ virtual bool IsVisibleEntityIndividuallySelectableInViewport(size_t index) const = 0;
+ virtual AZStd::optional GetVisibleEntityIndexFromId(AZ::EntityId entityId) const = 0;
+ };
+
//! A cache of packed EntityData that can be iterated over efficiently without
//! the need to make individual EBus calls
class EditorVisibleEntityDataCache
- : private EditorEntityVisibilityNotificationBus::Router
+ : public EditorVisibleEntityDataCacheInterface
+ , private EditorEntityVisibilityNotificationBus::Router
, private EditorEntityLockComponentNotificationBus::Router
, private AZ::TransformNotificationBus::Router
, private EditorComponentSelectionNotificationsBus::Router
@@ -45,22 +71,18 @@ namespace AzToolsFramework
void CalculateVisibleEntityDatas(const AzFramework::ViewportInfo& viewportInfo);
- //! EditorVisibleEntityDataCache interface
- size_t VisibleEntityDataCount() const;
- AZ::Vector3 GetVisibleEntityPosition(size_t index) const;
- const AZ::Transform& GetVisibleEntityTransform(size_t index) const;
- AZ::EntityId GetVisibleEntityId(size_t index) const;
- ComponentEntityAccentType GetVisibleEntityAccent(size_t index) const;
- bool IsVisibleEntityLocked(size_t index) const;
- bool IsVisibleEntityVisible(size_t index) const;
- bool IsVisibleEntitySelected(size_t index) const;
- bool IsVisibleEntityIconHidden(size_t index) const;
- //! Returns true if the entity is individually selectable (none of its ancestors are a closed container entity).
- //! @note It may still be desirable to be able to 'click' an entity that is a descendant of a closed container
- //! to select the container itself, not the individual entity.
- bool IsVisibleEntityIndividuallySelectableInViewport(size_t index) const;
-
- AZStd::optional GetVisibleEntityIndexFromId(AZ::EntityId entityId) const;
+ //! EditorVisibleEntityDataCacheInterface overrides ...
+ size_t VisibleEntityDataCount() const override;
+ AZ::Vector3 GetVisibleEntityPosition(size_t index) const override;
+ const AZ::Transform& GetVisibleEntityTransform(size_t index) const override;
+ AZ::EntityId GetVisibleEntityId(size_t index) const override;
+ ComponentEntityAccentType GetVisibleEntityAccent(size_t index) const override;
+ bool IsVisibleEntityLocked(size_t index) const override;
+ bool IsVisibleEntityVisible(size_t index) const override;
+ bool IsVisibleEntitySelected(size_t index) const override;
+ bool IsVisibleEntityIconHidden(size_t index) const override;
+ bool IsVisibleEntityIndividuallySelectableInViewport(size_t index) const override;
+ AZStd::optional GetVisibleEntityIndexFromId(AZ::EntityId entityId) const override;
void AddEntityIds(const EntityIdList& entityIds);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframeworktestcommon_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframeworktestcommon_files.cmake
index b70407ac68..4259a6ee9c 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframeworktestcommon_files.cmake
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframeworktestcommon_files.cmake
@@ -9,6 +9,9 @@
set(FILES
UnitTest/AzToolsFrameworkTestHelpers.cpp
UnitTest/AzToolsFrameworkTestHelpers.h
+ UnitTest/Mocks/MockFocusModeInterface.h
+ UnitTest/Mocks/MockEditorVisibleEntityDataCacheInterface.h
+ UnitTest/Mocks/MockEditorViewportIconDisplayInterface.h
UnitTest/ToolsTestApplication.cpp
UnitTest/ToolsTestApplication.h
)
diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp
index dc9e1180b7..29d72a8270 100644
--- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp
+++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp
@@ -265,7 +265,7 @@ namespace UnitTest
using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
EditorInteractionSystemViewportSelectionRequestBus::Event(
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
- [](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
+ [](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique(entityDataCache, viewportEditorModeTracker);
diff --git a/Code/Framework/AzToolsFramework/Tests/EditorViewportIconTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorViewportIconTests.cpp
new file mode 100644
index 0000000000..46ce9804e6
--- /dev/null
+++ b/Code/Framework/AzToolsFramework/Tests/EditorViewportIconTests.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace UnitTest
+{
+ class EditorViewportIconFixture : public AllocatorsTestFixture
+ {
+ public:
+ inline static constexpr AzFramework::ViewportId TestViewportId = 2468;
+
+ void SetUp() override
+ {
+ AllocatorsTestFixture::SetUp();
+
+ m_focusModeMock = AZStd::make_unique<::testing::NiceMock>();
+ m_editorViewportIconDisplayMock = AZStd::make_unique<::testing::NiceMock>();
+ m_entityVisibleEntityDataCacheMock = AZStd::make_unique<::testing::NiceMock>();
+ m_editorHelpers = AZStd::make_unique(m_entityVisibleEntityDataCacheMock.get());
+ m_viewportSettings = AZStd::make_unique();
+
+ m_viewportSettings->Connect(TestViewportId);
+ m_viewportSettings->m_helpersVisible = false;
+ m_viewportSettings->m_iconsVisible = true;
+
+ m_cameraState = AzFramework::CreateDefaultCamera(AZ::Transform::CreateIdentity(), AZ::Vector2(1024.0f, 768.0f));
+
+ using ::testing::_;
+ using ::testing::Return;
+ ON_CALL(*m_entityVisibleEntityDataCacheMock, VisibleEntityDataCount()).WillByDefault(Return(1));
+ ON_CALL(*m_entityVisibleEntityDataCacheMock, GetVisibleEntityId(_)).WillByDefault(Return(AZ::EntityId()));
+ ON_CALL(*m_entityVisibleEntityDataCacheMock, IsVisibleEntityIconHidden(_)).WillByDefault(Return(false));
+ ON_CALL(*m_entityVisibleEntityDataCacheMock, IsVisibleEntityVisible(_)).WillByDefault(Return(true));
+ ON_CALL(*m_focusModeMock, IsInFocusSubTree(_)).WillByDefault(Return(true));
+ }
+
+ void TearDown() override
+ {
+ m_viewportSettings->Disconnect();
+ m_viewportSettings.reset();
+ m_editorHelpers.reset();
+ m_entityVisibleEntityDataCacheMock.reset();
+ m_editorViewportIconDisplayMock.reset();
+ m_focusModeMock.reset();
+
+ AllocatorsTestFixture::TearDown();
+ }
+
+ AZStd::unique_ptr m_viewportSettings;
+ AZStd::unique_ptr m_editorHelpers;
+ AZStd::unique_ptr<::testing::NiceMock> m_focusModeMock;
+ AZStd::unique_ptr<::testing::NiceMock> m_entityVisibleEntityDataCacheMock;
+ AZStd::unique_ptr<::testing::NiceMock> m_editorViewportIconDisplayMock;
+ AzFramework::CameraState m_cameraState;
+ };
+
+ TEST_F(EditorViewportIconFixture, ViewportIconsAreNotDisplayedWhenInBetweenCameraAndNearClipPlane)
+ {
+ NullDebugDisplayRequests nullDebugDisplayRequests;
+
+ const auto insideNearClip = m_cameraState.m_nearClip * 0.5f;
+
+ using ::testing::_;
+ using ::testing::Return;
+ // given
+ // entity position (where icon will be drawn) is in between near clip plane and camera position
+ ON_CALL(*m_entityVisibleEntityDataCacheMock, GetVisibleEntityPosition(_))
+ .WillByDefault(Return(AZ::Vector3(0.0f, insideNearClip, 0.0f)));
+
+ EXPECT_CALL(*m_editorViewportIconDisplayMock, DrawIcon(_)).Times(0);
+
+ // when
+ m_editorHelpers->DisplayHelpers(
+ AzFramework::ViewportInfo{ TestViewportId }, m_cameraState, nullDebugDisplayRequests,
+ [](AZ::EntityId)
+ {
+ return true;
+ });
+ }
+
+ TEST_F(EditorViewportIconFixture, ViewportIconsAreNotDisplayedWhenBehindCamera)
+ {
+ NullDebugDisplayRequests nullDebugDisplayRequests;
+
+ using ::testing::_;
+ using ::testing::Return;
+ // given
+ // entity position (where icon will be drawn) behind the camera position
+ ON_CALL(*m_entityVisibleEntityDataCacheMock, GetVisibleEntityPosition(_)).WillByDefault(Return(AZ::Vector3(0.0f, -1.0f, 0.0f)));
+
+ EXPECT_CALL(*m_editorViewportIconDisplayMock, DrawIcon(_)).Times(0);
+
+ // when
+ m_editorHelpers->DisplayHelpers(
+ AzFramework::ViewportInfo{ TestViewportId }, m_cameraState, nullDebugDisplayRequests,
+ [](AZ::EntityId)
+ {
+ return true;
+ });
+ }
+} // namespace UnitTest
diff --git a/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportEditorModeTests.cpp b/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportEditorModeTests.cpp
index 85b65f3edf..96e56d0c6a 100644
--- a/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportEditorModeTests.cpp
+++ b/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportEditorModeTests.cpp
@@ -573,7 +573,7 @@ namespace UnitTest
using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
EditorInteractionSystemViewportSelectionRequestBus::Event(
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
- [](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
+ [](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique(entityDataCache, viewportEditorModeTracker);
@@ -591,7 +591,7 @@ namespace UnitTest
using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
EditorInteractionSystemViewportSelectionRequestBus::Event(
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
- [](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
+ [](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique(entityDataCache, viewportEditorModeTracker);
@@ -599,7 +599,7 @@ namespace UnitTest
EditorInteractionSystemViewportSelectionRequestBus::Event(
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
- [](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
+ [](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique(entityDataCache, viewportEditorModeTracker);
diff --git a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake
index 2631a84325..b23713f891 100644
--- a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake
+++ b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake
@@ -24,6 +24,7 @@ set(FILES
ComponentModeTests.cpp
EditorTransformComponentSelectionTests.cpp
EditorVertexSelectionTests.cpp
+ EditorViewportIconTests.cpp
Entity/EditorEntityContextComponentTests.cpp
Entity/EditorEntityHelpersTests.cpp
Entity/EditorEntitySearchComponentTests.cpp
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/CryCommon/WinBase.cpp b/Code/Legacy/CryCommon/WinBase.cpp
index 771cde324e..6e6f5e210a 100644
--- a/Code/Legacy/CryCommon/WinBase.cpp
+++ b/Code/Legacy/CryCommon/WinBase.cpp
@@ -856,18 +856,4 @@ DLL_EXPORT void OutputDebugString(const char* outputString)
#endif
-// This code does not have a long life span and will be replaced soon
-#if defined(APPLE) || defined(LINUX) || defined(DEFINE_LEGACY_CRY_FILE_OPERATIONS)
-
-bool CrySetFileAttributes(const char* lpFileName, uint32 dwFileAttributes)
-{
- //TODO: implement
- printf("CrySetFileAttributes not properly implemented yet\n");
- return false;
-}
-
-
-
-#endif //defined(APPLE) || defined(LINUX)
-
#endif // AZ_TRAIT_LEGACY_CRYCOMMON_USE_WINDOWS_STUBS
diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h
index d2251c7091..512f8b4892 100644
--- a/Code/Legacy/CryCommon/platform.h
+++ b/Code/Legacy/CryCommon/platform.h
@@ -336,7 +336,6 @@ void SetFlags(T& dest, U flags, bool b)
#include AZ_RESTRICTED_FILE(platform_h)
#endif
-bool CrySetFileAttributes(const char* lpFileName, uint32 dwFileAttributes);
threadID CryGetCurrentThreadId();
#ifdef __GNUC__
diff --git a/Code/Legacy/CryCommon/platform_impl.cpp b/Code/Legacy/CryCommon/platform_impl.cpp
index 8cbc58ad95..3392c40771 100644
--- a/Code/Legacy/CryCommon/platform_impl.cpp
+++ b/Code/Legacy/CryCommon/platform_impl.cpp
@@ -24,7 +24,6 @@
#define PLATFORM_IMPL_H_SECTION_TRAITS 1
#define PLATFORM_IMPL_H_SECTION_CRYLOWLATENCYSLEEP 2
#define PLATFORM_IMPL_H_SECTION_CRYGETFILEATTRIBUTES 3
-#define PLATFORM_IMPL_H_SECTION_CRYSETFILEATTRIBUTES 4
#define PLATFORM_IMPL_H_SECTION_CRY_FILE_ATTRIBUTE_STUBS 5
#define PLATFORM_IMPL_H_SECTION_CRY_SYSTEM_FUNCTIONS 6
#define PLATFORM_IMPL_H_SECTION_VIRTUAL_ALLOCATORS 7
@@ -238,22 +237,6 @@ void InitRootDir(char szExeFileName[], uint nExeSize, char szExeRootName[], uint
}
}
-//////////////////////////////////////////////////////////////////////////
-bool CrySetFileAttributes(const char* lpFileName, uint32 dwFileAttributes)
-{
-#if defined(AZ_RESTRICTED_PLATFORM)
- #define AZ_RESTRICTED_SECTION PLATFORM_IMPL_H_SECTION_CRYSETFILEATTRIBUTES
- #include AZ_RESTRICTED_FILE(platform_impl_h)
-#endif
-#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
-#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
-#else
- AZStd::wstring lpFileNameW;
- AZStd::to_wstring(lpFileNameW, lpFileName);
- return SetFileAttributes(lpFileNameW.c_str(), dwFileAttributes) != 0;
-#endif
-}
-
//////////////////////////////////////////////////////////////////////////
threadID CryGetCurrentThreadId()
{
diff --git a/Code/Legacy/CrySystem/XML/xml.cpp b/Code/Legacy/CrySystem/XML/xml.cpp
index fb0714500c..2356e71518 100644
--- a/Code/Legacy/CrySystem/XML/xml.cpp
+++ b/Code/Legacy/CrySystem/XML/xml.cpp
@@ -1132,7 +1132,10 @@ bool CXmlNode::saveToFile(const char* fileName)
bool CXmlNode::saveToFile([[maybe_unused]] const char* fileName, size_t chunkSize, AZ::IO::HandleType fileHandle)
{
- CrySetFileAttributes(fileName, FILE_ATTRIBUTE_NORMAL);
+ if (AZ::IO::SystemFile::Exists(fileName) && !AZ::IO::SystemFile::IsWritable(fileName))
+ {
+ AZ::IO::SystemFile::SetWritable(fileName, true);
+ }
if (chunkSize < 256 * 1024) // make at least 256k
{
diff --git a/Code/Tools/AssetProcessor/assetprocessor_test_files.cmake b/Code/Tools/AssetProcessor/assetprocessor_test_files.cmake
index 20ab4b706d..bc7b16cc79 100644
--- a/Code/Tools/AssetProcessor/assetprocessor_test_files.cmake
+++ b/Code/Tools/AssetProcessor/assetprocessor_test_files.cmake
@@ -30,6 +30,8 @@ set(FILES
native/tests/assetBuilderSDK/SerializationDependenciesTests.cpp
native/tests/assetmanager/AssetProcessorManagerTest.cpp
native/tests/assetmanager/AssetProcessorManagerTest.h
+ native/tests/assetmanager/ModtimeScanningTests.cpp
+ native/tests/assetmanager/ModtimeScanningTests.h
native/tests/utilities/assetUtilsTest.cpp
native/tests/platformconfiguration/platformconfigurationtests.cpp
native/tests/platformconfiguration/platformconfigurationtests.h
diff --git a/Code/Tools/AssetProcessor/native/tests/PathDependencyManagerTests.cpp b/Code/Tools/AssetProcessor/native/tests/PathDependencyManagerTests.cpp
index 1d6e92e47e..5103643833 100644
--- a/Code/Tools/AssetProcessor/native/tests/PathDependencyManagerTests.cpp
+++ b/Code/Tools/AssetProcessor/native/tests/PathDependencyManagerTests.cpp
@@ -49,7 +49,7 @@ namespace UnitTests
}
struct PathDependencyBase
- : UnitTest::TraceBusRedirector
+ : ::UnitTest::TraceBusRedirector
{
void Init();
void Destroy();
@@ -65,7 +65,7 @@ namespace UnitTests
};
struct PathDependencyDeletionTest
- : UnitTest::ScopedAllocatorSetupFixture
+ : ::UnitTest::ScopedAllocatorSetupFixture
, PathDependencyBase
{
void SetUp() override
@@ -357,7 +357,7 @@ namespace UnitTests
}
struct PathDependencyBenchmarks
- : UnitTest::ScopedAllocatorFixture
+ : ::UnitTest::ScopedAllocatorFixture
, PathDependencyBase
{
static inline constexpr int NumTestDependencies = 4; // Must be a multiple of 4
@@ -530,7 +530,7 @@ namespace UnitTests
BENCHMARK_F(PathDependencyBenchmarksWrapperClass, BM_DeferredWildcardDependencyResolution)(benchmark::State& state)
{
- for (auto _ : state)
+ for ([[maybe_unused]] auto unused : state)
{
m_benchmarks->m_stateData->SetProductDependencies(m_benchmarks->m_dependencies);
diff --git a/Code/Tools/AssetProcessor/native/tests/SourceFileRelocatorTests.cpp b/Code/Tools/AssetProcessor/native/tests/SourceFileRelocatorTests.cpp
index 8d52ba23bd..bd2ef8b3cd 100644
--- a/Code/Tools/AssetProcessor/native/tests/SourceFileRelocatorTests.cpp
+++ b/Code/Tools/AssetProcessor/native/tests/SourceFileRelocatorTests.cpp
@@ -191,7 +191,7 @@ namespace UnitTests
m_data->m_perforceComponent = AZStd::make_unique();
m_data->m_perforceComponent->Activate();
- m_data->m_perforceComponent->SetConnection(new UnitTest::MockPerforceConnection(m_command));
+ m_data->m_perforceComponent->SetConnection(new ::UnitTest::MockPerforceConnection(m_command));
}
void TearDown() override
@@ -876,7 +876,7 @@ namespace UnitTests
QDir tempPath(m_tempDir.path());
auto filePath = QDir(tempPath.absoluteFilePath(m_data->m_scanFolder1.m_scanFolder.c_str())).absoluteFilePath("duplicate/file1.tif");
-
+
ASSERT_TRUE(AZ::IO::FileIOBase::GetInstance()->Exists(filePath.toUtf8().constData()));
auto result = m_data->m_reporter->Delete(filePath.toUtf8().constData(), false);
diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp
index 0908d0fdb9..347d2a6842 100644
--- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp
+++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp
@@ -22,108 +22,6 @@
using namespace AssetProcessor;
-class AssetProcessorManager_Test
- : public AssetProcessorManager
-{
-public:
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, AssetProcessedImpl_DifferentProductDependenciesPerProduct_SavesCorrectlyToDatabase);
-
- friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies);
- friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_DeferredResolution);
- friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, SameFilenameForAllPlatforms);
-
- friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_SourcePath);
-
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, DeleteFolder_SignalsDeleteOfContainedFiles);
-
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_BasicTest);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_WithDifferentTypes_BasicTest);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_Reverse_BasicTest);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_MissingFiles_ReturnsNoPathWithPlaceholders);
-
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_BeforeComputingDirtiness_AllDirty);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_EmptyDatabase_AllDirty);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_SameAsLastTime_NoneDirty);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_MoreThanLastTime_NewOneIsDirty);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_FewerThanLastTime_Dirty);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_ChangedPattern_CountsAsNew);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_ChangedPatternType_CountsAsNew);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_NewPattern_CountsAsNewBuilder);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_NewVersionNumber_IsNotANewBuilder);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_NewAnalysisFingerprint_IsNotANewBuilder);
-
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_BasicTest);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_UpdateTest);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_MissingFiles_ByUuid);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_MissingFiles_ByName);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_MissingFiles_ByUuid_UpdatesWhenTheyAppear);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_MissingFiles_ByName_UpdatesWhenTheyAppear);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_WildcardMissingFiles_ByName_UpdatesWhenTheyAppear);
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, JobDependencyOrderOnce_MultipleJobs_EmitOK);
-
- friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, SourceFileProcessFailure_ClearsFingerprint);
-
- friend class GTEST_TEST_CLASS_NAME_(AbsolutePathProductDependencyTest, UnresolvedProductPathDependency_AssetProcessedTwice_DoesNotDuplicateDependency);
- friend class GTEST_TEST_CLASS_NAME_(AbsolutePathProductDependencyTest, AbsolutePathProductDependency_RetryDeferredDependenciesWithMatchingSource_DependencyResolves);
- friend class GTEST_TEST_CLASS_NAME_(AbsolutePathProductDependencyTest, UnresolvedProductPathDependency_AssetProcessedTwice_ValidatePathDependenciesMap);
- friend class GTEST_TEST_CLASS_NAME_(AbsolutePathProductDependencyTest, UnresolvedSourceFileTypeProductPathDependency_DependencyHasNoProductOutput_ValidatePathDependenciesMap);
-
- friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping);
-
- friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_FileUnchanged);
-
- friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform);
-
- friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_ModifyFile);
- friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_ModifyFile_AndThenRevert_ProcessesAgain);
- friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_ModifyFilesSameHash_BothProcess);
- friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_ModifyTimestamp);
- friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_ModifyTimestampNoHashing_ProcessesFile);
- friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_ModifyMetadataFile);
- friend class GTEST_TEST_CLASS_NAME_(ModtimeScanningTest, ModtimeSkipping_DeleteFile);
- friend class GTEST_TEST_CLASS_NAME_(DeleteTest, DeleteFolderSharedAcrossTwoScanFolders_CorrectFileAndFolderAreDeletedFromCache);
- friend class GTEST_TEST_CLASS_NAME_(MetadataFileTest, MetadataFile_SourceFileExtensionDifferentCase);
-
- friend class AssetProcessorManagerTest;
- friend struct ModtimeScanningTest;
- friend struct JobDependencyTest;
- friend struct ChainJobDependencyTest;
- friend struct DeleteTest;
- friend struct PathDependencyTest;
- friend struct DuplicateProductsTest;
- friend struct DuplicateProcessTest;
- friend struct AbsolutePathProductDependencyTest;
- friend struct WildcardSourceDependencyTest;
-
- explicit AssetProcessorManager_Test(PlatformConfiguration* config, QObject* parent = nullptr);
- ~AssetProcessorManager_Test() override;
-
- bool CheckJobKeyToJobRunKeyMap(AZStd::string jobKey);
-
- int CountDirtyBuilders() const
- {
- int numDirty = 0;
- for (const auto& element : m_builderDataCache)
- {
- if (element.second.m_isDirty)
- {
- ++numDirty;
- }
- }
- return numDirty;
- }
-
- bool IsBuilderDirty(const AZ::Uuid& builderBusId) const
- {
- auto finder = m_builderDataCache.find(builderBusId);
- if (finder == m_builderDataCache.end())
- {
- return true;
- }
- return finder->second.m_isDirty;
- }
-};
-
AssetProcessorManager_Test::AssetProcessorManager_Test(AssetProcessor::PlatformConfiguration* config, QObject* parent /*= 0*/)
:AssetProcessorManager(config, parent)
{
@@ -3839,632 +3737,6 @@ TEST_F(AssetProcessorManagerTest, SourceFileProcessFailure_ClearsFingerprint)
ASSERT_EQ(source.m_analysisFingerprint, "");
}
-void ModtimeScanningTest::SetUp()
-{
- AssetProcessorManagerTest::SetUp();
-
- m_data = AZStd::make_unique();
-
- // We don't want the mock application manager to provide builder descriptors, mockBuilderInfoHandler will provide our own
- m_mockApplicationManager->BusDisconnect();
-
- m_data->m_mockBuilderInfoHandler.m_builderDesc = m_data->m_mockBuilderInfoHandler.CreateBuilderDesc("test builder", "{DF09DDC0-FD22-43B6-9E22-22C8574A6E1E}", { AssetBuilderSDK::AssetBuilderPattern("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard) });
- m_data->m_mockBuilderInfoHandler.BusConnect();
-
- ASSERT_TRUE(m_mockApplicationManager->GetBuilderByID("txt files", m_data->m_builderTxtBuilder));
-
- // Run this twice so the test builder doesn't get counted as a "new" builder and bypass the modtime skipping
- m_assetProcessorManager->ComputeBuilderDirty();
- m_assetProcessorManager->ComputeBuilderDirty();
-
- auto assetConnection = QObject::connect(m_assetProcessorManager.get(), &AssetProcessorManager::AssetToProcess, [this](JobDetails details)
- {
- m_data->m_processResults.push_back(AZStd::move(details));
- });
-
- auto deletedConnection = QObject::connect(m_assetProcessorManager.get(), &AssetProcessorManager::SourceDeleted, [this](QString file)
- {
- m_data->m_deletedSources.push_back(file);
- });
-
- // Create the test file
- const auto& scanFolder = m_config->GetScanFolderAt(0);
- m_data->m_relativePathFromWatchFolder[0] = "modtimeTestFile.txt";
- m_data->m_absolutePath.push_back(QDir(scanFolder.ScanPath()).absoluteFilePath(m_data->m_relativePathFromWatchFolder[0]));
-
- m_data->m_relativePathFromWatchFolder[1] = "modtimeTestDependency.txt";
- m_data->m_absolutePath.push_back(QDir(scanFolder.ScanPath()).absoluteFilePath(m_data->m_relativePathFromWatchFolder[1]));
-
- m_data->m_relativePathFromWatchFolder[2] = "modtimeTestDependency.txt.assetinfo";
- m_data->m_absolutePath.push_back(QDir(scanFolder.ScanPath()).absoluteFilePath(m_data->m_relativePathFromWatchFolder[2]));
-
- for (const auto& path : m_data->m_absolutePath)
- {
- ASSERT_TRUE(UnitTestUtils::CreateDummyFile(path, ""));
- }
-
- m_data->m_mockBuilderInfoHandler.m_dependencyFilePath = m_data->m_absolutePath[1].toUtf8().data();
-
- // Add file to database with no modtime
- {
- AssetDatabaseConnection connection;
- ASSERT_TRUE(connection.OpenDatabase());
- AzToolsFramework::AssetDatabase::FileDatabaseEntry fileEntry;
- fileEntry.m_fileName = m_data->m_relativePathFromWatchFolder[0].toUtf8().data();
- fileEntry.m_modTime = 0;
- fileEntry.m_isFolder = false;
- fileEntry.m_scanFolderPK = scanFolder.ScanFolderID();
-
- bool entryAlreadyExists;
- ASSERT_TRUE(connection.InsertFile(fileEntry, entryAlreadyExists));
- ASSERT_FALSE(entryAlreadyExists);
-
- fileEntry.m_fileID = AzToolsFramework::AssetDatabase::InvalidEntryId; // Reset the id so we make a new entry
- fileEntry.m_fileName = m_data->m_relativePathFromWatchFolder[1].toUtf8().data();
- ASSERT_TRUE(connection.InsertFile(fileEntry, entryAlreadyExists));
- ASSERT_FALSE(entryAlreadyExists);
-
- fileEntry.m_fileID = AzToolsFramework::AssetDatabase::InvalidEntryId; // Reset the id so we make a new entry
- fileEntry.m_fileName = m_data->m_relativePathFromWatchFolder[2].toUtf8().data();
- ASSERT_TRUE(connection.InsertFile(fileEntry, entryAlreadyExists));
- ASSERT_FALSE(entryAlreadyExists);
- }
-
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- ASSERT_TRUE(BlockUntilIdle(5000));
- ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 2);
- ASSERT_EQ(m_data->m_processResults.size(), 2);
- ASSERT_EQ(m_data->m_deletedSources.size(), 0);
-
- ProcessAssetJobs();
-
- m_data->m_processResults.clear();
- m_data->m_mockBuilderInfoHandler.m_createJobsCount = 0;
-
- m_isIdling = false;
-}
-
-void ModtimeScanningTest::TearDown()
-{
- m_data = nullptr;
-
- AssetProcessorManagerTest::TearDown();
-}
-
-void ModtimeScanningTest::ProcessAssetJobs()
-{
- m_data->m_productPaths.clear();
-
- for (const auto& processResult : m_data->m_processResults)
- {
- auto file = QDir(processResult.m_destinationPath).absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName.toLower() + ".arc1");
- m_data->m_productPaths.emplace(
- QDir(processResult.m_jobEntry.m_watchFolderPath)
- .absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName)
- .toUtf8()
- .constData(),
- file);
-
- // Create the file on disk
- ASSERT_TRUE(UnitTestUtils::CreateDummyFile(file, "products."));
-
- AssetBuilderSDK::ProcessJobResponse response;
- response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
- response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(file.toUtf8().constData(), AZ::Uuid::CreateNull(), 1));
-
- QMetaObject::invokeMethod(m_assetProcessorManager.get(), "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResult.m_jobEntry), Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
- }
-
- ASSERT_TRUE(BlockUntilIdle(5000));
-
- m_isIdling = false;
-}
-
-void ModtimeScanningTest::SimulateAssetScanner(QSet filePaths)
-{
- QMetaObject::invokeMethod(m_assetProcessorManager.get(), "OnAssetScannerStatusChange", Qt::QueuedConnection, Q_ARG(AssetProcessor::AssetScanningStatus, AssetProcessor::AssetScanningStatus::Started));
- QMetaObject::invokeMethod(m_assetProcessorManager.get(), "AssessFilesFromScanner", Qt::QueuedConnection, Q_ARG(QSet, filePaths));
- QMetaObject::invokeMethod(m_assetProcessorManager.get(), "OnAssetScannerStatusChange", Qt::QueuedConnection, Q_ARG(AssetProcessor::AssetScanningStatus, AssetProcessor::AssetScanningStatus::Completed));
-}
-
-QSet ModtimeScanningTest::BuildFileSet()
-{
- QSet filePaths;
-
- for (const auto& path : m_data->m_absolutePath)
- {
- QFileInfo fileInfo(path);
- auto modtime = fileInfo.lastModified();
- AZ::u64 fileSize = fileInfo.size();
- filePaths.insert(AssetFileInfo(path, modtime, fileSize, m_config->GetScanFolderForFile(path), false));
- }
-
- return filePaths;
-}
-
-void ModtimeScanningTest::ExpectWork(int createJobs, int processJobs)
-{
- ASSERT_TRUE(BlockUntilIdle(5000));
-
- EXPECT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, createJobs);
- EXPECT_EQ(m_data->m_processResults.size(), processJobs);
- EXPECT_FALSE(m_data->m_processResults[0].m_autoFail);
- EXPECT_FALSE(m_data->m_processResults[1].m_autoFail);
- EXPECT_EQ(m_data->m_deletedSources.size(), 0);
-
- m_isIdling = false;
-}
-
-void ModtimeScanningTest::ExpectNoWork()
-{
- // Since there's no work to do, the idle event isn't going to trigger, just process events a couple times
- for (int i = 0; i < 10; ++i)
- {
- QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
- }
-
- ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 0);
- ASSERT_EQ(m_data->m_processResults.size(), 0);
- ASSERT_EQ(m_data->m_deletedSources.size(), 0);
-
- m_isIdling = false;
-}
-
-void ModtimeScanningTest::SetFileContents(QString filePath, QString contents)
-{
- QFile file(filePath);
- file.open(QIODevice::WriteOnly | QIODevice::Truncate);
- file.write(contents.toUtf8().constData());
- file.close();
-}
-
-TEST_F(ModtimeScanningTest, ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping)
-{
- using namespace AzToolsFramework::AssetSystem;
-
- // Make sure modtime skipping is disabled
- // We're just going to do 1 quick sanity test to make sure the files are still processed when modtime skipping is turned off
- m_assetProcessorManager->m_allowModtimeSkippingFeature = false;
-
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- // 2 create jobs but 0 process jobs because the file has already been processed before in SetUp
- ExpectWork(2, 0);
-}
-
-TEST_F(ModtimeScanningTest, ModtimeSkipping_FileUnchanged)
-{
- using namespace AzToolsFramework::AssetSystem;
-
- // Enable the features we're testing
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
- AssetUtilities::SetUseFileHashOverride(true, true);
-
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- ExpectNoWork();
-}
-
-TEST_F(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform)
-{
- using namespace AzToolsFramework::AssetSystem;
-
- // Enable the features we're testing
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
- AssetUtilities::SetUseFileHashOverride(true, true);
-
- // Enable android platform after the initial SetUp has already processed the files for pc
- QDir tempPath(m_tempDir.path());
- AssetBuilderSDK::PlatformInfo androidPlatform("android", { "host", "renderer" });
- m_config->EnablePlatform(androidPlatform, true);
-
- // There's no way to remove scanfolders and adding a new one after enabling the platform will cause the pc assets to build as well, which we don't want
- // Instead we'll just const cast the vector and modify the enabled platforms for the scanfolder
- auto& platforms = const_cast&>(m_config->GetScanFolderAt(0).GetPlatforms());
- platforms.push_back(androidPlatform);
-
- // We need the builder fingerprints to be updated to reflect the newly enabled platform
- m_assetProcessorManager->ComputeBuilderDirty();
-
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- ExpectWork(4, 2); // CreateJobs = 4, 2 files * 2 platforms. ProcessJobs = 2, just the android platform jobs (pc is already processed)
-
- ASSERT_TRUE(m_data->m_processResults[0].m_destinationPath.contains("android"));
- ASSERT_TRUE(m_data->m_processResults[1].m_destinationPath.contains("android"));
-}
-
-TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyTimestamp)
-{
- // Update the timestamp on a file without changing its contents
- // This should not cause any job to run since the hash of the file is the same before/after
- // Additionally, the timestamp stored in the database should be updated
- using namespace AzToolsFramework::AssetSystem;
-
- uint64_t timestamp = 1594923423;
-
- QString databaseName, scanfolderName;
- m_config->ConvertToRelativePath(m_data->m_absolutePath[1], databaseName, scanfolderName);
- auto* scanFolder = m_config->GetScanFolderForFile(m_data->m_absolutePath[1]);
-
- AzToolsFramework::AssetDatabase::FileDatabaseEntry fileEntry;
-
- m_assetProcessorManager.get()->m_stateData->GetFileByFileNameAndScanFolderId(databaseName, scanFolder->ScanFolderID(), fileEntry);
-
- ASSERT_NE(fileEntry.m_modTime, timestamp);
- uint64_t existingTimestamp = fileEntry.m_modTime;
-
- // Modify the timestamp on just one file
- AzToolsFramework::ToolsFileUtils::SetModificationTime(m_data->m_absolutePath[1].toUtf8().data(), timestamp);
-
- // Enable the features we're testing
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
- AssetUtilities::SetUseFileHashOverride(true, true);
-
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- ExpectNoWork();
-
- m_assetProcessorManager.get()->m_stateData->GetFileByFileNameAndScanFolderId(databaseName, scanFolder->ScanFolderID(), fileEntry);
-
- // The timestamp should be updated even though nothing processed
- ASSERT_NE(fileEntry.m_modTime, existingTimestamp);
-}
-
-TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyTimestampNoHashing_ProcessesFile)
-{
- // Update the timestamp on a file without changing its contents
- // This should not cause any job to run since the hash of the file is the same before/after
- // Additionally, the timestamp stored in the database should be updated
- using namespace AzToolsFramework::AssetSystem;
-
- uint64_t timestamp = 1594923423;
-
- // Modify the timestamp on just one file
- AzToolsFramework::ToolsFileUtils::SetModificationTime(m_data->m_absolutePath[1].toUtf8().data(), timestamp);
-
- // Enable the features we're testing
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
- AssetUtilities::SetUseFileHashOverride(true, false);
-
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- ExpectWork(2, 2);
-}
-
-TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyFile)
-{
- using namespace AzToolsFramework::AssetSystem;
-
- SetFileContents(m_data->m_absolutePath[1].toUtf8().constData(), "hello world");
-
- // Enable the features we're testing
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
- AssetUtilities::SetUseFileHashOverride(true, true);
-
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- // Even though we're only updating one file, we're expecting 2 createJob calls because our test file is a dependency that triggers the other test file to process as well
- ExpectWork(2, 2);
-}
-
-TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyFile_AndThenRevert_ProcessesAgain)
-{
- using namespace AzToolsFramework::AssetSystem;
- auto theFile = m_data->m_absolutePath[1].toUtf8();
- const char* theFileString = theFile.constData();
-
- SetFileContents(theFileString, "hello world");
-
- // Enable the features we're testing
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
- AssetUtilities::SetUseFileHashOverride(true, true);
-
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- // Even though we're only updating one file, we're expecting 2 createJob calls because our test file is a dependency that triggers the other test file to process as well
- ExpectWork(2, 2);
- ProcessAssetJobs();
-
- m_data->m_mockBuilderInfoHandler.m_createJobsCount = 0;
- m_data->m_processResults.clear();
- m_data->m_deletedSources.clear();
-
- SetFileContents(theFileString, "");
-
- filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- // Expect processing to happen again
- ExpectWork(2, 2);
-}
-
-struct LockedFileTest
- : ModtimeScanningTest
- , AssetProcessor::ConnectionBus::Handler
-{
- MOCK_METHOD3(SendRaw, size_t (unsigned, unsigned, const QByteArray&));
- MOCK_METHOD3(SendPerPlatform, size_t (unsigned, const AzFramework::AssetSystem::BaseAssetProcessorMessage&, const QString&));
- MOCK_METHOD4(SendRawPerPlatform, size_t (unsigned, unsigned, const QByteArray&, const QString&));
- MOCK_METHOD2(SendRequest, unsigned (const AzFramework::AssetSystem::BaseAssetProcessorMessage&, const ResponseCallback&));
- MOCK_METHOD2(SendResponse, size_t (unsigned, const AzFramework::AssetSystem::BaseAssetProcessorMessage&));
- MOCK_METHOD1(RemoveResponseHandler, void (unsigned));
-
- size_t Send(unsigned, const AzFramework::AssetSystem::BaseAssetProcessorMessage& message) override
- {
- using SourceFileNotificationMessage = AzToolsFramework::AssetSystem::SourceFileNotificationMessage;
- switch (message.GetMessageType())
- {
- case SourceFileNotificationMessage::MessageType:
- if (const auto sourceFileMessage = azrtti_cast(&message); sourceFileMessage != nullptr &&
- sourceFileMessage->m_type == SourceFileNotificationMessage::NotificationType::FileRemoved)
- {
- // The File Remove message will occur before an attempt to delete the file
- // Wait for more than 1 File Remove message.
- // This indicates the AP has attempted to delete the file once, failed to do so and is now retrying
- ++m_deleteCounter;
-
- if(m_deleteCounter > 1 && m_callback)
- {
- m_callback();
- m_callback = {}; // Unset it to be safe, we only intend to run the callback once
- }
- }
- break;
- default:
- break;
- }
-
- return 0;
- }
-
- void SetUp() override
- {
- ModtimeScanningTest::SetUp();
-
- ConnectionBus::Handler::BusConnect(0);
- }
-
- void TearDown() override
- {
- ConnectionBus::Handler::BusDisconnect();
-
- ModtimeScanningTest::TearDown();
- }
-
- AZStd::atomic_int m_deleteCounter{ 0 };
- AZStd::function m_callback;
-};
-
-TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeleteFails)
-{
- auto theFile = m_data->m_absolutePath[1].toUtf8();
- const char* theFileString = theFile.constData();
- auto [sourcePath, productPath] = *m_data->m_productPaths.find(theFileString);
-
- {
- QFile file(theFileString);
- file.remove();
- }
-
- ASSERT_GT(m_data->m_productPaths.size(), 0);
- QFile product(productPath);
-
- ASSERT_TRUE(product.open(QIODevice::ReadOnly));
-
- // Check if we can delete the file now, if we can't, proceed with the test
- // If we can, it means the OS running this test doesn't lock open files so there's nothing to test
- if (!AZ::IO::SystemFile::Delete(productPath.toUtf8().constData()))
- {
- QMetaObject::invokeMethod(
- m_assetProcessorManager.get(), "AssessDeletedFile", Qt::QueuedConnection, Q_ARG(QString, QString(theFileString)));
-
- EXPECT_TRUE(BlockUntilIdle(5000));
-
- EXPECT_TRUE(QFile::exists(productPath));
- EXPECT_EQ(m_data->m_deletedSources.size(), 0);
- }
- else
- {
- SUCCEED() << "Skipping test. OS does not lock open files.";
- }
-}
-
-TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeletesWhenReleased)
-{
- // This test is intended to verify the AP will successfully retry deleting a source asset
- // when one of its product assets is locked temporarily
- // We'll lock the file by holding it open
-
- auto theFile = m_data->m_absolutePath[1].toUtf8();
- const char* theFileString = theFile.constData();
- auto [sourcePath, productPath] = *m_data->m_productPaths.find(theFileString);
-
- {
- QFile file(theFileString);
- file.remove();
- }
-
- ASSERT_GT(m_data->m_productPaths.size(), 0);
- QFile product(productPath);
-
- // Open the file and keep it open to lock it
- // We'll start a thread later to unlock the file
- // This will allow us to test how AP handles trying to delete a locked file
- ASSERT_TRUE(product.open(QIODevice::ReadOnly));
-
- // Check if we can delete the file now, if we can't, proceed with the test
- // If we can, it means the OS running this test doesn't lock open files so there's nothing to test
- if (!AZ::IO::SystemFile::Delete(productPath.toUtf8().constData()))
- {
- m_deleteCounter = 0;
-
- // Set up a callback which will fire after at least 1 retry
- // Unlock the file at that point so AP can successfully delete it
- m_callback = [&product]()
- {
- product.close();
- };
-
- QMetaObject::invokeMethod(
- m_assetProcessorManager.get(), "AssessDeletedFile", Qt::QueuedConnection, Q_ARG(QString, QString(theFileString)));
-
- EXPECT_TRUE(BlockUntilIdle(5000));
-
- EXPECT_FALSE(QFile::exists(productPath));
- EXPECT_EQ(m_data->m_deletedSources.size(), 1);
-
- EXPECT_GT(m_deleteCounter, 1); // Make sure the AP tried more than once to delete the file
- m_errorAbsorber->ExpectAsserts(0);
- }
- else
- {
- SUCCEED() << "Skipping test. OS does not lock open files.";
- }
-}
-
-TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyFilesSameHash_BothProcess)
-{
- using namespace AzToolsFramework::AssetSystem;
-
- SetFileContents(m_data->m_absolutePath[1].toUtf8().constData(), "hello world");
-
- // Enable the features we're testing
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
- AssetUtilities::SetUseFileHashOverride(true, true);
-
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- // Even though we're only updating one file, we're expecting 2 createJob calls because our test file is a dependency that triggers the other test file to process as well
- ExpectWork(2, 2);
- ProcessAssetJobs();
-
- m_data->m_mockBuilderInfoHandler.m_createJobsCount = 0;
- m_data->m_processResults.clear();
- m_data->m_deletedSources.clear();
-
- // Make file 0 have the same contents as file 1
- SetFileContents(m_data->m_absolutePath[0].toUtf8().constData(), "hello world");
-
- filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- ExpectWork(1, 1);
-}
-
-TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyMetadataFile)
-{
- using namespace AzToolsFramework::AssetSystem;
-
- SetFileContents(m_data->m_absolutePath[2].toUtf8().constData(), "hello world");
-
- // Enable the features we're testing
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
- AssetUtilities::SetUseFileHashOverride(true, true);
-
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- // Even though we're only updating one file, we're expecting 2 createJob calls because our test file is a metadata file
- // that triggers the source file which is a dependency that triggers the other test file to process as well
- ExpectWork(2, 2);
-}
-
-TEST_F(ModtimeScanningTest, ModtimeSkipping_DeleteFile)
-{
- using namespace AzToolsFramework::AssetSystem;
-
- // Enable the features we're testing
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
- AssetUtilities::SetUseFileHashOverride(true, true);
-
- ASSERT_TRUE(QFile::remove(m_data->m_absolutePath[0]));
-
- // Feed in ONLY one file (the one we didn't delete)
- QSet filePaths;
- QFileInfo fileInfo(m_data->m_absolutePath[1]);
- auto modtime = fileInfo.lastModified();
- AZ::u64 fileSize = fileInfo.size();
- filePaths.insert(AssetFileInfo(m_data->m_absolutePath[1], modtime, fileSize, &m_config->GetScanFolderAt(0), false));
-
- SimulateAssetScanner(filePaths);
-
- QElapsedTimer timer;
- timer.start();
-
- do
- {
- QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
- } while (m_data->m_deletedSources.size() < m_data->m_relativePathFromWatchFolder[0].size() && timer.elapsed() < 5000);
-
- ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 0);
- ASSERT_EQ(m_data->m_processResults.size(), 0);
- ASSERT_THAT(m_data->m_deletedSources, testing::ElementsAre(m_data->m_relativePathFromWatchFolder[0]));
-}
-
-TEST_F(ModtimeScanningTest, ReprocessRequest_FileNotModified_FileProcessed)
-{
- using namespace AzToolsFramework::AssetSystem;
-
- m_assetProcessorManager->RequestReprocess(m_data->m_absolutePath[0]);
-
- ASSERT_TRUE(BlockUntilIdle(5000));
-
- ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 1);
- ASSERT_EQ(m_data->m_processResults.size(), 1);
-}
-
-TEST_F(ModtimeScanningTest, ReprocessRequest_SourceWithDependency_BothWillProcess)
-{
- using namespace AzToolsFramework::AssetSystem;
-
- using SourceFileDependencyEntry = AzToolsFramework::AssetDatabase::SourceFileDependencyEntry;
-
- SourceFileDependencyEntry newEntry1;
- newEntry1.m_sourceDependencyID = AzToolsFramework::AssetDatabase::InvalidEntryId;
- newEntry1.m_builderGuid = AZ::Uuid::CreateRandom();
- newEntry1.m_source = m_data->m_absolutePath[0].toUtf8().constData();
- newEntry1.m_dependsOnSource = m_data->m_absolutePath[1].toUtf8().constData();
- newEntry1.m_typeOfDependency = SourceFileDependencyEntry::DEP_SourceToSource;
-
- m_assetProcessorManager->RequestReprocess(m_data->m_absolutePath[0]);
- ASSERT_TRUE(BlockUntilIdle(5000));
-
- ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 1);
- ASSERT_EQ(m_data->m_processResults.size(), 1);
-
- m_assetProcessorManager->RequestReprocess(m_data->m_absolutePath[1]);
- ASSERT_TRUE(BlockUntilIdle(5000));
-
- ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 3);
- ASSERT_EQ(m_data->m_processResults.size(), 3);
-}
-
-TEST_F(ModtimeScanningTest, ReprocessRequest_RequestFolder_SourceAssetsWillProcess)
-{
- using namespace AzToolsFramework::AssetSystem;
-
- const auto& scanFolder = m_config->GetScanFolderAt(0);
-
- QString scanPath = scanFolder.ScanPath();
- m_assetProcessorManager->RequestReprocess(scanPath);
- ASSERT_TRUE(BlockUntilIdle(5000));
-
- // two text files are source assets, assetinfo is not
- ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 2);
- ASSERT_EQ(m_data->m_processResults.size(), 2);
-}
-
//////////////////////////////////////////////////////////////////////////
MockBuilderInfoHandler::~MockBuilderInfoHandler()
@@ -5205,130 +4477,7 @@ TEST_F(ChainJobDependencyTest, TestChainDependency_Multi)
}
}
-void DeleteTest::SetUp()
-{
- AssetProcessorManagerTest::SetUp();
- m_data = AZStd::make_unique();
-
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
-
- // We don't want the mock application manager to provide builder descriptors, mockBuilderInfoHandler will provide our own
- m_mockApplicationManager->BusDisconnect();
-
- m_data->m_mockBuilderInfoHandler.m_builderDesc = m_data->m_mockBuilderInfoHandler.CreateBuilderDesc("test builder", "{DF09DDC0-FD22-43B6-9E22-22C8574A6E1E}", { AssetBuilderSDK::AssetBuilderPattern("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard) });
- m_data->m_mockBuilderInfoHandler.BusConnect();
-
- ASSERT_TRUE(m_mockApplicationManager->GetBuilderByID("txt files", m_data->m_builderTxtBuilder));
-
- // Run this twice so the test builder doesn't get counted as a "new" builder and bypass the modtime skipping
- m_assetProcessorManager->ComputeBuilderDirty();
- m_assetProcessorManager->ComputeBuilderDirty();
-
- auto setupConnectionsFunc = [this]()
- {
- QObject::connect(m_assetProcessorManager.get(), &AssetProcessorManager::AssetToProcess, [this](JobDetails details)
- {
- m_data->m_processResults.push_back(AZStd::move(details));
- });
-
- QObject::connect(m_assetProcessorManager.get(), &AssetProcessorManager::SourceDeleted, [this](QString file)
- {
- m_data->m_deletedSources.push_back(file);
- });
- };
-
- auto createFileAndAddToDatabaseFunc = [this](const AssetProcessor::ScanFolderInfo* scanFolder, QString file)
- {
- using namespace AzToolsFramework::AssetDatabase;
-
- QString watchFolderPath = scanFolder->ScanPath();
- QString absPath(QDir(watchFolderPath).absoluteFilePath(file));
- UnitTestUtils::CreateDummyFile(absPath);
-
- m_data->m_absolutePath.push_back(absPath);
-
- AzToolsFramework::AssetDatabase::FileDatabaseEntry fileEntry;
- fileEntry.m_fileName = file.toUtf8().constData();
- fileEntry.m_modTime = 0;
- fileEntry.m_isFolder = false;
- fileEntry.m_scanFolderPK = scanFolder->ScanFolderID();
-
- bool entryAlreadyExists;
- ASSERT_TRUE(m_assetProcessorManager->m_stateData->InsertFile(fileEntry, entryAlreadyExists));
- ASSERT_FALSE(entryAlreadyExists);
- };
-
- setupConnectionsFunc();
-
- // Create test files
- QDir tempPath(m_tempDir.path());
- const auto* scanFolder1 = m_config->GetScanFolderByPath(tempPath.absoluteFilePath("subfolder1"));
- const auto* scanFolder4 = m_config->GetScanFolderByPath(tempPath.absoluteFilePath("subfolder4"));
-
- createFileAndAddToDatabaseFunc(scanFolder1, QString("textures/a.txt"));
- createFileAndAddToDatabaseFunc(scanFolder4, QString("textures/b.txt"));
-
- // Run the test files through AP all the way to processing stage
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- ASSERT_TRUE(BlockUntilIdle(5000));
- ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 2);
- ASSERT_EQ(m_data->m_processResults.size(), 2);
- ASSERT_EQ(m_data->m_deletedSources.size(), 0);
-
- ProcessAssetJobs();
-
- m_data->m_processResults.clear();
- m_data->m_mockBuilderInfoHandler.m_createJobsCount = 0;
-
- // Reboot the APM since we added stuff to the database that needs to be loaded on-startup of the APM
- m_assetProcessorManager.reset(new AssetProcessorManager_Test(m_config.get()));
-
- m_idleConnection = QObject::connect(m_assetProcessorManager.get(), &AssetProcessor::AssetProcessorManager::AssetProcessorManagerIdleState, [this](bool newState)
- {
- m_isIdling = newState;
- });
-
- setupConnectionsFunc();
-
- m_assetProcessorManager->ComputeBuilderDirty();
-}
-
-TEST_F(DeleteTest, DeleteFolderSharedAcrossTwoScanFolders_CorrectFileAndFolderAreDeletedFromCache)
-{
- // There was a bug where AP wasn't repopulating the "known folders" list when modtime skipping was enabled and no work was needed
- // As a result, deleting a folder didn't count as a "folder", so the wrong code path was taken. This test makes sure the correct deletion events fire
-
- using namespace AzToolsFramework::AssetSystem;
-
- // Modtime skipping has to be on for this
- m_assetProcessorManager->m_allowModtimeSkippingFeature = true;
-
- // Feed in the files from the asset scanner, no jobs should run since they're already up-to-date
- QSet filePaths = BuildFileSet();
- SimulateAssetScanner(filePaths);
-
- ExpectNoWork();
-
- // Delete one of the folders
- QDir tempPath(m_tempDir.path());
- QString absPath(tempPath.absoluteFilePath("subfolder1/textures"));
- QDir(absPath).removeRecursively();
-
- AZStd::vector deletedFolders;
- QObject::connect(m_assetProcessorManager.get(), &AssetProcessorManager::SourceFolderDeleted, [&deletedFolders](QString file)
- {
- deletedFolders.push_back(file.toUtf8().constData());
- });
-
- m_assetProcessorManager->AssessDeletedFile(absPath);
- ASSERT_TRUE(BlockUntilIdle(5000));
-
- ASSERT_THAT(m_data->m_deletedSources, testing::UnorderedElementsAre("textures/a.txt"));
- ASSERT_THAT(deletedFolders, testing::UnorderedElementsAre("textures"));
-}
void DuplicateProcessTest::SetUp()
{
diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h
index c532b08016..4e644ea457 100644
--- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h
+++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h
@@ -37,6 +37,114 @@ public:
MOCK_METHOD1(GetAssetDatabaseLocation, bool(AZStd::string&));
};
+class AssetProcessorManager_Test : public AssetProcessor::AssetProcessorManager
+{
+public:
+ friend class GTEST_TEST_CLASS_NAME_(
+ AssetProcessorManagerTest, AssetProcessedImpl_DifferentProductDependenciesPerProduct_SavesCorrectlyToDatabase);
+
+ friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies);
+ friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_DeferredResolution);
+ friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, SameFilenameForAllPlatforms);
+
+ friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_SourcePath);
+
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, DeleteFolder_SignalsDeleteOfContainedFiles);
+
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_BasicTest);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_WithDifferentTypes_BasicTest);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_Reverse_BasicTest);
+ friend class GTEST_TEST_CLASS_NAME_(
+ AssetProcessorManagerTest, QueryAbsolutePathDependenciesRecursive_MissingFiles_ReturnsNoPathWithPlaceholders);
+
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_BeforeComputingDirtiness_AllDirty);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_EmptyDatabase_AllDirty);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_SameAsLastTime_NoneDirty);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_MoreThanLastTime_NewOneIsDirty);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_FewerThanLastTime_Dirty);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_ChangedPattern_CountsAsNew);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_ChangedPatternType_CountsAsNew);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_NewPattern_CountsAsNewBuilder);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_NewVersionNumber_IsNotANewBuilder);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, BuilderDirtiness_NewAnalysisFingerprint_IsNotANewBuilder);
+
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_BasicTest);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_UpdateTest);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_MissingFiles_ByUuid);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_MissingFiles_ByName);
+ friend class GTEST_TEST_CLASS_NAME_(
+ AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_MissingFiles_ByUuid_UpdatesWhenTheyAppear);
+ friend class GTEST_TEST_CLASS_NAME_(
+ AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_MissingFiles_ByName_UpdatesWhenTheyAppear);
+ friend class GTEST_TEST_CLASS_NAME_(
+ AssetProcessorManagerTest, UpdateSourceFileDependenciesDatabase_WildcardMissingFiles_ByName_UpdatesWhenTheyAppear);
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, JobDependencyOrderOnce_MultipleJobs_EmitOK);
+
+ friend class GTEST_TEST_CLASS_NAME_(AssetProcessorManagerTest, SourceFileProcessFailure_ClearsFingerprint);
+
+ friend class GTEST_TEST_CLASS_NAME_(
+ AbsolutePathProductDependencyTest, UnresolvedProductPathDependency_AssetProcessedTwice_DoesNotDuplicateDependency);
+ friend class GTEST_TEST_CLASS_NAME_(
+ AbsolutePathProductDependencyTest, AbsolutePathProductDependency_RetryDeferredDependenciesWithMatchingSource_DependencyResolves);
+ friend class GTEST_TEST_CLASS_NAME_(
+ AbsolutePathProductDependencyTest, UnresolvedProductPathDependency_AssetProcessedTwice_ValidatePathDependenciesMap);
+ friend class GTEST_TEST_CLASS_NAME_(
+ AbsolutePathProductDependencyTest,
+ UnresolvedSourceFileTypeProductPathDependency_DependencyHasNoProductOutput_ValidatePathDependenciesMap);
+
+ friend class GTEST_TEST_CLASS_NAME_(DeleteTest, DeleteFolderSharedAcrossTwoScanFolders_CorrectFileAndFolderAreDeletedFromCache);
+ friend class GTEST_TEST_CLASS_NAME_(MetadataFileTest, MetadataFile_SourceFileExtensionDifferentCase);
+
+ friend class AssetProcessorManagerTest;
+ friend struct JobDependencyTest;
+ friend struct ChainJobDependencyTest;
+ friend struct DeleteTest;
+ friend struct PathDependencyTest;
+ friend struct DuplicateProductsTest;
+ friend struct DuplicateProcessTest;
+ friend struct AbsolutePathProductDependencyTest;
+ friend struct WildcardSourceDependencyTest;
+
+ explicit AssetProcessorManager_Test(AssetProcessor::PlatformConfiguration* config, QObject* parent = nullptr);
+ ~AssetProcessorManager_Test() override;
+
+ bool CheckJobKeyToJobRunKeyMap(AZStd::string jobKey);
+
+ int CountDirtyBuilders() const
+ {
+ int numDirty = 0;
+ for (const auto& element : m_builderDataCache)
+ {
+ if (element.second.m_isDirty)
+ {
+ ++numDirty;
+ }
+ }
+ return numDirty;
+ }
+
+ bool IsBuilderDirty(const AZ::Uuid& builderBusId) const
+ {
+ auto finder = m_builderDataCache.find(builderBusId);
+ if (finder == m_builderDataCache.end())
+ {
+ return true;
+ }
+ return finder->second.m_isDirty;
+ }
+
+ void RecomputeDirtyBuilders()
+ {
+ // Run this twice so the test builder doesn't get counted as a "new" builder and bypass the modtime skipping
+ ComputeBuilderDirty();
+ ComputeBuilderDirty();
+ }
+
+ using AssetProcessorManager::m_stateData;
+ using AssetProcessorManager::ComputeBuilderDirty;
+};
+
+
class AssetProcessorManagerTest
: public AssetProcessor::AssetProcessorTest
{
@@ -165,33 +273,6 @@ struct MockBuilderInfoHandler
int m_createJobsCount = 0;
};
-struct ModtimeScanningTest
- : public AssetProcessorManagerTest
-{
- void SetUp() override;
- void TearDown() override;
-
- void ProcessAssetJobs();
- void SimulateAssetScanner(QSet filePaths);
- QSet BuildFileSet();
- void ExpectWork(int createJobs, int processJobs);
- void ExpectNoWork();
- void SetFileContents(QString filePath, QString contents);
-
- struct StaticData
- {
- QString m_relativePathFromWatchFolder[3];
- AZStd::vector m_absolutePath;
- AZStd::vector m_processResults;
- AZStd::unordered_multimap m_productPaths;
- AZStd::vector m_deletedSources;
- AZStd::shared_ptr m_builderTxtBuilder;
- MockBuilderInfoHandler m_mockBuilderInfoHandler;
- };
-
- AZStd::unique_ptr m_data;
-};
-
struct MetadataFileTest
: public AssetProcessorManagerTest
@@ -274,9 +355,3 @@ struct DuplicateProductsTest
{
void SetupDuplicateProductsTest(QString& sourceFile, QDir& tempPath, QString& productFile, AZStd::vector& jobDetails, AssetBuilderSDK::ProcessJobResponse& response, bool multipleOutputs, QString extension);
};
-
-struct DeleteTest
- : public ModtimeScanningTest
-{
- void SetUp() override;
-};
diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/ModtimeScanningTests.cpp b/Code/Tools/AssetProcessor/native/tests/assetmanager/ModtimeScanningTests.cpp
new file mode 100644
index 0000000000..6b3124ca00
--- /dev/null
+++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/ModtimeScanningTests.cpp
@@ -0,0 +1,706 @@
+/*
+ * 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 UnitTests
+{
+ using AssetFileInfo = AssetProcessor::AssetFileInfo;
+
+ void ModtimeScanningTest::SetUpAssetProcessorManager()
+ {
+ using namespace AssetProcessor;
+
+ m_assetProcessorManager->SetEnableModtimeSkippingFeature(true);
+ m_assetProcessorManager->RecomputeDirtyBuilders();
+
+ QObject::connect(
+ m_assetProcessorManager.get(), &AssetProcessorManager::AssetToProcess,
+ [this](JobDetails details)
+ {
+ m_data->m_processResults.push_back(AZStd::move(details));
+ });
+
+ QObject::connect(
+ m_assetProcessorManager.get(), &AssetProcessorManager::SourceDeleted,
+ [this](QString file)
+ {
+ m_data->m_deletedSources.push_back(file);
+ });
+
+ m_idleConnection = QObject::connect(
+ m_assetProcessorManager.get(), &AssetProcessor::AssetProcessorManager::AssetProcessorManagerIdleState,
+ [this](bool newState)
+ {
+ m_isIdling = newState;
+ });
+ }
+
+ void ModtimeScanningTest::SetUp()
+ {
+ using namespace AssetProcessor;
+
+ AssetProcessorManagerTest::SetUp();
+
+ m_data = AZStd::make_unique();
+
+ // We don't want the mock application manager to provide builder descriptors, mockBuilderInfoHandler will provide our own
+ m_mockApplicationManager->BusDisconnect();
+
+ m_data->m_mockBuilderInfoHandler.m_builderDesc = m_data->m_mockBuilderInfoHandler.CreateBuilderDesc(
+ "test builder", "{DF09DDC0-FD22-43B6-9E22-22C8574A6E1E}",
+ { AssetBuilderSDK::AssetBuilderPattern("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard) });
+ m_data->m_mockBuilderInfoHandler.BusConnect();
+
+ ASSERT_TRUE(m_mockApplicationManager->GetBuilderByID("txt files", m_data->m_builderTxtBuilder));
+
+ SetUpAssetProcessorManager();
+
+ // Create the test file
+ const auto& scanFolder = m_config->GetScanFolderAt(0);
+ m_data->m_relativePathFromWatchFolder[0] = "modtimeTestFile.txt";
+ m_data->m_absolutePath.push_back(QDir(scanFolder.ScanPath()).absoluteFilePath(m_data->m_relativePathFromWatchFolder[0]));
+
+ m_data->m_relativePathFromWatchFolder[1] = "modtimeTestDependency.txt";
+ m_data->m_absolutePath.push_back(QDir(scanFolder.ScanPath()).absoluteFilePath(m_data->m_relativePathFromWatchFolder[1]));
+
+ m_data->m_relativePathFromWatchFolder[2] = "modtimeTestDependency.txt.assetinfo";
+ m_data->m_absolutePath.push_back(QDir(scanFolder.ScanPath()).absoluteFilePath(m_data->m_relativePathFromWatchFolder[2]));
+
+ for (const auto& path : m_data->m_absolutePath)
+ {
+ ASSERT_TRUE(UnitTestUtils::CreateDummyFile(path, ""));
+ }
+
+ m_data->m_mockBuilderInfoHandler.m_dependencyFilePath = m_data->m_absolutePath[1].toUtf8().data();
+
+ // Add file to database with no modtime
+ {
+ AssetDatabaseConnection connection;
+ ASSERT_TRUE(connection.OpenDatabase());
+ AzToolsFramework::AssetDatabase::FileDatabaseEntry fileEntry;
+ fileEntry.m_fileName = m_data->m_relativePathFromWatchFolder[0].toUtf8().data();
+ fileEntry.m_modTime = 0;
+ fileEntry.m_isFolder = false;
+ fileEntry.m_scanFolderPK = scanFolder.ScanFolderID();
+
+ bool entryAlreadyExists;
+ ASSERT_TRUE(connection.InsertFile(fileEntry, entryAlreadyExists));
+ ASSERT_FALSE(entryAlreadyExists);
+
+ fileEntry.m_fileID = AzToolsFramework::AssetDatabase::InvalidEntryId; // Reset the id so we make a new entry
+ fileEntry.m_fileName = m_data->m_relativePathFromWatchFolder[1].toUtf8().data();
+ ASSERT_TRUE(connection.InsertFile(fileEntry, entryAlreadyExists));
+ ASSERT_FALSE(entryAlreadyExists);
+
+ fileEntry.m_fileID = AzToolsFramework::AssetDatabase::InvalidEntryId; // Reset the id so we make a new entry
+ fileEntry.m_fileName = m_data->m_relativePathFromWatchFolder[2].toUtf8().data();
+ ASSERT_TRUE(connection.InsertFile(fileEntry, entryAlreadyExists));
+ ASSERT_FALSE(entryAlreadyExists);
+ }
+
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ ASSERT_TRUE(BlockUntilIdle(5000));
+ ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 2);
+ ASSERT_EQ(m_data->m_processResults.size(), 2);
+ ASSERT_EQ(m_data->m_deletedSources.size(), 0);
+
+ ProcessAssetJobs();
+
+ m_data->m_processResults.clear();
+ m_data->m_mockBuilderInfoHandler.m_createJobsCount = 0;
+
+ m_isIdling = false;
+ }
+
+ void ModtimeScanningTest::TearDown()
+ {
+ m_data = nullptr;
+
+ AssetProcessorManagerTest::TearDown();
+ }
+
+ void ModtimeScanningTest::ProcessAssetJobs()
+ {
+ m_data->m_productPaths.clear();
+
+ for (const auto& processResult : m_data->m_processResults)
+ {
+ auto file =
+ QDir(processResult.m_destinationPath).absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName.toLower() + ".arc1");
+ m_data->m_productPaths.emplace(
+ QDir(processResult.m_jobEntry.m_watchFolderPath)
+ .absoluteFilePath(processResult.m_jobEntry.m_databaseSourceName)
+ .toUtf8()
+ .constData(),
+ file);
+
+ // Create the file on disk
+ ASSERT_TRUE(UnitTestUtils::CreateDummyFile(file, "products."));
+
+ AssetBuilderSDK::ProcessJobResponse response;
+ response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
+ response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(file.toUtf8().constData(), AZ::Uuid::CreateNull(), 1));
+
+ using JobEntry = AssetProcessor::JobEntry;
+
+ QMetaObject::invokeMethod(
+ m_assetProcessorManager.get(), "AssetProcessed", Qt::QueuedConnection, Q_ARG(JobEntry, processResult.m_jobEntry),
+ Q_ARG(AssetBuilderSDK::ProcessJobResponse, response));
+ }
+
+ ASSERT_TRUE(BlockUntilIdle(5000));
+
+ m_isIdling = false;
+ }
+
+ void ModtimeScanningTest::SimulateAssetScanner(QSet filePaths)
+ {
+ QMetaObject::invokeMethod(
+ m_assetProcessorManager.get(), "OnAssetScannerStatusChange", Qt::QueuedConnection,
+ Q_ARG(AssetProcessor::AssetScanningStatus, AssetProcessor::AssetScanningStatus::Started));
+ QMetaObject::invokeMethod(
+ m_assetProcessorManager.get(), "AssessFilesFromScanner", Qt::QueuedConnection, Q_ARG(QSet, filePaths));
+ QMetaObject::invokeMethod(
+ m_assetProcessorManager.get(), "OnAssetScannerStatusChange", Qt::QueuedConnection,
+ Q_ARG(AssetProcessor::AssetScanningStatus, AssetProcessor::AssetScanningStatus::Completed));
+ }
+
+ QSet ModtimeScanningTest::BuildFileSet()
+ {
+ QSet filePaths;
+
+ for (const auto& path : m_data->m_absolutePath)
+ {
+ QFileInfo fileInfo(path);
+ auto modtime = fileInfo.lastModified();
+ AZ::u64 fileSize = fileInfo.size();
+ filePaths.insert(AssetFileInfo(path, modtime, fileSize, m_config->GetScanFolderForFile(path), false));
+ }
+
+ return filePaths;
+ }
+
+ void ModtimeScanningTest::ExpectWork(int createJobs, int processJobs)
+ {
+ ASSERT_TRUE(BlockUntilIdle(5000));
+
+ EXPECT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, createJobs);
+ EXPECT_EQ(m_data->m_processResults.size(), processJobs);
+ for (int i = 0; i < processJobs; ++i)
+ {
+ EXPECT_FALSE(m_data->m_processResults[i].m_autoFail);
+ }
+ EXPECT_EQ(m_data->m_deletedSources.size(), 0);
+
+ m_isIdling = false;
+ }
+
+ void ModtimeScanningTest::ExpectNoWork()
+ {
+ // Since there's no work to do, the idle event isn't going to trigger, just process events a couple times
+ for (int i = 0; i < 10; ++i)
+ {
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
+ }
+
+ ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 0);
+ ASSERT_EQ(m_data->m_processResults.size(), 0);
+ ASSERT_EQ(m_data->m_deletedSources.size(), 0);
+
+ m_isIdling = false;
+ }
+
+ void ModtimeScanningTest::SetFileContents(QString filePath, QString contents)
+ {
+ QFile file(filePath);
+ file.open(QIODevice::WriteOnly | QIODevice::Truncate);
+ file.write(contents.toUtf8().constData());
+ file.close();
+ }
+
+ TEST_F(ModtimeScanningTest, ModtimeSkipping_FileUnchanged_WithoutModtimeSkipping)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+
+ // Make sure modtime skipping is disabled
+ // We're just going to do 1 quick sanity test to make sure the files are still processed when modtime skipping is turned off
+ m_assetProcessorManager->SetEnableModtimeSkippingFeature(false);
+
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ // 2 create jobs but 0 process jobs because the file has already been processed before in SetUp
+ ExpectWork(2, 0);
+ }
+
+ TEST_F(ModtimeScanningTest, ModtimeSkipping_FileUnchanged)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+
+ AssetUtilities::SetUseFileHashOverride(true, true);
+
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ ExpectNoWork();
+ }
+
+ TEST_F(ModtimeScanningTest, ModtimeSkipping_EnablePlatform_ShouldProcessFilesForPlatform)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+
+ AssetUtilities::SetUseFileHashOverride(true, true);
+
+ // Enable android platform after the initial SetUp has already processed the files for pc
+ QDir tempPath(m_tempDir.path());
+ AssetBuilderSDK::PlatformInfo androidPlatform("android", { "host", "renderer" });
+ m_config->EnablePlatform(androidPlatform, true);
+
+ // There's no way to remove scanfolders and adding a new one after enabling the platform will cause the pc assets to build as well,
+ // which we don't want Instead we'll just const cast the vector and modify the enabled platforms for the scanfolder
+ auto& platforms = const_cast&>(m_config->GetScanFolderAt(0).GetPlatforms());
+ platforms.push_back(androidPlatform);
+
+ // We need the builder fingerprints to be updated to reflect the newly enabled platform
+ m_assetProcessorManager->ComputeBuilderDirty();
+
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ ExpectWork(
+ 4, 2); // CreateJobs = 4, 2 files * 2 platforms. ProcessJobs = 2, just the android platform jobs (pc is already processed)
+
+ ASSERT_TRUE(m_data->m_processResults[0].m_destinationPath.contains("android"));
+ ASSERT_TRUE(m_data->m_processResults[1].m_destinationPath.contains("android"));
+ }
+
+ TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyTimestamp)
+ {
+ // Update the timestamp on a file without changing its contents
+ // This should not cause any job to run since the hash of the file is the same before/after
+ // Additionally, the timestamp stored in the database should be updated
+ using namespace AzToolsFramework::AssetSystem;
+
+ uint64_t timestamp = 1594923423;
+
+ QString databaseName, scanfolderName;
+ m_config->ConvertToRelativePath(m_data->m_absolutePath[1], databaseName, scanfolderName);
+ auto* scanFolder = m_config->GetScanFolderForFile(m_data->m_absolutePath[1]);
+
+ AzToolsFramework::AssetDatabase::FileDatabaseEntry fileEntry;
+
+ m_assetProcessorManager->m_stateData->GetFileByFileNameAndScanFolderId(databaseName, scanFolder->ScanFolderID(), fileEntry);
+
+ ASSERT_NE(fileEntry.m_modTime, timestamp);
+ uint64_t existingTimestamp = fileEntry.m_modTime;
+
+ // Modify the timestamp on just one file
+ AzToolsFramework::ToolsFileUtils::SetModificationTime(m_data->m_absolutePath[1].toUtf8().data(), timestamp);
+
+ AssetUtilities::SetUseFileHashOverride(true, true);
+
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ ExpectNoWork();
+
+ m_assetProcessorManager->m_stateData->GetFileByFileNameAndScanFolderId(databaseName, scanFolder->ScanFolderID(), fileEntry);
+
+ // The timestamp should be updated even though nothing processed
+ ASSERT_NE(fileEntry.m_modTime, existingTimestamp);
+ }
+
+ TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyTimestampNoHashing_ProcessesFile)
+ {
+ // Update the timestamp on a file without changing its contents
+ // This should not cause any job to run since the hash of the file is the same before/after
+ // Additionally, the timestamp stored in the database should be updated
+ using namespace AzToolsFramework::AssetSystem;
+
+ uint64_t timestamp = 1594923423;
+
+ // Modify the timestamp on just one file
+ AzToolsFramework::ToolsFileUtils::SetModificationTime(m_data->m_absolutePath[1].toUtf8().data(), timestamp);
+
+ AssetUtilities::SetUseFileHashOverride(true, false);
+
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ ExpectWork(2, 2);
+ }
+
+ TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyFile)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+
+ SetFileContents(m_data->m_absolutePath[1].toUtf8().constData(), "hello world");
+
+ AssetUtilities::SetUseFileHashOverride(true, true);
+
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ // Even though we're only updating one file, we're expecting 2 createJob calls because our test file is a dependency that triggers
+ // the other test file to process as well
+ ExpectWork(2, 2);
+ }
+
+ TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyFile_AndThenRevert_ProcessesAgain)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+ auto theFile = m_data->m_absolutePath[1].toUtf8();
+ const char* theFileString = theFile.constData();
+
+ SetFileContents(theFileString, "hello world");
+
+ AssetUtilities::SetUseFileHashOverride(true, true);
+
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ // Even though we're only updating one file, we're expecting 2 createJob calls because our test file is a dependency that triggers
+ // the other test file to process as well
+ ExpectWork(2, 2);
+ ProcessAssetJobs();
+
+ m_data->m_mockBuilderInfoHandler.m_createJobsCount = 0;
+ m_data->m_processResults.clear();
+ m_data->m_deletedSources.clear();
+
+ SetFileContents(theFileString, "");
+
+ filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ // Expect processing to happen again
+ ExpectWork(2, 2);
+ }
+
+ TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyFilesSameHash_BothProcess)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+
+ SetFileContents(m_data->m_absolutePath[1].toUtf8().constData(), "hello world");
+
+ AssetUtilities::SetUseFileHashOverride(true, true);
+
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ // Even though we're only updating one file, we're expecting 2 createJob calls because our test file is a dependency that triggers
+ // the other test file to process as well
+ ExpectWork(2, 2);
+ ProcessAssetJobs();
+
+ m_data->m_mockBuilderInfoHandler.m_createJobsCount = 0;
+ m_data->m_processResults.clear();
+ m_data->m_deletedSources.clear();
+
+ // Make file 0 have the same contents as file 1
+ SetFileContents(m_data->m_absolutePath[0].toUtf8().constData(), "hello world");
+
+ filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ ExpectWork(1, 1);
+ }
+
+ TEST_F(ModtimeScanningTest, ModtimeSkipping_ModifyMetadataFile)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+
+ SetFileContents(m_data->m_absolutePath[2].toUtf8().constData(), "hello world");
+
+ AssetUtilities::SetUseFileHashOverride(true, true);
+
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ // Even though we're only updating one file, we're expecting 2 createJob calls because our test file is a metadata file
+ // that triggers the source file which is a dependency that triggers the other test file to process as well
+ ExpectWork(2, 2);
+ }
+
+ TEST_F(ModtimeScanningTest, ModtimeSkipping_DeleteFile)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+
+ AssetUtilities::SetUseFileHashOverride(true, true);
+
+ ASSERT_TRUE(QFile::remove(m_data->m_absolutePath[0]));
+
+ // Feed in ONLY one file (the one we didn't delete)
+ QSet filePaths;
+ QFileInfo fileInfo(m_data->m_absolutePath[1]);
+ auto modtime = fileInfo.lastModified();
+ AZ::u64 fileSize = fileInfo.size();
+ filePaths.insert(AssetFileInfo(m_data->m_absolutePath[1], modtime, fileSize, &m_config->GetScanFolderAt(0), false));
+
+ SimulateAssetScanner(filePaths);
+
+ QElapsedTimer timer;
+ timer.start();
+
+ do
+ {
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
+ } while (m_data->m_deletedSources.size() < m_data->m_relativePathFromWatchFolder[0].size() && timer.elapsed() < 5000);
+
+ ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 0);
+ ASSERT_EQ(m_data->m_processResults.size(), 0);
+ ASSERT_THAT(m_data->m_deletedSources, testing::ElementsAre(m_data->m_relativePathFromWatchFolder[0]));
+ }
+
+ TEST_F(ModtimeScanningTest, ReprocessRequest_FileNotModified_FileProcessed)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+
+ m_assetProcessorManager->RequestReprocess(m_data->m_absolutePath[0]);
+
+ ASSERT_TRUE(BlockUntilIdle(5000));
+
+ ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 1);
+ ASSERT_EQ(m_data->m_processResults.size(), 1);
+ }
+
+ TEST_F(ModtimeScanningTest, ReprocessRequest_SourceWithDependency_BothWillProcess)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+
+ using SourceFileDependencyEntry = AzToolsFramework::AssetDatabase::SourceFileDependencyEntry;
+
+ SourceFileDependencyEntry newEntry1;
+ newEntry1.m_sourceDependencyID = AzToolsFramework::AssetDatabase::InvalidEntryId;
+ newEntry1.m_builderGuid = AZ::Uuid::CreateRandom();
+ newEntry1.m_source = m_data->m_absolutePath[0].toUtf8().constData();
+ newEntry1.m_dependsOnSource = m_data->m_absolutePath[1].toUtf8().constData();
+ newEntry1.m_typeOfDependency = SourceFileDependencyEntry::DEP_SourceToSource;
+
+ m_assetProcessorManager->RequestReprocess(m_data->m_absolutePath[0]);
+ ASSERT_TRUE(BlockUntilIdle(5000));
+
+ ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 1);
+ ASSERT_EQ(m_data->m_processResults.size(), 1);
+
+ m_assetProcessorManager->RequestReprocess(m_data->m_absolutePath[1]);
+ ASSERT_TRUE(BlockUntilIdle(5000));
+
+ ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 3);
+ ASSERT_EQ(m_data->m_processResults.size(), 3);
+ }
+
+ TEST_F(ModtimeScanningTest, ReprocessRequest_RequestFolder_SourceAssetsWillProcess)
+ {
+ using namespace AzToolsFramework::AssetSystem;
+
+ const auto& scanFolder = m_config->GetScanFolderAt(0);
+
+ QString scanPath = scanFolder.ScanPath();
+ m_assetProcessorManager->RequestReprocess(scanPath);
+ ASSERT_TRUE(BlockUntilIdle(5000));
+
+ // two text files are source assets, assetinfo is not
+ ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 2);
+ ASSERT_EQ(m_data->m_processResults.size(), 2);
+ }
+
+ void DeleteTest::SetUp()
+ {
+ AssetProcessorManagerTest::SetUp();
+
+ m_data = AZStd::make_unique();
+
+ // We don't want the mock application manager to provide builder descriptors, mockBuilderInfoHandler will provide our own
+ m_mockApplicationManager->BusDisconnect();
+
+ m_data->m_mockBuilderInfoHandler.m_builderDesc = m_data->m_mockBuilderInfoHandler.CreateBuilderDesc(
+ "test builder", "{DF09DDC0-FD22-43B6-9E22-22C8574A6E1E}",
+ { AssetBuilderSDK::AssetBuilderPattern("*.txt", AssetBuilderSDK::AssetBuilderPattern::Wildcard) });
+ m_data->m_mockBuilderInfoHandler.BusConnect();
+
+ ASSERT_TRUE(m_mockApplicationManager->GetBuilderByID("txt files", m_data->m_builderTxtBuilder));
+
+ SetUpAssetProcessorManager();
+
+ auto createFileAndAddToDatabaseFunc = [this](const AssetProcessor::ScanFolderInfo* scanFolder, QString file)
+ {
+ using namespace AzToolsFramework::AssetDatabase;
+
+ QString watchFolderPath = scanFolder->ScanPath();
+ QString absPath(QDir(watchFolderPath).absoluteFilePath(file));
+ UnitTestUtils::CreateDummyFile(absPath);
+
+ m_data->m_absolutePath.push_back(absPath);
+
+ AzToolsFramework::AssetDatabase::FileDatabaseEntry fileEntry;
+ fileEntry.m_fileName = file.toUtf8().constData();
+ fileEntry.m_modTime = 0;
+ fileEntry.m_isFolder = false;
+ fileEntry.m_scanFolderPK = scanFolder->ScanFolderID();
+
+ bool entryAlreadyExists;
+ ASSERT_TRUE(m_assetProcessorManager->m_stateData->InsertFile(fileEntry, entryAlreadyExists));
+ ASSERT_FALSE(entryAlreadyExists);
+ };
+
+ // Create test files
+ QDir tempPath(m_tempDir.path());
+ const auto* scanFolder1 = m_config->GetScanFolderByPath(tempPath.absoluteFilePath("subfolder1"));
+ const auto* scanFolder4 = m_config->GetScanFolderByPath(tempPath.absoluteFilePath("subfolder4"));
+
+ createFileAndAddToDatabaseFunc(scanFolder1, QString("textures/a.txt"));
+ createFileAndAddToDatabaseFunc(scanFolder4, QString("textures/b.txt"));
+
+ // Run the test files through AP all the way to processing stage
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ ASSERT_TRUE(BlockUntilIdle(5000));
+ ASSERT_EQ(m_data->m_mockBuilderInfoHandler.m_createJobsCount, 2);
+ ASSERT_EQ(m_data->m_processResults.size(), 2);
+ ASSERT_EQ(m_data->m_deletedSources.size(), 0);
+
+ ProcessAssetJobs();
+
+ m_data->m_processResults.clear();
+ m_data->m_mockBuilderInfoHandler.m_createJobsCount = 0;
+
+ // Reboot the APM since we added stuff to the database that needs to be loaded on-startup of the APM
+ m_assetProcessorManager.reset(new AssetProcessorManager_Test(m_config.get()));
+
+ SetUpAssetProcessorManager();
+ }
+
+ TEST_F(DeleteTest, DeleteFolderSharedAcrossTwoScanFolders_CorrectFileAndFolderAreDeletedFromCache)
+ {
+ // There was a bug where AP wasn't repopulating the "known folders" list when modtime skipping was enabled and no work was needed
+ // As a result, deleting a folder didn't count as a "folder", so the wrong code path was taken. This test makes sure the correct
+ // deletion events fire
+
+ using namespace AzToolsFramework::AssetSystem;
+
+ // Feed in the files from the asset scanner, no jobs should run since they're already up-to-date
+ QSet filePaths = BuildFileSet();
+ SimulateAssetScanner(filePaths);
+
+ ExpectNoWork();
+
+ // Delete one of the folders
+ QDir tempPath(m_tempDir.path());
+ QString absPath(tempPath.absoluteFilePath("subfolder1/textures"));
+ QDir(absPath).removeRecursively();
+
+ AZStd::vector deletedFolders;
+ QObject::connect(
+ m_assetProcessorManager.get(), &AssetProcessor::AssetProcessorManager::SourceFolderDeleted,
+ [&deletedFolders](QString file)
+ {
+ deletedFolders.push_back(file.toUtf8().constData());
+ });
+
+ m_assetProcessorManager->AssessDeletedFile(absPath);
+ ASSERT_TRUE(BlockUntilIdle(5000));
+
+ ASSERT_THAT(m_data->m_deletedSources, testing::UnorderedElementsAre("textures/a.txt"));
+ ASSERT_THAT(deletedFolders, testing::UnorderedElementsAre("textures"));
+ }
+
+ TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeleteFails)
+ {
+ auto theFile = m_data->m_absolutePath[1].toUtf8();
+ const char* theFileString = theFile.constData();
+ auto [sourcePath, productPath] = *m_data->m_productPaths.find(theFileString);
+
+ {
+ QFile file(theFileString);
+ file.remove();
+ }
+
+ ASSERT_GT(m_data->m_productPaths.size(), 0);
+ QFile product(productPath);
+
+ ASSERT_TRUE(product.open(QIODevice::ReadOnly));
+
+ // Check if we can delete the file now, if we can't, proceed with the test
+ // If we can, it means the OS running this test doesn't lock open files so there's nothing to test
+ if (!AZ::IO::SystemFile::Delete(productPath.toUtf8().constData()))
+ {
+ QMetaObject::invokeMethod(
+ m_assetProcessorManager.get(), "AssessDeletedFile", Qt::QueuedConnection, Q_ARG(QString, QString(theFileString)));
+
+ EXPECT_TRUE(BlockUntilIdle(5000));
+
+ EXPECT_TRUE(QFile::exists(productPath));
+ EXPECT_EQ(m_data->m_deletedSources.size(), 0);
+ }
+ else
+ {
+ SUCCEED() << "Skipping test. OS does not lock open files.";
+ }
+ }
+
+ TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeletesWhenReleased)
+ {
+ // This test is intended to verify the AP will successfully retry deleting a source asset
+ // when one of its product assets is locked temporarily
+ // We'll lock the file by holding it open
+
+ auto theFile = m_data->m_absolutePath[1].toUtf8();
+ const char* theFileString = theFile.constData();
+ auto [sourcePath, productPath] = *m_data->m_productPaths.find(theFileString);
+
+ {
+ QFile file(theFileString);
+ file.remove();
+ }
+
+ ASSERT_GT(m_data->m_productPaths.size(), 0);
+ QFile product(productPath);
+
+ // Open the file and keep it open to lock it
+ // We'll start a thread later to unlock the file
+ // This will allow us to test how AP handles trying to delete a locked file
+ ASSERT_TRUE(product.open(QIODevice::ReadOnly));
+
+ // Check if we can delete the file now, if we can't, proceed with the test
+ // If we can, it means the OS running this test doesn't lock open files so there's nothing to test
+ if (!AZ::IO::SystemFile::Delete(productPath.toUtf8().constData()))
+ {
+ m_deleteCounter = 0;
+
+ // Set up a callback which will fire after at least 1 retry
+ // Unlock the file at that point so AP can successfully delete it
+ m_callback = [&product]()
+ {
+ product.close();
+ };
+
+ QMetaObject::invokeMethod(
+ m_assetProcessorManager.get(), "AssessDeletedFile", Qt::QueuedConnection, Q_ARG(QString, QString(theFileString)));
+
+ EXPECT_TRUE(BlockUntilIdle(5000));
+
+ EXPECT_FALSE(QFile::exists(productPath));
+ EXPECT_EQ(m_data->m_deletedSources.size(), 1);
+
+ EXPECT_GT(m_deleteCounter, 1); // Make sure the AP tried more than once to delete the file
+ m_errorAbsorber->ExpectAsserts(0);
+ }
+ else
+ {
+ SUCCEED() << "Skipping test. OS does not lock open files.";
+ }
+ }
+}
diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/ModtimeScanningTests.h b/Code/Tools/AssetProcessor/native/tests/assetmanager/ModtimeScanningTests.h
new file mode 100644
index 0000000000..ef57c70536
--- /dev/null
+++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/ModtimeScanningTests.h
@@ -0,0 +1,105 @@
+/*
+ * 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
+
+namespace UnitTests
+{
+ struct ModtimeScanningTest : AssetProcessorManagerTest
+ {
+ void SetUpAssetProcessorManager();
+ void SetUp() override;
+ void TearDown() override;
+
+ void ProcessAssetJobs();
+ void SimulateAssetScanner(QSet filePaths);
+ QSet BuildFileSet();
+ void ExpectWork(int createJobs, int processJobs);
+ void ExpectNoWork();
+ void SetFileContents(QString filePath, QString contents);
+
+ struct StaticData
+ {
+ QString m_relativePathFromWatchFolder[3];
+ AZStd::vector m_absolutePath;
+ AZStd::vector m_processResults;
+ AZStd::unordered_multimap m_productPaths;
+ AZStd::vector