gdharness 1.3.42 → 1.3.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/build/cli.js +383 -243
  2. package/build/godot/addons/auto_reload/auto_reload.gd +18 -19
  3. package/build/godot/addons/gdharness_editor/animation_reads.gd +55 -33
  4. package/build/godot/addons/gdharness_editor/bridge_client.gd +53 -58
  5. package/build/godot/addons/gdharness_editor/declared_values.gd +68 -32
  6. package/build/godot/addons/gdharness_editor/file_reads.gd +83 -42
  7. package/build/godot/addons/gdharness_editor/file_walk.gd +12 -5
  8. package/build/godot/addons/gdharness_editor/headless_check.gd +68 -44
  9. package/build/godot/addons/gdharness_editor/plugin.gd +2 -3
  10. package/build/godot/addons/gdharness_editor/property_paths.gd +22 -12
  11. package/build/godot/addons/gdharness_editor/property_values.gd +143 -78
  12. package/build/godot/addons/gdharness_editor/reading.gd +51 -17
  13. package/build/godot/addons/gdharness_editor/same_values.gd +4 -4
  14. package/build/godot/addons/gdharness_editor/scene_file.gd +127 -80
  15. package/build/godot/addons/gdharness_editor/scene_uids.gd +12 -6
  16. package/build/godot/addons/gdharness_editor/serialisation.gd +75 -51
  17. package/build/godot/addons/gdharness_editor/setting_reads.gd +7 -6
  18. package/build/godot/addons/gdharness_editor/tool_executor.gd +3 -6
  19. package/build/godot/addons/gdharness_editor/tools/animation_states.gd +37 -27
  20. package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +79 -49
  21. package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd +70 -40
  22. package/build/godot/addons/gdharness_editor/tools/class_tools.gd +65 -42
  23. package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +24 -22
  24. package/build/godot/addons/gdharness_editor/tools/navigation_bake.gd +49 -29
  25. package/build/godot/addons/gdharness_editor/tools/play_tools.gd +26 -21
  26. package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +40 -40
  27. package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +166 -107
  28. package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +16 -9
  29. package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +68 -41
  30. package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +35 -20
  31. package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +28 -13
  32. package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd +12 -5
  33. package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +113 -67
  34. package/build/godot/addons/gdharness_editor/tools/script_paths.gd +20 -8
  35. package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +11 -8
  36. package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +47 -34
  37. package/build/godot/addons/gdharness_editor/tools/tileset_tools.gd +77 -50
  38. package/build/godot/addons/gdharness_editor/value_shapes.gd +5 -6
  39. package/build/godot/addons/gdharness_runtime/call_errors.gd +1 -2
  40. package/build/godot/addons/gdharness_runtime/declared_values.gd +68 -32
  41. package/build/godot/addons/gdharness_runtime/error_report.gd +1 -2
  42. package/build/godot/addons/gdharness_runtime/reading.gd +51 -17
  43. package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +84 -63
  44. package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +149 -147
  45. package/build/godot/addons/gdharness_runtime/runtime_capture.gd +64 -42
  46. package/build/godot/addons/gdharness_runtime/runtime_changes.gd +184 -122
  47. package/build/godot/addons/gdharness_runtime/runtime_frames.gd +2 -2
  48. package/build/godot/addons/gdharness_runtime/runtime_hover.gd +24 -20
  49. package/build/godot/addons/gdharness_runtime/runtime_input.gd +134 -92
  50. package/build/godot/addons/gdharness_runtime/runtime_items.gd +29 -13
  51. package/build/godot/addons/gdharness_runtime/runtime_menus.gd +0 -1
  52. package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +34 -17
  53. package/build/godot/addons/gdharness_runtime/runtime_pad.gd +17 -13
  54. package/build/godot/addons/gdharness_runtime/runtime_paths.gd +84 -46
  55. package/build/godot/addons/gdharness_runtime/runtime_queries.gd +117 -79
  56. package/build/godot/addons/gdharness_runtime/runtime_says.gd +14 -17
  57. package/build/godot/addons/gdharness_runtime/runtime_screen.gd +23 -16
  58. package/build/godot/addons/gdharness_runtime/runtime_targets.gd +117 -66
  59. package/build/godot/addons/gdharness_runtime/runtime_touch.gd +15 -15
  60. package/build/godot/addons/gdharness_runtime/runtime_typing.gd +44 -27
  61. package/build/godot/addons/gdharness_runtime/runtime_values.gd +108 -73
  62. package/build/godot/addons/gdharness_runtime/runtime_waits.gd +111 -84
  63. package/build/godot/addons/gdharness_runtime/runtime_words.gd +10 -7
  64. package/build/godot/addons/gdharness_runtime/serialisation.gd +75 -51
  65. package/build/godot/addons/gdharness_runtime/value_shapes.gd +5 -6
  66. package/build/godot/addons/gdharness_tests/bench.gd +4 -5
  67. package/build/godot/addons/gdharness_tests/event.gd +10 -5
  68. package/build/godot/addons/gdharness_tests/share.gd +38 -18
  69. package/build/godot/addons/gdharness_tests/suites.gd +3 -3
  70. package/build/godot/addons/gdharness_tests/wait.gd +3 -2
  71. package/build/godot/loader/loader.gd +9 -9
  72. package/build/godot/operations/animation_reads.gd +55 -33
  73. package/build/godot/operations/audio_buses.gd +48 -19
  74. package/build/godot/operations/class_cache.gd +16 -11
  75. package/build/godot/operations/classdb_queries.gd +89 -44
  76. package/build/godot/operations/declared_values.gd +68 -32
  77. package/build/godot/operations/dependencies.gd +190 -109
  78. package/build/godot/operations/editor_tools.gd +10 -10
  79. package/build/godot/operations/export_presets.gd +100 -54
  80. package/build/godot/operations/file_reads.gd +83 -42
  81. package/build/godot/operations/file_walk.gd +12 -5
  82. package/build/godot/operations/gdscript_analysis.gd +86 -65
  83. package/build/godot/operations/gdscript_authoring.gd +83 -36
  84. package/build/godot/operations/godot_operations.gd +17 -11
  85. package/build/godot/operations/import_pipeline.gd +110 -59
  86. package/build/godot/operations/input_actions.gd +62 -39
  87. package/build/godot/operations/patterns.gd +3 -1
  88. package/build/godot/operations/plugins.gd +36 -16
  89. package/build/godot/operations/project_config.gd +61 -32
  90. package/build/godot/operations/project_diagnostics.gd +24 -11
  91. package/build/godot/operations/project_file.gd +16 -16
  92. package/build/godot/operations/project_validation.gd +71 -44
  93. package/build/godot/operations/property_paths.gd +22 -12
  94. package/build/godot/operations/property_values.gd +143 -78
  95. package/build/godot/operations/reading.gd +51 -17
  96. package/build/godot/operations/rename_checks.gd +2 -2
  97. package/build/godot/operations/resource_files.gd +11 -9
  98. package/build/godot/operations/same_values.gd +4 -4
  99. package/build/godot/operations/scene_connections.gd +27 -13
  100. package/build/godot/operations/script_check.gd +52 -49
  101. package/build/godot/operations/serialisation.gd +75 -51
  102. package/build/godot/operations/setting_reads.gd +7 -6
  103. package/build/godot/operations/value_shapes.gd +5 -6
  104. package/build/godot/tests/listed.gd +321 -268
  105. package/build/keeper.js +43 -43
  106. package/package.json +1 -1
