gdharness 1.3.41 → 1.3.43

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 (107) hide show
  1. package/build/cli.js +131 -47
  2. package/build/godot/addons/auto_reload/auto_reload.gd +18 -19
  3. package/build/godot/addons/gdharness_editor/animation_reads.gd +84 -35
  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 +114 -39
  7. package/build/godot/addons/gdharness_editor/file_walk.gd +12 -5
  8. package/build/godot/addons/gdharness_editor/headless_check.gd +94 -41
  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 +37 -12
  13. package/build/godot/addons/gdharness_editor/same_values.gd +4 -4
  14. package/build/godot/addons/gdharness_editor/scene_file.gd +136 -79
  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 +41 -28
  20. package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +84 -50
  21. package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd +70 -40
  22. package/build/godot/addons/gdharness_editor/tools/class_tools.gd +34 -30
  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 +181 -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 +75 -43
  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 +66 -0
  33. package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd.uid +1 -0
  34. package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +171 -62
  35. package/build/godot/addons/gdharness_editor/tools/script_paths.gd +20 -8
  36. package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +11 -8
  37. package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +47 -34
  38. package/build/godot/addons/gdharness_editor/tools/tileset_tools.gd +77 -50
  39. package/build/godot/addons/gdharness_editor/value_shapes.gd +5 -6
  40. package/build/godot/addons/gdharness_runtime/call_errors.gd +1 -2
  41. package/build/godot/addons/gdharness_runtime/declared_values.gd +68 -32
  42. package/build/godot/addons/gdharness_runtime/error_report.gd +1 -2
  43. package/build/godot/addons/gdharness_runtime/reading.gd +37 -12
  44. package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +84 -63
  45. package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +153 -148
  46. package/build/godot/addons/gdharness_runtime/runtime_capture.gd +64 -42
  47. package/build/godot/addons/gdharness_runtime/runtime_changes.gd +184 -122
  48. package/build/godot/addons/gdharness_runtime/runtime_frames.gd +2 -2
  49. package/build/godot/addons/gdharness_runtime/runtime_hover.gd +24 -20
  50. package/build/godot/addons/gdharness_runtime/runtime_input.gd +134 -92
  51. package/build/godot/addons/gdharness_runtime/runtime_items.gd +29 -13
  52. package/build/godot/addons/gdharness_runtime/runtime_menus.gd +0 -1
  53. package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +38 -20
  54. package/build/godot/addons/gdharness_runtime/runtime_pad.gd +17 -13
  55. package/build/godot/addons/gdharness_runtime/runtime_paths.gd +84 -46
  56. package/build/godot/addons/gdharness_runtime/runtime_queries.gd +117 -79
  57. package/build/godot/addons/gdharness_runtime/runtime_says.gd +14 -17
  58. package/build/godot/addons/gdharness_runtime/runtime_screen.gd +23 -16
  59. package/build/godot/addons/gdharness_runtime/runtime_targets.gd +117 -66
  60. package/build/godot/addons/gdharness_runtime/runtime_touch.gd +211 -0
  61. package/build/godot/addons/gdharness_runtime/runtime_touch.gd.uid +1 -0
  62. package/build/godot/addons/gdharness_runtime/runtime_typing.gd +44 -27
  63. package/build/godot/addons/gdharness_runtime/runtime_values.gd +108 -73
  64. package/build/godot/addons/gdharness_runtime/runtime_waits.gd +111 -84
  65. package/build/godot/addons/gdharness_runtime/runtime_words.gd +10 -7
  66. package/build/godot/addons/gdharness_runtime/serialisation.gd +75 -51
  67. package/build/godot/addons/gdharness_runtime/value_shapes.gd +5 -6
  68. package/build/godot/addons/gdharness_tests/bench.gd +4 -5
  69. package/build/godot/addons/gdharness_tests/event.gd +10 -5
  70. package/build/godot/addons/gdharness_tests/share.gd +38 -18
  71. package/build/godot/addons/gdharness_tests/suites.gd +3 -3
  72. package/build/godot/addons/gdharness_tests/wait.gd +3 -2
  73. package/build/godot/loader/loader.gd +9 -9
  74. package/build/godot/operations/animation_reads.gd +84 -35
  75. package/build/godot/operations/audio_buses.gd +48 -19
  76. package/build/godot/operations/class_cache.gd +16 -11
  77. package/build/godot/operations/classdb_queries.gd +89 -44
  78. package/build/godot/operations/declared_values.gd +68 -32
  79. package/build/godot/operations/dependencies.gd +139 -93
  80. package/build/godot/operations/editor_tools.gd +9 -10
  81. package/build/godot/operations/export_presets.gd +100 -54
  82. package/build/godot/operations/file_reads.gd +114 -39
  83. package/build/godot/operations/file_walk.gd +12 -5
  84. package/build/godot/operations/gdscript_analysis.gd +105 -66
  85. package/build/godot/operations/gdscript_authoring.gd +138 -39
  86. package/build/godot/operations/godot_operations.gd +17 -11
  87. package/build/godot/operations/import_pipeline.gd +110 -59
  88. package/build/godot/operations/input_actions.gd +63 -39
  89. package/build/godot/operations/patterns.gd +3 -1
  90. package/build/godot/operations/plugins.gd +36 -16
  91. package/build/godot/operations/project_config.gd +144 -27
  92. package/build/godot/operations/project_diagnostics.gd +24 -11
  93. package/build/godot/operations/project_file.gd +16 -16
  94. package/build/godot/operations/project_validation.gd +71 -44
  95. package/build/godot/operations/property_paths.gd +22 -12
  96. package/build/godot/operations/property_values.gd +143 -78
  97. package/build/godot/operations/reading.gd +37 -12
  98. package/build/godot/operations/rename_checks.gd +2 -2
  99. package/build/godot/operations/resource_files.gd +11 -9
  100. package/build/godot/operations/same_values.gd +4 -4
  101. package/build/godot/operations/scene_connections.gd +27 -13
  102. package/build/godot/operations/script_check.gd +52 -49
  103. package/build/godot/operations/serialisation.gd +75 -51
  104. package/build/godot/operations/setting_reads.gd +7 -6
  105. package/build/godot/operations/value_shapes.gd +5 -6
  106. package/build/godot/tests/listed.gd +321 -268
  107. package/package.json +1 -1
