Merge branch 'development' into Atom/dmcdiar/ATOM-16896
This commit is contained in:
@@ -14,30 +14,44 @@ from scene_api.scene_data import SceneGraphName
|
||||
|
||||
|
||||
def log_exception_traceback():
|
||||
"""
|
||||
Outputs an exception stacktrace.
|
||||
"""
|
||||
"""Outputs an exception stacktrace."""
|
||||
data = traceback.format_exc()
|
||||
logger = logging.getLogger('python')
|
||||
logger.error(data)
|
||||
|
||||
|
||||
def sanitize_name_for_disk(name: str):
|
||||
"""
|
||||
Removes illegal filename characters from a string.
|
||||
def sanitize_name_for_disk(name: str) -> str:
|
||||
"""Removes illegal filename characters from a string.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name :
|
||||
String to clean.
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
Name with illegal characters removed.
|
||||
|
||||
:param name: String to clean.
|
||||
:return: Name with illegal characters removed.
|
||||
"""
|
||||
return "".join(char for char in name if char not in "|<>:\"/?*\\")
|
||||
|
||||
|
||||
def get_mesh_node_names(scene_graph: sceneData.SceneGraph) -> Tuple[List[SceneGraphName], List[str]]:
|
||||
"""
|
||||
Returns a tuple of all the mesh nodes as well as all the node paths
|
||||
"""Returns a tuple of all the mesh nodes as well as all the node paths
|
||||
|
||||
Parameters
|
||||
----------
|
||||
scene_graph :
|
||||
Scene graph to search
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
Tuple[List[SceneGraphName], List[str]]
|
||||
Tuple of [Mesh Nodes, All Node Paths]
|
||||
|
||||
:param scene_graph: Scene graph to search
|
||||
:return: Tuple of [Mesh Nodes, All Node Paths]
|
||||
"""
|
||||
import azlmbr.scene as sceneApi
|
||||
import azlmbr.scene.graph
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import azlmbr.bus
|
||||
import azlmbr.math
|
||||
|
||||
from scene_api.scene_data import PrimitiveShape, DecompositionMode
|
||||
from scene_api.scene_data import PrimitiveShape, DecompositionMode, ColorChannel, TangentSpaceSource, TangentSpaceMethod
|
||||
from scene_helpers import *
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ def add_physx_meshes(scene_manifest: sceneData.SceneManifest, source_file_name:
|
||||
triangle = scene_manifest.add_physx_triangle_mesh_group(source_file_name + "_triangle", False, True, True, True, True, True)
|
||||
scene_manifest.physx_mesh_group_add_selected_unselected_nodes(triangle, [first_mesh], all_except_first_mesh)
|
||||
|
||||
|
||||
def update_manifest(scene):
|
||||
import uuid, os
|
||||
import azlmbr.scene.graph
|
||||
@@ -114,10 +115,11 @@ def update_manifest(scene):
|
||||
if node != mesh_path:
|
||||
scene_manifest.mesh_group_unselect_node(mesh_group, node)
|
||||
|
||||
scene_manifest.mesh_group_add_cloth_rule(mesh_group, mesh_path, "Col0", 1, "Col0", 2, "Col0", 2, 3)
|
||||
scene_manifest.mesh_group_add_cloth_rule(mesh_group, mesh_path, "Col0", ColorChannel.GREEN, "Col0",
|
||||
ColorChannel.BLUE, "Col0", ColorChannel.BLUE, ColorChannel.ALPHA)
|
||||
scene_manifest.mesh_group_add_advanced_mesh_rule(mesh_group, True, False, True, "Col0")
|
||||
scene_manifest.mesh_group_add_skin_rule(mesh_group, 3, 0.002)
|
||||
scene_manifest.mesh_group_add_tangent_rule(mesh_group, 1, 0)
|
||||
scene_manifest.mesh_group_add_tangent_rule(mesh_group, TangentSpaceSource.MIKKT_GENERATION, TangentSpaceMethod.TSPACE_BASIC)
|
||||
|
||||
# Create an editor entity
|
||||
entity_id = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "CreateEditorReadyEntity", mesh_group_name)
|
||||
|
||||
+6
-2
@@ -140,12 +140,16 @@ class TestHelper:
|
||||
# make sure the server launcher is running
|
||||
waiter.wait_for(lambda: process_utils.process_exists("AutomatedTesting.ServerLauncher", ignore_extensions=True), timeout=5.0, exc=AssertionError("AutomatedTesting.ServerLauncher has NOT launched!"), interval=1.0)
|
||||
|
||||
# make sure the editor connects to the editor-server and sends the level data packet
|
||||
wait_for_critical_expected_line("MultiplayerEditorConnection: Editor-server activation has found and connected to the editor.", section_tracer.prints, 15.0)
|
||||
|
||||
wait_for_critical_expected_line("Editor is sending the editor-server the level data packet.", section_tracer.prints, 5.0)
|
||||
|
||||
# make sure the editor finally connects to the editor-server network simulation
|
||||
wait_for_critical_expected_line("Logger: Editor Server completed receiving the editor's level assets, responding to Editor...", section_tracer.prints, 5.0)
|
||||
|
||||
wait_for_critical_expected_line("Editor-server ready. Editor has successfully connected to the editor-server's network simulation.", section_tracer.prints, 5.0)
|
||||
|
||||
wait_for_critical_unexpected_line(f"MultiplayerSystemComponent: SpawnDefaultPlayerPrefab failed. Missing sv_defaultPlayerSpawnAsset at path '{sv_default_player_spawn_asset.lower()}'.", section_tracer.prints, 0.5)
|
||||
|
||||
TestHelper.wait_for_condition(lambda : multiplayer.PythonEditorFuncs_is_in_game_mode(), 5.0)
|
||||
Report.critical_result(msgtuple_success_fail, multiplayer.PythonEditorFuncs_is_in_game_mode())
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ class TestAutomationBase:
|
||||
@staticmethod
|
||||
def _kill_ly_processes(include_asset_processor=True):
|
||||
LY_PROCESSES = [
|
||||
'Editor', 'Profiler', 'RemoteConsole',
|
||||
'Editor', 'Profiler', 'RemoteConsole', 'AutomatedTesting.ServerLauncher'
|
||||
]
|
||||
AP_PROCESSES = [
|
||||
'AssetProcessor', 'AssetProcessorBatch', 'AssetBuilder', 'CrySCompileServer',
|
||||
|
||||
+155
-155
@@ -5,7 +5,7 @@
|
||||
"ClassData": {
|
||||
"m_scriptCanvas": {
|
||||
"Id": {
|
||||
"id": 20239954977260
|
||||
"id": 11859291537220
|
||||
},
|
||||
"Name": "AutoComponent_NetworkInput",
|
||||
"Components": {
|
||||
@@ -81,7 +81,7 @@
|
||||
"m_nodes": [
|
||||
{
|
||||
"Id": {
|
||||
"id": 20265724781036
|
||||
"id": 11872176439108
|
||||
},
|
||||
"Name": "SC-Node(NotEqualTo)",
|
||||
"Components": {
|
||||
@@ -232,7 +232,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20257134846444
|
||||
"id": 11893651275588
|
||||
},
|
||||
"Name": "SC-Node(NotEqualTo)",
|
||||
"Components": {
|
||||
@@ -383,7 +383,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20278609682924
|
||||
"id": 11897946242884
|
||||
},
|
||||
"Name": "SC-Node(Print)",
|
||||
"Components": {
|
||||
@@ -423,16 +423,16 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"m_format": "AutoComponent_NetworkInput ProcessInput called!",
|
||||
"m_format": "AutoComponent_NetworkInput ProcessInput called!\n",
|
||||
"m_unresolvedString": [
|
||||
"AutoComponent_NetworkInput ProcessInput called!"
|
||||
"AutoComponent_NetworkInput ProcessInput called!\n"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20244249944556
|
||||
"id": 11885061340996
|
||||
},
|
||||
"Name": "SC-Node(CreateFromValues)",
|
||||
"Components": {
|
||||
@@ -571,7 +571,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20252839879148
|
||||
"id": 11867881471812
|
||||
},
|
||||
"Name": "EBusEventHandler",
|
||||
"Components": {
|
||||
@@ -862,7 +862,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20248544911852
|
||||
"id": 11863586504516
|
||||
},
|
||||
"Name": "SC-Node(ExtractProperty)",
|
||||
"Components": {
|
||||
@@ -1003,7 +1003,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20270019748332
|
||||
"id": 11880766373700
|
||||
},
|
||||
"Name": "SC-Node(Print)",
|
||||
"Components": {
|
||||
@@ -1043,16 +1043,16 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"m_format": "AutoComponent_NetworkInput received bad fwdback!",
|
||||
"m_format": "AutoComponent_NetworkInput received bad fwdback!\n",
|
||||
"m_unresolvedString": [
|
||||
"AutoComponent_NetworkInput received bad fwdback!"
|
||||
"AutoComponent_NetworkInput received bad fwdback!\n"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20274314715628
|
||||
"id": 11889356308292
|
||||
},
|
||||
"Name": "SC-Node(Print)",
|
||||
"Components": {
|
||||
@@ -1092,16 +1092,16 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"m_format": "AutoComponent_NetworkInput received bad leftright!",
|
||||
"m_format": "AutoComponent_NetworkInput received bad leftright!\n",
|
||||
"m_unresolvedString": [
|
||||
"AutoComponent_NetworkInput received bad leftright!"
|
||||
"AutoComponent_NetworkInput received bad leftright!\n"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20261429813740
|
||||
"id": 11876471406404
|
||||
},
|
||||
"Name": "SC-Node(Print)",
|
||||
"Components": {
|
||||
@@ -1141,9 +1141,9 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"m_format": "AutoComponent_NetworkInput CreateInput called!",
|
||||
"m_format": "AutoComponent_NetworkInput CreateInput called!\n",
|
||||
"m_unresolvedString": [
|
||||
"AutoComponent_NetworkInput CreateInput called!"
|
||||
"AutoComponent_NetworkInput CreateInput called!\n"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1152,7 +1152,7 @@
|
||||
"m_connections": [
|
||||
{
|
||||
"Id": {
|
||||
"id": 20282904650220
|
||||
"id": 11902241210180
|
||||
},
|
||||
"Name": "srcEndpoint=(NetworkTestPlayerComponentBusHandler Handler: ExecutionSlot:CreateInput), destEndpoint=(Print: In)",
|
||||
"Components": {
|
||||
@@ -1161,7 +1161,7 @@
|
||||
"Id": 3586317167340048684,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20252839879148
|
||||
"id": 11867881471812
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{B831AC60-7641-4B74-9829-26A3576B4766}"
|
||||
@@ -1169,7 +1169,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20261429813740
|
||||
"id": 11876471406404
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{2B6DB3BC-AA87-4280-B4C3-42C1EE17CBA3}"
|
||||
@@ -1180,7 +1180,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20287199617516
|
||||
"id": 11906536177476
|
||||
},
|
||||
"Name": "srcEndpoint=(NetworkTestPlayerComponentBusHandler Handler: ExecutionSlot:CreateInput), destEndpoint=(CreateFromValues: In)",
|
||||
"Components": {
|
||||
@@ -1189,7 +1189,7 @@
|
||||
"Id": 15956251897822268937,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20252839879148
|
||||
"id": 11867881471812
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{B831AC60-7641-4B74-9829-26A3576B4766}"
|
||||
@@ -1197,7 +1197,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20244249944556
|
||||
"id": 11885061340996
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{514CDDAA-290F-4758-B28F-4003E719E635}"
|
||||
@@ -1208,7 +1208,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20291494584812
|
||||
"id": 11910831144772
|
||||
},
|
||||
"Name": "srcEndpoint=(CreateFromValues: Result: NetworkTestPlayerComponentNetworkInput), destEndpoint=(NetworkTestPlayerComponentBusHandler Handler: Result: NetworkTestPlayerComponentNetworkInput)",
|
||||
"Components": {
|
||||
@@ -1217,7 +1217,7 @@
|
||||
"Id": 3864080489501353126,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20244249944556
|
||||
"id": 11885061340996
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{90E52F81-54E0-4C63-9881-B661FB5D87D1}"
|
||||
@@ -1225,7 +1225,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20252839879148
|
||||
"id": 11867881471812
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{ADF9B366-8324-4C1E-B601-C059DA70FDDE}"
|
||||
@@ -1236,7 +1236,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20295789552108
|
||||
"id": 11915126112068
|
||||
},
|
||||
"Name": "srcEndpoint=(NetworkTestPlayerComponentBusHandler Handler: ExecutionSlot:ProcessInput), destEndpoint=(Print: In)",
|
||||
"Components": {
|
||||
@@ -1245,7 +1245,7 @@
|
||||
"Id": 8628095809445337119,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20252839879148
|
||||
"id": 11867881471812
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{4C8F2908-12B0-4C35-8468-31D3D4DF36AA}"
|
||||
@@ -1253,7 +1253,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20278609682924
|
||||
"id": 11897946242884
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{D994D58A-DBF1-4929-B779-F0D2CBAD2F0D}"
|
||||
@@ -1264,7 +1264,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20300084519404
|
||||
"id": 11919421079364
|
||||
},
|
||||
"Name": "srcEndpoint=(NetworkTestPlayerComponentBusHandler Handler: ExecutionSlot:ProcessInput), destEndpoint=(Extract Properties: In)",
|
||||
"Components": {
|
||||
@@ -1273,7 +1273,7 @@
|
||||
"Id": 10621112306443381493,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20252839879148
|
||||
"id": 11867881471812
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{4C8F2908-12B0-4C35-8468-31D3D4DF36AA}"
|
||||
@@ -1281,7 +1281,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20248544911852
|
||||
"id": 11863586504516
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{C80C50EE-F216-4F44-B107-6B35354AFD52}"
|
||||
@@ -1292,7 +1292,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20304379486700
|
||||
"id": 11923716046660
|
||||
},
|
||||
"Name": "srcEndpoint=(NetworkTestPlayerComponentBusHandler Handler: NetworkTestPlayerComponentNetworkInput), destEndpoint=(Extract Properties: Source)",
|
||||
"Components": {
|
||||
@@ -1301,7 +1301,7 @@
|
||||
"Id": 14013500888143163469,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20252839879148
|
||||
"id": 11867881471812
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{8F69FA2E-28D8-4DF1-A4B5-AEF3985095C5}"
|
||||
@@ -1309,7 +1309,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20248544911852
|
||||
"id": 11863586504516
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{D387C800-352B-4B01-8765-4F4B40DF45CB}"
|
||||
@@ -1320,7 +1320,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20308674453996
|
||||
"id": 11928011013956
|
||||
},
|
||||
"Name": "srcEndpoint=(Extract Properties: Out), destEndpoint=(Not Equal To (!=): In)",
|
||||
"Components": {
|
||||
@@ -1329,7 +1329,7 @@
|
||||
"Id": 14597948098713219792,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20248544911852
|
||||
"id": 11863586504516
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{C69C098D-D667-4DC7-85E5-AFD119727D94}"
|
||||
@@ -1337,7 +1337,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20257134846444
|
||||
"id": 11893651275588
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{AE7E453C-15DE-47D2-954A-05C3895B7AC6}"
|
||||
@@ -1348,7 +1348,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20312969421292
|
||||
"id": 11932305981252
|
||||
},
|
||||
"Name": "srcEndpoint=(Extract Properties: FwdBack: Number), destEndpoint=(Not Equal To (!=): Value A)",
|
||||
"Components": {
|
||||
@@ -1357,7 +1357,7 @@
|
||||
"Id": 14915522756837814768,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20248544911852
|
||||
"id": 11863586504516
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{0C03D491-DE25-46C2-BF09-14769FA49FDB}"
|
||||
@@ -1365,7 +1365,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20257134846444
|
||||
"id": 11893651275588
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{57EBC15B-452E-49B3-8BD3-4FBBB07F1F14}"
|
||||
@@ -1376,7 +1376,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20317264388588
|
||||
"id": 11936600948548
|
||||
},
|
||||
"Name": "srcEndpoint=(Extract Properties: Out), destEndpoint=(Not Equal To (!=): In)",
|
||||
"Components": {
|
||||
@@ -1385,7 +1385,7 @@
|
||||
"Id": 6510282773353837676,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20248544911852
|
||||
"id": 11863586504516
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{C69C098D-D667-4DC7-85E5-AFD119727D94}"
|
||||
@@ -1393,7 +1393,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20265724781036
|
||||
"id": 11872176439108
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{AE7E453C-15DE-47D2-954A-05C3895B7AC6}"
|
||||
@@ -1404,7 +1404,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20321559355884
|
||||
"id": 11940895915844
|
||||
},
|
||||
"Name": "srcEndpoint=(Extract Properties: LeftRight: Number), destEndpoint=(Not Equal To (!=): Value A)",
|
||||
"Components": {
|
||||
@@ -1413,7 +1413,7 @@
|
||||
"Id": 16150645152204311425,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20248544911852
|
||||
"id": 11863586504516
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{4C13F9EF-60BF-4AD1-8FA9-66F46455411C}"
|
||||
@@ -1421,7 +1421,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20265724781036
|
||||
"id": 11872176439108
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{57EBC15B-452E-49B3-8BD3-4FBBB07F1F14}"
|
||||
@@ -1432,7 +1432,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20325854323180
|
||||
"id": 11945190883140
|
||||
},
|
||||
"Name": "srcEndpoint=(Not Equal To (!=): True), destEndpoint=(Print: In)",
|
||||
"Components": {
|
||||
@@ -1441,7 +1441,7 @@
|
||||
"Id": 3322355580364572639,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20257134846444
|
||||
"id": 11893651275588
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{AC364E17-A9A1-42DB-A29D-7B2D666E4287}"
|
||||
@@ -1449,7 +1449,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20270019748332
|
||||
"id": 11880766373700
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{733AA75D-022C-45E9-9D0F-3EF9A1633ADC}"
|
||||
@@ -1460,7 +1460,7 @@
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"id": 20330149290476
|
||||
"id": 11949485850436
|
||||
},
|
||||
"Name": "srcEndpoint=(Not Equal To (!=): True), destEndpoint=(Print: In)",
|
||||
"Components": {
|
||||
@@ -1469,7 +1469,7 @@
|
||||
"Id": 1975626970668030308,
|
||||
"sourceEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20265724781036
|
||||
"id": 11872176439108
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{AC364E17-A9A1-42DB-A29D-7B2D666E4287}"
|
||||
@@ -1477,7 +1477,7 @@
|
||||
},
|
||||
"targetEndpoint": {
|
||||
"nodeId": {
|
||||
"id": 20274314715628
|
||||
"id": 11889356308292
|
||||
},
|
||||
"slotId": {
|
||||
"m_id": "{733AA75D-022C-45E9-9D0F-3EF9A1633ADC}"
|
||||
@@ -1498,16 +1498,16 @@
|
||||
"GraphCanvasData": [
|
||||
{
|
||||
"Key": {
|
||||
"id": 20239954977260
|
||||
"id": 11859291537220
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
"{5F84B500-8C45-40D1-8EFC-A5306B241444}": {
|
||||
"$type": "SceneComponentSaveData",
|
||||
"ViewParams": {
|
||||
"Scale": 1.0097068678919363,
|
||||
"AnchorX": 1086.4539794921875,
|
||||
"AnchorY": 198.07728576660156
|
||||
"Scale": 0.8416459517191037,
|
||||
"AnchorX": -80.7940673828125,
|
||||
"AnchorY": -622.589599609375
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1515,38 +1515,7 @@
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 20244249944556
|
||||
},
|
||||
"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": [
|
||||
740.0,
|
||||
100.0
|
||||
]
|
||||
},
|
||||
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
|
||||
"$type": "StylingComponentSaveData",
|
||||
"SubStyle": ".method"
|
||||
},
|
||||
"{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
|
||||
"$type": "PersistentIdComponentSaveData",
|
||||
"PersistentId": "{7A7C96CB-4B5A-48DD-A0AD-0094A113549B}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 20248544911852
|
||||
"id": 11863586504516
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
@@ -1576,7 +1545,7 @@
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 20252839879148
|
||||
"id": 11867881471812
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
@@ -1613,67 +1582,7 @@
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 20257134846444
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
"{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
|
||||
"$type": "NodeSaveData"
|
||||
},
|
||||
"{328FF15C-C302-458F-A43D-E1794DE0904E}": {
|
||||
"$type": "GeneralNodeTitleComponentSaveData",
|
||||
"PaletteOverride": "MathNodeTitlePalette"
|
||||
},
|
||||
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
|
||||
"$type": "GeometrySaveData",
|
||||
"Position": [
|
||||
1040.0,
|
||||
320.0
|
||||
]
|
||||
},
|
||||
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
|
||||
"$type": "StylingComponentSaveData"
|
||||
},
|
||||
"{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
|
||||
"$type": "PersistentIdComponentSaveData",
|
||||
"PersistentId": "{71AB4748-41F4-4FEA-874C-F54037236F31}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 20261429813740
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
"{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
|
||||
"$type": "NodeSaveData"
|
||||
},
|
||||
"{328FF15C-C302-458F-A43D-E1794DE0904E}": {
|
||||
"$type": "GeneralNodeTitleComponentSaveData",
|
||||
"PaletteOverride": "StringNodeTitlePalette"
|
||||
},
|
||||
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
|
||||
"$type": "GeometrySaveData",
|
||||
"Position": [
|
||||
740.0,
|
||||
-100.0
|
||||
]
|
||||
},
|
||||
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
|
||||
"$type": "StylingComponentSaveData"
|
||||
},
|
||||
"{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
|
||||
"$type": "PersistentIdComponentSaveData",
|
||||
"PersistentId": "{26E363EE-F35A-4096-88EF-DF907A809894}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 20265724781036
|
||||
"id": 11872176439108
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
@@ -1703,7 +1612,37 @@
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 20270019748332
|
||||
"id": 11876471406404
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
"{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
|
||||
"$type": "NodeSaveData"
|
||||
},
|
||||
"{328FF15C-C302-458F-A43D-E1794DE0904E}": {
|
||||
"$type": "GeneralNodeTitleComponentSaveData",
|
||||
"PaletteOverride": "StringNodeTitlePalette"
|
||||
},
|
||||
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
|
||||
"$type": "GeometrySaveData",
|
||||
"Position": [
|
||||
740.0,
|
||||
-100.0
|
||||
]
|
||||
},
|
||||
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
|
||||
"$type": "StylingComponentSaveData"
|
||||
},
|
||||
"{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
|
||||
"$type": "PersistentIdComponentSaveData",
|
||||
"PersistentId": "{26E363EE-F35A-4096-88EF-DF907A809894}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 11880766373700
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
@@ -1733,7 +1672,38 @@
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 20274314715628
|
||||
"id": 11885061340996
|
||||
},
|
||||
"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": [
|
||||
740.0,
|
||||
100.0
|
||||
]
|
||||
},
|
||||
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
|
||||
"$type": "StylingComponentSaveData",
|
||||
"SubStyle": ".method"
|
||||
},
|
||||
"{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
|
||||
"$type": "PersistentIdComponentSaveData",
|
||||
"PersistentId": "{7A7C96CB-4B5A-48DD-A0AD-0094A113549B}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 11889356308292
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
@@ -1763,7 +1733,37 @@
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 20278609682924
|
||||
"id": 11893651275588
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
"{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": {
|
||||
"$type": "NodeSaveData"
|
||||
},
|
||||
"{328FF15C-C302-458F-A43D-E1794DE0904E}": {
|
||||
"$type": "GeneralNodeTitleComponentSaveData",
|
||||
"PaletteOverride": "MathNodeTitlePalette"
|
||||
},
|
||||
"{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": {
|
||||
"$type": "GeometrySaveData",
|
||||
"Position": [
|
||||
1040.0,
|
||||
320.0
|
||||
]
|
||||
},
|
||||
"{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": {
|
||||
"$type": "StylingComponentSaveData"
|
||||
},
|
||||
"{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": {
|
||||
"$type": "PersistentIdComponentSaveData",
|
||||
"PersistentId": "{71AB4748-41F4-4FEA-874C-F54037236F31}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Key": {
|
||||
"id": 11897946242884
|
||||
},
|
||||
"Value": {
|
||||
"ComponentData": {
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d674eac2070ed0028ceff1e84692c9cf1f69db2192c2295b6d714670ccd50308
|
||||
size 8936
|
||||
oid sha256:82a4ffbffeee43ea4ae293080e838bbc501fe9c7c20febc2e56e745451c95df3
|
||||
size 9221
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8a2c9ad554554eba1021abe0baf0b3455da1aaab2bb8331eb240f79c89031636
|
||||
size 5202
|
||||
oid sha256:3ef03f338cd867860068b5bd343f66fa9bda4f3de1662badf552f05716da35ed
|
||||
size 5161
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:982f085cfb17ce957cd1534e89a6fb5c76bcbe6936caec214ecd422b0a5dbe7b
|
||||
size 5214
|
||||
oid sha256:bf48b69c0cc2599581bd3d931d8adc6faba5d78d950c2c0946c19ec7ba7b6215
|
||||
size 5190
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3361ba7aa2faa53421d8a92ed0bb2e1747e766d93c0315484a3c85b74a6494c3
|
||||
size 8820
|
||||
oid sha256:be53bb087c53874577dad8f1fa084698c27fbad827f0ed7dc50927fb4c9d8884
|
||||
size 7748
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Debug/TraceMessageBus.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/UserSettings/UserSettingsComponent.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
#include <AzToolsFramework/Application/ToolsApplication.h>
|
||||
@@ -63,6 +64,11 @@ namespace DisplaySettingsPythonBindingsUnitTests
|
||||
|
||||
m_app.Start(appDesc);
|
||||
m_app.RegisterComponentDescriptor(AzToolsFramework::DisplaySettingsComponent::CreateDescriptor());
|
||||
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
|
||||
@@ -243,7 +243,7 @@ namespace AZ
|
||||
|
||||
if (StringFunc::StartsWith(curr->m_name, command, false))
|
||||
{
|
||||
AZLOG_INFO("- %s : %s\n", curr->m_name, curr->m_desc);
|
||||
AZLOG_INFO("- %s : %s", curr->m_name, curr->m_desc);
|
||||
|
||||
if (commandSubset.size() < MaxConsoleCommandPlusArgsLength)
|
||||
{
|
||||
@@ -433,29 +433,29 @@ namespace AZ
|
||||
{
|
||||
if ((curr->GetFlags() & requiredSet) != requiredSet)
|
||||
{
|
||||
AZLOG_WARN("%s failed required set flag check\n", curr->m_name);
|
||||
AZLOG_WARN("%s failed required set flag check", curr->m_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((curr->GetFlags() & requiredClear) != ConsoleFunctorFlags::Null)
|
||||
{
|
||||
AZLOG_WARN("%s failed required clear flag check\n", curr->m_name);
|
||||
AZLOG_WARN("%s failed required clear flag check", curr->m_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((curr->GetFlags() & ConsoleFunctorFlags::IsCheat) != ConsoleFunctorFlags::Null)
|
||||
{
|
||||
AZLOG_WARN("%s is marked as a cheat\n", curr->m_name);
|
||||
AZLOG_WARN("%s is marked as a cheat", curr->m_name);
|
||||
}
|
||||
|
||||
if ((curr->GetFlags() & ConsoleFunctorFlags::IsDeprecated) != ConsoleFunctorFlags::Null)
|
||||
{
|
||||
AZLOG_WARN("%s is marked as deprecated\n", curr->m_name);
|
||||
AZLOG_WARN("%s is marked as deprecated", curr->m_name);
|
||||
}
|
||||
|
||||
if ((curr->GetFlags() & ConsoleFunctorFlags::NeedsReload) != ConsoleFunctorFlags::Null)
|
||||
{
|
||||
AZLOG_WARN("Changes to %s will only take effect after level reload\n", curr->m_name);
|
||||
AZLOG_WARN("Changes to %s will only take effect after level reload", curr->m_name);
|
||||
}
|
||||
|
||||
// Letting this intentionally fall-through, since in editor we can register common variables multiple times
|
||||
@@ -468,7 +468,7 @@ namespace AZ
|
||||
{
|
||||
CVarFixedString value;
|
||||
curr->GetValue(value);
|
||||
AZLOG_INFO("> %s : %s\n", curr->GetName(), value.empty() ? "<empty>" : value.c_str());
|
||||
AZLOG_INFO("> %s : %s", curr->GetName(), value.empty() ? "<empty>" : value.c_str());
|
||||
}
|
||||
flags = curr->GetFlags();
|
||||
}
|
||||
|
||||
@@ -119,25 +119,21 @@ namespace AZ
|
||||
void LoggerSystemComponent::LogInternalV(LogLevel level, const char* format, const char* file, const char* function, int32_t line, va_list args)
|
||||
{
|
||||
constexpr AZStd::size_t MaxLogBufferSize = 1000;
|
||||
char buffer[MaxLogBufferSize];
|
||||
auto buffer = AZStd::fixed_string<MaxLogBufferSize>::format_arg(format, args);
|
||||
m_logEvent.Signal(level, buffer.c_str(), file, function, line);
|
||||
buffer += '\n';
|
||||
|
||||
const AZStd::size_t length = azvsnprintf(buffer, MaxLogBufferSize, format, args);
|
||||
buffer[AZStd::min<AZStd::size_t>(length + 1, MaxLogBufferSize - 1)] = '\0';
|
||||
m_logEvent.Signal(level, buffer, file, function, line);
|
||||
|
||||
// Force a new-line before calling the AZ::Debug::Trace functions, as they assume a newline is present
|
||||
buffer[AZStd::min<AZStd::size_t>(length + 1, MaxLogBufferSize - 2)] = '\n';
|
||||
switch (level)
|
||||
{
|
||||
case LogLevel::Warn:
|
||||
AZ_Warning("Logger", true, buffer);
|
||||
AZ_Warning("Logger", true, buffer.c_str());
|
||||
break;
|
||||
case LogLevel::Error:
|
||||
AZ_Error("Logger", true, buffer);
|
||||
AZ_Error("Logger", true, buffer.c_str());
|
||||
break;
|
||||
default:
|
||||
// Catch all else with trace
|
||||
AZ::Debug::Trace::Output("Logger", buffer);
|
||||
AZ::Debug::Trace::Output("Logger", buffer.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#define AZ_TRAIT_UNIT_TEST_DILLER_TRIGGER_EVENT_COUNT 100000
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_ATOM_RPI_TESTS true
|
||||
#define AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS true
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_FRAMEPROFILER_TEST true
|
||||
#define AZ_TRAIT_DISABLE_FAILED_FRAMEWORK_TESTS true
|
||||
|
||||
@@ -158,16 +158,16 @@ namespace AzToolsFramework
|
||||
|
||||
bool success = true;
|
||||
AZStd::vector<char> fileBuffer;
|
||||
const AZ::IO::Path workingPath{ dirToArchive };
|
||||
const AZ::IO::FixedMaxPath workingPath{ dirToArchive };
|
||||
|
||||
for (const auto& fileName : foundFiles.GetValue())
|
||||
{
|
||||
bool thisSuccess = false;
|
||||
|
||||
AZ::IO::PathView relativePath = AZ::IO::PathView{ fileName }.LexicallyRelative(workingPath);
|
||||
AZ::IO::FixedMaxPath relativePath = AZ::IO::FixedMaxPath{ fileName }.LexicallyRelative(workingPath);
|
||||
AZ::IO::FixedMaxPath fullPath = (workingPath / relativePath);
|
||||
|
||||
AZ::IO::Path fullPath = (workingPath / relativePath);
|
||||
if (ArchiveUtils::ReadFile(fullPath, AZ::IO::OpenMode::ModeRead, fileBuffer))
|
||||
if (ArchiveUtils::ReadFile(static_cast<AZ::IO::PathView>(fullPath), AZ::IO::OpenMode::ModeRead, fileBuffer))
|
||||
{
|
||||
int result = archive->UpdateFile(
|
||||
relativePath.Native(), fileBuffer.data(), fileBuffer.size(), s_compressionMethod,
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
|
||||
#include <AzFramework/Input/Buses/Notifications/InputChannelNotificationBus.h>
|
||||
#include <AzFramework/Input/Buses/Notifications/InputTextNotificationBus.h>
|
||||
#include <AzFramework/Input/Buses/Requests/InputChannelRequestBus.h>
|
||||
#include <AzQtComponents/Utilities/QtWindowUtilities.h>
|
||||
|
||||
@@ -24,6 +25,30 @@
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
static bool HandleTextEvent(QEvent::Type eventType, Qt::Key key, QString keyText, bool isAutoRepeat)
|
||||
{
|
||||
bool textConsumed = false;
|
||||
|
||||
if (key == Qt::Key_Backspace)
|
||||
{
|
||||
keyText = "\b";
|
||||
}
|
||||
|
||||
if (!keyText.isEmpty())
|
||||
{
|
||||
// key events are first sent as shortcuts, if accepted they are then re-sent as traditional key
|
||||
// down events. dispatching the key event as text during a shortcut (and auto-repeat press)
|
||||
// ensures all printable keys a fair chance at being consumed before processing elsewhere
|
||||
if (eventType == QEvent::Type::ShortcutOverride || (eventType == QEvent::Type::KeyPress && isAutoRepeat))
|
||||
{
|
||||
AzFramework::InputTextNotificationBus::Broadcast(
|
||||
&AzFramework::InputTextNotifications::OnInputTextEvent, AZStd::string(keyText.toUtf8().data()), textConsumed);
|
||||
}
|
||||
}
|
||||
|
||||
return textConsumed;
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::InitializeKeyMappings()
|
||||
{
|
||||
// This assumes modifier keys (ctrl/shift/alt) map to the left control/shift/alt keys as Qt provides no way to disambiguate
|
||||
@@ -194,6 +219,7 @@ namespace AzToolsFramework
|
||||
|
||||
// Install a global event filter to ensure we don't miss mouse and key release events.
|
||||
QApplication::instance()->installEventFilter(this);
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
bool QtEventToAzInputMapper::HandlesInputEvent(const AzFramework::InputChannel& channel) const
|
||||
@@ -317,6 +343,19 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ::s32 QtEventToAzInputMapper::GetPriority() const
|
||||
{
|
||||
return AzFramework::InputChannelEventListener::GetPriorityLast();
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::OnInputChannelEvent(const AzFramework::InputChannel& inputChannel, bool& hasBeenConsumed)
|
||||
{
|
||||
if (m_enabled && hasBeenConsumed)
|
||||
{
|
||||
m_lastConsumedInputChannelIdCrc32 = inputChannel.GetInputChannelId().GetNameCrc32();
|
||||
}
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::NotifyUpdateChannelIfNotIdle(const AzFramework::InputChannel* channel, QEvent* event)
|
||||
{
|
||||
if (channel->GetState() != AzFramework::InputChannel::State::Idle)
|
||||
@@ -357,6 +396,9 @@ namespace AzToolsFramework
|
||||
|
||||
if (buttonChannel)
|
||||
{
|
||||
// reset the consumed event cache so the chain of calls from UpdateState below can properly update it, if necessary
|
||||
m_lastConsumedInputChannelIdCrc32 = 0;
|
||||
|
||||
if (mouseEvent->type() != QEvent::Type::MouseButtonRelease)
|
||||
{
|
||||
buttonChannel->UpdateState(true);
|
||||
@@ -366,7 +408,16 @@ namespace AzToolsFramework
|
||||
buttonChannel->UpdateState(false);
|
||||
}
|
||||
|
||||
NotifyUpdateChannelIfNotIdle(buttonChannel, mouseEvent);
|
||||
if (m_lastConsumedInputChannelIdCrc32 == buttonChannel->GetInputChannelId().GetNameCrc32())
|
||||
{
|
||||
// a standard az-input handler consumed the event so mark it as such
|
||||
mouseEvent->accept();
|
||||
}
|
||||
else
|
||||
{
|
||||
// only notify if not consumed elsewhere
|
||||
NotifyUpdateChannelIfNotIdle(buttonChannel, mouseEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,16 +459,24 @@ namespace AzToolsFramework
|
||||
|
||||
void QtEventToAzInputMapper::HandleKeyEvent(QKeyEvent* keyEvent)
|
||||
{
|
||||
// Ignore key repeat events, they're unrelated to actual physical button presses.
|
||||
const Qt::Key key = static_cast<Qt::Key>(keyEvent->key());
|
||||
const QEvent::Type eventType = keyEvent->type();
|
||||
|
||||
// special handling for text events in edit mode
|
||||
if (HandleTextEvent(eventType, key, keyEvent->text(), keyEvent->isAutoRepeat()))
|
||||
{
|
||||
keyEvent->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore key repeat events for non-text, they're unrelated to actual physical button presses.
|
||||
if (keyEvent->isAutoRepeat())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Qt::Key key = static_cast<Qt::Key>(keyEvent->key());
|
||||
|
||||
// For ShortcutEvent, only continue processing if we're in the HighPriorityKeys set.
|
||||
if (keyEvent->type() != QEvent::Type::ShortcutOverride || m_highPriorityKeys.find(key) != m_highPriorityKeys.end())
|
||||
if (eventType != QEvent::Type::ShortcutOverride || m_highPriorityKeys.find(key) != m_highPriorityKeys.end())
|
||||
{
|
||||
if (auto keyIt = m_keyMappings.find(key); keyIt != m_keyMappings.end())
|
||||
{
|
||||
@@ -425,7 +484,7 @@ namespace AzToolsFramework
|
||||
|
||||
if (keyChannel)
|
||||
{
|
||||
if (keyEvent->type() == QEvent::Type::KeyPress || keyEvent->type() == QEvent::Type::ShortcutOverride)
|
||||
if (eventType == QEvent::Type::KeyPress || eventType == QEvent::Type::ShortcutOverride)
|
||||
{
|
||||
keyChannel->UpdateState(true);
|
||||
}
|
||||
@@ -451,8 +510,22 @@ namespace AzToolsFramework
|
||||
{
|
||||
wheelAngle = angleDelta.y();
|
||||
}
|
||||
|
||||
// reset the consumed event cache so the chain of calls from ProcessRawInputEvent below can properly update it, if necessary
|
||||
m_lastConsumedInputChannelIdCrc32 = 0;
|
||||
|
||||
cursorZChannel->ProcessRawInputEvent(aznumeric_cast<float>(wheelAngle));
|
||||
NotifyUpdateChannelIfNotIdle(cursorZChannel, wheelEvent);
|
||||
|
||||
if (m_lastConsumedInputChannelIdCrc32 == cursorZChannel->GetInputChannelId().GetNameCrc32())
|
||||
{
|
||||
// a standard az-input handler consumed the event so mark it as such
|
||||
wheelEvent->accept();
|
||||
}
|
||||
else
|
||||
{
|
||||
// only notify if not consumed elsewhere
|
||||
NotifyUpdateChannelIfNotIdle(cursorZChannel, wheelEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::ClearInputChannels(QEvent* event)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <AzFramework/Input/Channels/InputChannelDigitalWithSharedPosition2D.h>
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
|
||||
|
||||
#include <AzFramework/Input/Events/InputChannelEventListener.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
|
||||
#include <QEvent>
|
||||
@@ -34,7 +34,9 @@ namespace AzToolsFramework
|
||||
{
|
||||
//! Maps events from the Qt input system to synthetic InputChannels in AzFramework
|
||||
//! that can be used by AzFramework::ViewportControllers.
|
||||
class QtEventToAzInputMapper final : public QObject
|
||||
class QtEventToAzInputMapper final
|
||||
: public QObject
|
||||
, public AzFramework::InputChannelNotificationBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -69,6 +71,11 @@ namespace AzToolsFramework
|
||||
//! \param event The underlying Qt event that triggered this change, if applicable.
|
||||
void InputChannelUpdated(const AzFramework::InputChannel* channel, QEvent* event);
|
||||
|
||||
protected:
|
||||
// AzFramework::InputChannelNotificationBus overrides ...
|
||||
AZ::s32 GetPriority() const override;
|
||||
void OnInputChannelEvent(const AzFramework::InputChannel& inputChannel, bool& hasBeenConsumed) override;
|
||||
|
||||
private:
|
||||
// Gets an input channel of the specified type by ID.
|
||||
template<class TInputChannel>
|
||||
@@ -161,6 +168,8 @@ namespace AzToolsFramework
|
||||
AZStd::unordered_set<Qt::Key> m_highPriorityKeys;
|
||||
// A lookup table for AZ input channel ID -> physical input channel on our mouse or keyboard device.
|
||||
AZStd::unordered_map<AzFramework::InputChannelId, AzFramework::InputChannel*> m_channels;
|
||||
// The crc32 of the last consumed input event's channel id.
|
||||
AZ::Crc32 m_lastConsumedInputChannelIdCrc32 = 0;
|
||||
// Where the mouse cursor was at the last cursor event.
|
||||
QPoint m_previousGlobalCursorPosition;
|
||||
// The source widget to map events from, used to calculate the relative mouse position within the widget bounds.
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace AzToolsFramework
|
||||
return result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success;
|
||||
}
|
||||
|
||||
// some assets may come in from the JSON serialzier with no AssetID, but have an asset hint
|
||||
// some assets may come in from the JSON serializer with no AssetID, but have an asset hint
|
||||
// this attempts to fix up the assets using the assetHint field
|
||||
void FixUpInvalidAssets(AZ::Data::Asset<AZ::Data::AssetData>& asset)
|
||||
{
|
||||
|
||||
+34
@@ -56,6 +56,40 @@ namespace UnitTest
|
||||
QApplication::sendEvent(widget, &mouseMoveEvent);
|
||||
}
|
||||
|
||||
void MouseScroll(QWidget* widget, QPoint localEventPosition, QPoint wheelDelta,
|
||||
Qt::MouseButtons mouseButtons, Qt::KeyboardModifiers keyboardModifiers)
|
||||
{
|
||||
const QPoint globalEventPos = widget->mapToGlobal(localEventPosition);
|
||||
const QPoint zero = QPoint();
|
||||
|
||||
QWheelEvent wheelEventBegin(globalEventPos, zero, zero, wheelDelta, mouseButtons, keyboardModifiers, Qt::ScrollBegin, false);
|
||||
QApplication::sendEvent(widget, &wheelEventBegin);
|
||||
|
||||
QWheelEvent wheelEventUpdate(globalEventPos, zero, zero, wheelDelta, mouseButtons, keyboardModifiers, Qt::ScrollUpdate, false);
|
||||
QApplication::sendEvent(widget, &wheelEventUpdate);
|
||||
|
||||
QWheelEvent wheelEventEnd(globalEventPos, zero, zero, zero, mouseButtons, keyboardModifiers, Qt::ScrollEnd, false);
|
||||
QApplication::sendEvent(widget, &wheelEventEnd);
|
||||
}
|
||||
|
||||
AZStd::string QtKeyToAzString(Qt::Key key, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
QKeySequence keySequence = QKeySequence(key);
|
||||
QString keyText = keySequence.toString();
|
||||
|
||||
// QKeySequence seems to uppercase alpha keys regardless of shift-modifier
|
||||
if (modifiers == Qt::NoModifier && keyText.isUpper())
|
||||
{
|
||||
keyText = keyText.toLower();
|
||||
}
|
||||
else if (modifiers != Qt::ShiftModifier)
|
||||
{
|
||||
keyText = QString();
|
||||
}
|
||||
|
||||
return AZStd::string(keyText.toUtf8().data());
|
||||
}
|
||||
|
||||
bool TestWidget::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
AZ_UNUSED(watched);
|
||||
|
||||
+14
@@ -77,6 +77,20 @@ namespace UnitTest
|
||||
/// @param mouseButton The button to be held during the move.
|
||||
void MouseMove(QWidget* widget, const QPoint& initialPosition, const QPoint& mouseDelta, Qt::MouseButton mouseButton = Qt::NoButton);
|
||||
|
||||
/// Performs a full series (begin, update, end) of mouse wheel events on the provided widget.
|
||||
/// @param widget The widget to perform the mouse wheel events on.
|
||||
/// @param localEventPosition The position of the mouse relative to the widget (will be remapped to a global position internally).
|
||||
/// @param wheelDelta How far to move the mouse (note: mouseDelta may be zero and the mouse will only be moved to initialPosition).
|
||||
/// @param mouseButtons Optional mouse buttons to include during the wheel events, defaults to Qt::NoButton
|
||||
/// @param keyboardModifiers Optional keyboard modifiers to include during the wheel events, defaults to Qt::NoModifier
|
||||
void MouseScroll(QWidget* widget, QPoint localEventPosition, QPoint wheelDelta,
|
||||
Qt::MouseButtons mouseButtons = Qt::NoButton, Qt::KeyboardModifiers keyboardModifiers = Qt::NoModifier);
|
||||
|
||||
/// Convert a Qt::Key + optional modifiers to the printable text of the key sequence
|
||||
/// @param key The widget to perform the mouse wheel event on.
|
||||
/// @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 widget to store QActions generated by EditorTransformComponentSelection.
|
||||
class TestWidget : public QWidget
|
||||
{
|
||||
|
||||
+26
-27
@@ -2504,6 +2504,29 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
// do not create manipulators for the container entity of the focused prefab.
|
||||
if (auto prefabFocusPublicInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabFocusPublicInterface>::Get())
|
||||
{
|
||||
AzFramework::EntityContextId editorEntityContextId = GetEntityContextId();
|
||||
if (AZ::EntityId focusRoot = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
|
||||
focusRoot.IsValid())
|
||||
{
|
||||
m_selectedEntityIds.erase(focusRoot);
|
||||
}
|
||||
}
|
||||
|
||||
// do not create manipulators for any entities marked as read only
|
||||
if (auto readOnlyEntityPublicInterface = AZ::Interface<ReadOnlyEntityPublicInterface>::Get())
|
||||
{
|
||||
AZStd::erase_if(
|
||||
m_selectedEntityIds,
|
||||
[readOnlyEntityPublicInterface](auto entityId)
|
||||
{
|
||||
return readOnlyEntityPublicInterface->IsReadOnly(entityId);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// note: create/destroy pattern to be addressed
|
||||
DestroyManipulators(m_entityIdManipulators);
|
||||
CreateEntityIdManipulators();
|
||||
@@ -3586,10 +3609,9 @@ namespace AzToolsFramework
|
||||
debugDisplay.SetLineWidth(1.0f);
|
||||
|
||||
const float labelOffset = ed_viewportGizmoAxisLabelOffset;
|
||||
const float screenScale = GetScreenDisplayScaling(viewportId);
|
||||
const auto labelXScreenPosition = (gizmoStart + (gizmoAxisX * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
|
||||
const auto labelYScreenPosition = (gizmoStart + (gizmoAxisY * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
|
||||
const auto labelZScreenPosition = (gizmoStart + (gizmoAxisZ * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
|
||||
const auto labelXScreenPosition = (gizmoStart + (gizmoAxisX * labelOffset)) * editorCameraState.m_viewportSize;
|
||||
const auto labelYScreenPosition = (gizmoStart + (gizmoAxisY * labelOffset)) * editorCameraState.m_viewportSize;
|
||||
const auto labelZScreenPosition = (gizmoStart + (gizmoAxisZ * labelOffset)) * editorCameraState.m_viewportSize;
|
||||
|
||||
// draw the label of of each axis for the gizmo
|
||||
const float labelSize = ed_viewportGizmoAxisLabelSize;
|
||||
@@ -3636,29 +3658,6 @@ namespace AzToolsFramework
|
||||
m_selectedEntityIds.clear();
|
||||
m_selectedEntityIds.reserve(selectedEntityIds.size());
|
||||
AZStd::copy(selectedEntityIds.begin(), selectedEntityIds.end(), AZStd::inserter(m_selectedEntityIds, m_selectedEntityIds.end()));
|
||||
|
||||
// Do not create manipulators for the container entity of the focused prefab.
|
||||
if (auto prefabFocusPublicInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabFocusPublicInterface>::Get())
|
||||
{
|
||||
AzFramework::EntityContextId editorEntityContextId = GetEntityContextId();
|
||||
if (AZ::EntityId focusRoot = prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
|
||||
focusRoot.IsValid())
|
||||
{
|
||||
m_selectedEntityIds.erase(focusRoot);
|
||||
}
|
||||
}
|
||||
|
||||
// Do not create manipulators for any entities marked as read only
|
||||
if (auto readOnlyEntityPublicInterface = AZ::Interface<ReadOnlyEntityPublicInterface>::Get())
|
||||
{
|
||||
AZStd::erase_if(
|
||||
m_selectedEntityIds,
|
||||
[readOnlyEntityPublicInterface](auto entityId)
|
||||
{
|
||||
return readOnlyEntityPublicInterface->IsReadOnly(entityId);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorTransformComponentSelection::OnTransformChanged(
|
||||
|
||||
@@ -69,12 +69,12 @@ namespace UnitTest
|
||||
|
||||
QString GetArchiveFolderName()
|
||||
{
|
||||
return "Archive";
|
||||
return "archive";
|
||||
}
|
||||
|
||||
QString GetExtractFolderName()
|
||||
{
|
||||
return "Extracted";
|
||||
return "extracted";
|
||||
}
|
||||
|
||||
void CreateArchiveFolder(QString archiveFolderName, QStringList fileList)
|
||||
@@ -90,7 +90,7 @@ namespace UnitTest
|
||||
|
||||
QString CreateArchiveListTextFile()
|
||||
{
|
||||
QString listFilePath = QDir(m_tempDir.GetDirectory()).absoluteFilePath("FileList.txt");
|
||||
QString listFilePath = QDir(m_tempDir.GetDirectory()).absoluteFilePath("filelist.txt");
|
||||
QString textContent = CreateArchiveFileList().join("\n");
|
||||
EXPECT_TRUE(CreateDummyFile(listFilePath, textContent));
|
||||
return listFilePath;
|
||||
@@ -151,11 +151,7 @@ namespace UnitTest
|
||||
UnitTest::ScopedTemporaryDirectory m_tempDir;
|
||||
};
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
TEST_F(ArchiveComponentTest, DISABLED_CreateArchive_FilesAtThreeDepths_ArchiveCreated)
|
||||
#else
|
||||
TEST_F(ArchiveComponentTest, CreateArchive_FilesAtThreeDepths_ArchiveCreated)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
{
|
||||
EXPECT_TRUE(m_tempDir.IsValid());
|
||||
CreateArchiveFolder();
|
||||
@@ -167,11 +163,7 @@ namespace UnitTest
|
||||
EXPECT_TRUE(createResult);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
TEST_F(ArchiveComponentTest, DISABLED_ListFilesInArchive_FilesAtThreeDepths_FilesFound)
|
||||
#else
|
||||
TEST_F(ArchiveComponentTest, ListFilesInArchive_FilesAtThreeDepths_FilesFound)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
{
|
||||
EXPECT_TRUE(m_tempDir.IsValid());
|
||||
CreateArchiveFolder();
|
||||
@@ -190,11 +182,7 @@ namespace UnitTest
|
||||
EXPECT_EQ(fileList.size(), 6);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
TEST_F(ArchiveComponentTest, DISABLED_CreateDeltaCatalog_AssetsNotRegistered_Failure)
|
||||
#else
|
||||
TEST_F(ArchiveComponentTest, CreateDeltaCatalog_AssetsNotRegistered_Failure)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
{
|
||||
QStringList fileList = CreateArchiveFileList();
|
||||
|
||||
@@ -213,11 +201,7 @@ namespace UnitTest
|
||||
EXPECT_EQ(catalogCreated, false);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
TEST_F(ArchiveComponentTest, DISABLED_AddFilesToArchive_FromListFile_Success)
|
||||
#else
|
||||
TEST_F(ArchiveComponentTest, AddFilesToArchive_FromListFile_Success)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
{
|
||||
QString listFile = CreateArchiveListTextFile();
|
||||
CreateArchiveFolder(GetArchiveFolderName(), CreateArchiveFileList());
|
||||
@@ -233,11 +217,7 @@ namespace UnitTest
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
TEST_F(ArchiveComponentTest, DISABLED_ExtractArchive_AllFiles_Success)
|
||||
#else
|
||||
TEST_F(ArchiveComponentTest, ExtractArchive_AllFiles_Success)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
{
|
||||
CreateArchiveFolder();
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
@@ -264,11 +244,7 @@ namespace UnitTest
|
||||
}
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
TEST_F(ArchiveComponentTest, DISABLED_CreateDeltaCatalog_ArchiveWithoutCatalogAssetsRegistered_Success)
|
||||
#else
|
||||
TEST_F(ArchiveComponentTest, CreateDeltaCatalog_ArchiveWithoutCatalogAssetsRegistered_Success)
|
||||
#endif // AZ_TRAIT_DISABLE_FAILED_ARCHIVE_TESTS
|
||||
{
|
||||
QStringList fileList = CreateArchiveFileList();
|
||||
|
||||
|
||||
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* 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 <AzToolsFramework/Input/QtEventToAzInputMapper.h>
|
||||
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
|
||||
#include <AzFramework/Input/Events/InputTextEventListener.h>
|
||||
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
static bool IsMouseButton(const AzFramework::InputChannelId& inputChannelId)
|
||||
{
|
||||
const auto& buttons = AzFramework::InputDeviceMouse::Button::All;
|
||||
const auto& it = AZStd::find(buttons.cbegin(), buttons.cend(), inputChannelId);
|
||||
return it != buttons.cend();
|
||||
}
|
||||
|
||||
class QtEventToAzInputMapperFixture
|
||||
: public AllocatorsTestFixture
|
||||
, public AzFramework::InputChannelNotificationBus::Handler
|
||||
, public AzFramework::InputTextNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
static inline constexpr QSize WidgetSize = QSize(1920, 1080);
|
||||
static inline constexpr int TestDeviceIdSeed = 4321;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
AllocatorsTestFixture::SetUp();
|
||||
|
||||
m_rootWidget = AZStd::make_unique<QWidget>();
|
||||
m_rootWidget->setFixedSize(WidgetSize);
|
||||
m_rootWidget->move(0, 0);
|
||||
|
||||
m_inputChannelMapper = AZStd::make_unique<AzToolsFramework::QtEventToAzInputMapper>(m_rootWidget.get(), TestDeviceIdSeed);
|
||||
|
||||
// listen for events signaled from QtEventToAzInputMapper and forward to the controller list
|
||||
QObject::connect(m_inputChannelMapper.get(), &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, m_rootWidget.get(),
|
||||
[this]([[maybe_unused]] const AzFramework::InputChannel* inputChannel, QEvent* event)
|
||||
{
|
||||
const QEvent::Type eventType = event->type();
|
||||
|
||||
if (eventType == QEvent::Type::MouseButtonPress ||
|
||||
eventType == QEvent::Type::MouseButtonRelease ||
|
||||
eventType == QEvent::Type::MouseButtonDblClick)
|
||||
{
|
||||
m_signalEvents.push_back(QtEventInfo(static_cast<QMouseEvent*>(event)));
|
||||
event->accept();
|
||||
}
|
||||
else if (eventType == QEvent::Type::Wheel)
|
||||
{
|
||||
m_signalEvents.push_back(QtEventInfo(static_cast<QWheelEvent*>(event)));
|
||||
event->accept();
|
||||
}
|
||||
else if (eventType == QEvent::Type::KeyPress ||
|
||||
eventType == QEvent::Type::KeyRelease ||
|
||||
eventType == QEvent::Type::ShortcutOverride)
|
||||
{
|
||||
m_signalEvents.push_back(QtEventInfo(static_cast<QKeyEvent*>(event)));
|
||||
event->accept();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_inputChannelMapper.reset();
|
||||
|
||||
m_rootWidget.reset();
|
||||
|
||||
AllocatorsTestFixture::TearDown();
|
||||
}
|
||||
|
||||
void OnInputChannelEvent(const AzFramework::InputChannel& inputChannel, bool& hasBeenConsumed) override
|
||||
{
|
||||
AZ_Assert(hasBeenConsumed == false, "Unexpected input event consumed elsewhere during QtEventToAzInputMapper tests");
|
||||
|
||||
const AzFramework::InputChannelId& inputChannelId = inputChannel.GetInputChannelId();
|
||||
const AzFramework::InputDeviceId& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId();
|
||||
|
||||
if (AzFramework::InputDeviceMouse::IsMouseDevice(inputDeviceId))
|
||||
{
|
||||
if (IsMouseButton(inputChannelId))
|
||||
{
|
||||
m_azChannelEvents.push_back(AzEventInfo(inputChannel));
|
||||
hasBeenConsumed = m_captureAzEvents;
|
||||
}
|
||||
else if (inputChannelId == AzFramework::InputDeviceMouse::Movement::Z)
|
||||
{
|
||||
m_azChannelEvents.push_back(AzEventInfo(inputChannel));
|
||||
hasBeenConsumed = m_captureAzEvents;
|
||||
}
|
||||
}
|
||||
else if (AzFramework::InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
|
||||
{
|
||||
m_azChannelEvents.push_back(AzEventInfo(inputChannel));
|
||||
hasBeenConsumed = m_captureAzEvents;
|
||||
}
|
||||
}
|
||||
|
||||
void OnInputTextEvent(const AZStd::string& textUtf8, bool& hasBeenConsumed) override
|
||||
{
|
||||
AZ_Assert(hasBeenConsumed == false, "Unexpected text event consumed elsewhere during QtEventToAzInputMapper tests");
|
||||
|
||||
m_azTextEvents.push_back(textUtf8);
|
||||
hasBeenConsumed = m_captureTextEvents;
|
||||
}
|
||||
|
||||
// simple structure for caching minimal QtEvent data necessary for testing
|
||||
struct QtEventInfo
|
||||
{
|
||||
explicit QtEventInfo(QMouseEvent* mouseEvent)
|
||||
: m_eventType(mouseEvent->type())
|
||||
, m_button(mouseEvent->button())
|
||||
{
|
||||
}
|
||||
|
||||
explicit QtEventInfo(QWheelEvent* mouseWheelEvent)
|
||||
: m_eventType(mouseWheelEvent->type())
|
||||
, m_scrollPhase(mouseWheelEvent->phase())
|
||||
{
|
||||
}
|
||||
|
||||
explicit QtEventInfo(QKeyEvent* keyEvent)
|
||||
: m_eventType(keyEvent->type())
|
||||
, m_key(keyEvent->key())
|
||||
{
|
||||
}
|
||||
|
||||
QEvent::Type m_eventType{ QEvent::None };
|
||||
Qt::MouseButton m_button{ Qt::NoButton };
|
||||
Qt::ScrollPhase m_scrollPhase{ Qt::NoScrollPhase };
|
||||
int m_key{ 0 };
|
||||
};
|
||||
|
||||
// simple structure for caching minimal AzInput event data necessary for testing
|
||||
struct AzEventInfo
|
||||
{
|
||||
AzEventInfo() = delete;
|
||||
explicit AzEventInfo(const AzFramework::InputChannel& inputChannel)
|
||||
: m_inputChannelId(inputChannel.GetInputChannelId())
|
||||
, m_isActive(inputChannel.IsActive())
|
||||
{
|
||||
}
|
||||
|
||||
AzFramework::InputChannelId m_inputChannelId;
|
||||
bool m_isActive;
|
||||
};
|
||||
|
||||
|
||||
AZStd::unique_ptr<QWidget> m_rootWidget;
|
||||
|
||||
AZStd::unique_ptr<AzToolsFramework::QtEventToAzInputMapper> m_inputChannelMapper;
|
||||
|
||||
AZStd::vector<QtEventInfo> m_signalEvents;
|
||||
AZStd::vector<AzEventInfo> m_azChannelEvents;
|
||||
AZStd::vector<AZStd::string> m_azTextEvents;
|
||||
|
||||
bool m_captureAzEvents{ false };
|
||||
bool m_captureTextEvents{ false };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Qt event forwarding through the internal signal handler test
|
||||
TEST_F(QtEventToAzInputMapperFixture, MouseWheel_NoAzHandlers_ReceivedThreeSignalAndZeroAzChannelEvents)
|
||||
{
|
||||
// setup
|
||||
const QPoint mouseEventPos = QPoint(WidgetSize.width() / 2, WidgetSize.height() / 2);
|
||||
const QPoint scrollDelta = QPoint(10, 10);
|
||||
|
||||
MouseScroll(m_rootWidget.get(), mouseEventPos, scrollDelta);
|
||||
|
||||
// qt validation
|
||||
ASSERT_EQ(m_signalEvents.size(), 3);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[0].m_eventType, QEvent::Type::Wheel);
|
||||
EXPECT_EQ(m_signalEvents[0].m_scrollPhase, Qt::ScrollBegin);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[1].m_eventType, QEvent::Type::Wheel);
|
||||
EXPECT_EQ(m_signalEvents[1].m_scrollPhase, Qt::ScrollUpdate);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[2].m_eventType, QEvent::Type::Wheel);
|
||||
EXPECT_EQ(m_signalEvents[2].m_scrollPhase, Qt::ScrollEnd);
|
||||
|
||||
// az validation
|
||||
EXPECT_EQ(m_azChannelEvents.size(), 0);
|
||||
}
|
||||
|
||||
// Qt event to AzInput event conversion test
|
||||
TEST_F(QtEventToAzInputMapperFixture, MouseWheel_AzHandlerNotCaptured_ReceivedThreeSignalAndThreeAzChannelEvents)
|
||||
{
|
||||
// setup
|
||||
const AzFramework::InputChannelId mouseWheelId = AzFramework::InputDeviceMouse::Movement::Z;
|
||||
const char* mouseWheelChannelName = mouseWheelId.GetName();
|
||||
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusConnect();
|
||||
m_captureAzEvents = false;
|
||||
|
||||
const QPoint mouseEventPos = QPoint(WidgetSize.width() / 2, WidgetSize.height() / 2);
|
||||
const QPoint scrollDelta = QPoint(10, 10);
|
||||
|
||||
MouseScroll(m_rootWidget.get(), mouseEventPos, scrollDelta);
|
||||
|
||||
// qt validation
|
||||
ASSERT_EQ(m_signalEvents.size(), 3);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[0].m_eventType, QEvent::Type::Wheel);
|
||||
EXPECT_EQ(m_signalEvents[0].m_scrollPhase, Qt::ScrollBegin);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[1].m_eventType, QEvent::Type::Wheel);
|
||||
EXPECT_EQ(m_signalEvents[1].m_scrollPhase, Qt::ScrollUpdate);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[2].m_eventType, QEvent::Type::Wheel);
|
||||
EXPECT_EQ(m_signalEvents[2].m_scrollPhase, Qt::ScrollEnd);
|
||||
|
||||
// az validation
|
||||
ASSERT_EQ(m_azChannelEvents.size(), 3);
|
||||
|
||||
EXPECT_STREQ(m_azChannelEvents[0].m_inputChannelId.GetName(), mouseWheelChannelName);
|
||||
EXPECT_STREQ(m_azChannelEvents[1].m_inputChannelId.GetName(), mouseWheelChannelName);
|
||||
EXPECT_STREQ(m_azChannelEvents[2].m_inputChannelId.GetName(), mouseWheelChannelName);
|
||||
|
||||
// cleanup
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
// AzInput event handler consumption test
|
||||
TEST_F(QtEventToAzInputMapperFixture, MouseWheel_AzHandlerCaptured_ReceivedZeroSignalAndThreeAzChannelEvents)
|
||||
{
|
||||
// setup
|
||||
const AzFramework::InputChannelId mouseWheelId = AzFramework::InputDeviceMouse::Movement::Z;
|
||||
const char* mouseWheelChannelName = mouseWheelId.GetName();
|
||||
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusConnect();
|
||||
m_captureAzEvents = true;
|
||||
|
||||
const QPoint mouseEventPos = QPoint(WidgetSize.width() / 2, WidgetSize.height() / 2);
|
||||
const QPoint scrollDelta = QPoint(10, 10);
|
||||
|
||||
MouseScroll(m_rootWidget.get(), mouseEventPos, scrollDelta);
|
||||
|
||||
// qt validation
|
||||
EXPECT_EQ(m_signalEvents.size(), 0);
|
||||
|
||||
// az validation
|
||||
ASSERT_EQ(m_azChannelEvents.size(), 3);
|
||||
|
||||
EXPECT_STREQ(m_azChannelEvents[0].m_inputChannelId.GetName(), mouseWheelChannelName);
|
||||
EXPECT_STREQ(m_azChannelEvents[1].m_inputChannelId.GetName(), mouseWheelChannelName);
|
||||
EXPECT_STREQ(m_azChannelEvents[2].m_inputChannelId.GetName(), mouseWheelChannelName);
|
||||
|
||||
// cleanup
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct MouseButtonIdsParam
|
||||
{
|
||||
Qt::MouseButton m_qt;
|
||||
AzFramework::InputChannelId m_az;
|
||||
};
|
||||
|
||||
class MouseButtonParamQtEventToAzInputMapperFixture
|
||||
: public QtEventToAzInputMapperFixture
|
||||
, public ::testing::WithParamInterface<MouseButtonIdsParam>
|
||||
{
|
||||
};
|
||||
|
||||
// Qt event forwarding through the internal signal handler test
|
||||
TEST_P(MouseButtonParamQtEventToAzInputMapperFixture, MouseClick_NoAzHandlers_ReceivedTwoSignalAndZeroAzChannelEvents)
|
||||
{
|
||||
// setup
|
||||
const MouseButtonIdsParam mouseButtonIds = GetParam();
|
||||
|
||||
const QPoint mouseEventPos = QPoint(WidgetSize.width() / 2, WidgetSize.height() / 2);
|
||||
QTest::mouseClick(m_rootWidget.get(), mouseButtonIds.m_qt, Qt::NoModifier, mouseEventPos);
|
||||
|
||||
// qt validation
|
||||
ASSERT_EQ(m_signalEvents.size(), 2);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[0].m_eventType, QEvent::Type::MouseButtonPress);
|
||||
EXPECT_EQ(m_signalEvents[0].m_button, mouseButtonIds.m_qt);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[1].m_eventType, QEvent::Type::MouseButtonRelease);
|
||||
EXPECT_EQ(m_signalEvents[1].m_button, mouseButtonIds.m_qt);
|
||||
|
||||
// az validation
|
||||
EXPECT_EQ(m_azChannelEvents.size(), 0);
|
||||
}
|
||||
|
||||
// Qt event to AzInput event conversion test
|
||||
TEST_P(MouseButtonParamQtEventToAzInputMapperFixture, MouseClick_AzHandlerNotCaptured_ReceivedTwoSignalAndTwoAzChannelEvents)
|
||||
{
|
||||
// setup
|
||||
const MouseButtonIdsParam mouseButtonIds = GetParam();
|
||||
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusConnect();
|
||||
m_captureAzEvents = false;
|
||||
|
||||
const QPoint mouseEventPos = QPoint(WidgetSize.width() / 2, WidgetSize.height() / 2);
|
||||
QTest::mouseClick(m_rootWidget.get(), mouseButtonIds.m_qt, Qt::NoModifier, mouseEventPos);
|
||||
|
||||
// qt validation
|
||||
ASSERT_EQ(m_signalEvents.size(), 2);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[0].m_eventType, QEvent::Type::MouseButtonPress);
|
||||
EXPECT_EQ(m_signalEvents[0].m_button, mouseButtonIds.m_qt);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[1].m_eventType, QEvent::Type::MouseButtonRelease);
|
||||
EXPECT_EQ(m_signalEvents[1].m_button, mouseButtonIds.m_qt);
|
||||
|
||||
// az validation
|
||||
ASSERT_EQ(m_azChannelEvents.size(), 2);
|
||||
|
||||
EXPECT_STREQ(m_azChannelEvents[0].m_inputChannelId.GetName(), mouseButtonIds.m_az.GetName());
|
||||
EXPECT_TRUE(m_azChannelEvents[0].m_isActive);
|
||||
|
||||
EXPECT_STREQ(m_azChannelEvents[1].m_inputChannelId.GetName(), mouseButtonIds.m_az.GetName());
|
||||
EXPECT_FALSE(m_azChannelEvents[1].m_isActive);
|
||||
|
||||
// cleanup
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
// AzInput event handler consumption test
|
||||
TEST_P(MouseButtonParamQtEventToAzInputMapperFixture, MouseClick_AzHandlerCaptured_ReceivedZeroSignalAndTwoAzChannelEvents)
|
||||
{
|
||||
// setup
|
||||
const MouseButtonIdsParam mouseButtonIds = GetParam();
|
||||
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusConnect();
|
||||
m_captureAzEvents = true;
|
||||
|
||||
const QPoint mouseEventPos = QPoint(WidgetSize.width() / 2, WidgetSize.height() / 2);
|
||||
QTest::mouseClick(m_rootWidget.get(), mouseButtonIds.m_qt, Qt::NoModifier, mouseEventPos);
|
||||
|
||||
// qt validation
|
||||
EXPECT_EQ(m_signalEvents.size(), 0);
|
||||
|
||||
// az validation
|
||||
ASSERT_EQ(m_azChannelEvents.size(), 2);
|
||||
|
||||
EXPECT_STREQ(m_azChannelEvents[0].m_inputChannelId.GetName(), mouseButtonIds.m_az.GetName());
|
||||
EXPECT_TRUE(m_azChannelEvents[0].m_isActive);
|
||||
|
||||
EXPECT_STREQ(m_azChannelEvents[1].m_inputChannelId.GetName(), mouseButtonIds.m_az.GetName());
|
||||
EXPECT_FALSE(m_azChannelEvents[1].m_isActive);
|
||||
|
||||
// cleanup
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(All, MouseButtonParamQtEventToAzInputMapperFixture,
|
||||
testing::Values(
|
||||
MouseButtonIdsParam{ Qt::MouseButton::LeftButton, AzFramework::InputDeviceMouse::Button::Left },
|
||||
MouseButtonIdsParam{ Qt::MouseButton::RightButton, AzFramework::InputDeviceMouse::Button::Right },
|
||||
MouseButtonIdsParam{ Qt::MouseButton::MiddleButton, AzFramework::InputDeviceMouse::Button::Middle }
|
||||
),
|
||||
[](const ::testing::TestParamInfo<MouseButtonIdsParam>& info)
|
||||
{
|
||||
return info.param.m_az.GetName();
|
||||
}
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct KeyEventIdsParam
|
||||
{
|
||||
Qt::Key m_qt;
|
||||
AzFramework::InputChannelId m_az;
|
||||
};
|
||||
|
||||
class PrintableKeyEventParamQtEventToAzInputMapperFixture
|
||||
: public QtEventToAzInputMapperFixture
|
||||
, public ::testing::WithParamInterface<KeyEventIdsParam>
|
||||
{
|
||||
};
|
||||
|
||||
// Qt event forwarding through the internal signal handler test
|
||||
TEST_P(PrintableKeyEventParamQtEventToAzInputMapperFixture, KeyClick_NoAzHandlers_ReceivedTwoSignalAndZeroAzEvents)
|
||||
{
|
||||
// setup
|
||||
const KeyEventIdsParam keyEventIds = GetParam();
|
||||
const Qt::KeyboardModifiers modifiers = Qt::NoModifier;
|
||||
|
||||
QTest::keyClick(m_rootWidget.get(), keyEventIds.m_qt, modifiers);
|
||||
|
||||
// qt validation
|
||||
ASSERT_EQ(m_signalEvents.size(), 2);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[0].m_eventType, QEvent::Type::KeyPress);
|
||||
EXPECT_EQ(m_signalEvents[0].m_key, keyEventIds.m_qt);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[1].m_eventType, QEvent::Type::KeyRelease);
|
||||
EXPECT_EQ(m_signalEvents[1].m_key, keyEventIds.m_qt);
|
||||
|
||||
// az validation
|
||||
EXPECT_EQ(m_azChannelEvents.size(), 0);
|
||||
EXPECT_EQ(m_azTextEvents.size(), 0);
|
||||
}
|
||||
|
||||
// Qt event to AzInput event conversion test
|
||||
TEST_P(PrintableKeyEventParamQtEventToAzInputMapperFixture, KeyClick_AzHandlersNotCaptured_ReceivedTwoSignalAndThreeAzEvents)
|
||||
{
|
||||
// setup
|
||||
const KeyEventIdsParam keyEventIds = GetParam();
|
||||
const Qt::KeyboardModifiers modifiers = Qt::NoModifier;
|
||||
|
||||
AZStd::string keyAsText = QtKeyToAzString(keyEventIds.m_qt, modifiers);
|
||||
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusConnect();
|
||||
m_captureAzEvents = false;
|
||||
|
||||
AzFramework::InputTextNotificationBus::Handler::BusConnect();
|
||||
m_captureAzEvents = false;
|
||||
|
||||
QTest::keyClick(m_rootWidget.get(), keyEventIds.m_qt, modifiers);
|
||||
|
||||
// qt validation
|
||||
ASSERT_EQ(m_signalEvents.size(), 2);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[0].m_eventType, QEvent::Type::KeyPress);
|
||||
EXPECT_EQ(m_signalEvents[0].m_key, keyEventIds.m_qt);
|
||||
|
||||
EXPECT_EQ(m_signalEvents[1].m_eventType, QEvent::Type::KeyRelease);
|
||||
EXPECT_EQ(m_signalEvents[1].m_key, keyEventIds.m_qt);
|
||||
|
||||
// az validation
|
||||
ASSERT_EQ(m_azTextEvents.size(), 1);
|
||||
|
||||
EXPECT_STREQ(m_azTextEvents[0].c_str(), keyAsText.c_str());
|
||||
|
||||
ASSERT_EQ(m_azChannelEvents.size(), 2);
|
||||
|
||||
EXPECT_STREQ(m_azChannelEvents[0].m_inputChannelId.GetName(), keyEventIds.m_az.GetName());
|
||||
EXPECT_TRUE(m_azChannelEvents[0].m_isActive);
|
||||
|
||||
EXPECT_STREQ(m_azChannelEvents[1].m_inputChannelId.GetName(), keyEventIds.m_az.GetName());
|
||||
EXPECT_FALSE(m_azChannelEvents[1].m_isActive);
|
||||
|
||||
// cleanup
|
||||
AzFramework::InputTextNotificationBus::Handler::BusDisconnect();
|
||||
AzFramework::InputChannelNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(All, PrintableKeyEventParamQtEventToAzInputMapperFixture,
|
||||
testing::Values(
|
||||
KeyEventIdsParam{ Qt::Key_0, AzFramework::InputDeviceKeyboard::Key::Alphanumeric0 },
|
||||
KeyEventIdsParam{ Qt::Key_1, AzFramework::InputDeviceKeyboard::Key::Alphanumeric1 },
|
||||
KeyEventIdsParam{ Qt::Key_2, AzFramework::InputDeviceKeyboard::Key::Alphanumeric2 },
|
||||
KeyEventIdsParam{ Qt::Key_3, AzFramework::InputDeviceKeyboard::Key::Alphanumeric3 },
|
||||
KeyEventIdsParam{ Qt::Key_4, AzFramework::InputDeviceKeyboard::Key::Alphanumeric4 },
|
||||
KeyEventIdsParam{ Qt::Key_5, AzFramework::InputDeviceKeyboard::Key::Alphanumeric5 },
|
||||
KeyEventIdsParam{ Qt::Key_6, AzFramework::InputDeviceKeyboard::Key::Alphanumeric6 },
|
||||
KeyEventIdsParam{ Qt::Key_7, AzFramework::InputDeviceKeyboard::Key::Alphanumeric7 },
|
||||
KeyEventIdsParam{ Qt::Key_8, AzFramework::InputDeviceKeyboard::Key::Alphanumeric8 },
|
||||
KeyEventIdsParam{ Qt::Key_9, AzFramework::InputDeviceKeyboard::Key::Alphanumeric9 },
|
||||
|
||||
KeyEventIdsParam{ Qt::Key_A, AzFramework::InputDeviceKeyboard::Key::AlphanumericA },
|
||||
KeyEventIdsParam{ Qt::Key_B, AzFramework::InputDeviceKeyboard::Key::AlphanumericB },
|
||||
KeyEventIdsParam{ Qt::Key_C, AzFramework::InputDeviceKeyboard::Key::AlphanumericC },
|
||||
KeyEventIdsParam{ Qt::Key_D, AzFramework::InputDeviceKeyboard::Key::AlphanumericD },
|
||||
KeyEventIdsParam{ Qt::Key_E, AzFramework::InputDeviceKeyboard::Key::AlphanumericE },
|
||||
KeyEventIdsParam{ Qt::Key_F, AzFramework::InputDeviceKeyboard::Key::AlphanumericF },
|
||||
KeyEventIdsParam{ Qt::Key_G, AzFramework::InputDeviceKeyboard::Key::AlphanumericG },
|
||||
KeyEventIdsParam{ Qt::Key_H, AzFramework::InputDeviceKeyboard::Key::AlphanumericH },
|
||||
KeyEventIdsParam{ Qt::Key_I, AzFramework::InputDeviceKeyboard::Key::AlphanumericI },
|
||||
KeyEventIdsParam{ Qt::Key_J, AzFramework::InputDeviceKeyboard::Key::AlphanumericJ },
|
||||
KeyEventIdsParam{ Qt::Key_K, AzFramework::InputDeviceKeyboard::Key::AlphanumericK },
|
||||
KeyEventIdsParam{ Qt::Key_L, AzFramework::InputDeviceKeyboard::Key::AlphanumericL },
|
||||
KeyEventIdsParam{ Qt::Key_M, AzFramework::InputDeviceKeyboard::Key::AlphanumericM },
|
||||
KeyEventIdsParam{ Qt::Key_N, AzFramework::InputDeviceKeyboard::Key::AlphanumericN },
|
||||
KeyEventIdsParam{ Qt::Key_O, AzFramework::InputDeviceKeyboard::Key::AlphanumericO },
|
||||
KeyEventIdsParam{ Qt::Key_P, AzFramework::InputDeviceKeyboard::Key::AlphanumericP },
|
||||
KeyEventIdsParam{ Qt::Key_Q, AzFramework::InputDeviceKeyboard::Key::AlphanumericQ },
|
||||
KeyEventIdsParam{ Qt::Key_R, AzFramework::InputDeviceKeyboard::Key::AlphanumericR },
|
||||
KeyEventIdsParam{ Qt::Key_S, AzFramework::InputDeviceKeyboard::Key::AlphanumericS },
|
||||
KeyEventIdsParam{ Qt::Key_T, AzFramework::InputDeviceKeyboard::Key::AlphanumericT },
|
||||
KeyEventIdsParam{ Qt::Key_U, AzFramework::InputDeviceKeyboard::Key::AlphanumericU },
|
||||
KeyEventIdsParam{ Qt::Key_V, AzFramework::InputDeviceKeyboard::Key::AlphanumericV },
|
||||
KeyEventIdsParam{ Qt::Key_W, AzFramework::InputDeviceKeyboard::Key::AlphanumericW },
|
||||
KeyEventIdsParam{ Qt::Key_X, AzFramework::InputDeviceKeyboard::Key::AlphanumericX },
|
||||
KeyEventIdsParam{ Qt::Key_Y, AzFramework::InputDeviceKeyboard::Key::AlphanumericY },
|
||||
KeyEventIdsParam{ Qt::Key_Z, AzFramework::InputDeviceKeyboard::Key::AlphanumericZ },
|
||||
|
||||
// these may need to be special cased due to the printable text conversion
|
||||
//KeyEventIdsParam{ Qt::Key_Space, AzFramework::InputDeviceKeyboard::Key::EditSpace },
|
||||
//KeyEventIdsParam{ Qt::Key_Tab, AzFramework::InputDeviceKeyboard::Key::EditTab },
|
||||
|
||||
KeyEventIdsParam{ Qt::Key_Apostrophe, AzFramework::InputDeviceKeyboard::Key::PunctuationApostrophe },
|
||||
KeyEventIdsParam{ Qt::Key_Backslash, AzFramework::InputDeviceKeyboard::Key::PunctuationBackslash },
|
||||
KeyEventIdsParam{ Qt::Key_BracketLeft, AzFramework::InputDeviceKeyboard::Key::PunctuationBracketL },
|
||||
KeyEventIdsParam{ Qt::Key_BracketRight, AzFramework::InputDeviceKeyboard::Key::PunctuationBracketR },
|
||||
KeyEventIdsParam{ Qt::Key_Comma, AzFramework::InputDeviceKeyboard::Key::PunctuationComma },
|
||||
KeyEventIdsParam{ Qt::Key_Equal, AzFramework::InputDeviceKeyboard::Key::PunctuationEquals },
|
||||
KeyEventIdsParam{ Qt::Key_hyphen, AzFramework::InputDeviceKeyboard::Key::PunctuationHyphen },
|
||||
KeyEventIdsParam{ Qt::Key_Period, AzFramework::InputDeviceKeyboard::Key::PunctuationPeriod },
|
||||
KeyEventIdsParam{ Qt::Key_Semicolon, AzFramework::InputDeviceKeyboard::Key::PunctuationSemicolon },
|
||||
KeyEventIdsParam{ Qt::Key_Slash, AzFramework::InputDeviceKeyboard::Key::PunctuationSlash },
|
||||
KeyEventIdsParam{ Qt::Key_QuoteLeft, AzFramework::InputDeviceKeyboard::Key::PunctuationTilde }
|
||||
),
|
||||
[](const ::testing::TestParamInfo<KeyEventIdsParam>& info)
|
||||
{
|
||||
return info.param.m_az.GetName();
|
||||
}
|
||||
);
|
||||
} // namespace UnitTest
|
||||
@@ -6,18 +6,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Component/ComponentApplicationLifecycle.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzTest/AzTest.h>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
using namespace AZ;
|
||||
|
||||
// Handle asserts
|
||||
class ToolsFrameworkHook
|
||||
: public AZ::Test::ITestEnvironment
|
||||
@@ -25,12 +24,12 @@ class ToolsFrameworkHook
|
||||
public:
|
||||
void SetupEnvironment() override
|
||||
{
|
||||
AllocatorInstance<SystemAllocator>::Create();
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
|
||||
}
|
||||
|
||||
void TeardownEnvironment() override
|
||||
{
|
||||
AllocatorInstance<SystemAllocator>::Destroy();
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -38,12 +37,17 @@ AZTEST_EXPORT int AZ_UNIT_TEST_HOOK_NAME(int argc, char** argv)
|
||||
{
|
||||
::testing::InitGoogleMock(&argc, argv);
|
||||
QApplication app(argc, argv);
|
||||
auto styleManager = AZStd::make_unique< AzQtComponents::StyleManager>(&app);
|
||||
auto styleManager = AZStd::make_unique<AzQtComponents::StyleManager>(&app);
|
||||
AZ::IO::FixedMaxPath engineRootPath;
|
||||
{
|
||||
AZ::ComponentApplication componentApplication(argc, argv);
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
|
||||
|
||||
AZ::ComponentApplicationLifecycle::RegisterEvent(*settingsRegistry, "SystemComponentsDeactivated");
|
||||
AZ::ComponentApplicationLifecycle::RegisterEvent(*settingsRegistry, "ConsoleUnavailable");
|
||||
AZ::ComponentApplicationLifecycle::RegisterEvent(*settingsRegistry, "SettingsRegistryUnavailable");
|
||||
AZ::ComponentApplicationLifecycle::RegisterEvent(*settingsRegistry, "SystemAllocatorPendingDestruction");
|
||||
}
|
||||
styleManager->initialize(&app, engineRootPath);
|
||||
AZ::Test::printUnusedParametersWarning(argc, argv);
|
||||
|
||||
@@ -176,7 +176,6 @@ namespace UnitTest
|
||||
TEST_F(PrefabFixupTest, Test_LoadInstanceFromPrefabDom_Overload3)
|
||||
{
|
||||
Instance instance;
|
||||
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>> referencedAssets;
|
||||
Instance::EntityList entityList;
|
||||
(PrefabDomUtils::LoadInstanceFromPrefabDom(instance, entityList, m_prefabDom));
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ set(FILES
|
||||
FocusMode/EditorFocusModeSelectionTests.cpp
|
||||
FocusMode/EditorFocusModeTests.cpp
|
||||
GenericComponentWrapperTest.cpp
|
||||
Input/QtEventToAzInputMapperTests.cpp
|
||||
InstanceDataHierarchy.cpp
|
||||
IntegerPrimtitiveTestConfig.h
|
||||
LogLines.cpp
|
||||
|
||||
@@ -1080,7 +1080,7 @@ AZ_POP_DISABLE_WARNING
|
||||
{
|
||||
m_pUserCallback->OnInitProgress("Initializing additional systems...");
|
||||
}
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Initializing additional systems");
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Initializing additional systems\n");
|
||||
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init AIInit");
|
||||
|
||||
@@ -10,12 +10,7 @@
|
||||
{
|
||||
"Name": "DepthStencilTextureInput",
|
||||
"SlotType": "Input",
|
||||
"ScopeAttachmentUsage": "Shader",
|
||||
"ImageViewDesc": {
|
||||
"AspectFlags": [
|
||||
"Depth"
|
||||
]
|
||||
}
|
||||
"ScopeAttachmentUsage": "Shader"
|
||||
},
|
||||
{
|
||||
"Name": "NormalInput",
|
||||
|
||||
@@ -74,7 +74,7 @@ struct TileLightData
|
||||
|
||||
bool Light_IsInsideBin(uint package, uint bin)
|
||||
{
|
||||
return (package & (1 << bin)) != 0;
|
||||
return (package & (1u << bin)) != 0;
|
||||
}
|
||||
|
||||
uint PackLightIndexWithBinMask(uint ind, uint bins)
|
||||
@@ -130,7 +130,7 @@ uint NVLC_GetBin(const float viewZ, const TileLightData data)
|
||||
const float zFarCoordSystemAdjusted = data.zFar * RH_COORD_SYSTEM_REVERSE;
|
||||
|
||||
float f = saturate( (abs(viewZCoordSystemAdjusted) - zNearCoordSystemAdjusted) / (zFarCoordSystemAdjusted - zNearCoordSystemAdjusted) );
|
||||
float bin = min(f, 0.999999) * float(1 << data.logMaxBins);
|
||||
float bin = min(f, 0.999999) * float(1u << data.logMaxBins);
|
||||
|
||||
return uint(bin);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ void ApplyDecal(uint currDecalIndex, inout Surface surface)
|
||||
localPos = mul(decalRot, localPos);
|
||||
|
||||
float3 decalUVW = localPos * rcp(decal.m_halfSize);
|
||||
|
||||
[branch]
|
||||
if(decalUVW.x >= -1.0f && decalUVW.x <= 1.0f &&
|
||||
decalUVW.y >= -1.0f && decalUVW.y <= 1.0f &&
|
||||
decalUVW.z >= -1.0f && decalUVW.z <= 1.0f)
|
||||
@@ -72,6 +74,7 @@ void ApplyDecal(uint currDecalIndex, inout Surface surface)
|
||||
float2 normalMap = 0;
|
||||
// Each texture array handles a size permutation.
|
||||
// e.g. it could be that tex array 0 handles 256x256 and tex array 1 handles 512x64, etc.
|
||||
[branch]
|
||||
switch(textureArrayIndex)
|
||||
{
|
||||
case 0:
|
||||
|
||||
@@ -127,9 +127,9 @@ namespace AZ
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
ImageSubresourceLayoutPlaced() = default;
|
||||
ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, size_t offset);
|
||||
ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, uint32_t offset);
|
||||
|
||||
size_t m_offset = 0;
|
||||
uint32_t m_offset = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,78 +40,94 @@ namespace AZ
|
||||
public:
|
||||
FrameGraphAttachmentDatabase() = default;
|
||||
|
||||
/// Clears the database back to an empty state.
|
||||
//! Clears the database back to an empty state.
|
||||
void Clear();
|
||||
|
||||
/// Imports an image into the database.
|
||||
//! Imports an image into the database.
|
||||
ResultCode ImportImage(const AttachmentId& attachmentId, Ptr<Image> image);
|
||||
|
||||
/// Imports a swapchain into the database.
|
||||
//! Imports a swapchain into the database.
|
||||
ResultCode ImportSwapChain(const AttachmentId& attachmentId, Ptr<SwapChain> swapChain);
|
||||
|
||||
/// Imports a buffer into the database.
|
||||
//! Imports a buffer into the database.
|
||||
ResultCode ImportBuffer(const AttachmentId& attachmentId, Ptr<Buffer> buffer);
|
||||
|
||||
/// Creates a transient image and inserts it into the database.
|
||||
//! Creates a transient image and inserts it into the database.
|
||||
ResultCode CreateTransientImage(const TransientImageDescriptor& descriptor);
|
||||
|
||||
/// Creates a transient buffer and inserts it into the database.
|
||||
//! Creates a transient buffer and inserts it into the database.
|
||||
ResultCode CreateTransientBuffer(const TransientBufferDescriptor& descriptor);
|
||||
|
||||
/// Finds the attachment associated with \param attachmentId and returns its image descriptor.
|
||||
//! Finds the attachment associated with \param attachmentId and returns its image descriptor.
|
||||
ImageDescriptor GetImageDescriptor(const AttachmentId& attachmentId) const;
|
||||
|
||||
/// Finds the attachment associated with \param attachmentId and returns its buffer descriptor.
|
||||
//! Finds the attachment associated with \param attachmentId and returns its buffer descriptor.
|
||||
BufferDescriptor GetBufferDescriptor(const AttachmentId& attachmentId) const;
|
||||
|
||||
/// Returns whether the attachment exists in the database.
|
||||
//! Returns whether the attachment exists in the database.
|
||||
bool IsAttachmentValid(const AttachmentId& attachmentId) const;
|
||||
|
||||
/// Finds an attachment associated with \param attachmentId.
|
||||
//! Finds an attachment associated with \param attachmentId.
|
||||
const FrameAttachment* FindAttachment(const AttachmentId& attachmentId) const;
|
||||
FrameAttachment* FindAttachment(const AttachmentId& attachmentId);
|
||||
|
||||
/// Finds an attachment associated with \param attachmentId and attempts to cast
|
||||
/// to the requested type. Will return null if the type is not compatible, or the
|
||||
/// attachment was not found.
|
||||
//! Finds an attachment associated with \param attachmentId and attempts to cast
|
||||
//! to the requested type. Will return null if the type is not compatible, or the
|
||||
//! attachment was not found.
|
||||
template <typename AttachmentType>
|
||||
const AttachmentType* FindAttachment(const AttachmentId& attachmentId) const;
|
||||
|
||||
template <typename AttachmentType>
|
||||
AttachmentType* FindAttachment(const AttachmentId& attachmentId);
|
||||
|
||||
/// Returns the full list of attachments.
|
||||
//! Returns the full list of attachments.
|
||||
const AZStd::vector<FrameAttachment*>& GetAttachments() const;
|
||||
|
||||
/// Returns the full list of image attachments.
|
||||
//! Returns the full list of image attachments.
|
||||
const AZStd::vector<ImageFrameAttachment*>& GetImageAttachments() const;
|
||||
|
||||
/// Returns the full list of buffer attachments.
|
||||
//! Returns the full list of buffer attachments.
|
||||
const AZStd::vector<BufferFrameAttachment*>& GetBufferAttachments() const;
|
||||
|
||||
/// Returns the transient swap chain attachments registered in the graph.
|
||||
//! Returns the transient swap chain attachments registered in the graph.
|
||||
const AZStd::vector<SwapChainFrameAttachment*>& GetSwapChainAttachments() const;
|
||||
|
||||
/// Returns the imported image attachments registered in the graph.
|
||||
//! Returns the imported image attachments registered in the graph.
|
||||
const AZStd::vector<ImageFrameAttachment*>& GetImportedImageAttachments() const;
|
||||
|
||||
/// Returns the imported buffer attachments registered in the graph.
|
||||
//! Returns the imported buffer attachments registered in the graph.
|
||||
const AZStd::vector<BufferFrameAttachment*>& GetImportedBufferAttachments() const;
|
||||
|
||||
/// Returns the transient image attachments registered in the graph.
|
||||
//! Returns the transient image attachments registered in the graph.
|
||||
const AZStd::vector<ImageFrameAttachment*>& GetTransientImageAttachments() const;
|
||||
|
||||
/// Returns the transient buffer attachments registered in the graph.
|
||||
//! Returns the transient buffer attachments registered in the graph.
|
||||
const AZStd::vector<BufferFrameAttachment*>& GetTransientBufferAttachments() const;
|
||||
|
||||
/// Finds the list of scope attachments used by a scope for the given attachment.
|
||||
//! Finds the list of scope attachments used by a scope for the given attachment.
|
||||
const ScopeAttachmentPtrList* FindScopeAttachmentList(const ScopeId& scopeId, const AttachmentId& attachmentId) const;
|
||||
|
||||
/// Finds the scope attachment used by a scope for the given attachment. If multiple scope attachments are used for the
|
||||
/// same attachment (like binding multiple mips of a texture), the index parameter will specify which one to select.
|
||||
const ScopeAttachment* FindScopeAttachment(const ScopeId& scopeId, const AttachmentId& attachmentId, size_t index = 0) const;
|
||||
//! Finds the scope attachment used by a scope for the given attachment
|
||||
const ScopeAttachment* FindScopeAttachment(const ScopeId& scopeId, const AttachmentId& attachmentId) const;
|
||||
|
||||
/// Returns the full list of scope attachments.
|
||||
//! Finds the scope attachment used by a scope for the given attachment. If multiple scope image attachments are used for the
|
||||
//! same attachment, provide ScopeAttachmentUsage (in case attachments are merged) and
|
||||
//! ImageViewDescriptor (in case the attachments are different based on view, i.e different mips or aspect of a texture) to ensure
|
||||
//! that the correct scope attachment is returned.
|
||||
const ScopeAttachment* FindScopeAttachment(
|
||||
const ScopeId& scopeId,
|
||||
const AttachmentId& attachmentId,
|
||||
const ImageViewDescriptor& imageViewDescriptor,
|
||||
const RHI::ScopeAttachmentUsage attachmentUsage) const;
|
||||
|
||||
//! Finds the scope attachment used by a scope for the given attachment. If multiple scope attachments are used for the same attachment
|
||||
//! provide attachmentUsage to ensure that the correct scope attachment is returned
|
||||
const ScopeAttachment* FindScopeAttachment(
|
||||
const ScopeId& scopeId,
|
||||
const AttachmentId& attachmentId,
|
||||
const RHI::ScopeAttachmentUsage attachmentUsage) const;
|
||||
|
||||
//! Returns the full list of scope attachments.
|
||||
const ScopeAttachmentPtrList& GetScopeAttachments() const;
|
||||
|
||||
template <typename ScopeAttachmentType, typename... Args>
|
||||
@@ -120,8 +136,8 @@ namespace AZ
|
||||
FrameAttachment& attachment,
|
||||
Args&&... arguments);
|
||||
|
||||
/// Emplaces a use of a resource pool by a specific scope. Returns the ScopeId of the most recent use of the pool or en empty
|
||||
/// ScopeId if this is the first use.
|
||||
//! Emplaces a use of a resource pool by a specific scope. Returns the ScopeId of the most recent use of the pool or en empty
|
||||
//! ScopeId if this is the first use.
|
||||
ScopeId EmplaceResourcePoolUse(ResourcePool& pool, ScopeId scopeId);
|
||||
|
||||
private:
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI.Reflect/AttachmentId.h>
|
||||
#include <Atom/RHI.Reflect/AttachmentEnums.h>
|
||||
#include <Atom/RHI.Reflect/ScopeId.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -19,15 +20,15 @@ namespace AZ
|
||||
class BufferView;
|
||||
class Image;
|
||||
class ImageView;
|
||||
class ScopeAttachment;
|
||||
struct BufferDescriptor;
|
||||
struct ImageDescriptor;
|
||||
struct ImageViewDescriptor;
|
||||
|
||||
/**
|
||||
* FrameGraphCompileContext provides access to compiled image and buffer views
|
||||
* associated with the provided scope id, along with other query methods for
|
||||
* accessing attachment resource data. This information can be used to
|
||||
* compile ShaderResourceGroups.
|
||||
*/
|
||||
//! FrameGraphCompileContext provides access to compiled image and buffer views
|
||||
//! associated with the provided scope id, along with other query methods for
|
||||
//! accessing attachment resource data. This information can be used to
|
||||
//! compile ShaderResourceGroups.
|
||||
class FrameGraphCompileContext
|
||||
{
|
||||
public:
|
||||
@@ -37,31 +38,46 @@ namespace AZ
|
||||
const ScopeId& scopeId,
|
||||
const FrameGraphAttachmentDatabase& attachmentDatabase);
|
||||
|
||||
/// Returns the scope id associated with this context.
|
||||
//! Returns the scope id associated with this context.
|
||||
const ScopeId& GetScopeId() const;
|
||||
|
||||
/// Returns whether the given attachment id is valid within the current frame.
|
||||
//! Returns whether the given attachment id is valid within the current frame.
|
||||
bool IsAttachmentValid(const AttachmentId& attachmentId) const;
|
||||
|
||||
/// Returns the number of scope attachments used by the current scope for the given attachment
|
||||
//! Returns the number of scope attachments used by the current scope for the given attachment
|
||||
const size_t GetScopeAttachmentCount(const AttachmentId& attachmentId) const;
|
||||
|
||||
/// Returns the buffer view associated with usage on the current scope.
|
||||
const BufferView* GetBufferView(const AttachmentId& attachmentId, size_t index = 0) const;
|
||||
//! Returns the buffer view associated with the scope attachment.
|
||||
const BufferView* GetBufferView(const ScopeAttachment* scopeAttachment) const;
|
||||
|
||||
/// Returns the buffer associated with usage on the current scope.
|
||||
//! Returns the buffer view associated with the attachmentId.
|
||||
const BufferView* GetBufferView(const AttachmentId& attachmentId) const;
|
||||
|
||||
//! Returns the buffer view associated with attachmentId and the attachmentUsage on the current scope.
|
||||
const BufferView* GetBufferView(const AttachmentId& attachmentId, RHI::ScopeAttachmentUsage attachmentUsage) const;
|
||||
|
||||
//! Returns the buffer associated with attachmentId.
|
||||
const Buffer* GetBuffer(const AttachmentId& attachmentId) const;
|
||||
|
||||
/// Returns the image view associated with usage on the current scope.
|
||||
const ImageView* GetImageView(const AttachmentId& attachmentId, size_t index = 0) const;
|
||||
//! Returns the image view associated with the scope attachment
|
||||
const ImageView* GetImageView(const ScopeAttachment* scopeAttacment) const;
|
||||
|
||||
/// Returns the image associated with usage on the current scope.
|
||||
//! Returns the image view associated with attachmentId, attachmentUsage and imageViewDescriptor on the current scope.
|
||||
const ImageView* GetImageView(
|
||||
const AttachmentId& attachmentId,
|
||||
const ImageViewDescriptor& imageViewDescriptor,
|
||||
const RHI::ScopeAttachmentUsage attachmentUsage) const;
|
||||
|
||||
//! Returns the image view associated with the attachmentId.
|
||||
const ImageView* GetImageView(const AttachmentId& attachmentId) const;
|
||||
|
||||
//! Returns the image associated with the attachmentId.
|
||||
const Image* GetImage(const AttachmentId& attachmentId) const;
|
||||
|
||||
/// Returns the buffer descriptor for the given attachment id.
|
||||
//! Returns the buffer descriptor for the given attachment id.
|
||||
BufferDescriptor GetBufferDescriptor(const AttachmentId& attachmentId) const;
|
||||
|
||||
/// Returns the image descriptor for the given attachment id.
|
||||
//! Returns the image descriptor for the given attachment id.
|
||||
ImageDescriptor GetImageDescriptor(const AttachmentId& attachmentId) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -142,9 +142,6 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
// [GFX TODO][ATOM-1669]: Review if it's needed to validate
|
||||
// overlapping of ranges.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace AZ
|
||||
, m_blockElementHeight{blockElementHeight}
|
||||
{}
|
||||
|
||||
ImageSubresourceLayoutPlaced::ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, size_t offset)
|
||||
ImageSubresourceLayoutPlaced::ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, uint32_t offset)
|
||||
: ImageSubresourceLayout(subresourceLayout)
|
||||
, m_offset{offset}
|
||||
{}
|
||||
|
||||
@@ -209,7 +209,11 @@ namespace AZ
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ScopeAttachment* FrameGraphAttachmentDatabase::FindScopeAttachment(const ScopeId& scopeId, const AttachmentId& attachmentId, size_t index) const
|
||||
const ScopeAttachment* FrameGraphAttachmentDatabase::FindScopeAttachment(
|
||||
const ScopeId& scopeId,
|
||||
const AttachmentId& attachmentId,
|
||||
const ImageViewDescriptor& imageViewDescriptor,
|
||||
const RHI::ScopeAttachmentUsage attachmentUsage) const
|
||||
{
|
||||
const ScopeAttachmentPtrList* scopeAttachmentList = FindScopeAttachmentList(scopeId, attachmentId);
|
||||
if (!scopeAttachmentList)
|
||||
@@ -217,21 +221,93 @@ namespace AZ
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (index >= scopeAttachmentList->size())
|
||||
if (scopeAttachmentList->size() > 1)
|
||||
{
|
||||
AZ_Error("AttachmentDatabase", false,
|
||||
"Attempting to access scope attachment [%d], but list only has [%d] elements. ScopeId: [%s]. AttachmentId: [%s]",
|
||||
index,
|
||||
scopeAttachmentList->size(),
|
||||
scopeId.GetCStr(),
|
||||
attachmentId.GetCStr());
|
||||
//Find the attachment with the same view and usage
|
||||
auto findIter = AZStd::find_if(scopeAttachmentList->begin(), scopeAttachmentList->end(), [&](const ScopeAttachment* scopeAttacment)
|
||||
{
|
||||
const ImageScopeAttachment* imageAttachment = azrtti_cast<const ImageScopeAttachment*>(scopeAttacment);
|
||||
bool isSameView = imageAttachment->GetDescriptor().m_imageViewDescriptor.IsSameSubResource(imageViewDescriptor);
|
||||
|
||||
if (isSameView)
|
||||
{
|
||||
AZStd::vector<ScopeAttachmentUsageAndAccess> usageAndAccessVec = imageAttachment->GetUsageAndAccess();
|
||||
auto usageAccessIter = AZStd::find_if(usageAndAccessVec.begin(), usageAndAccessVec.end(), [&](const ScopeAttachmentUsageAndAccess usageAndAccess)
|
||||
{
|
||||
return usageAndAccess.m_usage == attachmentUsage;
|
||||
});
|
||||
|
||||
return usageAccessIter != usageAndAccessVec.end();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (findIter != scopeAttachmentList->end())
|
||||
{
|
||||
return *findIter;
|
||||
}
|
||||
|
||||
AZ_Error("AttachmentDatabase", false, "Couldnt find ScopeAttachment %s with the same view and usage for scope %s", attachmentId.GetCStr(), scopeId.GetCStr());
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*scopeAttachmentList)[0];
|
||||
}
|
||||
}
|
||||
|
||||
const ScopeAttachment* FrameGraphAttachmentDatabase::FindScopeAttachment(
|
||||
const ScopeId& scopeId,
|
||||
const AttachmentId& attachmentId,
|
||||
const RHI::ScopeAttachmentUsage attachmentUsage) const
|
||||
{
|
||||
const ScopeAttachmentPtrList* scopeAttachmentList = FindScopeAttachmentList(scopeId, attachmentId);
|
||||
if (!scopeAttachmentList)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return (*scopeAttachmentList)[index];
|
||||
}
|
||||
//More than one entry indicates that the same attachment is used multiple times in a scope.
|
||||
if (scopeAttachmentList->size() > 1)
|
||||
{
|
||||
//Find the attachment with the same usage
|
||||
auto findIter = AZStd::find_if(scopeAttachmentList->begin(), scopeAttachmentList->end(), [&](const ScopeAttachment* scopeAttacment)
|
||||
{
|
||||
AZStd::vector<ScopeAttachmentUsageAndAccess> usageAndAccessVec = scopeAttacment->GetUsageAndAccess();
|
||||
auto usageAccessIter = AZStd::find_if(usageAndAccessVec.begin(), usageAndAccessVec.end(), [&](const ScopeAttachmentUsageAndAccess usageAndAccess)
|
||||
{
|
||||
return usageAndAccess.m_usage == attachmentUsage;
|
||||
});
|
||||
|
||||
return usageAccessIter != usageAndAccessVec.end();
|
||||
});
|
||||
|
||||
if (findIter != scopeAttachmentList->end())
|
||||
{
|
||||
return *findIter;
|
||||
}
|
||||
|
||||
AZ_Error("AttachmentDatabase", false, "Couldnt find ScopeAttachment %s with the same view and usage for scope %s", attachmentId.GetCStr(), scopeId.GetCStr());
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*scopeAttachmentList)[0];
|
||||
}
|
||||
}
|
||||
|
||||
const ScopeAttachment* FrameGraphAttachmentDatabase::FindScopeAttachment(const ScopeId& scopeId, const AttachmentId& attachmentId) const
|
||||
{
|
||||
const ScopeAttachmentPtrList* scopeAttachmentList = FindScopeAttachmentList(scopeId, attachmentId);
|
||||
if (!scopeAttachmentList)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AZ_Error( "AttachmentDatabase", scopeAttachmentList->size() > 0, "Couldnt fine Scopeattachment %s for scope %s", attachmentId.GetCStr(), scopeId.GetCStr());
|
||||
return (*scopeAttachmentList)[0];
|
||||
}
|
||||
|
||||
const AZStd::vector<ImageFrameAttachment*>& FrameGraphAttachmentDatabase::GetImageAttachments() const
|
||||
{
|
||||
return m_imageAttachments;
|
||||
|
||||
@@ -40,9 +40,8 @@ namespace AZ
|
||||
return 0;
|
||||
}
|
||||
|
||||
const BufferView* FrameGraphCompileContext::GetBufferView(const AttachmentId& attachmentId, size_t index) const
|
||||
const BufferView* FrameGraphCompileContext::GetBufferView(const ScopeAttachment* scopeAttacment) const
|
||||
{
|
||||
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId, index);
|
||||
const BufferScopeAttachment* attachment = azrtti_cast<const BufferScopeAttachment*>(scopeAttacment);
|
||||
if (!attachment)
|
||||
{
|
||||
@@ -51,6 +50,18 @@ namespace AZ
|
||||
return attachment->GetBufferView();
|
||||
}
|
||||
|
||||
const BufferView* FrameGraphCompileContext::GetBufferView(const AttachmentId& attachmentId) const
|
||||
{
|
||||
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId);
|
||||
return GetBufferView(scopeAttacment);
|
||||
}
|
||||
|
||||
const BufferView* FrameGraphCompileContext::GetBufferView(const AttachmentId& attachmentId, const RHI::ScopeAttachmentUsage attachmentUsage) const
|
||||
{
|
||||
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId, attachmentUsage);
|
||||
return GetBufferView(scopeAttacment);
|
||||
}
|
||||
|
||||
const Buffer* FrameGraphCompileContext::GetBuffer(const AttachmentId& attachmentId) const
|
||||
{
|
||||
const BufferView* bufferView = GetBufferView(attachmentId);
|
||||
@@ -61,9 +72,8 @@ namespace AZ
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ImageView* FrameGraphCompileContext::GetImageView(const AttachmentId& attachmentId, size_t index) const
|
||||
const ImageView* FrameGraphCompileContext::GetImageView(const ScopeAttachment* scopeAttacment) const
|
||||
{
|
||||
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId, index);
|
||||
const ImageScopeAttachment* attachment = azrtti_cast<const ImageScopeAttachment*>(scopeAttacment);
|
||||
if (!attachment)
|
||||
{
|
||||
@@ -72,6 +82,18 @@ namespace AZ
|
||||
return attachment->GetImageView();
|
||||
}
|
||||
|
||||
const ImageView* FrameGraphCompileContext::GetImageView(const AttachmentId& attachmentId, const ImageViewDescriptor& imageViewDescriptor, RHI::ScopeAttachmentUsage attachmentUsage) const
|
||||
{
|
||||
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId, imageViewDescriptor, attachmentUsage);
|
||||
return GetImageView(scopeAttacment);
|
||||
}
|
||||
|
||||
const ImageView* FrameGraphCompileContext::GetImageView(const AttachmentId& attachmentId) const
|
||||
{
|
||||
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId);
|
||||
return GetImageView(scopeAttacment);
|
||||
}
|
||||
|
||||
const Image* FrameGraphCompileContext::GetImage(const AttachmentId& attachmentId) const
|
||||
{
|
||||
const ImageView* imageView = GetImageView(attachmentId);
|
||||
|
||||
@@ -112,6 +112,8 @@ namespace AZ
|
||||
{
|
||||
infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
|
||||
infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE);
|
||||
//Un-comment this if you want to break on warnings too
|
||||
//infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace AZ
|
||||
{
|
||||
const RHI::ImageDescriptor& imageDescriptor = GetDescriptor();
|
||||
|
||||
size_t byteOffset = 0;
|
||||
uint32_t byteOffset = 0;
|
||||
|
||||
if (subresourceLayouts)
|
||||
{
|
||||
|
||||
@@ -376,7 +376,7 @@ namespace AZ
|
||||
void Image::GetSubresourceLayoutsInternal(const RHI::ImageSubresourceRange& subresourceRange, RHI::ImageSubresourceLayoutPlaced* subresourceLayouts, size_t* totalSizeInBytes) const
|
||||
{
|
||||
const RHI::ImageDescriptor& imageDescriptor = GetDescriptor();
|
||||
size_t byteOffset = 0;
|
||||
uint32_t byteOffset = 0;
|
||||
const uint32_t offsetAligment = 4;
|
||||
for (uint16_t arraySlice = subresourceRange.m_arraySliceMin; arraySlice <= subresourceRange.m_mipSliceMax; ++arraySlice)
|
||||
{
|
||||
@@ -398,7 +398,7 @@ namespace AZ
|
||||
layout.m_size = subresourceLayout.m_size;
|
||||
}
|
||||
|
||||
byteOffset = RHI::AlignUp(byteOffset + static_cast<uint64_t>(subresourceLayout.m_bytesPerImage) * subresourceLayout.m_size.m_depth, offsetAligment);
|
||||
byteOffset = RHI::AlignUp(byteOffset + subresourceLayout.m_bytesPerImage * subresourceLayout.m_size.m_depth, offsetAligment);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,8 @@ namespace AZ
|
||||
}
|
||||
|
||||
m_descriptorSetAllocator = RHI::Ptr<DescriptorSetAllocator>(aznew DescriptorSetAllocator);
|
||||
// [GFX_TODO] ATOM-679 Set a proper pool size.
|
||||
const uint32_t descriptorSetsPerPool = 100;
|
||||
// [GFX_TODO] ATOM-16891 - Refactor Descriptor management system
|
||||
const uint32_t descriptorSetsPerPool = 20;
|
||||
DescriptorSetAllocator::Descriptor allocatorDescriptor;
|
||||
allocatorDescriptor.m_device = &device;
|
||||
allocatorDescriptor.m_layout = m_descriptorSetLayout.get();
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace AZ
|
||||
|
||||
ResourcePoolAssetType m_poolType = ResourcePoolAssetType::Unknown;
|
||||
AZStd::string m_poolName = "Unknown";
|
||||
size_t m_budgetInBytes = 0;
|
||||
uint32_t m_budgetInBytes = 0;
|
||||
|
||||
// Configuration for buffer pool
|
||||
RHI::HeapMemoryLevel m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
|
||||
|
||||
@@ -276,7 +276,8 @@ namespace AZ
|
||||
{
|
||||
inputIndex = imageIndex;
|
||||
}
|
||||
const RHI::ImageView* imageView = context.GetImageView(attachment->GetAttachmentId(), binding.m_attachmentUsageIndex);
|
||||
const RHI::ImageView* imageView =
|
||||
context.GetImageView(attachment->GetAttachmentId(), binding.m_unifiedScopeDesc.GetImageViewDescriptor(), binding.m_scopeAttachmentUsage);
|
||||
|
||||
if (binding.m_shaderImageDimensionsNameIndex.HasName())
|
||||
{
|
||||
@@ -315,7 +316,7 @@ namespace AZ
|
||||
{
|
||||
inputIndex = bufferIndex;
|
||||
}
|
||||
const RHI::BufferView* bufferView = context.GetBufferView(attachment->GetAttachmentId(), binding.m_attachmentUsageIndex);
|
||||
const RHI::BufferView* bufferView = context.GetBufferView(attachment->GetAttachmentId(), binding.m_scopeAttachmentUsage);
|
||||
m_shaderResourceGroup->SetBufferView(RHI::ShaderInputBufferIndex(inputIndex), bufferView, arrayIndex);
|
||||
++bufferIndex;
|
||||
}
|
||||
|
||||
@@ -112,12 +112,12 @@ namespace UnitTest
|
||||
: AZ::RHI::ShaderStageFunction(shaderStage)
|
||||
{}
|
||||
|
||||
void SetIndex(size_t index)
|
||||
void SetIndex(uint32_t index)
|
||||
{
|
||||
m_index = index;
|
||||
}
|
||||
|
||||
size_t m_index;
|
||||
int32_t m_index;
|
||||
|
||||
ShaderByteCode m_byteCode;
|
||||
|
||||
|
||||
@@ -1362,8 +1362,9 @@ namespace AZ::AtomBridge
|
||||
// if 2d draw need to project pos to screen first
|
||||
AzFramework::TextDrawParameters params;
|
||||
AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext();
|
||||
const auto dpiScaleFactor = viewportContext->GetDpiScalingFactor();
|
||||
params.m_drawViewportId = viewportContext->GetId(); // get the viewport ID so default viewport works
|
||||
params.m_position = AZ::Vector3(x, y, 1.0f);
|
||||
params.m_position = AZ::Vector3(x * dpiScaleFactor, y * dpiScaleFactor, 1.0f);
|
||||
params.m_color = m_rendState.m_color;
|
||||
params.m_scale = AZ::Vector2(size);
|
||||
params.m_hAlign = center ? AzFramework::TextHorizontalAlignment::Center : AzFramework::TextHorizontalAlignment::Left; //! Horizontal text alignment
|
||||
|
||||
@@ -254,7 +254,7 @@ namespace BarrierInput
|
||||
|
||||
static bool barrierBye([[maybe_unused]]BarrierClient* pContext, [[maybe_unused]]int* pArgs, [[maybe_unused]]Stream* pStream, [[maybe_unused]]int streamLeft)
|
||||
{
|
||||
AZLOG_INFO("BarrierClient: Server said bye. Disconnecting\n");
|
||||
AZLOG_INFO("BarrierClient: Server said bye. Disconnecting");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ namespace BarrierInput
|
||||
const char* packetStart = stream.GetData();
|
||||
if (packetLength > streamLength)
|
||||
{
|
||||
AZLOG_INFO("BarrierClient: Packet overruns buffer (Packet Length: %d Buffer Length: %d), probably lots of data on clipboard?\n", packetLength, streamLength);
|
||||
AZLOG_INFO("BarrierClient: Packet overruns buffer (Packet Length: %d Buffer Length: %d), probably lots of data on clipboard?", packetLength, streamLength);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ namespace BarrierInput
|
||||
const int lengthReceived = AZ::AzSock::Recv(m_socket, stream.GetBuffer(), stream.GetBufferSize(), 0);
|
||||
if (lengthReceived <= 0)
|
||||
{
|
||||
AZLOG_INFO("BarrierClient: Receive failed, reconnecting.\n");
|
||||
AZLOG_INFO("BarrierClient: Receive failed, reconnecting.");
|
||||
connected = false;
|
||||
continue;
|
||||
}
|
||||
@@ -386,7 +386,7 @@ namespace BarrierInput
|
||||
stream.SetLength(lengthReceived);
|
||||
if (!ProcessPackets(this, stream))
|
||||
{
|
||||
AZLOG_INFO("BarrierClient: Packet processing failed, reconnecting.\n");
|
||||
AZLOG_INFO("BarrierClient: Packet processing failed, reconnecting.");
|
||||
connected = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -401,34 +401,37 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel)
|
||||
const InputChannelId& inputChannelId = inputChannel.GetInputChannelId();
|
||||
const InputDeviceId& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId();
|
||||
|
||||
// Handle Keyboard Hotkeys
|
||||
if (InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId) && inputChannel.IsStateBegan())
|
||||
{
|
||||
// Cycle through ImGui Menu Bar States on Home button press
|
||||
if (inputChannelId == InputDeviceKeyboard::Key::NavigationHome)
|
||||
{
|
||||
ToggleThroughImGuiVisibleState();
|
||||
}
|
||||
bool consumeEvent = false;
|
||||
|
||||
// Cycle through Standalone Editor Window States
|
||||
if (inputChannel.GetInputChannelId() == InputDeviceKeyboard::Key::NavigationEnd)
|
||||
{
|
||||
if (gEnv->IsEditor() && m_editorWindowState == DisplayState::Hidden)
|
||||
{
|
||||
ImGuiUpdateListenerBus::Broadcast(&IImGuiUpdateListener::OnOpenEditorWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_editorWindowState = m_editorWindowState == DisplayState::Visible
|
||||
? DisplayState::VisibleNoMouse
|
||||
: DisplayState::Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Keyboard Modifier Keys
|
||||
// Handle Keyboard Inputs
|
||||
if (InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
|
||||
{
|
||||
// Handle Keyboard Hotkeys
|
||||
if (inputChannel.IsStateBegan())
|
||||
{
|
||||
// Cycle through ImGui Menu Bar States on Home button press
|
||||
if (inputChannelId == InputDeviceKeyboard::Key::NavigationHome)
|
||||
{
|
||||
ToggleThroughImGuiVisibleState();
|
||||
}
|
||||
|
||||
// Cycle through Standalone Editor Window States
|
||||
if (inputChannel.GetInputChannelId() == InputDeviceKeyboard::Key::NavigationEnd)
|
||||
{
|
||||
if (gEnv->IsEditor() && m_editorWindowState == DisplayState::Hidden)
|
||||
{
|
||||
ImGuiUpdateListenerBus::Broadcast(&IImGuiUpdateListener::OnOpenEditorWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_editorWindowState = m_editorWindowState == DisplayState::Visible
|
||||
? DisplayState::VisibleNoMouse
|
||||
: DisplayState::Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Keyboard Modifier Keys
|
||||
if (inputChannelId == InputDeviceKeyboard::Key::ModifierShiftL
|
||||
|| inputChannelId == InputDeviceKeyboard::Key::ModifierShiftR)
|
||||
{
|
||||
@@ -454,7 +457,7 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel)
|
||||
}
|
||||
|
||||
// Handle Controller Inputs
|
||||
if (InputDeviceGamepad::IsGamepadDevice(inputDeviceId))
|
||||
else if (InputDeviceGamepad::IsGamepadDevice(inputDeviceId))
|
||||
{
|
||||
// Only pipe in Controller Nav Inputs when at least 1 of the two controller modes are enabled.
|
||||
if (m_controllerModeFlags)
|
||||
@@ -496,32 +499,30 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel)
|
||||
{
|
||||
ToggleThroughImGuiVisibleState();
|
||||
}
|
||||
|
||||
// If we have the Discrete Input Mode Enabled.. and we are in the Visible State, then consume input here
|
||||
if (m_enableDiscreteInputMode && m_clientMenuBarState == DisplayState::Visible)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle Mouse Inputs
|
||||
if (InputDeviceMouse::IsMouseDevice(inputDeviceId))
|
||||
else if (InputDeviceMouse::IsMouseDevice(inputDeviceId))
|
||||
{
|
||||
const int mouseButtonIndex = GetAzMouseButtonIndex(inputChannelId);
|
||||
if (0 <= mouseButtonIndex && mouseButtonIndex < AZ_ARRAY_SIZE(io.MouseDown))
|
||||
{
|
||||
io.MouseDown[mouseButtonIndex] = inputChannel.IsActive();
|
||||
|
||||
// only consume the event during edit mode in the editor so the viewport doesn't also respond to it
|
||||
consumeEvent = gEnv->IsEditing() && io.WantCaptureMouse;
|
||||
}
|
||||
else if (inputChannelId == InputDeviceMouse::Movement::Z)
|
||||
{
|
||||
io.MouseWheel = inputChannel.GetValue() / static_cast<float>(IMGUI_WHEEL_DELTA);
|
||||
|
||||
// only consume the event during edit mode in the editor so the viewport doesn't also respond to it
|
||||
consumeEvent = gEnv->IsEditing() && io.WantCaptureMouse;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Touch Inputs
|
||||
if (InputDeviceTouch::IsTouchDevice(inputDeviceId))
|
||||
else if (InputDeviceTouch::IsTouchDevice(inputDeviceId))
|
||||
{
|
||||
const int touchIndex = GetAzTouchIndex(inputChannelId);
|
||||
if (0 <= touchIndex && touchIndex < AZ_ARRAY_SIZE(io.MouseDown))
|
||||
@@ -542,7 +543,7 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel)
|
||||
}
|
||||
|
||||
// Handle Virtual Keyboard Inputs
|
||||
if (InputDeviceVirtualKeyboard::IsVirtualKeyboardDevice(inputDeviceId))
|
||||
else if (InputDeviceVirtualKeyboard::IsVirtualKeyboardDevice(inputDeviceId))
|
||||
{
|
||||
if (inputChannelId == AzFramework::InputDeviceVirtualKeyboard::Command::EditEnter)
|
||||
{
|
||||
@@ -554,13 +555,16 @@ bool ImGuiManager::OnInputChannelEventFiltered(const InputChannel& inputChannel)
|
||||
if (m_clientMenuBarState == DisplayState::Visible
|
||||
|| m_editorWindowState == DisplayState::Visible)
|
||||
{
|
||||
// If we have the Discrete Input Mode Enabled.. then consume the input here.
|
||||
// If we have the Discrete Input Mode Enabled.. then consume the input here.
|
||||
if (m_enableDiscreteInputMode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return consumeEvent;
|
||||
}
|
||||
|
||||
// don't allow event capturing when ImGui isn't active
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Multiplayer
|
||||
else
|
||||
{
|
||||
m_networkEditorInterface->SendReliablePacket(editorServerToEditorConnectionId, MultiplayerEditorPackets::EditorServerReadyForLevelData());
|
||||
AZ_Printf("MultiplayerEditorConnection", "Editor-server activation has found and connected to the editor.")
|
||||
AZ_Printf("MultiplayerEditorConnection", "Editor-server activation has found and connected to the editor.\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1135,9 +1135,15 @@ namespace Multiplayer
|
||||
// make sure the player prefab path is lowercase (how it's stored in the cache folder)
|
||||
auto sv_defaultPlayerSpawnAssetLowerCase = static_cast<AZ::CVarFixedString>(sv_defaultPlayerSpawnAsset);
|
||||
AZStd::to_lower(sv_defaultPlayerSpawnAssetLowerCase.begin(), sv_defaultPlayerSpawnAssetLowerCase.end());
|
||||
PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast<AZ::CVarFixedString>(sv_defaultPlayerSpawnAssetLowerCase).c_str()));
|
||||
PrefabEntityId playerPrefabEntityId(AZ::Name(sv_defaultPlayerSpawnAssetLowerCase.c_str()));
|
||||
|
||||
INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity(), Multiplayer::AutoActivate::DoNotActivate);
|
||||
|
||||
AZ_Warning(
|
||||
"MultiplayerSystemComponent", !entityList.empty(),
|
||||
"SpawnDefaultPlayerPrefab failed. Missing sv_defaultPlayerSpawnAsset at path '%s'.\n",
|
||||
sv_defaultPlayerSpawnAssetLowerCase.c_str())
|
||||
|
||||
for (NetworkEntityHandle subEntity : entityList)
|
||||
{
|
||||
subEntity.Activate();
|
||||
|
||||
@@ -324,7 +324,8 @@ namespace Profiler
|
||||
// Gets called when region ends and all data is set
|
||||
void CpuTimingLocalStorage::AddCachedRegion(const CachedTimeRegion& timeRegionCached)
|
||||
{
|
||||
if (m_hitSizeLimitMap[timeRegionCached.m_groupRegionName.m_regionName])
|
||||
if (auto iter = m_hitSizeLimitMap.find(timeRegionCached.m_groupRegionName.m_regionName);
|
||||
iter != m_hitSizeLimitMap.end() && iter->second)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <AzCore/Debug/ProfilerBus.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/JSON/filereadstream.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
|
||||
@@ -375,6 +376,7 @@ namespace Profiler
|
||||
|
||||
DrawTable();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void ImGuiCpuProfiler::DrawFilePicker()
|
||||
@@ -597,8 +599,9 @@ namespace Profiler
|
||||
|
||||
DrawFrameBoundaries();
|
||||
|
||||
// Draw an invisible button to capture inputs
|
||||
ImGui::InvisibleButton("Timeline Input", { ImGui::GetWindowContentRegionWidth(), baseRow * RowHeight });
|
||||
// Draw an invisible button to capture inputs and make sure it has a non-zero height
|
||||
ImGui::InvisibleButton("Timeline Input",
|
||||
{ ImGui::GetWindowContentRegionWidth(), AZ::GetMax(baseRow, decltype(baseRow){1}) * RowHeight });
|
||||
|
||||
// Controls
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
@@ -643,7 +646,9 @@ namespace Profiler
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::EndChild(); // "Timeline"
|
||||
|
||||
ImGui::EndChild(); // "Options and Statistics"
|
||||
}
|
||||
|
||||
void ImGuiCpuProfiler::CacheCpuTimingStatistics()
|
||||
|
||||
@@ -7,13 +7,13 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
import typing
|
||||
import json
|
||||
import azlmbr.scene as sceneApi
|
||||
from enum import Enum, IntEnum
|
||||
from enum import IntEnum
|
||||
|
||||
|
||||
# Wraps the AZ.SceneAPI.Containers.SceneGraph.NodeIndex internal class
|
||||
class SceneGraphNodeIndex:
|
||||
def __init__(self, sceneGraphNodeIndex) -> None:
|
||||
self.nodeIndex = sceneGraphNodeIndex
|
||||
def __init__(self, scene_graph_node_index) -> None:
|
||||
self.nodeIndex = scene_graph_node_index
|
||||
|
||||
def as_number(self):
|
||||
return self.nodeIndex.AsNumber()
|
||||
@@ -29,9 +29,9 @@ class SceneGraphNodeIndex:
|
||||
|
||||
|
||||
# Wraps AZ.SceneAPI.Containers.SceneGraph.Name internal class
|
||||
class SceneGraphName():
|
||||
def __init__(self, sceneGraphName) -> None:
|
||||
self.name = sceneGraphName
|
||||
class SceneGraphName:
|
||||
def __init__(self, scene_graph_name) -> None:
|
||||
self.name = scene_graph_name
|
||||
|
||||
def get_path(self) -> str:
|
||||
return self.name.GetPath()
|
||||
@@ -41,9 +41,9 @@ class SceneGraphName():
|
||||
|
||||
|
||||
# Wraps AZ.SceneAPI.Containers.SceneGraph class
|
||||
class SceneGraph():
|
||||
def __init__(self, sceneGraphInstance) -> None:
|
||||
self.sceneGraph = sceneGraphInstance
|
||||
class SceneGraph:
|
||||
def __init__(self, scene_graph_instance) -> None:
|
||||
self.sceneGraph = scene_graph_instance
|
||||
|
||||
@classmethod
|
||||
def is_valid_name(cls, name):
|
||||
@@ -96,53 +96,161 @@ class SceneGraph():
|
||||
return self.sceneGraph.GetNodeContent(node)
|
||||
|
||||
|
||||
class ColorChannel(IntEnum):
|
||||
RED = 0
|
||||
""" Red color channel """
|
||||
GREEN = 1
|
||||
""" Green color channel """
|
||||
BLUE = 2
|
||||
""" Blue color channel """
|
||||
ALPHA = 3
|
||||
""" Alpha color channel """
|
||||
|
||||
|
||||
class TangentSpaceSource(IntEnum):
|
||||
SCENE = 0
|
||||
""" Extract the tangents and bitangents directly from the source scene file. """
|
||||
MIKKT_GENERATION = 1
|
||||
""" Use MikkT algorithm to generate tangents """
|
||||
|
||||
|
||||
class TangentSpaceMethod(IntEnum):
|
||||
TSPACE = 0
|
||||
""" Generates the tangents and bitangents with their true magnitudes which can be used for relief mapping effects.
|
||||
It calculates the 'real' bitangent which may not be perpendicular to the tangent.
|
||||
However, both, the tangent and bitangent are perpendicular to the vertex normal.
|
||||
"""
|
||||
TSPACE_BASIC = 1
|
||||
""" Calculates unit vector tangents and bitangents at pixel/vertex level which are sufficient for basic normal mapping. """
|
||||
|
||||
|
||||
class PrimitiveShape(IntEnum):
|
||||
BEST_FIT = 0
|
||||
""" The algorithm will determine which of the shapes fits best. """
|
||||
SPHERE = 1
|
||||
""" Sphere shape """
|
||||
BOX = 2
|
||||
""" Box shape """
|
||||
CAPSULE = 3
|
||||
""" Capsule shape """
|
||||
|
||||
|
||||
class DecompositionMode(IntEnum):
|
||||
VOXEL = 0
|
||||
""" Voxel-based approximate convex decomposition """
|
||||
TETRAHEDRON = 1
|
||||
""" Tetrahedron-based approximate convex decomposition """
|
||||
|
||||
|
||||
# Contains a dictionary to contain and export AZ.SceneAPI.Containers.SceneManifest
|
||||
class SceneManifest():
|
||||
class SceneManifest:
|
||||
def __init__(self):
|
||||
self.manifest = {'values': []}
|
||||
|
||||
def add_mesh_group(self, name: str) -> dict:
|
||||
meshGroup = {}
|
||||
meshGroup['$type'] = '{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup'
|
||||
meshGroup['name'] = name
|
||||
meshGroup['nodeSelectionList'] = {'selectedNodes': [], 'unselectedNodes': []}
|
||||
meshGroup['rules'] = {'rules': [{'$type': 'MaterialRule'}]}
|
||||
self.manifest['values'].append(meshGroup)
|
||||
return meshGroup
|
||||
"""Adds a Mesh Group to the scene manifest.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name :
|
||||
Name of the mesh group. This will become a file on disk and be usable as a Mesh in the editor.
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
Newly created mesh group.
|
||||
|
||||
"""
|
||||
mesh_group = {
|
||||
'$type': '{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup',
|
||||
'name': name,
|
||||
'nodeSelectionList': {'selectedNodes': [], 'unselectedNodes': []},
|
||||
'rules': {'rules': [{'$type': 'MaterialRule'}]}
|
||||
}
|
||||
self.manifest['values'].append(mesh_group)
|
||||
return mesh_group
|
||||
|
||||
def add_prefab_group(self, name: str, id: str, json: dict) -> dict:
|
||||
prefabGroup = {}
|
||||
prefabGroup['$type'] = '{99FE3C6F-5B55-4D8B-8013-2708010EC715} PrefabGroup'
|
||||
prefabGroup['name'] = name
|
||||
prefabGroup['id'] = id
|
||||
prefabGroup['prefabDomData'] = json
|
||||
self.manifest['values'].append(prefabGroup)
|
||||
return prefabGroup
|
||||
"""Adds a Prefab Group to the scene manifest. This will become a file on disk and be usable as a ProceduralPrefab in the editor.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name :
|
||||
Name of the prefab.
|
||||
id :
|
||||
Unique ID for this prefab group.
|
||||
json :
|
||||
The prefab template data.
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
The newly created Prefab group
|
||||
|
||||
"""
|
||||
prefab_group = {
|
||||
'$type': '{99FE3C6F-5B55-4D8B-8013-2708010EC715} PrefabGroup',
|
||||
'name': name,
|
||||
'id': id,
|
||||
'prefabDomData': json
|
||||
}
|
||||
self.manifest['values'].append(prefab_group)
|
||||
return prefab_group
|
||||
|
||||
def mesh_group_select_node(self, mesh_group: dict, node_name: str) -> None:
|
||||
"""Adds a node as a selected node.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh group to apply the selection to.
|
||||
node_name :
|
||||
Path of the node.
|
||||
|
||||
"""
|
||||
mesh_group['nodeSelectionList']['selectedNodes'].append(node_name)
|
||||
|
||||
def mesh_group_unselect_node(self, mesh_group: dict, node_name: str) -> None:
|
||||
"""Adds a node as an unselected node.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh group to apply the selection to.
|
||||
node_name :
|
||||
Path of the node.
|
||||
|
||||
"""
|
||||
mesh_group['nodeSelectionList']['unselectedNodes'].append(node_name)
|
||||
|
||||
def mesh_group_add_advanced_coordinate_system(self, mesh_group: dict, origin_node_name: str, translation: object,
|
||||
rotation: object, scale: float) -> None:
|
||||
def mesh_group_add_advanced_coordinate_system(self, mesh_group: dict,
|
||||
origin_node_name: str = '',
|
||||
translation: typing.Optional[object] = None,
|
||||
rotation: typing.Optional[object] = None,
|
||||
scale: float = 1.0) -> None:
|
||||
"""Adds an Advanced Coordinate System rule which modifies the target coordinate system,
|
||||
applying a transformation to all data (transforms and vertex data if it exists).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh group to add the Advanced Coordinate System rule to.
|
||||
origin_node_name :
|
||||
Path of the node to use as the origin.
|
||||
translation :
|
||||
Moves the group along the given vector.
|
||||
rotation :
|
||||
Sets the orientation offset of the processed mesh in degrees. Rotates the group after translation.
|
||||
scale :
|
||||
Sets the scale offset of the processed mesh.
|
||||
|
||||
"""
|
||||
origin_rule = {
|
||||
'$type': 'CoordinateSystemRule',
|
||||
'useAdvancedData': True,
|
||||
'originNodeName': '' if origin_node_name is None else origin_node_name
|
||||
'originNodeName': self.__default_or_value(origin_node_name, '')
|
||||
}
|
||||
if translation is not None:
|
||||
origin_rule['translation'] = translation
|
||||
@@ -153,31 +261,57 @@ class SceneManifest():
|
||||
mesh_group['rules']['rules'].append(origin_rule)
|
||||
|
||||
def mesh_group_add_comment(self, mesh_group: dict, comment: str) -> None:
|
||||
commentRule = {
|
||||
"""Adds a Comment rule.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh group to add the comment rule to.
|
||||
comment :
|
||||
Text for the comment rule.
|
||||
|
||||
"""
|
||||
comment_rule = {
|
||||
'$type': 'CommentRule',
|
||||
'comment': comment
|
||||
}
|
||||
mesh_group['rules']['rules'].append(commentRule)
|
||||
mesh_group['rules']['rules'].append(comment_rule)
|
||||
|
||||
def __default_or_value(self, val, default):
|
||||
return default if val is None else val
|
||||
|
||||
def mesh_group_add_cloth_rule(self, mesh_group: dict, cloth_node_name: str,
|
||||
inverse_masses_stream_name: str, inverse_masses_channel: int,
|
||||
motion_constraints_stream_name: str, motion_constraints_channel: int,
|
||||
backstop_stream_name: str, backstop_offset_channel: int,
|
||||
backstop_radius_channel: int) -> None:
|
||||
"""
|
||||
Adds a Cloth rule. 0 = Red, 1 = Green, 2 = Blue, 3 = Alpha
|
||||
:param mesh_group: Mesh Group to add the cloth rule to
|
||||
:param cloth_node_name: Name of the node that the rule applies to
|
||||
:param inverse_masses_stream_name: Name of the color stream to use for inverse masses
|
||||
:param inverse_masses_channel: Color channel (index) for inverse masses
|
||||
:param motion_constraints_stream_name: Name of the color stream to use for motion constraints
|
||||
:param motion_constraints_channel: Color channel (index) for motion constraints
|
||||
:param backstop_stream_name: Name of the color stream to use for backstop
|
||||
:param backstop_offset_channel: Color channel (index) for backstop offset value
|
||||
:param backstop_radius_channel: Color chnanel (index) for backstop radius value
|
||||
def mesh_group_add_cloth_rule(self, mesh_group: dict,
|
||||
cloth_node_name: str,
|
||||
inverse_masses_stream_name: typing.Optional[str],
|
||||
inverse_masses_channel: typing.Optional[ColorChannel],
|
||||
motion_constraints_stream_name: typing.Optional[str],
|
||||
motion_constraints_channel: typing.Optional[ColorChannel],
|
||||
backstop_stream_name: typing.Optional[str],
|
||||
backstop_offset_channel: typing.Optional[ColorChannel],
|
||||
backstop_radius_channel: typing.Optional[ColorChannel]) -> None:
|
||||
"""Adds a Cloth rule.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh Group to add the cloth rule to
|
||||
cloth_node_name :
|
||||
Name of the node that the rule applies to
|
||||
inverse_masses_stream_name :
|
||||
Name of the color stream to use for inverse masses
|
||||
inverse_masses_channel :
|
||||
Color channel (index) for inverse masses
|
||||
motion_constraints_stream_name :
|
||||
Name of the color stream to use for motion constraints
|
||||
motion_constraints_channel :
|
||||
Color channel (index) for motion constraints
|
||||
backstop_stream_name :
|
||||
Name of the color stream to use for backstop
|
||||
backstop_offset_channel :
|
||||
Color channel (index) for backstop offset value
|
||||
backstop_radius_channel :
|
||||
Color channel (index) for backstop radius value
|
||||
|
||||
"""
|
||||
cloth_rule = {
|
||||
'$type': 'ClothRule',
|
||||
@@ -186,22 +320,31 @@ class SceneManifest():
|
||||
}
|
||||
|
||||
if inverse_masses_channel is not None:
|
||||
cloth_rule['inverseMassesChannel'] = inverse_masses_channel
|
||||
cloth_rule['inverseMassesChannel'] = int(inverse_masses_channel)
|
||||
cloth_rule['motionConstraintsStreamName'] = self.__default_or_value(motion_constraints_stream_name, 'Default: 1.0')
|
||||
if motion_constraints_channel is not None:
|
||||
cloth_rule['motionConstraintsChannel'] = motion_constraints_channel
|
||||
cloth_rule['motionConstraintsChannel'] = int(motion_constraints_channel)
|
||||
cloth_rule['backstopStreamName'] = self.__default_or_value(backstop_stream_name, 'None')
|
||||
if backstop_offset_channel is not None:
|
||||
cloth_rule['backstopOffsetChannel'] = backstop_offset_channel
|
||||
cloth_rule['backstopOffsetChannel'] = int(backstop_offset_channel)
|
||||
if backstop_radius_channel is not None:
|
||||
cloth_rule['backstopRadiusChannel'] = backstop_radius_channel
|
||||
cloth_rule['backstopRadiusChannel'] = int(backstop_radius_channel)
|
||||
mesh_group['rules']['rules'].append(cloth_rule)
|
||||
|
||||
def mesh_group_add_lod_rule(self, mesh_group: dict) -> dict:
|
||||
"""
|
||||
Adds an LOD rule
|
||||
:param mesh_group: Mesh Group to add the rule to
|
||||
:return: LOD rule
|
||||
"""Adds an LOD rule.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh Group to add the rule to.
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
LOD rule.
|
||||
|
||||
"""
|
||||
lod_rule = {
|
||||
'$type': '{6E796AC8-1484-4909-860A-6D3F22A7346F} LodRule',
|
||||
@@ -212,47 +355,76 @@ class SceneManifest():
|
||||
return lod_rule
|
||||
|
||||
def lod_rule_add_lod(self, lod_rule: dict) -> dict:
|
||||
"""
|
||||
Adds an LOD level to the LOD rule. Nodes are added in order. The first node added represents LOD1, 2nd LOD2, etc
|
||||
:param lod_rule: LOD rule to add the LOD level to
|
||||
:return: LOD level
|
||||
"""Adds an LOD level to the LOD rule. Nodes are added in order. The first node added represents LOD1, 2nd LOD2, etc.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
lod_rule :
|
||||
LOD rule to add the LOD level to.
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
LOD level.
|
||||
|
||||
"""
|
||||
lod = {'selectedNodes': [], 'unselectedNodes': []}
|
||||
lod_rule['nodeSelectionList'].append(lod)
|
||||
return lod
|
||||
|
||||
def lod_select_node(self, lod: dict, selected_node: str) -> None:
|
||||
"""
|
||||
Adds a node as a selected node
|
||||
:param lod: LOD level to add the node to
|
||||
:param selected_node: Path of the node
|
||||
"""Adds a node as a selected node.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
lod :
|
||||
LOD level to add the node to.
|
||||
selected_node :
|
||||
Path of the node.
|
||||
|
||||
"""
|
||||
lod['selectedNodes'].append(selected_node)
|
||||
|
||||
def lod_unselect_node(self, lod: dict, unselected_node: str) -> None:
|
||||
"""
|
||||
Adds a node as an unselected node
|
||||
:param lod: LOD rule to add the node to
|
||||
:param unselected_node: Path of the node
|
||||
"""Adds a node as an unselected node.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
lod :
|
||||
LOD rule to add the node to.
|
||||
unselected_node :
|
||||
Path of the node.
|
||||
|
||||
"""
|
||||
lod['unselectedNodes'].append(unselected_node)
|
||||
|
||||
def mesh_group_add_advanced_mesh_rule(self, mesh_group: dict, use_32bit_vertices: bool, merge_meshes: bool,
|
||||
use_custom_normals: bool,
|
||||
vertex_color_stream: str) -> None:
|
||||
"""
|
||||
Adds an Advanced Mesh rule
|
||||
:param mesh_group: Mesh Group to add the rule to
|
||||
:param use_32bit_vertices: False = 16bit vertex position precision. True = 32bit vertex position precision
|
||||
:param merge_meshes: Merge all meshes into a single mesh
|
||||
:param use_custom_normals: True = use normals from DCC tool. False = average normals
|
||||
:param vertex_color_stream: Color stream name to use for Vertex Coloring
|
||||
def mesh_group_add_advanced_mesh_rule(self, mesh_group: dict,
|
||||
use_32bit_vertices: bool = False,
|
||||
merge_meshes: bool = True,
|
||||
use_custom_normals: bool = True,
|
||||
vertex_color_stream: typing.Optional[str] = None) -> None:
|
||||
"""Adds an Advanced Mesh rule.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh Group to add the rule to.
|
||||
use_32bit_vertices :
|
||||
False = 16bit vertex position precision. True = 32bit vertex position precision.
|
||||
merge_meshes :
|
||||
Merge all meshes into a single mesh.
|
||||
use_custom_normals :
|
||||
True = use normals from DCC tool. False = average normals.
|
||||
vertex_color_stream :
|
||||
Color stream name to use for Vertex Coloring.
|
||||
|
||||
"""
|
||||
rule = {
|
||||
'$type': 'StaticMeshAdvancedRule',
|
||||
'use32bitVertices': self.__default_or_value(use_32bit_vertices, False),
|
||||
'mergeMeshes': self.__default_or_value(merge_meshes, True),
|
||||
'useCustomNormals': self.__default_or_value(use_custom_normals, True)
|
||||
'use32bitVertices': use_32bit_vertices,
|
||||
'mergeMeshes': merge_meshes,
|
||||
'useCustomNormals': use_custom_normals
|
||||
}
|
||||
|
||||
if vertex_color_stream is not None:
|
||||
@@ -260,37 +432,51 @@ class SceneManifest():
|
||||
|
||||
mesh_group['rules']['rules'].append(rule)
|
||||
|
||||
def mesh_group_add_skin_rule(self, mesh_group: dict, max_weights_per_vertex: int, weight_threshold: float) -> None:
|
||||
"""
|
||||
Adds a Skin rule
|
||||
:param mesh_group: Mesh Group to add the rule to
|
||||
:param max_weights_per_vertex: Max number of joints that can influence a vertex
|
||||
:param weight_threshold: Weight values below this value will be treated as 0
|
||||
def mesh_group_add_skin_rule(self, mesh_group: dict, max_weights_per_vertex: int = 4, weight_threshold: float = 0.001) -> None:
|
||||
"""Adds a Skin rule.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh Group to add the rule to.
|
||||
max_weights_per_vertex :
|
||||
Max number of joints that can influence a vertex.
|
||||
weight_threshold :
|
||||
Weight values below this value will be treated as 0.
|
||||
|
||||
"""
|
||||
rule = {
|
||||
'$type': 'SkinRule',
|
||||
'maxWeightsPerVertex': self.__default_or_value(max_weights_per_vertex, 4),
|
||||
'weightThreshold': self.__default_or_value(weight_threshold, 0.001)
|
||||
'maxWeightsPerVertex': max_weights_per_vertex,
|
||||
'weightThreshold': weight_threshold
|
||||
}
|
||||
|
||||
mesh_group['rules']['rules'].append(rule)
|
||||
|
||||
def mesh_group_add_tangent_rule(self, mesh_group: dict, tangent_space: int, tspace_method: int) -> None:
|
||||
"""
|
||||
Adds a Tangent rule to control tangent space generation
|
||||
:param mesh_group: Mesh Group to add the rule to
|
||||
:param tangent_space: Tangent space source. 0 = Scene, 1 = MikkT Tangent Generation
|
||||
:param tspace_method: MikkT Generation method. 0 = TSpace, 1 = TSpaceBasic
|
||||
def mesh_group_add_tangent_rule(self, mesh_group: dict,
|
||||
tangent_space: TangentSpaceSource = TangentSpaceSource.SCENE,
|
||||
tspace_method: TangentSpaceMethod = TangentSpaceMethod.TSPACE) -> None:
|
||||
"""Adds a Tangent rule to control tangent space generation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh Group to add the rule to.
|
||||
tangent_space :
|
||||
Tangent space source. 0 = Scene, 1 = MikkT Tangent Generation.
|
||||
tspace_method :
|
||||
MikkT Generation method. 0 = TSpace, 1 = TSpaceBasic.
|
||||
|
||||
"""
|
||||
rule = {
|
||||
'$type': 'TangentsRule',
|
||||
'tangentSpace': self.__default_or_value(tangent_space, 1),
|
||||
'tSpaceMethod': self.__default_or_value(tspace_method, 0)
|
||||
'tangentSpace': int(tangent_space),
|
||||
'tSpaceMethod': int(tspace_method)
|
||||
}
|
||||
|
||||
mesh_group['rules']['rules'].append(rule)
|
||||
|
||||
def __add_physx_base_mesh_group(self, name: str, physics_material: typing.Optional[str]) -> dict:
|
||||
def __add_physx_base_mesh_group(self, name: str, physics_material: typing.Optional[str] = None) -> dict:
|
||||
import azlmbr.math
|
||||
group = {
|
||||
'$type': '{5B03C8E6-8CEE-4DA0-A7FA-CD88689DD45B} MeshGroup',
|
||||
@@ -314,7 +500,9 @@ class SceneManifest():
|
||||
|
||||
return group
|
||||
|
||||
def add_physx_triangle_mesh_group(self, name: str, merge_meshes: bool = True, weld_vertices: bool = False,
|
||||
def add_physx_triangle_mesh_group(self, name: str,
|
||||
merge_meshes: bool = True,
|
||||
weld_vertices: bool = False,
|
||||
disable_clean_mesh: bool = False,
|
||||
force_32bit_indices: bool = False,
|
||||
suppress_triangle_mesh_remap_table: bool = False,
|
||||
@@ -322,26 +510,42 @@ class SceneManifest():
|
||||
mesh_weld_tolerance: float = 0.0,
|
||||
num_tris_per_leaf: int = 4,
|
||||
physics_material: typing.Optional[str] = None) -> dict:
|
||||
"""
|
||||
Adds a Triangle type PhysX Mesh Group to the scene.
|
||||
"""Adds a Triangle type PhysX Mesh Group to the scene.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name :
|
||||
Name of the mesh group.
|
||||
merge_meshes :
|
||||
When true, all selected nodes will be merged into a single collision mesh.
|
||||
weld_vertices :
|
||||
When true, mesh welding is performed. Clean mesh must be enabled.
|
||||
disable_clean_mesh :
|
||||
When true, mesh cleaning is disabled. This makes cooking faster.
|
||||
force_32bit_indices :
|
||||
When true, 32-bit indices will always be created regardless of triangle count.
|
||||
suppress_triangle_mesh_remap_table :
|
||||
When true, the face remap table is not created.
|
||||
This saves a significant amount of memory, but the SDK will not be able to provide the remap
|
||||
information for internal mesh triangles returned by collisions, sweeps or raycasts hits.
|
||||
build_triangle_adjacencies :
|
||||
When true, the triangle adjacency information is created.
|
||||
mesh_weld_tolerance :
|
||||
If mesh welding is enabled, this controls the distance at
|
||||
which vertices are welded. If mesh welding is not enabled, this value defines the
|
||||
acceptance distance for mesh validation. Provided no two vertices are within this
|
||||
distance, the mesh is considered to be clean. If not, a warning will be emitted.
|
||||
num_tris_per_leaf :
|
||||
Mesh cooking hint for max triangles per leaf limit. Fewer triangles per leaf
|
||||
produces larger meshes with better runtime performance and worse cooking performance.
|
||||
physics_material :
|
||||
Configure which physics material to use.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
The newly created mesh group.
|
||||
|
||||
:param name: Name of the mesh group.
|
||||
:param merge_meshes: When true, all selected nodes will be merged into a single collision mesh.
|
||||
:param weld_vertices: When true, mesh welding is performed. Clean mesh must be enabled.
|
||||
:param disable_clean_mesh: When true, mesh cleaning is disabled. This makes cooking faster.
|
||||
:param force_32bit_indices: When true, 32-bit indices will always be created regardless of triangle count.
|
||||
:param suppress_triangle_mesh_remap_table: When true, the face remap table is not created.
|
||||
This saves a significant amount of memory, but the SDK will not be able to provide the remap
|
||||
information for internal mesh triangles returned by collisions, sweeps or raycasts hits.
|
||||
:param build_triangle_adjacencies: When true, the triangle adjacency information is created.
|
||||
:param mesh_weld_tolerance: If mesh welding is enabled, this controls the distance at
|
||||
which vertices are welded. If mesh welding is not enabled, this value defines the
|
||||
acceptance distance for mesh validation. Provided no two vertices are within this
|
||||
distance, the mesh is considered to be clean. If not, a warning will be emitted.
|
||||
:param num_tris_per_leaf: Mesh cooking hint for max triangles per leaf limit. Fewer triangles per leaf
|
||||
produces larger meshes with better runtime performance and worse cooking performance.
|
||||
:param physics_material: Configure which physics material to use.
|
||||
:return: The newly created mesh group.
|
||||
"""
|
||||
group = self.__add_physx_base_mesh_group(name, physics_material)
|
||||
group["export method"] = 0
|
||||
@@ -367,32 +571,49 @@ class SceneManifest():
|
||||
gauss_map_limit: int = 32,
|
||||
build_gpu_data: bool = False,
|
||||
physics_material: typing.Optional[str] = None) -> dict:
|
||||
"""
|
||||
Adds a Convex type PhysX Mesh Group to the scene.
|
||||
"""Adds a Convex type PhysX Mesh Group to the scene.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name :
|
||||
Name of the mesh group.
|
||||
area_test_epsilon :
|
||||
If the area of a triangle of the hull is below this value, the triangle will be
|
||||
rejected. This test is done only if Check Zero Area Triangles is used.
|
||||
plane_tolerance :
|
||||
The value is used during hull construction. When a new point is about to be added
|
||||
to the hull it gets dropped when the point is closer to the hull than the planeTolerance.
|
||||
use_16bit_indices :
|
||||
Denotes the use of 16-bit vertex indices in Convex triangles or polygons.
|
||||
check_zero_area_triangles :
|
||||
Checks and removes almost zero-area triangles during convex hull computation.
|
||||
The rejected area size is specified in Area Test Epsilon.
|
||||
quantize_input :
|
||||
Quantizes the input vertices using the k-means clustering.
|
||||
use_plane_shifting :
|
||||
Enables plane shifting vertex limit algorithm. Plane shifting is an alternative
|
||||
algorithm for the case when the computed hull has more vertices than the specified vertex
|
||||
limit.
|
||||
shift_vertices :
|
||||
Convex hull input vertices are shifted to be around origin to provide better
|
||||
computation stability
|
||||
gauss_map_limit :
|
||||
Vertex limit beyond which additional acceleration structures are computed for each
|
||||
convex mesh. Increase that limit to reduce memory usage. Computing the extra structures
|
||||
all the time does not guarantee optimal performance.
|
||||
build_gpu_data :
|
||||
When true, additional information required for GPU-accelerated rigid body
|
||||
simulation is created. This can increase memory usage and cooking times for convex meshes
|
||||
and triangle meshes. Convex hulls are created with respect to GPU simulation limitations.
|
||||
Vertex limit is set to 64 and vertex limit per face is internally set to 32.
|
||||
physics_material :
|
||||
Configure which physics material to use.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
The newly created mesh group.
|
||||
|
||||
:param name: Name of the mesh group.
|
||||
:param area_test_epsilon: If the area of a triangle of the hull is below this value, the triangle will be
|
||||
rejected. This test is done only if Check Zero Area Triangles is used.
|
||||
:param plane_tolerance: The value is used during hull construction. When a new point is about to be added
|
||||
to the hull it gets dropped when the point is closer to the hull than the planeTolerance.
|
||||
:param use_16bit_indices: Denotes the use of 16-bit vertex indices in Convex triangles or polygons.
|
||||
:param check_zero_area_triangles: Checks and removes almost zero-area triangles during convex hull computation.
|
||||
The rejected area size is specified in Area Test Epsilon.
|
||||
:param quantize_input: Quantizes the input vertices using the k-means clustering.
|
||||
:param use_plane_shifting: Enables plane shifting vertex limit algorithm. Plane shifting is an alternative
|
||||
algorithm for the case when the computed hull has more vertices than the specified vertex
|
||||
limit.
|
||||
:param shift_vertices: Convex hull input vertices are shifted to be around origin to provide better
|
||||
computation stability
|
||||
:param gauss_map_limit: Vertex limit beyond which additional acceleration structures are computed for each
|
||||
convex mesh. Increase that limit to reduce memory usage. Computing the extra structures
|
||||
all the time does not guarantee optimal performance.
|
||||
:param build_gpu_data: When true, additional information required for GPU-accelerated rigid body
|
||||
simulation is created. This can increase memory usage and cooking times for convex meshes
|
||||
and triangle meshes. Convex hulls are created with respect to GPU simulation limitations.
|
||||
Vertex limit is set to 64 and vertex limit per face is internally set to 32.
|
||||
:param physics_material: Configure which physics material to use.
|
||||
:return: The newly created mesh group.
|
||||
"""
|
||||
group = self.__add_physx_base_mesh_group(name, physics_material)
|
||||
group["export method"] = 1
|
||||
@@ -414,17 +635,27 @@ class SceneManifest():
|
||||
primitive_shape_target: PrimitiveShape = PrimitiveShape.BEST_FIT,
|
||||
volume_term_coefficient: float = 0.0,
|
||||
physics_material: typing.Optional[str] = None) -> dict:
|
||||
"""
|
||||
Adds a Primitive Shape type PhysX Mesh Group to the scene
|
||||
"""Adds a Primitive Shape type PhysX Mesh Group to the scene
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name :
|
||||
Name of the mesh group.
|
||||
primitive_shape_target :
|
||||
The shape that should be fitted to this mesh. If BEST_FIT is selected, the
|
||||
algorithm will determine which of the shapes fits best.
|
||||
volume_term_coefficient :
|
||||
This parameter controls how aggressively the primitive fitting algorithm will try
|
||||
to minimize the volume of the fitted primitive. A value of 0 (no volume minimization) is
|
||||
recommended for most meshes, especially those with moderate to high vertex counts.
|
||||
physics_material :
|
||||
Configure which physics material to use.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
The newly created mesh group.
|
||||
|
||||
:param name: Name of the mesh group.
|
||||
:param primitive_shape_target: The shape that should be fitted to this mesh. If BEST_FIT is selected, the
|
||||
algorithm will determine which of the shapes fits best.
|
||||
:param volume_term_coefficient: This parameter controls how aggressively the primitive fitting algorithm will try
|
||||
to minimize the volume of the fitted primitive. A value of 0 (no volume minimization) is
|
||||
recommended for most meshes, especially those with moderate to high vertex counts.
|
||||
:param physics_material: Configure which physics material to use.
|
||||
:return: The newly created mesh group.
|
||||
"""
|
||||
group = self.__add_physx_base_mesh_group(name, physics_material)
|
||||
group["export method"] = 2
|
||||
@@ -447,26 +678,40 @@ class SceneManifest():
|
||||
convex_hull_downsampling: int = 4,
|
||||
pca: bool = False,
|
||||
project_hull_vertices: bool = True) -> None:
|
||||
"""
|
||||
Enables and configures mesh decomposition for a PhysX Mesh Group.
|
||||
"""Enables and configures mesh decomposition for a PhysX Mesh Group.
|
||||
Only valid for convex or primitive mesh types.
|
||||
|
||||
:param mesh_group: Mesh group to configure decomposition for.
|
||||
:param max_convex_hulls: Controls the maximum number of hulls to generate.
|
||||
:param max_num_vertices_per_convex_hull: Controls the maximum number of triangles per convex hull.
|
||||
:param concavity: Maximum concavity of each approximate convex hull.
|
||||
:param resolution: Maximum number of voxels generated during the voxelization stage.
|
||||
:param mode: Select voxel-based approximate convex decomposition or tetrahedron-based
|
||||
approximate convex decomposition.
|
||||
:param alpha: Controls the bias toward clipping along symmetry planes.
|
||||
:param beta: Controls the bias toward clipping along revolution axes.
|
||||
:param min_volume_per_convex_hull: Controls the adaptive sampling of the generated convex hulls.
|
||||
:param plane_downsampling: Controls the granularity of the search for the best clipping plane.
|
||||
:param convex_hull_downsampling: Controls the precision of the convex hull generation process
|
||||
during the clipping plane selection stage.
|
||||
:param pca: Enable or disable normalizing the mesh before applying the convex decomposition.
|
||||
:param project_hull_vertices: Project the output convex hull vertices onto the original source mesh to increase
|
||||
the floating point accuracy of the results.
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh group to configure decomposition for.
|
||||
max_convex_hulls :
|
||||
Controls the maximum number of hulls to generate.
|
||||
max_num_vertices_per_convex_hull :
|
||||
Controls the maximum number of triangles per convex hull.
|
||||
concavity :
|
||||
Maximum concavity of each approximate convex hull.
|
||||
resolution :
|
||||
Maximum number of voxels generated during the voxelization stage.
|
||||
mode :
|
||||
Select voxel-based approximate convex decomposition or tetrahedron-based
|
||||
approximate convex decomposition.
|
||||
alpha :
|
||||
Controls the bias toward clipping along symmetry planes.
|
||||
beta :
|
||||
Controls the bias toward clipping along revolution axes.
|
||||
min_volume_per_convex_hull :
|
||||
Controls the adaptive sampling of the generated convex hulls.
|
||||
plane_downsampling :
|
||||
Controls the granularity of the search for the best clipping plane.
|
||||
convex_hull_downsampling :
|
||||
Controls the precision of the convex hull generation process
|
||||
during the clipping plane selection stage.
|
||||
pca :
|
||||
Enable or disable normalizing the mesh before applying the convex decomposition.
|
||||
project_hull_vertices :
|
||||
Project the output convex hull vertices onto the original source mesh to increase
|
||||
the floating point accuracy of the results.
|
||||
"""
|
||||
mesh_group['DecomposeMeshes'] = True
|
||||
mesh_group['ConvexDecompositionParams'] = {
|
||||
@@ -485,41 +730,54 @@ class SceneManifest():
|
||||
}
|
||||
|
||||
def physx_mesh_group_add_selected_node(self, mesh_group: dict, node: str) -> None:
|
||||
"""
|
||||
Adds a node to the selected nodes list
|
||||
"""Adds a node to the selected nodes list
|
||||
|
||||
:param mesh_group: Mesh group to add to.
|
||||
:param node: Node path to add.
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh group to add to.
|
||||
node :
|
||||
Node path to add.
|
||||
"""
|
||||
mesh_group['NodeSelectionList']['selectedNodes'].append(node)
|
||||
|
||||
def physx_mesh_group_add_unselected_node(self, mesh_group: dict, node: str) -> None:
|
||||
"""
|
||||
Adds a node to the unselected nodes list
|
||||
"""Adds a node to the unselected nodes list
|
||||
|
||||
:param mesh_group: Mesh group to add to.
|
||||
:param node: Node path to add.
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh group to add to.
|
||||
node :
|
||||
Node path to add.
|
||||
"""
|
||||
mesh_group['NodeSelectionList']['unselectedNodes'].append(node)
|
||||
|
||||
def physx_mesh_group_add_selected_unselected_nodes(self, mesh_group: dict, selected: typing.List[str],
|
||||
unselected: typing.List[str]) -> None:
|
||||
"""
|
||||
Adds a set of nodes to the selected/unselected node lists
|
||||
"""Adds a set of nodes to the selected/unselected node lists
|
||||
|
||||
:param mesh_group: Mesh group to add to.
|
||||
:param selected: List of node paths to add to the selected list.
|
||||
:param unselected: List of node paths to add to the unselected list.
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh group to add to.
|
||||
selected :
|
||||
List of node paths to add to the selected list.
|
||||
unselected :
|
||||
List of node paths to add to the unselected list.
|
||||
"""
|
||||
mesh_group['NodeSelectionList']['selectedNodes'].extend(selected)
|
||||
mesh_group['NodeSelectionList']['unselectedNodes'].extend(unselected)
|
||||
|
||||
def physx_mesh_group_add_comment(self, mesh_group: dict, comment: str) -> None:
|
||||
"""
|
||||
Adds a comment rule
|
||||
"""Adds a comment rule
|
||||
|
||||
:param mesh_group: Mesh group to add the rule to.
|
||||
:param comment: Comment string.
|
||||
Parameters
|
||||
----------
|
||||
mesh_group :
|
||||
Mesh group to add the rule to.
|
||||
comment :
|
||||
Comment string.
|
||||
"""
|
||||
rule = {
|
||||
"$type": "CommentRule",
|
||||
|
||||
@@ -281,7 +281,8 @@ namespace ScriptCanvasBuilder
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AzFramework::StringFunc::Find(fileNameOnly, s_unitTestParseErrorPrefix) != AZStd::string::npos)
|
||||
if (!ScriptCanvas::Grammar::g_processingErrorsForUnitTestsEnabled
|
||||
&& AzFramework::StringFunc::Find(fileNameOnly, s_unitTestParseErrorPrefix) != AZStd::string::npos)
|
||||
{
|
||||
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
||||
}
|
||||
|
||||
@@ -431,16 +431,6 @@ namespace ScriptCanvasEditor
|
||||
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
|
||||
}
|
||||
|
||||
void EditorScriptCanvasComponent::OnStartPlayInEditor()
|
||||
{
|
||||
ScriptCanvas::Execution::PerformanceStatisticsEBus::Broadcast(&ScriptCanvas::Execution::PerformanceStatisticsBus::ClearSnaphotStatistics);
|
||||
}
|
||||
|
||||
void EditorScriptCanvasComponent::OnStopPlayInEditor()
|
||||
{
|
||||
AZ::ScriptSystemRequestBus::Broadcast(&AZ::ScriptSystemRequests::GarbageCollect);
|
||||
}
|
||||
|
||||
void EditorScriptCanvasComponent::SetAssetId(const SourceHandle& assetId)
|
||||
{
|
||||
if (m_sourceHandle.Describe() != assetId.Describe())
|
||||
|
||||
+1
-1
@@ -190,7 +190,7 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
scriptCanvasSlot = eventHandler->GetSlot(slotId);
|
||||
|
||||
int& index = (scriptCanvasSlot->IsData() && scriptCanvasSlot->IsInput()) ? paramIndex : outputIndex;
|
||||
int& index = (scriptCanvasSlot && scriptCanvasSlot->IsData() && scriptCanvasSlot->IsInput()) ? paramIndex : outputIndex;
|
||||
|
||||
if (scriptCanvasSlot && scriptCanvasSlot->IsVisible())
|
||||
{
|
||||
|
||||
+1
-3
@@ -93,9 +93,7 @@ namespace ScriptCanvasEditor
|
||||
|
||||
//=====================================================================
|
||||
// EditorEntityContextNotificationBus
|
||||
void OnStartPlayInEditor() override;
|
||||
|
||||
void OnStopPlayInEditor() override;
|
||||
|
||||
|
||||
protected:
|
||||
enum class SourceChangeDescription : AZ::u8
|
||||
|
||||
@@ -102,9 +102,6 @@ namespace ScriptCanvasEditor
|
||||
void Log(const char* format, ...);
|
||||
|
||||
private:
|
||||
|
||||
bool m_verbose = true;
|
||||
|
||||
StateMachine* m_stateMachine;
|
||||
};
|
||||
|
||||
@@ -363,7 +360,7 @@ namespace ScriptCanvasEditor
|
||||
template <typename Traits>
|
||||
void ScriptCanvasEditor::State<Traits>::Log(const char* format, ...)
|
||||
{
|
||||
if (m_verbose)
|
||||
if (m_stateMachine->GetVerbose())
|
||||
{
|
||||
char sBuffer[2048];
|
||||
va_list ArgList;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <ScriptCanvas/Core/Datum.h>
|
||||
#include <ScriptCanvas/Data/DataRegistry.h>
|
||||
#include <ScriptCanvas/Libraries/Libraries.h>
|
||||
#include <ScriptCanvas/PerformanceStatisticsBus.h>
|
||||
#include <ScriptCanvas/Variable/VariableCore.h>
|
||||
#include <ScriptCanvas/View/EditCtrls/GenericLineEditCtrl.h>
|
||||
|
||||
@@ -338,10 +339,20 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
};
|
||||
|
||||
openers.push_back({ "O3DE_ScriptCanvasEditor", "Open In Script Canvas Editor...", QIcon(), scriptCanvasEditorCallback });
|
||||
openers.push_back({ "O3DE_ScriptCanvasEditor", "Open In Script Canvas Editor...", QIcon(ScriptCanvasAssetDescription().GetIconPathImpl()), scriptCanvasEditorCallback });
|
||||
}
|
||||
}
|
||||
|
||||
void SystemComponent::OnStartPlayInEditor()
|
||||
{
|
||||
ScriptCanvas::Execution::PerformanceStatisticsEBus::Broadcast(&ScriptCanvas::Execution::PerformanceStatisticsBus::ClearSnaphotStatistics);
|
||||
}
|
||||
|
||||
void SystemComponent::OnStopPlayInEditor()
|
||||
{
|
||||
AZ::ScriptSystemRequestBus::Broadcast(&AZ::ScriptSystemRequests::GarbageCollect);
|
||||
}
|
||||
|
||||
void SystemComponent::OnUserSettingsActivated()
|
||||
{
|
||||
PopulateEditorCreatableTypes();
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/Model.h>
|
||||
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Bus/ScriptCanvasExecutionBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
@@ -36,6 +37,8 @@ namespace ScriptCanvasEditor
|
||||
, private AZ::Data::AssetBus::MultiHandler
|
||||
, private AzToolsFramework::AssetSeedManagerRequests::Bus::Handler
|
||||
, private AzToolsFramework::EditorContextMenuBus::Handler
|
||||
, private AzToolsFramework::EditorEntityContextNotificationBus::Handler
|
||||
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(SystemComponent, "{1DE7A120-4371-4009-82B5-8140CB1D7B31}");
|
||||
@@ -97,7 +100,12 @@ namespace ScriptCanvasEditor
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
protected:
|
||||
void OnStartPlayInEditor() override;
|
||||
|
||||
void OnStopPlayInEditor() override;
|
||||
|
||||
private:
|
||||
SystemComponent(const SystemComponent&) = delete;
|
||||
|
||||
|
||||
@@ -1880,10 +1880,6 @@ namespace ScriptCanvasEditor
|
||||
|
||||
void MainWindow::OnFileOpen()
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext);
|
||||
AZ_Assert(serializeContext, "Failed to acquire application serialize context.");
|
||||
|
||||
AZStd::string assetRoot;
|
||||
{
|
||||
AZStd::array<char, AZ::IO::MaxPathLength> assetRootChar;
|
||||
@@ -1892,21 +1888,9 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
|
||||
AZStd::string assetPath = AZStd::string::format("%s/scriptcanvas", assetRoot.c_str());
|
||||
|
||||
AZ::EBusAggregateResults<AZStd::vector<AZStd::string>> fileFilters;
|
||||
AssetRegistryRequestBus::BroadcastResult(fileFilters, &AssetRegistryRequests::GetAssetHandlerFileFilters);
|
||||
|
||||
QString filter;
|
||||
|
||||
AZStd::set<AZStd::string> filterSet;
|
||||
auto aggregateFilters = fileFilters.values;
|
||||
for (auto aggregateFilters2 : fileFilters.values)
|
||||
{
|
||||
for (const AZStd::string& fileFilter : aggregateFilters2)
|
||||
{
|
||||
filterSet.insert(fileFilter);
|
||||
}
|
||||
}
|
||||
AZStd::set<AZStd::string> filterSet { ".scriptcanvas" };
|
||||
|
||||
QStringList nameFilters;
|
||||
|
||||
|
||||
@@ -188,6 +188,11 @@ namespace ScriptCanvasEditor
|
||||
OnButtonPressUpgradeImplementation(info);
|
||||
}
|
||||
|
||||
void Controller::OnUpgradeDependencyWaitInterval([[maybe_unused]] const SourceHandle& info)
|
||||
{
|
||||
AddLogEntries();
|
||||
}
|
||||
|
||||
void Controller::OnUpgradeModificationBegin([[maybe_unused]] const ModifyConfiguration& config, const SourceHandle& info)
|
||||
{
|
||||
for (auto* item : FindTableItems(info))
|
||||
@@ -210,6 +215,8 @@ namespace ScriptCanvasEditor
|
||||
else
|
||||
{
|
||||
VE_LOG("Failed to modify %s: %s", result.asset.Path().c_str(), result.errorMessage.data());
|
||||
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data()
|
||||
, false, "Failed to modify %s: %s", result.asset.Path().c_str(), result.errorMessage.data());
|
||||
}
|
||||
|
||||
for (auto* item : FindTableItems(info))
|
||||
|
||||
@@ -93,9 +93,10 @@ namespace ScriptCanvasEditor
|
||||
( const ModifyConfiguration& config
|
||||
, const AZStd::vector<SourceHandle>& assets
|
||||
, const AZStd::vector<size_t>& sortedOrder) override;
|
||||
void OnUpgradeDependencyWaitInterval(const SourceHandle& info) override;
|
||||
void OnUpgradeModificationBegin(const ModifyConfiguration& config, const SourceHandle& info) override;
|
||||
void OnUpgradeModificationEnd(const ModifyConfiguration& config, const SourceHandle& info, ModificationResult result) override;
|
||||
|
||||
|
||||
void SetLoggingPreferences();
|
||||
void SetSpinnerIsBusy(bool isBusy);
|
||||
void SetRowBusy(int index);
|
||||
|
||||
@@ -145,6 +145,7 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
|
||||
Idle();
|
||||
RestoreSettings();
|
||||
}
|
||||
|
||||
void Model::OnScanComplete()
|
||||
@@ -161,6 +162,7 @@ namespace ScriptCanvasEditor
|
||||
return;
|
||||
}
|
||||
|
||||
CacheSettings();
|
||||
m_state = State::Scanning;
|
||||
m_log.Activate();
|
||||
m_keepEditorAlive = AZStd::make_unique<EditorKeepAlive>();
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace ScriptCanvasEditor
|
||||
SourceHandle modifySingleAsset;
|
||||
bool backupGraphBeforeModification = false;
|
||||
bool successfulDependencyUpgradeRequired = true;
|
||||
AZ::s32 perDependencyWaitSecondsMax = 20;
|
||||
};
|
||||
|
||||
struct ModificationResult
|
||||
@@ -98,6 +99,7 @@ namespace ScriptCanvasEditor
|
||||
( const ModifyConfiguration& config
|
||||
, const AZStd::vector<SourceHandle>& assets
|
||||
, const AZStd::vector<size_t>& sortedOrder) = 0;
|
||||
virtual void OnUpgradeDependencyWaitInterval(const SourceHandle& info) = 0;
|
||||
virtual void OnUpgradeModificationBegin(const ModifyConfiguration& config, const SourceHandle& info) = 0;
|
||||
virtual void OnUpgradeModificationEnd(const ModifyConfiguration& config, const SourceHandle& info, ModificationResult result) = 0;
|
||||
};
|
||||
|
||||
@@ -30,38 +30,93 @@ namespace ScriptCanvasEditor
|
||||
AZ_Assert(m_config.modification, "No modification function provided");
|
||||
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeBegin, modification, m_assets);
|
||||
AZ::SystemTickBus::Handler::BusConnect();
|
||||
AzFramework::AssetSystemInfoBus::Handler::BusConnect();
|
||||
m_result.asset = m_assets[GetCurrentIndex()];
|
||||
}
|
||||
|
||||
size_t Modifier::GetCurrentIndex() const
|
||||
Modifier::~Modifier()
|
||||
{
|
||||
return m_state == State::GatheringDependencies
|
||||
? m_assetIndex
|
||||
: m_dependencyOrderedAssetIndicies[m_assetIndex];
|
||||
|
||||
AzFramework::AssetSystemInfoBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
AZStd::unordered_set<size_t>& Modifier::GetOrCreateDependencyIndexSet()
|
||||
bool Modifier::AllDependenciesCleared(const AZStd::unordered_set<size_t>& dependencies) const
|
||||
{
|
||||
auto iter = m_dependencies.find(m_assetIndex);
|
||||
if (iter == m_dependencies.end())
|
||||
for (auto index : dependencies)
|
||||
{
|
||||
iter = m_dependencies.insert_or_assign(m_assetIndex, AZStd::unordered_set<size_t>()).first;
|
||||
SourceHandle dependency = m_assets[index];
|
||||
CompleteDescriptionInPlace(dependency);
|
||||
|
||||
if (dependency.Id().IsNull() || !m_assetsCompletedByAP.contains(dependency.Id()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
const ModificationResults& Modifier::GetResult() const
|
||||
bool Modifier::AnyDependenciesFailed(const AZStd::unordered_set<size_t>& dependencies) const
|
||||
{
|
||||
return m_results;
|
||||
for (auto index : dependencies)
|
||||
{
|
||||
SourceHandle dependency = m_assets[index];
|
||||
CompleteDescriptionInPlace(dependency);
|
||||
|
||||
if (dependency.Id().IsNull() || m_assetsFailedByAP.contains(dependency.Id()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Modifier::AssetCompilationSuccess([[maybe_unused]] const AZStd::string& assetPath)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
|
||||
m_successNotifications.insert(assetPath);
|
||||
}
|
||||
|
||||
void Modifier::AssetCompilationFailed(const AZStd::string& assetPath)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
|
||||
m_failureNotifications.insert(assetPath);
|
||||
}
|
||||
|
||||
AZStd::sys_time_t Modifier::CalculateRemainingWaitTime(const AZStd::unordered_set<size_t>& dependencies) const
|
||||
{
|
||||
auto maxSeconds = AZStd::chrono::seconds(dependencies.size() * m_config.perDependencyWaitSecondsMax);
|
||||
auto waitedSeconds = AZStd::chrono::seconds(AZStd::chrono::system_clock::now() - m_waitTimeStamp);
|
||||
return (maxSeconds - waitedSeconds).count();
|
||||
}
|
||||
|
||||
void Modifier::CheckDependencies()
|
||||
{
|
||||
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeModificationBegin, m_config, m_result.asset);
|
||||
|
||||
if (auto dependencies = GetDependencies(GetCurrentIndex()); dependencies != nullptr && !dependencies->empty())
|
||||
{
|
||||
VE_LOG
|
||||
( "dependencies found for %s, update will wait for the AP to finish processing them"
|
||||
, m_result.asset.Path().c_str());
|
||||
|
||||
m_waitTimeStamp = AZStd::chrono::system_clock::now();
|
||||
m_waitLogTimeStamp = AZStd::chrono::system_clock::time_point{};
|
||||
m_modifyState = ModifyState::WaitingForDependencyProcessing;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_modifyState = ModifyState::StartModification;
|
||||
}
|
||||
}
|
||||
|
||||
void Modifier::GatherDependencies()
|
||||
{
|
||||
AZ::SerializeContext* serializeContext{};
|
||||
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
||||
AZ_Assert(serializeContext, "SerializeContext is required to enumerate dependent assets in the ScriptCanvas file");
|
||||
|
||||
LoadAsset();
|
||||
bool anyFailures = false;
|
||||
|
||||
if (m_result.asset.Get() && m_result.asset.Mod()->GetGraphData())
|
||||
@@ -101,7 +156,7 @@ namespace ScriptCanvasEditor
|
||||
, nullptr))
|
||||
{
|
||||
anyFailures = true;
|
||||
VE_LOG("Modifier: ERROR - Failed to gather dependencies from graph data: %s"
|
||||
VE_LOG("Modifier: ERROR - Failed to gather dependencies from graph data: %s"
|
||||
, m_result.asset.Path().c_str())
|
||||
}
|
||||
}
|
||||
@@ -111,16 +166,52 @@ namespace ScriptCanvasEditor
|
||||
VE_LOG("Modifier: ERROR - Failed to load asset %s for modification, even though it scanned properly"
|
||||
, m_result.asset.Path().c_str());
|
||||
}
|
||||
|
||||
|
||||
ModelNotificationsBus::Broadcast
|
||||
( &ModelNotificationsTraits::OnUpgradeDependenciesGathered
|
||||
, m_result.asset
|
||||
, anyFailures ? Result::Failure : Result::Success);
|
||||
}
|
||||
|
||||
ReleaseCurrentAsset();
|
||||
size_t Modifier::GetCurrentIndex() const
|
||||
{
|
||||
return m_state == State::GatheringDependencies
|
||||
? m_assetIndex
|
||||
: m_dependencyOrderedAssetIndicies[m_assetIndex];
|
||||
}
|
||||
|
||||
// Flush asset database events to ensure no asset references are held by closures queued on Ebuses.
|
||||
AZ::Data::AssetManager::Instance().DispatchEvents();
|
||||
const AZStd::unordered_set<size_t>* Modifier::GetDependencies(size_t index) const
|
||||
{
|
||||
auto iter = m_dependencies.find(index);
|
||||
return iter != m_dependencies.end() ? &iter->second : nullptr;
|
||||
}
|
||||
|
||||
AZStd::unordered_set<size_t>& Modifier::GetOrCreateDependencyIndexSet()
|
||||
{
|
||||
auto iter = m_dependencies.find(m_assetIndex);
|
||||
if (iter == m_dependencies.end())
|
||||
{
|
||||
iter = m_dependencies.insert_or_assign(m_assetIndex, AZStd::unordered_set<size_t>()).first;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
const ModificationResults& Modifier::GetResult() const
|
||||
{
|
||||
return m_results;
|
||||
}
|
||||
|
||||
void Modifier::InitializeResult()
|
||||
{
|
||||
m_result = {};
|
||||
|
||||
if (m_assetIndex != m_assets.size())
|
||||
{
|
||||
m_result.asset = m_assets[GetCurrentIndex()];
|
||||
CompleteDescriptionInPlace(m_result.asset);
|
||||
m_attemptedAssets.insert(m_result.asset.Id());
|
||||
}
|
||||
}
|
||||
|
||||
void Modifier::LoadAsset()
|
||||
@@ -144,7 +235,7 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
else if (m_result.asset.Describe() != result.asset.Describe())
|
||||
{
|
||||
ReportModificationError("Received modifiction complete notification for different result");
|
||||
ReportModificationError("Received modification complete notification for different result");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -154,9 +245,6 @@ namespace ScriptCanvasEditor
|
||||
|
||||
void Modifier::ModifyCurrentAsset()
|
||||
{
|
||||
m_result = {};
|
||||
m_result.asset = m_assets[GetCurrentIndex()];
|
||||
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeModificationBegin, m_config, m_result.asset);
|
||||
LoadAsset();
|
||||
|
||||
if (m_result.asset.IsGraphValid())
|
||||
@@ -171,50 +259,17 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
}
|
||||
|
||||
void Modifier::ModifyNextAsset()
|
||||
void Modifier::NextAsset()
|
||||
{
|
||||
ModelNotificationsBus::Broadcast
|
||||
( &ModelNotificationsTraits::OnUpgradeModificationEnd, m_config, m_result.asset, m_result);
|
||||
ModificationNotificationsBus::Handler::BusDisconnect();
|
||||
m_modifyState = ModifyState::Idle;
|
||||
ReleaseCurrentAsset();
|
||||
++m_assetIndex;
|
||||
m_result = {};
|
||||
InitializeResult();
|
||||
}
|
||||
|
||||
void Modifier::ReleaseCurrentAsset()
|
||||
void Modifier::NextModification()
|
||||
{
|
||||
m_result.asset = m_result.asset.Describe();
|
||||
}
|
||||
|
||||
void Modifier::ReportModificationError(AZStd::string_view report)
|
||||
{
|
||||
m_result.errorMessage = report;
|
||||
m_results.m_failures.push_back({ m_result.asset.Describe(), report });
|
||||
ModifyNextAsset();
|
||||
}
|
||||
|
||||
void Modifier::ReportModificationSuccess()
|
||||
{
|
||||
m_result.asset = m_result.asset.Describe();
|
||||
m_results.m_successes.push_back({ m_result.asset.Describe(), {} });
|
||||
ModifyNextAsset();
|
||||
}
|
||||
|
||||
void Modifier::ReportSaveResult()
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
|
||||
m_fileSaver.reset();
|
||||
|
||||
if (m_fileSaveResult.fileSaveError.empty())
|
||||
{
|
||||
ReportModificationSuccess();
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportModificationError(m_fileSaveResult.fileSaveError);
|
||||
}
|
||||
|
||||
ModelNotificationsBus::Broadcast( &ModelNotificationsTraits::OnUpgradeModificationEnd, m_config, m_result.asset, m_result);
|
||||
ModificationNotificationsBus::Handler::BusDisconnect();
|
||||
NextAsset();
|
||||
m_fileSaveResult = {};
|
||||
m_modifyState = ModifyState::Idle;
|
||||
}
|
||||
@@ -224,7 +279,7 @@ namespace ScriptCanvasEditor
|
||||
if (!result.tempFileRemovalError.empty())
|
||||
{
|
||||
VE_LOG
|
||||
( "Temporary file not removed for %s: %s"
|
||||
("Temporary file not removed for %s: %s"
|
||||
, m_result.asset.Path().c_str()
|
||||
, result.tempFileRemovalError.c_str());
|
||||
}
|
||||
@@ -252,6 +307,78 @@ namespace ScriptCanvasEditor
|
||||
AZ::SystemTickBus::ExecuteQueuedEvents();
|
||||
}
|
||||
|
||||
void Modifier::ProcessNotifications()
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
|
||||
|
||||
for (const auto& assetPath : m_successNotifications)
|
||||
{
|
||||
VE_LOG("received AssetCompilationSuccess: %s", assetPath.c_str());
|
||||
SourceHandle sourceHandle(nullptr, {}, assetPath.c_str());
|
||||
CompleteDescriptionInPlace(sourceHandle);
|
||||
|
||||
if (m_attemptedAssets.contains(sourceHandle.Id()))
|
||||
{
|
||||
m_assetsCompletedByAP.insert(sourceHandle.Id());
|
||||
}
|
||||
}
|
||||
|
||||
m_successNotifications.clear();
|
||||
|
||||
for (const auto& assetPath : m_failureNotifications)
|
||||
{
|
||||
VE_LOG("received AssetCompilationFailed: %s", assetPath.c_str());
|
||||
SourceHandle sourceHandle(nullptr, {}, assetPath.c_str());
|
||||
CompleteDescriptionInPlace(sourceHandle);
|
||||
|
||||
if (m_attemptedAssets.contains(sourceHandle.Id()))
|
||||
{
|
||||
m_assetsFailedByAP.insert(sourceHandle.Id());
|
||||
}
|
||||
}
|
||||
|
||||
m_failureNotifications.clear();
|
||||
}
|
||||
|
||||
void Modifier::ReleaseCurrentAsset()
|
||||
{
|
||||
m_result.asset = m_result.asset.Describe();
|
||||
// Flush asset database events to ensure no asset references are held by closures queued on Ebuses.
|
||||
AZ::Data::AssetManager::Instance().DispatchEvents();
|
||||
}
|
||||
|
||||
void Modifier::ReportModificationError(AZStd::string_view report)
|
||||
{
|
||||
m_result.errorMessage = report;
|
||||
m_results.m_failures.push_back({ m_result.asset.Describe(), report });
|
||||
m_assetsFailedByAP.insert(m_result.asset.Id());
|
||||
NextModification();
|
||||
}
|
||||
|
||||
void Modifier::ReportModificationSuccess()
|
||||
{
|
||||
// \note DO NOT put asset into the m_assetsCompletedByAP here. That can only be done when the message is received by the AP
|
||||
m_results.m_successes.push_back({ m_result.asset.Describe(), {} });
|
||||
AzFramework::AssetSystemRequestBus::Broadcast(
|
||||
&AzFramework::AssetSystem::AssetSystemRequests::EscalateAssetByUuid, m_result.asset.Id());
|
||||
NextModification();
|
||||
}
|
||||
|
||||
void Modifier::ReportSaveResult()
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
|
||||
m_fileSaver.reset();
|
||||
|
||||
if (m_fileSaveResult.fileSaveError.empty())
|
||||
{
|
||||
ReportModificationSuccess();
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportModificationError(m_fileSaveResult.fileSaveError);
|
||||
}
|
||||
}
|
||||
|
||||
void Modifier::SaveModifiedGraph(const ModificationResult& result)
|
||||
{
|
||||
m_modifyState = ModifyState::Saving;
|
||||
@@ -316,49 +443,87 @@ namespace ScriptCanvasEditor
|
||||
|
||||
m_assetIndex = 0;
|
||||
m_state = State::ModifyingGraphs;
|
||||
InitializeResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
GatherDependencies();
|
||||
ReleaseCurrentAsset();
|
||||
++m_assetIndex;
|
||||
NextAsset();
|
||||
}
|
||||
}
|
||||
|
||||
void Modifier::TickUpdateGraph()
|
||||
{
|
||||
if (m_assetIndex == m_assets.size())
|
||||
{
|
||||
VE_LOG("Modifier: Complete.");
|
||||
AZ::SystemTickBus::Handler::BusDisconnect();
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
|
||||
|
||||
if (m_onComplete)
|
||||
switch (m_modifyState)
|
||||
{
|
||||
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::Idle:
|
||||
if (m_assetIndex == m_assets.size())
|
||||
{
|
||||
m_onComplete();
|
||||
VE_LOG("Modifier: Complete.");
|
||||
AZ::SystemTickBus::Handler::BusDisconnect();
|
||||
|
||||
if (m_onComplete)
|
||||
{
|
||||
m_onComplete();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckDependencies();
|
||||
}
|
||||
break;
|
||||
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::WaitingForDependencyProcessing:
|
||||
WaitForDependencies();
|
||||
break;
|
||||
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::StartModification:
|
||||
ModifyCurrentAsset();
|
||||
break;
|
||||
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::ReportResult:
|
||||
ReportSaveResult();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
|
||||
}
|
||||
|
||||
switch (m_modifyState)
|
||||
{
|
||||
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::Idle:
|
||||
ModifyCurrentAsset();
|
||||
break;
|
||||
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::ReportResult:
|
||||
ReportSaveResult();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
void Modifier::WaitForDependencies()
|
||||
{
|
||||
const AZ::s32 LogPeriodSeconds = 5;
|
||||
|
||||
ProcessNotifications();
|
||||
|
||||
auto dependencies = GetDependencies(GetCurrentIndex());
|
||||
if (dependencies == nullptr || dependencies->empty() || AllDependenciesCleared(*dependencies))
|
||||
{
|
||||
m_modifyState = ModifyState::StartModification;
|
||||
}
|
||||
else if (AnyDependenciesFailed(*dependencies))
|
||||
{
|
||||
ReportModificationError("A required dependency failed to update, graph cannot update.");
|
||||
}
|
||||
else if (AZStd::chrono::seconds(CalculateRemainingWaitTime(*dependencies)).count() < 0)
|
||||
{
|
||||
ReportModificationError("Dependency update time has taken too long, aborting modification.");
|
||||
}
|
||||
else if (AZStd::chrono::seconds(AZStd::chrono::system_clock::now() - m_waitLogTimeStamp).count() > LogPeriodSeconds)
|
||||
{
|
||||
m_waitLogTimeStamp = AZStd::chrono::system_clock::now();
|
||||
|
||||
AZ_TracePrintf
|
||||
( ScriptCanvas::k_VersionExplorerWindow.data()
|
||||
, "Waiting for dependencies for %d more seconds: %s"
|
||||
, AZStd::chrono::seconds(CalculateRemainingWaitTime(*dependencies)).count()
|
||||
, m_result.asset.Path().c_str());
|
||||
|
||||
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeDependencyWaitInterval, m_result.asset);
|
||||
}
|
||||
}
|
||||
|
||||
const AZStd::unordered_set<size_t>* Modifier::Sorter::GetDependencies(size_t index) const
|
||||
{
|
||||
auto iter = modifier->m_dependencies.find(index);
|
||||
return iter != modifier->m_dependencies.end() ? &iter->second : nullptr;
|
||||
return modifier->GetDependencies(index);
|
||||
}
|
||||
|
||||
void Modifier::Sorter::Sort()
|
||||
@@ -379,7 +544,7 @@ namespace ScriptCanvasEditor
|
||||
if (markedTemporary.contains(index))
|
||||
{
|
||||
AZ_Error
|
||||
(ScriptCanvas::k_VersionExplorerWindow.data()
|
||||
( ScriptCanvas::k_VersionExplorerWindow.data()
|
||||
, false
|
||||
, "Modifier: Dependency sort has failed during, circular dependency detected for Asset: %s"
|
||||
, modifier->m_result.asset.Path().c_str());
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/FileSaver.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h>
|
||||
#include <ScriptCanvas/Core/Core.h>
|
||||
@@ -17,9 +18,10 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
class Modifier
|
||||
: private AZ::SystemTickBus::Handler
|
||||
, private ModificationNotificationsBus::Handler
|
||||
class Modifier final
|
||||
: public AZ::SystemTickBus::Handler
|
||||
, public ModificationNotificationsBus::Handler
|
||||
, public AzFramework::AssetSystemInfoBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Modifier, AZ::SystemAllocator, 0);
|
||||
@@ -29,6 +31,8 @@ namespace ScriptCanvasEditor
|
||||
, AZStd::vector<SourceHandle>&& assets
|
||||
, AZStd::function<void()> onComplete);
|
||||
|
||||
virtual ~Modifier();
|
||||
|
||||
const ModificationResults& GetResult() const;
|
||||
ModificationResults&& TakeResult();
|
||||
|
||||
@@ -56,6 +60,8 @@ namespace ScriptCanvasEditor
|
||||
enum class ModifyState
|
||||
{
|
||||
Idle,
|
||||
WaitingForDependencyProcessing,
|
||||
StartModification,
|
||||
InProgress,
|
||||
Saving,
|
||||
ReportResult
|
||||
@@ -76,30 +82,49 @@ namespace ScriptCanvasEditor
|
||||
// dependency indices by asset info index (only exist if graphs have them)
|
||||
AZStd::unordered_map<size_t, AZStd::unordered_set<size_t>> m_dependencies;
|
||||
AZStd::unordered_map<AZ::Uuid, size_t> m_assetInfoIndexById;
|
||||
AZStd::vector<size_t> m_failures;
|
||||
ModifyConfiguration m_config;
|
||||
ModificationResult m_result;
|
||||
ModificationResults m_results;
|
||||
AZStd::unique_ptr<FileSaver> m_fileSaver;
|
||||
FileSaveResult m_fileSaveResult;
|
||||
// m_attemptedAssets is assets attempted to be processed by modification, as opposed to
|
||||
// those processed by the AP as a result of one of their dependencies being processed.
|
||||
AZStd::unordered_set<AZ::Uuid> m_attemptedAssets;
|
||||
AZStd::unordered_set<AZ::Uuid> m_assetsCompletedByAP;
|
||||
AZStd::unordered_set<AZ::Uuid> m_assetsFailedByAP;
|
||||
AZStd::chrono::system_clock::time_point m_waitLogTimeStamp;
|
||||
AZStd::chrono::system_clock::time_point m_waitTimeStamp;
|
||||
AZStd::unordered_set<AZStd::string> m_successNotifications;
|
||||
AZStd::unordered_set<AZStd::string> m_failureNotifications;
|
||||
|
||||
size_t GetCurrentIndex() const;
|
||||
bool AllDependenciesCleared(const AZStd::unordered_set<size_t>& dependencies) const;
|
||||
bool AnyDependenciesFailed(const AZStd::unordered_set<size_t>& dependencies) const;
|
||||
void AssetCompilationSuccess(const AZStd::string& assetPath) override;
|
||||
void AssetCompilationFailed(const AZStd::string& assetPath) override;
|
||||
AZStd::sys_time_t CalculateRemainingWaitTime(const AZStd::unordered_set<size_t>& dependencies) const;
|
||||
void CheckDependencies();
|
||||
void GatherDependencies();
|
||||
size_t GetCurrentIndex() const;
|
||||
const AZStd::unordered_set<size_t>* GetDependencies(size_t index) const;
|
||||
AZStd::unordered_set<size_t>& GetOrCreateDependencyIndexSet();
|
||||
void InitializeResult();
|
||||
void LoadAsset();
|
||||
void ModifyCurrentAsset();
|
||||
void ModifyNextAsset();
|
||||
void ModificationComplete(const ModificationResult& result) override;
|
||||
void ModifyCurrentAsset();
|
||||
void NextAsset();
|
||||
void NextModification();
|
||||
void OnFileSaveComplete(const FileSaveResult& result);
|
||||
void OnSystemTick() override;
|
||||
void ProcessNotifications();
|
||||
void ReleaseCurrentAsset();
|
||||
void ReportModificationError(AZStd::string_view report);
|
||||
void ReportModificationSuccess();
|
||||
void ReportSaveResult();
|
||||
void SaveModifiedGraph(const ModificationResult& result);
|
||||
void SortGraphsByDependencies();
|
||||
void OnFileSaveComplete(const FileSaveResult& result);
|
||||
void OnSystemTick() override;
|
||||
void TickGatherDependencies();
|
||||
void TickUpdateGraph();
|
||||
void WaitForDependencies();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace ScriptCanvas
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -503,20 +503,21 @@ namespace ScriptCanvas
|
||||
|
||||
void InitializeInterpretedStatics(RuntimeData& runtimeData)
|
||||
{
|
||||
if (!runtimeData.m_areStaticsInitialized)
|
||||
AZ_Error("ScriptCanvas", !runtimeData.m_areStaticsInitialized, "ScriptCanvas runtime data already initalized");
|
||||
{
|
||||
runtimeData.m_areStaticsInitialized = true;
|
||||
|
||||
for (auto& dependency : runtimeData.m_requiredAssets)
|
||||
{
|
||||
InitializeInterpretedStatics(dependency.Get()->GetData());
|
||||
if (!dependency.Get()->GetData().m_areStaticsInitialized)
|
||||
{
|
||||
InitializeInterpretedStatics(dependency.Get()->GetData());
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(AZ_PROFILE_BUILD) || defined(AZ_DEBUG_BUILD)
|
||||
Execution::InitializeFromLuaStackFunctions(const_cast<Grammar::DebugSymbolMap&>(runtimeData.m_debugMap));
|
||||
#endif
|
||||
AZ_WarningOnce("ScriptCanvas", !runtimeData.m_areStaticsInitialized, "ScriptCanvas runtime data already initalized");
|
||||
|
||||
if (runtimeData.RequiresStaticInitialization())
|
||||
{
|
||||
AZ::ScriptLoadResult result{};
|
||||
|
||||
+4
-1
@@ -49,7 +49,10 @@ namespace ScriptCanvas
|
||||
, config.asset.GetId().ToString<AZStd::string>().data());
|
||||
#endif
|
||||
|
||||
Execution::InitializeInterpretedStatics(runtimeAsset->GetData());
|
||||
if (!runtimeAsset->GetData().m_areStaticsInitialized)
|
||||
{
|
||||
Execution::InitializeInterpretedStatics(runtimeAsset->GetData());
|
||||
}
|
||||
}
|
||||
|
||||
void ExecutionStateInterpreted::ClearLuaRegistryIndex()
|
||||
|
||||
@@ -2384,9 +2384,8 @@ namespace ScriptCanvas
|
||||
AZ_TracePrintf("ScriptCanvas", "%s", pretty.data());
|
||||
AZ_TracePrintf("ScriptCanvas", "SubgraphInterface:");
|
||||
AZ_TracePrintf("ScriptCanvas", ToString(m_subgraphInterface).data());
|
||||
AZ_TracePrintf("Script Canvas", "Parse Duration: %8.4f ms\n", m_parseDuration / 1000.0);
|
||||
}
|
||||
|
||||
AZ_TracePrintf("Script Canvas", "Parse Duration: %8.4f ms\n", m_parseDuration / 1000.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace ScriptCanvas
|
||||
AZ_CVAR(bool, g_disableParseOnGraphValidation, false, {}, AZ::ConsoleFunctorFlags::Null, "In case parsing the graph is interfering with opening a graph, disable parsing on validation");
|
||||
AZ_CVAR(bool, g_printAbstractCodeModel, true, {}, AZ::ConsoleFunctorFlags::Null, "Print out the Abstract Code Model at the end of parsing for debug purposes.");
|
||||
AZ_CVAR(bool, g_printAbstractCodeModelAtPrefabTime, false, {}, AZ::ConsoleFunctorFlags::Null, "Print out the Abstract Code Model at the end of parsing (at prefab time) for debug purposes.");
|
||||
AZ_CVAR(bool, g_processingErrorsForUnitTestsEnabled, false, {}, AZ::ConsoleFunctorFlags::Null, "Enable AP processing errors on parse failure for unit tests.");
|
||||
AZ_CVAR(bool, g_saveRawTranslationOuputToFile, true, {}, AZ::ConsoleFunctorFlags::Null, "Save out the raw result of translation for debug purposes.");
|
||||
AZ_CVAR(bool, g_saveRawTranslationOuputToFileAtPrefabTime, false, {}, AZ::ConsoleFunctorFlags::Null, "Save out the raw result of translation (at prefab time) for debug purposes.");
|
||||
|
||||
|
||||
@@ -245,6 +245,7 @@ namespace ScriptCanvas
|
||||
AZ_CVAR_EXTERNED(bool, g_disableParseOnGraphValidation);
|
||||
AZ_CVAR_EXTERNED(bool, g_printAbstractCodeModel);
|
||||
AZ_CVAR_EXTERNED(bool, g_printAbstractCodeModelAtPrefabTime);
|
||||
AZ_CVAR_EXTERNED(bool, g_processingErrorsForUnitTestsEnabled);
|
||||
AZ_CVAR_EXTERNED(bool, g_saveRawTranslationOuputToFile);
|
||||
AZ_CVAR_EXTERNED(bool, g_saveRawTranslationOuputToFileAtPrefabTime);
|
||||
|
||||
|
||||
Vendored
+41
-15
@@ -76,11 +76,11 @@ def palRm(path) {
|
||||
def palRmDir(path) {
|
||||
if (env.IS_UNIX) {
|
||||
sh label: "Removing ${path}",
|
||||
script: "rm -rf ${path}"
|
||||
script: "if [ -d ${path} ]; then rm -rf ${path}; fi"
|
||||
} else {
|
||||
def win_path = path.replace('/','\\')
|
||||
bat label: "Removing ${win_path}",
|
||||
script: "rd /s /q ${win_path}"
|
||||
script: "IF exist ${win_path} rd /s /q ${win_path}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,10 +406,6 @@ def ExportTestResults(Map options, String platform, String type, String workspac
|
||||
def o3deroot = "${workspace}/${ENGINE_REPOSITORY_NAME}"
|
||||
dir("${o3deroot}/${params.OUTPUT_DIRECTORY}") {
|
||||
junit testResults: "Testing/**/*.xml"
|
||||
palRmDir("Testing")
|
||||
// Recreate test runner xml directories that need to be pre generated
|
||||
palMkdir("Testing/Pytest")
|
||||
palMkdir("Testing/Gtest")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -461,9 +457,26 @@ def UploadAPLogs(String platformName, String jobName, String workspace, Map para
|
||||
}
|
||||
}
|
||||
|
||||
def PostBuildCommonSteps(String workspace, boolean mount = true) {
|
||||
echo 'Starting post-build common steps...'
|
||||
def UploadTestArtifacts(String workspace, String outputDirectory) {
|
||||
catchError(message: "Error archiving test artifacts (this won't fail the build)", buildResult: 'UNSTABLE', stageResult: 'FAILURE') {
|
||||
def cmakeBuildDir = [workspace, ENGINE_REPOSITORY_NAME, outputDirectory].join('/')
|
||||
echo "Uploading Test Artifacts: ${cmakeBuildDir}/Testing"
|
||||
ArchiveArtifactsOnS3("${cmakeBuildDir}/Testing", "test_artifacts", true)
|
||||
}
|
||||
}
|
||||
|
||||
def PostBuildCommonSteps(String workspace, Map params, boolean mount = true) {
|
||||
echo 'Starting post-build common steps...'
|
||||
if (params && params.containsKey('OUTPUT_DIRECTORY')){
|
||||
dir([workspace, ENGINE_REPOSITORY_NAME, params.OUTPUT_DIRECTORY].join('/')){
|
||||
// Clean up Testing directory
|
||||
palRmDir("Testing")
|
||||
// Recreate test runner xml directories that need to be pre generated to prevent race condition on incremental runs
|
||||
palMkdir("Testing/Pytest")
|
||||
palMkdir("Testing/Gtest")
|
||||
}
|
||||
}
|
||||
|
||||
if (mount) {
|
||||
def pythonCmd = ''
|
||||
if(env.IS_UNIX) pythonCmd = 'sudo -E python3 -u '
|
||||
@@ -532,10 +545,18 @@ def CreateUploadAPLogsStage(String platformName, String jobName, String workspac
|
||||
}
|
||||
}
|
||||
|
||||
def CreateTeardownStage(Map environmentVars) {
|
||||
def CreateUploadTestArtifactStage(String jobName, String workspace, String outputDirectory) {
|
||||
return {
|
||||
stage("${jobName}_upload_test_artifacts") {
|
||||
UploadTestArtifacts(workspace, outputDirectory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def CreateTeardownStage(Map environmentVars, Map params) {
|
||||
return {
|
||||
stage('Teardown') {
|
||||
PostBuildCommonSteps(environmentVars['WORKSPACE'], environmentVars['MOUNT_VOLUME'])
|
||||
PostBuildCommonSteps(environmentVars['WORKSPACE'], params, environmentVars['MOUNT_VOLUME'])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -552,6 +573,7 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar
|
||||
}
|
||||
withEnv(GetEnvStringList(envVars)) {
|
||||
def build_job_name = build_job.key
|
||||
def params = platform.value.build_types[build_job_name].PARAMETERS
|
||||
try {
|
||||
CreateSetupStage(pipelineConfig, snapshot, repositoryName, projectName, pipelineName, branchName, platform.key, build_job.key, envVars, onlyMountEBSVolume).call()
|
||||
|
||||
@@ -559,6 +581,7 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar
|
||||
pipelineEnvVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName)
|
||||
build_job.value.steps.each { build_step ->
|
||||
build_job_name = build_step
|
||||
params = platform.value.build_types[build_job_name].PARAMETERS
|
||||
// This addition of maps makes it that the right operand will override entries if they overlap with the left operand
|
||||
envVars = pipelineEnvVars + GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, platform.value.build_types[build_step].PIPELINE_ENV ?: EMPTY_JSON, pipelineName)
|
||||
try {
|
||||
@@ -586,16 +609,18 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar
|
||||
if (build_job_name.toLowerCase().contains('asset') && env.IS_UPLOAD_AP_LOGS?.toBoolean()) {
|
||||
CreateUploadAPLogsStage(platform.key, build_job_name, envVars['WORKSPACE'], platform.value.build_types[build_job_name].PARAMETERS).call()
|
||||
}
|
||||
// Upload test artifacts only on builds that failed and ran test suites
|
||||
if (env.IS_UPLOAD_TEST_ARTIFACTS?.toBoolean() && params.containsKey('CMAKE_TARGET') && params.CMAKE_TARGET.contains("TEST_SUITE")) {
|
||||
CreateUploadTestArtifactStage(build_job_name, envVars['WORKSPACE'], params.OUTPUT_DIRECTORY).call()
|
||||
}
|
||||
// All other errors will be raised outside the retry block
|
||||
currentResult = envVars['ON_FAILURE_MARK'] ?: 'FAILURE'
|
||||
currentException = e.toString()
|
||||
}
|
||||
finally {
|
||||
def params = platform.value.build_types[build_job_name].PARAMETERS
|
||||
|
||||
if (env.MARS_REPO && params && params.containsKey('TEST_METRICS') && params.TEST_METRICS == 'True') {
|
||||
def output_directory = params.OUTPUT_DIRECTORY
|
||||
def configuration = params.CONFIGURATION
|
||||
CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call()
|
||||
CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, params.OUTPUT_DIRECTORY, params.CONFIGURATION).call()
|
||||
}
|
||||
if (params && params.containsKey('TEST_RESULTS') && params.TEST_RESULTS == 'True') {
|
||||
CreateExportTestResultsStage(pipelineConfig, platform.key, build_job_name, envVars, params).call()
|
||||
@@ -603,7 +628,7 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar
|
||||
if (params && params.containsKey('TEST_SCREENSHOTS') && params.TEST_SCREENSHOTS == 'True' && currentResult == 'FAILURE') {
|
||||
CreateExportTestScreenshotsStage(pipelineConfig, branchName, platform.key, build_job_name, envVars, params).call()
|
||||
}
|
||||
CreateTeardownStage(envVars).call()
|
||||
CreateTeardownStage(envVars, params).call()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -854,6 +879,7 @@ finally {
|
||||
"build_number": env.BUILD_NUMBER,
|
||||
"repository_name": env.REPOSITORY_NAME,
|
||||
"branch_name": env.BRANCH_NAME,
|
||||
"pipeline_name": GetRunningPipelineName(env.JOB_NAME),
|
||||
"build_result": "${currentBuild.currentResult}",
|
||||
"build_failure": buildFailure,
|
||||
"recreate_volume": env.RECREATE_VOLUME,
|
||||
|
||||
Reference in New Issue
Block a user