@@ -1,6 +1,5 @@
1
1
  @tool
2
2
  extends RefCounted
3
-
4
3
  ## Bakes what a NavigationRegion2D or NavigationRegion3D in a scene file navigates by, as the
5
4
  ## editor's Bake button does, and saves it where the region keeps it.
6
5
  ##
@@ -13,10 +12,11 @@ extends RefCounted
13
12
 
14
13
  const GdhSceneFile = preload("../scene_file.gd")
15
14
  const GdhSceneUids = preload("../scene_uids.gd")
16
-
17
15
  ## The names NavigationPolygon.SourceGeometryMode and NavigationMesh.SourceGeometryMode give each
18
16
  ## mode, which share their values.
19
- const SOURCE_MODES: Array[String] = ["root_node_children", "groups_with_children", "groups_explicit"]
17
+ const SOURCE_MODES: Array[String] = [
18
+ "root_node_children", "groups_with_children", "groups_explicit",
19
+ ]
20
20
 
21
21
 
22
22
  ## Bakes the region [param region] of [param scene], answering what it now holds or why not.
@@ -55,13 +55,16 @@ static func bake(scene: GdhSceneFile, region: Node) -> Dictionary:
55
55
  var file: String = held.resource_path.get_slice("::", 0)
56
56
  var embedded: bool = file.is_empty() or held.resource_path.contains("::")
57
57
  if embedded and not file.is_empty() and file != scene.path:
58
- return scene.refuse(
59
- (
58
+ return (
59
+ scene
60
+ . refuse(
60
61
  (
61
- "The %s %s holds is built into %s, and a bake here cannot save that file. Bake the "
62
- + "region there, or save the %s to a file of its own."
62
+ (
63
+ "The %s %s holds is built into %s, and a bake here cannot save that file. "
64
+ + "Bake the region there, or save the %s to a file of its own."
65
+ )
66
+ % [held.get_class(), at, file, held.get_class()]
63
67
  )
64
- % [held.get_class(), at, file, held.get_class()]
65
68
  )
66
69
  )
67
70
 
@@ -78,7 +81,8 @@ static func bake(scene: GdhSceneFile, region: Node) -> Dictionary:
78
81
  }
79
82
  if made:
80
83
  answer["made"] = (
81
- "%s held no %s, so one was made and built into the scene, with the defaults." % [at, property]
84
+ "%s held no %s, so one was made and built into the scene, with the defaults."
85
+ % [at, property]
82
86
  )
83
87
  if polygons == 0:
84
88
  answer["note"] = _why_empty(held, flat, parsed)
@@ -86,17 +90,17 @@ static func bake(scene: GdhSceneFile, region: Node) -> Dictionary:
86
90
  answer["note"] = _nothing_read(scene, held)
87
91
  if not flat and not Engine.is_editor_hint() and _reads_meshes(region, held):
88
92
  answer["meshesNote"] = (
89
- "The engine's warning that it had to parse RenderingServer meshes at runtime is about a "
90
- + "game rebaking as it runs, where reading a mesh back from the GPU stalls a frame. A "
91
- + "headless engine gives it for any bake read from MeshInstance3D nodes; this one ran once "
92
- + "and is saved."
93
+ "The engine's warning that it had to parse RenderingServer meshes at runtime is about "
94
+ + "a game rebaking as it runs, where reading a mesh back from the GPU stalls a frame. "
95
+ + "A headless engine gives it for any bake read from MeshInstance3D nodes; this one "
96
+ + "ran once and is saved."
93
97
  )
94
98
 
95
99
  if not embedded:
96
100
  scene.close()
97
101
  var saving: Error = GdhSceneUids.save_keeping_uid(held, file)
98
102
  if saving != OK:
99
- return {"ok": false, "error": "Failed to save %s: %s" % [file, error_string(saving)]}
103
+ return { "ok": false, "error": "Failed to save %s: %s" % [file, error_string(saving)] }
100
104
  if Engine.is_editor_hint():
101
105
  EditorInterface.get_resource_filesystem().update_file(file)
102
106
  answer["savedTo"] = file
@@ -121,7 +125,9 @@ static func bake(scene: GdhSceneFile, region: Node) -> Dictionary:
121
125
  static func _parse_and_bake(scene: GdhSceneFile, at: String, held: Resource, flat: bool) -> bool:
122
126
  var copy: Node = scene.root.duplicate(Node.DUPLICATE_GROUPS)
123
127
  var reading: Resource = held.duplicate()
124
- var group_property: String = "source_geometry_group_name" if flat else "geometry_source_group_name"
128
+ var group_property: String = (
129
+ "source_geometry_group_name" if flat else "geometry_source_group_name"
130
+ )
125
131
  var group: String = str(held.get(group_property))
126
132
  var own_group: String = "_gdh_bake_%d" % copy.get_instance_id()
127
133
  reading.set(group_property, own_group)
@@ -136,8 +142,8 @@ static func _parse_and_bake(scene: GdhSceneFile, at: String, held: Resource, fla
136
142
  var outline: NavigationPolygon = reading
137
143
  var geometry: NavigationMeshSourceGeometryData2D = NavigationMeshSourceGeometryData2D.new()
138
144
  NavigationServer2D.parse_source_geometry_data(outline, geometry, region)
139
- # has_data() counts only traversable outlines, so a bake carving every obstacle it read would
140
- # still say it read nothing.
145
+ # has_data() counts only traversable outlines, so a bake carving every obstacle it read
146
+ # would still say it read nothing.
141
147
  found = (
142
148
  not geometry.get_obstruction_outlines().is_empty()
143
149
  or not geometry.get_projected_obstructions().is_empty()
@@ -211,12 +217,15 @@ static func _why_empty(held: Resource, flat: bool, parsed: bool) -> String:
211
217
  return (
212
218
  "The NavigationPolygon has no outlines, and a 2D bake fills only the area its "
213
219
  + "outlines enclose, less what the obstacles inside take. Give it outlines with "
214
- + "scene_node set, such as navigation_polygon/outlines [[[0, 0], [512, 0], [512, 512], "
215
- + "[0, 512]]], then bake again."
220
+ + "scene_node set, such as navigation_polygon/outlines [[[0, 0], [512, 0], [512, "
221
+ + "512], [0, 512]]], then bake again."
216
222
  )
217
223
  return (
218
224
  (
219
- "Nothing was left to walk inside the outlines once the obstacles read from %s, and the "
225
+ (
226
+ "Nothing was left to walk inside the outlines once the obstacles read from %s, "
227
+ + "and the "
228
+ )
220
229
  % _source_said(polygon.source_geometry_mode, polygon.source_geometry_group_name)
221
230
  )
222
231
  + "agent_radius %s kept from their edges, were taken out." % polygon.agent_radius
@@ -225,17 +234,27 @@ static func _why_empty(held: Resource, flat: bool, parsed: bool) -> String:
225
234
  if not parsed:
226
235
  return (
227
236
  (
228
- "No geometry was read from %s with geometry_parsed_geometry_type %s, so there was nothing to "
237
+ (
238
+ "No geometry was read from %s with geometry_parsed_geometry_type %s, so there "
239
+ + "was nothing to "
240
+ )
229
241
  % [
230
- _source_said(mesh.geometry_source_geometry_mode, mesh.geometry_source_group_name),
231
- ["mesh_instances", "static_colliders", "both"][mesh.geometry_parsed_geometry_type],
242
+ _source_said(
243
+ mesh.geometry_source_geometry_mode, mesh.geometry_source_group_name
244
+ ),
245
+ ["mesh_instances", "static_colliders", "both"][
246
+ mesh.geometry_parsed_geometry_type
247
+ ],
232
248
  ]
233
249
  )
234
- + "bake: mesh_instances reads MeshInstance3D nodes, static_colliders the shapes of physics "
235
- + "bodies on geometry_collision_mask, and both reads both."
250
+ + "bake: mesh_instances reads MeshInstance3D nodes, static_colliders the shapes of "
251
+ + "physics bodies on geometry_collision_mask, and both reads both."
236
252
  )
237
253
  return (
238
- "The geometry read gave no floor an agent of agent_height %s and agent_radius %s can stand on."
254
+ (
255
+ "The geometry read gave no floor an agent of agent_height %s and agent_radius %s can "
256
+ + "stand on."
257
+ )
239
258
  % [mesh.agent_height, mesh.agent_radius]
240
259
  )
241
260
 
@@ -252,7 +271,7 @@ static func _nothing_read(scene: GdhSceneFile, held: Resource) -> String:
252
271
  )
253
272
  % [
254
273
  _source_said(polygon.source_geometry_mode, polygon.source_geometry_group_name),
255
- polygon.agent_radius
274
+ polygon.agent_radius,
256
275
  ]
257
276
  )
258
277
  var outside: PackedStringArray = []
@@ -270,8 +289,9 @@ static func _nothing_read(scene: GdhSceneFile, held: Resource) -> String:
270
289
  return said
271
290
  return (
272
291
  (
273
- "%s %s %s outside what was read; the bake reads a node elsewhere once it is in the group %s and "
274
- + "source_geometry_mode is groups_with_children, or once it is moved under the region."
292
+ "%s %s %s outside what was read; the bake reads a node elsewhere once it is in the "
293
+ + "group %s and source_geometry_mode is groups_with_children, or once it is moved "
294
+ + "under the region."
275
295
  )
276
296
  % [
277
297
  said,
@@ -1,6 +1,5 @@
1
1
  @tool
2
2
  extends Node
3
-
4
3
  ## Running the game from the editor, so the editor is the one debugging it.
5
4
  ##
6
5
  ## A game started as its own process is a game nothing is attached to: the editor's debug adapter
@@ -10,7 +9,6 @@ extends Node
10
9
 
11
10
  ## What the display server calls itself when the engine was started with no display at all.
12
11
  const GdhRead = preload("../reading.gd")
13
-
14
12
  const HEADLESS_DISPLAY: String = "headless"
15
13
  ## Where Godot keeps the port its own debugger listens on for a game it is playing. One setting
16
14
  ## for every editor on the machine, and bound only while a game runs.
@@ -18,7 +16,6 @@ const DEBUGGER_SETTING: String = "network/debug/remote_port"
18
16
  const LOOPBACK: String = "127.0.0.1"
19
17
 
20
18
  var _editor_plugin: EditorPlugin = null
21
-
22
19
  ## Which play this is, counted up for every one the editor starts, whoever starts it. What a server
23
20
  ## writes about a play is kept on disk after it, and the editor saying it is playing does not say
24
21
  ## which play: a server picking a play back up read the console of an earlier one as this one's.
@@ -29,14 +26,14 @@ var _was_playing: bool = false
29
26
  var _awaited: bool = false
30
27
 
31
28
 
32
- func set_editor_plugin(plugin: EditorPlugin) -> void:
33
- _editor_plugin = plugin
34
-
35
-
36
29
  func _process(_delta: float) -> void:
37
30
  _count_a_play_begun()
38
31
 
39
32
 
33
+ func set_editor_plugin(plugin: EditorPlugin) -> void:
34
+ _editor_plugin = plugin
35
+
36
+
40
37
  ## Counts a play the editor has begun since the last look, whoever began it. Looked at every frame
41
38
  ## and before the count is read: read alone, a play begun in this frame went uncounted until this
42
39
  ## node's turn came round, and a server asking before then was told the earlier play's number with
@@ -60,20 +57,23 @@ func play_scene(args: Dictionary) -> Dictionary:
60
57
  # play was answered as started.
61
58
  var main: String = str(ProjectSettings.get_setting("application/run/main_scene", ""))
62
59
  if main.is_empty():
63
- return {"ok": false, "error": "The project has no main scene to play."}
60
+ return { "ok": false, "error": "The project has no main scene to play." }
64
61
  if not ResourceLoader.exists(main, "PackedScene"):
65
62
  return {
66
63
  "ok": false,
67
64
  "error":
68
65
  (
69
- "The main scene, %s, is not there, so the editor would ask for another rather than play."
66
+ (
67
+ "The main scene, %s, is not there, so the editor would ask for another "
68
+ + "rather than play."
69
+ )
70
70
  % main
71
- )
71
+ ),
72
72
  }
73
73
  else:
74
74
  full_path = scene_path if scene_path.begins_with("res://") else "res://" + scene_path
75
75
  if not ResourceLoader.exists(full_path, "PackedScene"):
76
- return {"ok": false, "error": "No scene at " + full_path}
76
+ return { "ok": false, "error": "No scene at " + full_path }
77
77
 
78
78
  if EditorInterface.is_playing_scene():
79
79
  EditorInterface.stop_playing_scene()
@@ -138,7 +138,7 @@ func stop_playing(_args: Dictionary) -> Dictionary:
138
138
  # Known over now rather than at the next frame's look: a play somebody else starts before that
139
139
  # look would otherwise be read as this one still going, and given its number and its console.
140
140
  _was_playing = EditorInterface.is_playing_scene()
141
- return {"ok": true, "wasPlaying": was_playing, "playing": _was_playing}
141
+ return { "ok": true, "wasPlaying": was_playing, "playing": _was_playing }
142
142
 
143
143
 
144
144
  ## Restarts the editor, which is how a replaced addon is picked up.
@@ -167,7 +167,7 @@ func restart_editor(_args: Dictionary) -> Dictionary:
167
167
  "This editor is headless, and the engine does not hand back the arguments it was "
168
168
  + "started with, so nothing can bring it back as the editor it is. Start it again "
169
169
  + "yourself."
170
- )
170
+ ),
171
171
  }