@@ -14,15 +14,6 @@ const RUNTIME: String = "res://addons/gdharness_runtime/runtime_autoload.gd"
14
14
  var _runtime: Node
15
15
 
16
16
 
17
- ## Whether gdharness's runtime is listening in this engine: false in a release build, a script run
18
- ## and an engine without the addon, though this node is in every one of them.
19
- func serving() -> bool:
20
- if not is_instance_valid(_runtime) or not _runtime.has_method("serving"):
21
- return false
22
- var answered: Variant = _runtime.call("serving")
23
- return answered is bool and answered
24
-
25
-
26
17
  func _ready() -> void:
27
18
  if not OS.is_debug_build() or not ResourceLoader.exists(RUNTIME):
28
19
  return
@@ -38,3 +29,12 @@ func _ready() -> void:
38
29
  # Added now, it announces before the main scene runs, as it does when an entry names it.
39
30
  add_child(runtime)
40
31
  _runtime = runtime
32
+
33
+
34
+ ## Whether gdharness's runtime is listening in this engine: false in a release build, a script run
35
+ ## and an engine without the addon, though this node is in every one of them.
36
+ func serving() -> bool:
37
+ if not is_instance_valid(_runtime) or not _runtime.has_method("serving"):
38
+ return false
39
+ var answered: Variant = _runtime.call("serving")
40
+ return answered is bool and answered
@@ -1,13 +1,11 @@
1
1
  extends RefCounted
2
-
3
- ## Animations and state machines read off their nodes: by the editor's tools from the scene it holds,
4
- ## and by a headless engine with none connected from a bare node of the class given what the file
5
- ## stores, which runs no script of the scene's, so a read answers the same either way.
2
+ ## Animations and state machines read off their nodes: by the editor's tools from the scene it
3
+ ## holds, and by a headless engine with none connected from a bare node of the class given what the
4
+ ## file stores, which runs no script of the scene's, so a read answers the same either way.
6
5
 
7
6
  const GdhFileReads = preload("file_reads.gd")
8
7
  const GdhRead = preload("reading.gd")
9
8
  const GdhSerialisation = preload("serialisation.gd")