172
172
 
173
173
  var saving: Dictionary = _save_everything()
@@ -177,7 +177,7 @@ func restart_editor(_args: Dictionary) -> Dictionary:
177
177
  # Deferred so this answer is on its way out before the editor goes.
178
178
  EditorInterface.restart_editor.call_deferred(true)
179
179
 
180
- return {"ok": true, "restarting": true, "saved": saving["saved"]}
180
+ return { "ok": true, "restarting": true, "saved": saving["saved"] }
181
181
 
182
182
 
183
183
  ## Saves every open scene, answering a refusal naming what is still unsaved, or the scenes that had
@@ -193,7 +193,7 @@ static func _save_everything() -> Dictionary:
193
193
  EditorInterface.save_all_scenes()
194
194
  var left: PackedStringArray = EditorInterface.get_unsaved_scenes()
195
195
  if left.is_empty():
196
- return {"ok": true, "saved": changed}
196
+ return { "ok": true, "saved": changed }
197
197
  var named: Array[String] = []
198
198
  for scene: String in left:
199
199
  named.append(scene if not scene.is_empty() else "a scene that has never been saved")
@@ -202,15 +202,15 @@ static func _save_everything() -> Dictionary:
202
202
  "error":
203
203
  (
204
204
  (
205
- "%s still %s unsaved changes after saving, and ending the editor would lose them. Save "
206
- + "or close %s in the editor first."
205
+ "%s still %s unsaved changes after saving, and ending the editor would lose them. "
206
+ + "Save or close %s in the editor first."
207
207
  )
208
208
  % [
209
209
  ", ".join(PackedStringArray(named)),
210
210
  "has" if named.size() == 1 else "have",
211
- "it" if named.size() == 1 else "them"
211
+ "it" if named.size() == 1 else "them",
212
212
  ]
213
- )
213
+ ),
214
214
  }
215
215
 
216
216
 
@@ -230,7 +230,7 @@ func quit_editor(_args: Dictionary) -> Dictionary:
230
230
  # Deferred so this answer is on its way out before the editor goes.
231
231
  _leave.call_deferred()
232
232
 
233
- return {"ok": true, "quitting": true, "saved": saving["saved"]}
233
+ return { "ok": true, "quitting": true, "saved": saving["saved"] }
234
234
 
235
235
 
236
236
  ## What the editor said as it started each of its servers, and the debug adapter started again when
@@ -258,7 +258,12 @@ func editor_servers(args: Dictionary) -> Dictionary:
258
258
  parent.add_child(adapter)
259
259
  parent.move_child(adapter, at)
260
260
  rebound = true
261
- return {"ok": true, "said": said, "rebound": rebound, "saidSince": _servers_said().slice(said.size())}
261
+ return {
262
+ "ok": true,
263
+ "said": said,
264
+ "rebound": rebound,
265
+ "saidSince": _servers_said().slice(said.size()),
266
+ }
262
267
 
263
268
 
264
269
  ## The lines the editor's log panel holds about its language server and debug adapter, in order.
@@ -1,6 +1,5 @@
1
1
  @tool
2
2
  extends Node
3
-
4
3
  ## The engine's script profiler on a game the editor plays, summed here for the server.
5
4
  ##
6
5
  ## The editor is that game's debugger, so the profiler is switched on through the editor's own
@@ -11,7 +10,6 @@ extends Node
11
10
  ## expose to scripts: found by its class in the editor's tree and connected to by name.
12
11
 
13
12
  const GdhRead = preload("../reading.gd")
14
-
15
13
  ## The most functions a frame may carry when the server does not say. The engine names a function
16
14
  ## once, as it first appears, and the game's debugger queue drops those messages past its size, so
17
15
  ## the server keeps this below the queue the project sets; this is that for the engine's default.
@@ -26,37 +24,10 @@ const PROFILE_RECEIVED: String = "gdharness:profile_received"
26
24
  ## Kept in step with the runtime addon's runtime_autoload.gd.
27
25
  const PROFILE_FROM_START: String = "GDHARNESS_PROFILE_FROM_START"
28
26
 
29
-
30
- ## The editor's debugger sessions, numbered as the editor numbers its debugger tabs.
31
- class GdhSessions:
32
- extends EditorDebuggerPlugin
33
-
34
- signal session_started(session_id: int)
35
-
36
- func _setup_session(session_id: int) -> void:
37
- var session: EditorDebuggerSession = get_session(session_id)
38
- # int rather than Error: Signal.connect answers with a plain int.
39
- var joined: int = session.started.connect(func() -> void: session_started.emit(session_id))
40
- if joined != OK:
41
- push_error("gdharness could not watch debugger session %d start: %d" % [session_id, joined])
42
-
43
- func _has_capture(capture: String) -> bool:
44
- return capture == PROFILE_CAPTURE
45
-
46
- ## Answers a quitting game that its profile's totals arrived, which it waits for before it exits.
47
- ## The editor reads a session's messages in order, so the totals sent before this have been read.
48
- func _capture(message: String, _data: Array, session_id: int) -> bool:
49
- if message != PROFILE_SENT:
50
- return false
51
- get_session(session_id).send_message(PROFILE_RECEIVED, [])
52
- return true
53
-
54
-
55
27
  var _editor_plugin: EditorPlugin = null
56
28
  var _sessions: GdhSessions = null
57
29
  ## The debugger tabs connected to, by instance id, so none is connected twice.
58
30
  var _hooked: Dictionary[int, bool] = {}
59
-
60
31
  ## A play asked to be profiled before its session started.
61
32
  var _armed: bool = false
62
33
  var _session: int = -1
@@ -73,6 +44,12 @@ var _names: Dictionary[int, String] = {}
73
44
  var _totals: Dictionary[String, PackedFloat64Array] = {}
74
45
 
75
46
 
47
+ func _exit_tree() -> void:
48
+ if _editor_plugin != null and _sessions != null:
49
+ _editor_plugin.remove_debugger_plugin(_sessions)
50
+ _sessions = null
51
+
52
+
76
53
  func set_editor_plugin(plugin: EditorPlugin) -> void:
77
54
  _editor_plugin = plugin
78
55
  _sessions = GdhSessions.new()
@@ -82,12 +59,6 @@ func set_editor_plugin(plugin: EditorPlugin) -> void:
82
59
  plugin.add_debugger_plugin(_sessions)
83
60
 
84
61
 
85
- func _exit_tree() -> void:
86
- if _editor_plugin != null and _sessions != null:
87
- _editor_plugin.remove_debugger_plugin(_sessions)
88
- _sessions = null
89
-
90
-
91
62
  ## Switches the profiler on for the game being played, or with [code]arm[/code] for the next one
92
63
  ## to start and never the one playing: a start ends the game before it, which can still be going.
93
64
  ## Either way what was summed before is dropped.
@@ -98,8 +69,9 @@ func profile_start(args: Dictionary) -> Dictionary:
98
69
  "error":
99
70
  (
100
71
  (
101
- "This editor's debugger has no %s node to read the profiler from, which is where Godot"
102
- + " 4.7 keeps it: a Godot that moved it has to be met by a gdharness that knows where."
72
+ "This editor's debugger has no %s node to read the profiler from, which is "
73
+ + "where Godot 4.7 keeps it: a Godot that moved it has to be met by a "
74
+ + "gdharness that knows where."
103
75
  )
104
76
  % DEBUGGER_CLASS
105
77
  ),
@@ -113,12 +85,12 @@ func profile_start(args: Dictionary) -> Dictionary:
113
85
  # runtime addon to hold its start until the profiler is on, which the session's start
114
86
  # switches on with a message the game reads only on a later poll.
115
87
  OS.set_environment(PROFILE_FROM_START, "1")
116
- return {"ok": true, "started": false, "armed": true, "session": -1}
88
+ return { "ok": true, "started": false, "armed": true, "session": -1 }
117
89
  var active: int = _active_session()
118
90
  if active < 0:
119
- return {"ok": true, "started": false, "armed": false, "session": -1}
91
+ return { "ok": true, "started": false, "armed": false, "session": -1 }
120
92
  _switch_on(active)
121
- return {"ok": true, "started": true, "armed": false, "session": active}
93
+ return { "ok": true, "started": true, "armed": false, "session": active }
122
94
 
123
95
 
124
96
  ## What has been summed, for the server to put into an answer.
@@ -256,3 +228,31 @@ func _add(data: Array, into: Dictionary[String, PackedFloat64Array]) -> int:
256
228
  into[signature] = sum
257
229
  carried += 1
258
230
  return carried
231
+
232
+
233
+ ## The editor's debugger sessions, numbered as the editor numbers its debugger tabs.
234
+ class GdhSessions:
235
+ extends EditorDebuggerPlugin
236
+
237
+ signal session_started(session_id: int)
238
+
239
+ func _setup_session(session_id: int) -> void:
240
+ var session: EditorDebuggerSession = get_session(session_id)
241
+ # int rather than Error: Signal.connect answers with a plain int.
242
+ var joined: int = session.started.connect(func() -> void: session_started.emit(session_id))
243
+ if joined != OK:
244
+ push_error(
245
+ "gdharness could not watch debugger session %d start: %d" % [session_id, joined]
246
+ )
247
+
248
+ func _has_capture(capture: String) -> bool:
249
+ return capture == PROFILE_CAPTURE
250
+
251
+ ## Answers a quitting game that its profile's totals arrived, which it waits for before it
252
+ ## exits. The editor reads a session's messages in order, so the totals sent before this have
253
+ ## been read.
254
+ func _capture(message: String, _data: Array, session_id: int) -> bool:
255
+ if message != PROFILE_SENT:
256
+ return false
257
+ get_session(session_id).send_message(PROFILE_RECEIVED, [])
258
+ return true