10
-
11
9
  const LOOP_MODE_NAMES: Dictionary[int, String] = {
12
10
  Animation.LOOP_NONE: "none",
13
11
  Animation.LOOP_LINEAR: "linear",
@@ -37,7 +35,9 @@ const ADVANCE_MODE_NAMES: Dictionary[int, String] = {
37
35
 
38
36
 
39
37
  ## [method animations] of the AnimationPlayer at [param player_path] in the file [param scene_path].
40
- static func scene_animations(scene_path: String, player_path: String, animation_name: String) -> Dictionary:
38
+ static func scene_animations(
39
+ scene_path: String, player_path: String, animation_name: String
40
+ ) -> Dictionary:
41
41
  var made: Array = _bare(scene_path, player_path, "AnimationPlayer")
42
42
  if made[0] == null:
43
43
  return made[1]
@@ -48,7 +48,9 @@ static func scene_animations(scene_path: String, player_path: String, animation_
48
48
 
49
49
 
50
50
  ## [method states] of the AnimationTree at [param tree_path] in the file [param scene_path].
51
- static func scene_states(scene_path: String, tree_path: String, state_machine_path: String) -> Dictionary:
51
+ static func scene_states(
52
+ scene_path: String, tree_path: String, state_machine_path: String
53
+ ) -> Dictionary:
52
54
  var made: Array = _bare(scene_path, tree_path, "AnimationTree")
53
55
  if made[0] == null:
54
56
  return made[1]
@@ -64,7 +66,13 @@ static func scene_states(scene_path: String, tree_path: String, state_machine_pa
64
66
  player_path = "."
65
67
  var found: Array = _bare(scene_path, player_path, "AnimationPlayer")
66
68
  player = found[0]
67
- var answer: Dictionary = states(tree, state_machine_path, player, player_path)
69
+ var reached: Node = null
70
+ if player == null and not player_path.is_empty():
71
+ reached = _bare(scene_path, player_path, "Node")[0]
72
+ var unplayed: String = no_player(str(tree.anim_player), reached)
73
+ if reached != null:
74
+ reached.free()
75
+ var answer: Dictionary = states(tree, state_machine_path, player, player_path, unplayed)
68
76
  tree.free()
69
77
  if player != null:
70
78
  player.free()
@@ -98,9 +106,9 @@ static func animations(player: AnimationPlayer, animation_name: String) -> Dicti
98
106
  summary["animationName"] = called
99
107
  summary["tracks"] = listed_one.get_track_count()
100
108
  listed.append(summary)
101
- return {"ok": true, "animations": listed}
109
+ return { "ok": true, "animations": listed }
102
110
  if not player.has_animation(StringName(animation_name)):
103
- return {"ok": false, "error": no_animation(player, str(player.name), animation_name)}
111
+ return { "ok": false, "error": no_animation(player, str(player.name), animation_name) }
104
112
  var anim: Animation = player.get_animation(StringName(animation_name))
105
113
  var answer: Dictionary = _summary(anim)
106
114
  answer["ok"] = true
@@ -152,7 +160,8 @@ static func _track(anim: Animation, track: int, values: GdhSerialisation) -> Dic
152
160
  var kind: int = anim.track_get_type(track)
153
161
  var path: NodePath = anim.track_get_path(track)
154
162
  var shaped: Dictionary = {
155
- "type": TRACK_TYPE_NAMES.get(kind, str(kind)), "nodePath": str(path.get_concatenated_names())
163
+ "type": TRACK_TYPE_NAMES.get(kind, str(kind)),
164
+ "nodePath": str(path.get_concatenated_names()),
156
165
  }
157
166
  var property: String = str(path.get_concatenated_subnames())
158
167
  if not property.is_empty():
@@ -160,7 +169,7 @@ static func _track(anim: Animation, track: int, values: GdhSerialisation) -> Dic
160
169
  var keyframes: Array[Dictionary] = []
161
170
  var methods: Dictionary = {}
162
171
  for key: int in anim.track_get_key_count(track):
163
- var keyframe: Dictionary = {"time": held_seconds(anim.track_get_key_time(track, key))}
172
+ var keyframe: Dictionary = { "time": held_seconds(anim.track_get_key_time(track, key)) }
164
173
  if kind == Animation.TYPE_METHOD:
165
174
  var method: String = str(anim.method_track_get_name(track, key))
166
175
  methods[method] = true
@@ -182,7 +191,9 @@ static func _track(anim: Animation, track: int, values: GdhSerialisation) -> Dic
182
191
  ## The state machine at a slash-separated path of nested state machine names in [param tree], or
183
192
  ## null when any step of the path is not one. Every node in a tree of state machines is a state
184
193
  ## machine itself, so the walk asks each step for the child by name and refuses anything else.
185
- static func state_machine(tree: AnimationTree, state_machine_path: String) -> AnimationNodeStateMachine:
194
+ static func state_machine(
195
+ tree: AnimationTree, state_machine_path: String
196
+ ) -> AnimationNodeStateMachine:
186
197
  if tree == null:
187
198
  return null
188
199
  var current: AnimationNodeStateMachine = tree.tree_root as AnimationNodeStateMachine
@@ -201,8 +212,8 @@ static func no_machine(tree: AnimationTree, state_machine_path: String) -> Strin
201
212
  if tree == null or tree.tree_root == null:
202
213
  return (
203
214
  "The AnimationTree has no tree_root. Give it one with scene_node set: tree_root "
204
- + '{"_type": "AnimationNodeStateMachine"} builds one into the scene, and the res:// path '
205
- + "of one made with resource_edit create keeps it in a file of its own."
215
+ + '{"_type": "AnimationNodeStateMachine"} builds one into the scene, and the res:// '
216
+ + "path of one made with resource_edit create keeps it in a file of its own."
206
217
  )
207
218
  var current: AnimationNodeStateMachine = tree.tree_root as AnimationNodeStateMachine
208
219
  if current == null:
@@ -236,42 +247,74 @@ static func no_machine(tree: AnimationTree, state_machine_path: String) -> Strin
236
247
  return "No state machine at " + state_machine_path
237
248
 
238
249
 
250
+ ## Why no state finds its animation when [param anim_player], an AnimationTree's path to its player,
251
+ ## reaches no AnimationPlayer: [param reached] is the node it reaches instead, null for none.
252
+ static func no_player(anim_player: String, reached: Node) -> String:
253
+ var until: String = "so no state plays anything until scene_node set points anim_player at one."
254
+ if anim_player.is_empty():
255
+ return "The AnimationTree has no anim_player, " + until
256
+ if reached == null:
257
+ return "The AnimationTree's anim_player %s reaches no node, %s" % [anim_player, until]
258
+ return (
259
+ "The AnimationTree's anim_player %s reaches %s, a %s rather than an AnimationPlayer, %s"
260
+ % [anim_player, reached.name, reached.get_class(), until]
261
+ )
262
+
263
+
239
264
  ## Why a state playing [param animation_name] from [param player], at [param player_path] from the
240
265
  ## scene root as playerNodePath takes it, plays nothing yet. anim_player is relative to the tree
241
266
  ## ("../Anim"), which no argument takes.
242
- static func missing_animation(player: AnimationPlayer, player_path: String, animation_name: String) -> String:
267
+ static func missing_animation(
268
+ player: AnimationPlayer, player_path: String, animation_name: String
269
+ ) -> String:
243
270
  var said: String = (
244
- "The AnimationPlayer at %s has no animation %s yet, so the state plays nothing until it has one."
271
+ (
272
+ "The AnimationPlayer at %s has no animation %s yet, so the state plays nothing until "
273
+ + "it has one."
274
+ )
245
275
  % [player_path, animation_name]
246
276
  )
247
277
  var close: PackedStringArray = GdhRead.nearest(animation_name, player.get_animation_list())
248
278
  if close.is_empty():
249
279
  return said
250
280
  return (
251
- said + " The nearest %s %s." % ["it has is" if close.size() == 1 else "it has are", ", ".join(close)]
281
+ said
282
+ + (
283
+ " The nearest %s %s."
284
+ % ["it has is" if close.size() == 1 else "it has are", ", ".join(close)]
285
+ )
252
286
  )
253
287
 
254
288
 
255
289
  ## The states and transitions of the state machine at [param state_machine_path] in [param tree].
256
290
  ## A state playing an animation says whether [param player], at [param player_path], has it, as
257
- ## add_state answers: a state naming one it lacks plays nothing, and says so only in a log.
291
+ ## add_state answers: a state naming one it lacks plays nothing, and says so only in a log. With no
292
+ ## player, each says [param unplayed], what [method no_player] made of the tree's path.
258
293
  static func states(
259
- tree: AnimationTree, state_machine_path: String, player: AnimationPlayer, player_path: String
294
+ tree: AnimationTree,
295
+ state_machine_path: String,
296
+ player: AnimationPlayer,
297
+ player_path: String,
298
+ unplayed: String
260
299
  ) -> Dictionary:
261
300
  var sm: AnimationNodeStateMachine = state_machine(tree, state_machine_path)
262
301
  if sm == null:
263
- return {"ok": false, "error": no_machine(tree, state_machine_path)}
302
+ return { "ok": false, "error": no_machine(tree, state_machine_path) }
264
303
  var listed: Array[Dictionary] = []
265
304
  for state: StringName in sm.get_node_list():
266
305
  var node: AnimationNode = sm.get_node(state)
267
- var entry: Dictionary = {"stateName": str(state), "type": node.get_class()}
306
+ var entry: Dictionary = { "stateName": str(state), "type": node.get_class() }
268
307
  if node is AnimationNodeAnimation:
269
308
  var plays: AnimationNodeAnimation = node
270
309
  entry["animationName"] = str(plays.animation)
271
310
  var found: bool = player != null and player.has_animation(plays.animation)
272
311
  entry["animationFound"] = found
273
- if player != null and not found:
274
- entry["animationMissing"] = missing_animation(player, player_path, str(plays.animation))
312
+ if player == null:
313
+ entry["animationMissing"] = unplayed
314
+ elif not found:
315
+ entry["animationMissing"] = missing_animation(
316
+ player, player_path, str(plays.animation)
317
+ )
275
318
  listed.append(entry)
276
319
  var transitions: Array[Dictionary] = []
277
320
  for index: int in sm.get_transition_count():
@@ -279,8 +322,10 @@ static func states(
279
322
  var shaped: Dictionary = {
280
323
  "from": str(sm.get_transition_from(index)),
281
324
  "to": str(sm.get_transition_to(index)),
282
- "transitionType": SWITCH_MODE_NAMES.get(transition.switch_mode, str(transition.switch_mode)),
283
- "advanceMode": ADVANCE_MODE_NAMES.get(transition.advance_mode, str(transition.advance_mode)),
325
+ "transitionType":
326
+ SWITCH_MODE_NAMES.get(transition.switch_mode, str(transition.switch_mode)),
327
+ "advanceMode":
328
+ ADVANCE_MODE_NAMES.get(transition.advance_mode, str(transition.advance_mode)),
284
329
  }
285
330
  var condition: String = str(transition.advance_condition)
286
331
  if not condition.is_empty():
@@ -290,9 +335,9 @@ static func states(
290
335
  if not condition.is_empty() and transition.advance_mode != transition.ADVANCE_MODE_AUTO:
291
336
  shaped["conditionNote"] = (
292
337
  (
293
- "advanceMode is %s, so %s never advances it: the engine checks a condition only on an"
294
- + " auto transition%s. disconnect_states and connect_states again with the condition"
295
- + " write it as auto"
338
+ "advanceMode is %s, so %s never advances it: the engine checks a condition "
339
+ + "only on an auto transition%s. disconnect_states and connect_states again "
340
+ + "with the condition write it as auto"
296
341
  )
297
342
  % [
298
343
  shaped["advanceMode"],
@@ -301,16 +346,16 @@ static func states(
301
346
  ", and travel() still takes this one"
302
347
  if transition.advance_mode == transition.ADVANCE_MODE_ENABLED
303
348
  else ""
304
- )
349
+ ),
305
350
  ]
306
351
  )
307
352
  transitions.append(shaped)
308
- return {"ok": true, "states": listed, "transitions": transitions}
353
+ return { "ok": true, "states": listed, "transitions": transitions }
309
354
 
310
355
 
311
356
  ## The states of the AnimationTrees under [param root] that play [param animation_name] from
312
- ## [param player], as [[node, {animTreePath, state}]], a state named by the path of the nodes leading
313
- ## to it.
357
+ ## [param player], as [[node, {animTreePath, state}]], a state named by the path of the nodes
358
+ ## leading to it.
314
359
  static func states_playing(root: Node, player: AnimationPlayer, animation_name: String) -> Array:
315
360
  var found: Array = []
316
361
  var trees: Array[Node] = root.find_children("*", "AnimationTree", true, false)
@@ -331,7 +376,9 @@ static func _collect_playing(
331
376
  if node is AnimationNodeAnimation:
332
377
  var plays: AnimationNodeAnimation = node
333
378
  if plays.animation == StringName(animation_name):
334
- found.append([plays, {"animTreePath": tree_path, "state": "." if at.is_empty() else at}])
379
+ found.append(
380
+ [plays, { "animTreePath": tree_path, "state": "." if at.is_empty() else at }]
381
+ )
335
382
  return
336
383
  var children: Dictionary = {}
337
384
  if node is AnimationNodeStateMachine:
@@ -352,4 +399,6 @@ static func _collect_playing(
352
399
  children[str(point)] = plane.get_blend_point_node(point)
353
400
  for step: String in children:
354
401
  var child: AnimationNode = children[step]
355
- _collect_playing(child, step if at.is_empty() else at + "/" + step, tree_path, animation_name, found)
402
+ _collect_playing(
403
+ child, step if at.is_empty() else at + "/" + step, tree_path, animation_name, found
404
+ )
@@ -23,7 +23,9 @@ func create_audio_bus(params: Dictionary) -> Dictionary:
23
23
  # Sends are by name, so a second bus with one would leave every send to it meaning either.
24
24
  var existing: int = AudioServer.get_bus_index(bus_name)
25
25
  if existing != -1:
26
- return _log.failure("A bus named " + bus_name + " already exists, at index " + str(existing))
26
+ return _log.failure(
27
+ "A bus named " + bus_name + " already exists, at index " + str(existing)
28
+ )
27
29
 
28
30
  # Right after the bus it sends to, because a bus can only send to one before it. The engine
29
31
  # inserts there and moves every later bus down one, so the new bus is at that index: taking the
@@ -41,7 +43,7 @@ func create_audio_bus(params: Dictionary) -> Dictionary:
41
43
  var buses: Array[Dictionary] = []
42
44
  for i: int in range(AudioServer.bus_count):
43
45
  buses.append(_bus(i))
44
- return {"bus": _bus(new_idx), "buses": buses, "layout": layout}
46
+ return { "bus": _bus(new_idx), "buses": buses, "layout": layout }
45
47
 
46
48
 
47
49
  func remove_audio_bus(params: Dictionary) -> Dictionary:
@@ -52,7 +54,9 @@ func remove_audio_bus(params: Dictionary) -> Dictionary:
52
54
  if index == -1:
53
55
  return _log.failure("No bus named %s. The buses are %s." % [bus_name, ", ".join(_names())])
54
56
  if index == 0:
55
- return _log.failure("%s is the bus every other ends in, so it cannot be removed." % bus_name)
57
+ return _log.failure(
58
+ "%s is the bus every other ends in, so it cannot be removed." % bus_name
59
+ )
56
60
 
57
61
  # A bus sending to this one would be left sending to a name nothing has, which the engine reads
58
62
  # as Master; sent on to where this one went instead, the chain it was part of keeps its shape.
@@ -70,9 +74,9 @@ func remove_audio_bus(params: Dictionary) -> Dictionary:
70
74
  var buses: Array[Dictionary] = []
71
75
  for i: int in range(AudioServer.bus_count):
72
76
  buses.append(_bus(i))
73
- var answer: Dictionary = {"removed": bus_name, "buses": buses, "layout": layout}
77
+ var answer: Dictionary = { "removed": bus_name, "buses": buses, "layout": layout }
74
78
  if not resent.is_empty():
75
- answer["resent"] = {"buses": resent, "to": onward}
79
+ answer["resent"] = { "buses": resent, "to": onward }
76
80
  return answer
77
81
 
78
82
 
@@ -81,15 +85,19 @@ func get_audio_buses(_params: Dictionary) -> Dictionary:
81
85
  for i: int in range(AudioServer.bus_count):
82
86
  buses.append(_bus(i))
83
87
  var layout: String = _layout_path()
84
- var answer: Dictionary = {"bus_count": AudioServer.bus_count, "buses": buses, "layout": layout}
88
+ var answer: Dictionary = {
89
+ "bus_count": AudioServer.bus_count,
90
+ "buses": buses,
91
+ "layout": layout,
92
+ }
85
93
  # The setting names a path whether or not anything is there, and a project that never changed a
86
94
  # bus has no file: the path alone read as a layout the project keeps.
87
95
  if not FileAccess.file_exists(layout):
88
96
  answer["layout_on_disk"] = false
89
97
  answer["note"] = (
90
98
  (
91
- "Nothing is at %s, so these are the engine's default buses; the first change to a bus "
92
- + "writes the layout there."
99
+ "Nothing is at %s, so these are the engine's default buses; the first change to a "
100
+ + "bus writes the layout there."
93
101
  )
94
102
  % layout
95
103
  )
@@ -139,7 +147,10 @@ func set_audio_bus_effect(params: Dictionary) -> Dictionary:
139
147
  if layout.is_empty():
140
148
  return {}
141
149
  var answer: Dictionary = {
142
- "bus": _bus(bus_idx), "effect_index": effect_idx, "effect_type": effect.get_class(), "layout": layout
150
+ "bus": _bus(bus_idx),
151
+ "effect_index": effect_idx,
152
+ "effect_type": effect.get_class(),
153
+ "layout": layout,
143
154
  }
144
155
  if not replaced.is_empty():
145
156
  answer["replaced"] = replaced
@@ -157,7 +168,7 @@ func set_audio_bus_volume(params: Dictionary) -> Dictionary:
157
168
  var layout: String = _save_layout()
158
169
  if layout.is_empty():
159
170
  return {}
160
- return {"bus": _bus(bus_idx), "layout": layout}
171
+ return { "bus": _bus(bus_idx), "layout": layout }
161
172
 
162
173
 
163
174
  ## Renames a bus, and every send to it with it: the engine renames the one bus and leaves a bus that
@@ -177,7 +188,9 @@ func rename_audio_bus(params: Dictionary) -> Dictionary:
177
188
  )
178
189
  var existing: int = AudioServer.get_bus_index(new_name)
179
190
  if existing != -1:
180
- return _log.failure("A bus named " + new_name + " already exists, at index " + str(existing))
191
+ return _log.failure(
192
+ "A bus named " + new_name + " already exists, at index " + str(existing)
193
+ )
181
194
  AudioServer.set_bus_name(index, new_name)
182
195
  var resent: Array[String] = []
183
196
  for i: int in range(AudioServer.bus_count):
@@ -189,7 +202,7 @@ func rename_audio_bus(params: Dictionary) -> Dictionary:
189
202
  if layout.is_empty():
190
203
  return {}
191
204
  var answer: Dictionary = {
192
- "renamed": {"from": bus_name, "to": new_name}, "bus": _bus(index), "layout": layout
205
+ "renamed": { "from": bus_name, "to": new_name }, "bus": _bus(index), "layout": layout,
193
206
  }
194
207
  if not resent.is_empty():
195
208
  answer["resent"] = resent
@@ -211,7 +224,10 @@ func set_audio_bus_send(params: Dictionary) -> Dictionary:
211
224
  return _log.failure("No bus named %s. The buses are %s." % [send, ", ".join(_names())])
212
225
  if target == bus_idx:
213
226
  return _log.failure(
214
- "%s cannot send to itself; it can send to %s." % [bus_name, ", ".join(_names().slice(0, bus_idx))]
227
+ (
228
+ "%s cannot send to itself; it can send to %s."
229
+ % [bus_name, ", ".join(_names().slice(0, bus_idx))]
230
+ )
215
231
  )
216
232
  if target > bus_idx:
217
233
  return (
@@ -219,10 +235,17 @@ func set_audio_bus_send(params: Dictionary) -> Dictionary:
219
235
  . failure(
220
236
  (
221
237
  (
222
- "%s is bus %d and %s is bus %d: a bus sends only to one before it, which keeps sound from "
223
- + "going round in a loop, so %s can send to %s."
238
+ "%s is bus %d and %s is bus %d: a bus sends only to one before it, which "
239
+ + "keeps sound from going round in a loop, so %s can send to %s."
224
240
  )
225
- % [bus_name, bus_idx, send, target, bus_name, ", ".join(_names().slice(0, bus_idx))]
241
+ % [
242
+ bus_name,
243
+ bus_idx,
244
+ send,
245
+ target,
246
+ bus_name,
247
+ ", ".join(_names().slice(0, bus_idx)),
248
+ ]
226
249
  )
227
250
  )
228
251
  )
@@ -231,7 +254,7 @@ func set_audio_bus_send(params: Dictionary) -> Dictionary:
231
254
  var layout: String = _save_layout()
232
255
  if layout.is_empty():
233
256
  return {}
234
- return {"bus": _bus(bus_idx), "layout": layout}
257
+ return { "bus": _bus(bus_idx), "layout": layout }
235
258
 
236
259
 
237
260
  func _names() -> Array[String]:
@@ -270,7 +293,11 @@ func _bus(index: int) -> Dictionary:
270
293
 
271
294
 
272
295
  func _layout_path() -> String:
273
- return str(ProjectSettings.get_setting("audio/buses/default_bus_layout", "res://default_bus_layout.tres"))
296
+ return str(
297
+ ProjectSettings.get_setting(
298
+ "audio/buses/default_bus_layout", "res://default_bus_layout.tres"
299
+ )
300
+ )
274
301
 
275
302
 
276
303
  # The path the layout was written to, or empty with the reason on stderr.
@@ -285,7 +312,9 @@ func _save_layout() -> String:
285
312
 
286
313
  # Any effect class the engine has, by its class name or the part after "AudioEffect".
287
314
  func _effect_named(effect_type: String) -> AudioEffect:
288
- var cls: String = effect_type if effect_type.begins_with("AudioEffect") else "AudioEffect" + effect_type
315
+ var cls: String = (
316
+ effect_type if effect_type.begins_with("AudioEffect") else "AudioEffect" + effect_type
317
+ )
289
318
  if not ClassDB.class_exists(cls) or not ClassDB.is_parent_class(cls, "AudioEffect"):
290
319
  return null
291
320
  if not ClassDB.can_instantiate(cls):
@@ -9,7 +9,6 @@ const GdhPatterns = preload("patterns.gd")
9
9
  const GdhRead = preload("reading.gd")
10
10
  const GdhFileWalk = preload("file_walk.gd")
11
11
  const GdhLog = preload("logger.gd")
12
-
13
12
  const CACHE_PATH: String = "res://.godot/global_script_class_cache.cfg"
14
13
 
15
14
  var _log: GdhLog
@@ -30,9 +29,9 @@ func refresh_class_cache(_params: Dictionary) -> Dictionary:
30
29
  var entry: Dictionary = _entry_for(path, skipped)
31
30
  if not entry.is_empty():
32
31
  entries.append(entry)
33
- # Another language's classes are kept while their files are there. Only GDScript is read here and
34
- # the list is written whole, so a C# project's global classes were dropped from it and answered as
35
- # removed, and nothing started next could resolve them.
32
+ # Another language's classes are kept while their files are there. Only GDScript is read here
33
+ # and the list is written whole, so a C# project's global classes were dropped from it and
34
+ # answered as removed, and nothing started next could resolve them.
36
35
  var carried: Array[String] = []
37
36
  for entry: Variant in cached:
38
37
  if not entry is Dictionary:
@@ -43,7 +42,9 @@ func refresh_class_cache(_params: Dictionary) -> Dictionary:
43
42
  entries.append(listed)
44
43
  carried.append(str(listed.get("class", "")))
45
44
  # By name as text: StringName's own order is by identity, not by spelling.
46
- entries.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return str(a["class"]) < str(b["class"]))
45
+ entries.sort_custom(
46
+ func(a: Dictionary, b: Dictionary) -> bool: return str(a["class"]) < str(b["class"])
47
+ )
47
48
 
48
49
  var after: Dictionary = _entries_by_class(entries)
49
50
  var config: ConfigFile = ConfigFile.new()
@@ -52,7 +53,9 @@ func refresh_class_cache(_params: Dictionary) -> Dictionary:
52
53
  ProjectSettings.globalize_path(CACHE_PATH.get_base_dir())
53
54
  )
54
55
  if made != OK and made != ERR_ALREADY_EXISTS:
55
- return _log.failure("Could not make " + CACHE_PATH.get_base_dir() + ": " + error_string(made))
56
+ return _log.failure(
57
+ "Could not make " + CACHE_PATH.get_base_dir() + ": " + error_string(made)
58
+ )
56
59
  var err: Error = config.save(CACHE_PATH)
57
60
  if err != OK:
58
61
  return _log.failure("Failed to write " + CACHE_PATH + ": " + error_string(err))
@@ -139,7 +142,7 @@ func _base_of(path: String, header: Dictionary, skipped: Array[Dictionary]) -> V
139
142
  return ""
140
143
  var reached: String = opened + ":" + ".".join(PackedStringArray(names))
141
144
  if reached in visited:
142
- skipped.append({"path": path, "reason": "extends itself through " + parent_path})
145
+ skipped.append({ "path": path, "reason": "extends itself through " + parent_path })
143
146
  return null
144
147
  visited.append(reached)
145
148
  var lines: PackedStringArray = FileAccess.get_file_as_string(opened).split("\n")
@@ -162,7 +165,7 @@ static func _extends_parts(text: String) -> Dictionary:
162
165
  if rest.begins_with('"') or rest.begins_with("'"):
163
166
  var closing: int = rest.find(rest[0], 1)
164
167
  if closing == -1:
165
- return {"path": "", "names": [] as Array[String]}
168
+ return { "path": "", "names": [] as Array[String] }
166
169
  path = rest.substr(1, closing - 1)
167
170
  rest = rest.substr(closing + 1)
168
171
  var names: Array[String] = []
@@ -179,7 +182,7 @@ static func _extends_parts(text: String) -> Dictionary:
179
182
  break
180
183
  names.append(found.get_string(1))
181
184
  rest = rest.substr(found.get_end())
182
- return {"path": path, "names": names}
185
+ return { "path": path, "names": names }
183
186
 
184
187
 
185
188
  # The file the engine's class scan reads for an `extends` path. It opens the path as written, and
@@ -203,7 +206,7 @@ func _inner_class(lines: PackedStringArray, names: Array[String]) -> Dictionary:
203
206
  var found: Dictionary = {}
204
207
  for name: String in names:
205
208
  var at: int = -1
206
- found = {"found": true}
209
+ found = { "found": true }
207
210
  for index: int in range(start, end):
208
211
  var text: String = lines[index].strip_edges()
209
212
  if text.is_empty() or text.begins_with("#") or _indent(lines[index]) != depth:
@@ -255,7 +258,9 @@ func _header_of(path: String) -> Dictionary:
255
258
  # which is where the body begins.
256
259
  func _header_in(lines: PackedStringArray) -> Dictionary:
257
260
  var header: Dictionary = {}
258
- var annotation: RegEx = GdhPatterns.compiled('^@([a-z_]+)(?:\\(\\s*(?:"([^"]*)")?[^)]*\\))?\\s*')
261
+ var annotation: RegEx = GdhPatterns.compiled(
262
+ '^@([a-z_]+)(?:\\(\\s*(?:"([^"]*)")?[^)]*\\))?\\s*'
263
+ )
259
264
  var extends_line: RegEx = GdhPatterns.compiled("^extends\\s+(.*)$")
260
265
  var same_line: RegEx = GdhPatterns.compiled("^\\s+extends\\s+(.*)$")
261
266
  for line: String in lines: