gdharness 1.3.42 → 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 (105) hide show
  1. package/build/cli.js +62 -9
  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 +37 -12
  13. package/build/godot/addons/gdharness_editor/same_values.gd +4 -4
  14. package/build/godot/addons/gdharness_editor/scene_file.gd +109 -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 +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 +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 +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 +37 -12
  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 +139 -93
  78. package/build/godot/operations/editor_tools.gd +9 -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 +53 -29
  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 +37 -12
  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/package.json +1 -1
@@ -1,8 +1,7 @@
1
1
  @tool
2
2
  extends Node
3
-
4
- ## Animations and animation trees, edited in the open editor or, for a project no editor serves, by a
5
- ## headless engine.
3
+ ## Animations and animation trees, edited in the open editor or, for a project no editor serves, by
4
+ ## a headless engine.
6
5
 
7
6
  const GdhAnimationReads = preload("../animation_reads.gd")
8
7
  const GdhHeadlessCheck = preload("../headless_check.gd")
@@ -11,9 +10,10 @@ const GdhRead = preload("../reading.gd")
11
10
  const GdhSceneFile = preload("../scene_file.gd")
12
11
  const GdhSceneUids = preload("../scene_uids.gd")
13
12
  const GdhSerialisation = preload("../serialisation.gd")
14
-
15
13
  const LOOP_MODES: Dictionary = {
16
- "none": Animation.LOOP_NONE, "linear": Animation.LOOP_LINEAR, "pingpong": Animation.LOOP_PINGPONG
14
+ "none": Animation.LOOP_NONE,
15
+ "linear": Animation.LOOP_LINEAR,
16
+ "pingpong": Animation.LOOP_PINGPONG,
17
17
  }
18
18
 
19
19
  var _editor_plugin: EditorPlugin = null
@@ -74,7 +74,9 @@ func _not_of_kind(scene: GdhSceneFile, node: Node, node_path: String, kind: Stri
74
74
 
75
75
  ## Writes [param scene] once [param check] passes, then the files of [param homes], answering
76
76
  ## [param answer] or a refusal.
77
- func _finish(scene: GdhSceneFile, check: Callable, homes: Dictionary, answer: Dictionary) -> Dictionary:
77
+ func _finish(
78
+ scene: GdhSceneFile, check: Callable, homes: Dictionary, answer: Dictionary
79
+ ) -> Dictionary:
78
80
  if not Engine.is_editor_hint():
79
81
  for file: Variant in homes:
80
82
  var home: Resource = homes[file]
@@ -85,9 +87,9 @@ func _finish(scene: GdhSceneFile, check: Callable, homes: Dictionary, answer: Di
85
87
  (
86
88
  (
87
89
  (
88
- "Nothing was written: %s holds a resource with a script that is not a tool, and what "
89
- + "that script changed when a headless engine loaded it cannot be told apart from the "
90
- + "edit. "
90
+ "Nothing was written: %s holds a resource with a script that "
91
+ + "is not a tool, and what that script changed when a headless "
92
+ + "engine loaded it cannot be told apart from the edit. "
91
93
  )
92
94
  % file
93
95
  )
@@ -102,7 +104,7 @@ func _finish(scene: GdhSceneFile, check: Callable, homes: Dictionary, answer: Di
102
104
  var resource: Resource = homes[file]
103
105
  var saving: Error = GdhSceneUids.save_keeping_uid(resource, str(file))
104
106
  if saving != OK:
105
- return {"ok": false, "error": "Failed to save %s: %s" % [file, error_string(saving)]}
107
+ return { "ok": false, "error": "Failed to save %s: %s" % [file, error_string(saving)] }
106
108
  if Engine.is_editor_hint():
107
109
  EditorInterface.get_resource_filesystem().update_file(str(file))
108
110
  return answer
@@ -112,7 +114,10 @@ func _finish(scene: GdhSceneFile, check: Callable, homes: Dictionary, answer: Di
112
114
  ## engine ran as it loaded the file.
113
115
  func _scripted(resource: Resource) -> bool:
114
116
  var script: Script = resource.get_script()
115
- return (script != null and not script.is_tool()) or GdhHeadlessCheck.holds_scripted_embedded(resource, {})
117
+ return (
118
+ (script != null and not script.is_tool())
119
+ or GdhHeadlessCheck.holds_scripted_embedded(resource, {})
120
+ )
116
121
 
117
122
 
118
123
  func _parse_json_maybe(value: Variant) -> Variant:
@@ -160,11 +165,11 @@ func _homes(scene: GdhSceneFile, held: Array) -> Array:
160
165
  false,
161
166
  (
162
167
  (
163
- "The %s is kept in %s, not in %s, and an edit here would not be saved there. Edit it "
164
- + "where it is kept instead."
168
+ "The %s is kept in %s, not in %s, and an edit here would not be saved there. "
169
+ + "Edit it where it is kept instead."
165
170
  )
166
171
  % [entry[1], at.get_slice("::", 0), scene.path]
167
- )
172
+ ),
168
173
  ]
169
174
  return [true, homes]
170
175
 
@@ -198,7 +203,9 @@ func _library_of(player: AnimationPlayer, animation_name: String) -> AnimationLi
198
203
  ## The state machine at [param state_machine_path] in [param anim_tree], with the files it is kept
199
204
  ## in, as [machine, homes, why not].
200
205
  func _machine(scene: GdhSceneFile, anim_tree: AnimationTree, state_machine_path: String) -> Array:
201
- var sm: AnimationNodeStateMachine = GdhAnimationReads.state_machine(anim_tree, state_machine_path)
206
+ var sm: AnimationNodeStateMachine = GdhAnimationReads.state_machine(
207
+ anim_tree, state_machine_path
208
+ )
202
209
  if not sm:
203
210
  return [null, {}, GdhAnimationReads.no_machine(anim_tree, state_machine_path)]
204
211
  var homes: Array = _homes(scene, [[sm, "state machine"]])
@@ -225,7 +232,7 @@ func read_animations(args: Dictionary) -> Dictionary:
225
232
  var player_node_path: String = str(args.get("playerNodePath", "."))
226
233
  var animation_name: String = str(args.get("animationName", ""))
227
234
  if scene_path.strip_edges() == "res://":
228
- return {"ok": false, "error": "Missing scenePath"}
235
+ return { "ok": false, "error": "Missing scenePath" }
229
236
 
230
237
  var opened: Array = _read_at(scene_path, player_node_path, "AnimationPlayer")
231
238
  var scene: GdhSceneFile = opened[0]
@@ -250,9 +257,9 @@ func read_animation_states(args: Dictionary) -> Dictionary:
250
257
  var anim_tree_path: String = str(args.get("animTreePath", ""))
251
258
  var state_machine_path: String = str(args.get("stateMachinePath", ""))
252
259
  if scene_path.strip_edges() == "res://":
253
- return {"ok": false, "error": "Missing scenePath"}
260
+ return { "ok": false, "error": "Missing scenePath" }
254
261
  if anim_tree_path.is_empty():
255
- return {"ok": false, "error": "Missing animTreePath"}
262
+ return { "ok": false, "error": "Missing animTreePath" }
256
263
 
257
264
  var opened: Array = _read_at(scene_path, anim_tree_path, "AnimationTree")
258
265
  var scene: GdhSceneFile = opened[0]
@@ -264,7 +271,8 @@ func read_animation_states(args: Dictionary) -> Dictionary:
264
271
  var player_path: String = "" if player == null else scene.path_of(player)
265
272
  var unplayed: String = GdhAnimationReads.no_player(str(anim_tree.anim_player), reached)
266
273
  return _read_in(
267
- scene, GdhAnimationReads.states(anim_tree, state_machine_path, player, player_path, unplayed)
274
+ scene,
275
+ GdhAnimationReads.states(anim_tree, state_machine_path, player, player_path, unplayed)
268
276
  )
269
277
 
270
278
 
@@ -278,18 +286,18 @@ func create_animation(args: Dictionary) -> Dictionary:
278
286
  var loop_mode_name: String = str(args.get("loopMode", "none"))
279
287
 
280
288
  if scene_path.strip_edges() == "res://":
281
- return {"ok": false, "error": "Missing scenePath"}
289
+ return { "ok": false, "error": "Missing scenePath" }
282
290
  if animation_name.strip_edges().is_empty():
283
- return {"ok": false, "error": "Missing animationName"}
291
+ return { "ok": false, "error": "Missing animationName" }
284
292
  var named: String = _name_refusal(animation_name)
285
293
  if not named.is_empty():
286
- return {"ok": false, "error": named}
294
+ return { "ok": false, "error": named }
287
295
  var loop_modes: Dictionary = LOOP_MODES
288
296
  if not loop_modes.has(loop_mode_name):
289
- return {"ok": false, "error": "Unsupported loopMode: " + loop_mode_name}
297
+ return { "ok": false, "error": "Unsupported loopMode: " + loop_mode_name }
290
298
  var timing: String = _timing_refusal(args)
291
299
  if not timing.is_empty():
292
- return {"ok": false, "error": timing}
300
+ return { "ok": false, "error": timing }
293
301
 
294
302
  var opened: Array = _open_at(scene_path, player_node_path, "AnimationPlayer")
295
303
  var scene: GdhSceneFile = opened[0]
@@ -310,7 +318,9 @@ func create_animation(args: Dictionary) -> Dictionary:
310
318
  anim.length = GdhRead.as_float(args.get("length", 1.0), 1.0)
311
319
  anim.loop_mode = GdhRead.as_int(loop_modes[loop_mode_name]) as Animation.LoopMode
312
320
  anim.step = GdhRead.as_float(args.get("step", 0.1), 0.1)
313
- var called: String = animation_name.get_slice("/", 1) if animation_name.contains("/") else animation_name
321
+ var called: String = (
322
+ animation_name.get_slice("/", 1) if animation_name.contains("/") else animation_name
323
+ )
314
324
  # As the editor names a new one: the file keeps it as resource_name, which the inspector shows.
315
325
  anim.resource_name = called
316
326
  var add_err: Error = anim_lib.add_animation(StringName(called), anim)
@@ -327,10 +337,12 @@ func create_animation(args: Dictionary) -> Dictionary:
327
337
  "ok": true,
328
338
  "animationName": animation_name,
329
339
  "length": GdhAnimationReads.held_seconds(anim.length),
330
- "loopMode": loop_mode_name
340
+ "loopMode": loop_mode_name,
331
341
  }
332
342
  if library[2]:
333
- answer["libraryMade"] = animation_name.get_slice("/", 0) if animation_name.contains("/") else ""
343
+ answer["libraryMade"] = (
344
+ animation_name.get_slice("/", 0) if animation_name.contains("/") else ""
345
+ )
334
346
  var files: Dictionary = homes[1]
335
347
  return _finish(scene, check, files, answer)
336
348
 
@@ -341,8 +353,8 @@ static func _name_refusal(animation_name: String) -> String:
341
353
  if animation_name.count("/") > 1:
342
354
  return (
343
355
  (
344
- "%s names a library and an animation in it with one slash, as moves/walk; a library holds no "
345
- + "libraries."
356
+ "%s names a library and an animation in it with one slash, as moves/walk; a "
357
+ + "library holds no libraries."
346
358
  )
347
359
  % animation_name
348
360
  )
@@ -372,7 +384,9 @@ static func _past_length(anim: Animation, animation_name: String) -> String:
372
384
 
373
385
  ## The pastLength sentence for [param past], keys of [param anim] each named by its track's path and
374
386
  ## time, or "" for none.
375
- static func _past_sentence(anim: Animation, animation_name: String, past: PackedStringArray) -> String:
387
+ static func _past_sentence(
388
+ anim: Animation, animation_name: String, past: PackedStringArray
389
+ ) -> String:
376
390
  if past.is_empty():
377
391
  return ""
378
392
  return (
@@ -407,7 +421,10 @@ static func _timing_refusal(args: Dictionary) -> String:
407
421
  if args.has("length"):
408
422
  var length: Variant = args["length"]
409
423
  if not (length is float or length is int) or GdhRead.as_float(length) <= 0.0:
410
- return "length is the animation's length in seconds, more than 0, and %s is not." % _given(length)
424
+ return (
425
+ "length is the animation's length in seconds, more than 0, and %s is not."
426
+ % _given(length)
427
+ )
411
428
  if args.has("step"):
412
429
  var step: Variant = args["step"]
413
430
  if not (step is float or step is int) or GdhRead.as_float(step) < 0.0:
@@ -443,16 +460,19 @@ func set_animation(args: Dictionary) -> Dictionary:
443
460
  var animation_name: String = str(args.get("animationName", ""))
444
461
  var loop_mode_name: String = str(args.get("loopMode", ""))
445
462
  if scene_path.strip_edges() == "res://":
446
- return {"ok": false, "error": "Missing scenePath"}
463
+ return { "ok": false, "error": "Missing scenePath" }
447
464
  if animation_name.strip_edges().is_empty():
448
- return {"ok": false, "error": "Missing animationName"}
465
+ return { "ok": false, "error": "Missing animationName" }
449
466
  if not (args.has("length") or args.has("loopMode") or args.has("step")):
450
- return {"ok": false, "error": "set changes length, loopMode or step, and was given none of them."}
467
+ return {
468
+ "ok": false,
469
+ "error": "set changes length, loopMode or step, and was given none of them.",
470
+ }
451
471
  if args.has("loopMode") and not LOOP_MODES.has(loop_mode_name):
452
- return {"ok": false, "error": "Unsupported loopMode: " + loop_mode_name}
472
+ return { "ok": false, "error": "Unsupported loopMode: " + loop_mode_name }
453
473
  var timing: String = _timing_refusal(args)
454
474
  if not timing.is_empty():
455
- return {"ok": false, "error": timing}
475
+ return { "ok": false, "error": timing }
456
476
 
457
477
  var found: Array = _animation_at(scene_path, player_node_path, animation_name)
458
478
  if found[1] == null:
@@ -479,7 +499,10 @@ func set_animation(args: Dictionary) -> Dictionary:
479
499
  if copy == null or not copy.has_animation(StringName(animation_name)):
480
500
  return "%s would not be in the scene when it loads." % animation_name
481
501
  if not is_equal_approx(copy.get_animation(StringName(animation_name)).length, length):
482
- return "%s would not be %s s long when the scene loads." % [animation_name, _seconds(length)]
502
+ return (
503
+ "%s would not be %s s long when the scene loads."
504
+ % [animation_name, _seconds(length)]
505
+ )
483
506
  return ""
484
507
  var answer: Dictionary = {
485
508
  "ok": true,
@@ -504,12 +527,14 @@ func rename_animation(args: Dictionary) -> Dictionary:
504
527
  var animation_name: String = str(args.get("animationName", ""))
505
528
  var new_name: String = str(args.get("newName", "")).strip_edges()
506
529
  if scene_path.strip_edges() == "res://":
507
- return {"ok": false, "error": "Missing scenePath"}
530
+ return { "ok": false, "error": "Missing scenePath" }
508
531
  if animation_name.strip_edges().is_empty():
509
- return {"ok": false, "error": "Missing animationName"}
532
+ return { "ok": false, "error": "Missing animationName" }
510
533
  if new_name.is_empty():
511
- return {"ok": false, "error": "Missing newName"}
512
- var library_name: String = animation_name.get_slice("/", 0) if animation_name.contains("/") else ""
534
+ return { "ok": false, "error": "Missing newName" }
535
+ var library_name: String = (
536
+ animation_name.get_slice("/", 0) if animation_name.contains("/") else ""
537
+ )
513
538
  var prefix: String = "" if library_name.is_empty() else library_name + "/"
514
539
  if not prefix.is_empty() and new_name.begins_with(prefix):
515
540
  new_name = new_name.trim_prefix(prefix)
@@ -519,15 +544,18 @@ func rename_animation(args: Dictionary) -> Dictionary:
519
544
  "error":
520
545
  (
521
546
  (
522
- "rename keeps an animation in its library (%s), so newName is its name there, with "
523
- + "no library before a slash."
547
+ "rename keeps an animation in its library (%s), so newName is its name there, "
548
+ + "with no library before a slash."
524
549
  )
525
550
  % ("the default one" if library_name.is_empty() else library_name)
526
551
  ),
527
552
  }
528
553
  for forbidden: String in [":", ",", "["]:
529
554
  if new_name.contains(forbidden):
530
- return {"ok": false, "error": "An animation's name cannot hold : , or [, and %s does." % new_name}
555
+ return {
556
+ "ok": false,
557
+ "error": "An animation's name cannot hold : , or [, and %s does." % new_name,
558
+ }
531
559
  var new_full: String = prefix + new_name
532
560
 
533
561
  var found: Array = _animation_at(scene_path, player_node_path, animation_name)
@@ -557,7 +585,7 @@ func rename_animation(args: Dictionary) -> Dictionary:
557
585
  # As the editor's rename sets it: the library's key alone left the file's resource_name, which
558
586
  # the inspector shows, on the old name.
559
587
  player.get_animation(StringName(new_full)).resource_name = new_name
560
- var answer: Dictionary = {"ok": true, "animationName": new_full, "was": animation_name}
588
+ var answer: Dictionary = { "ok": true, "animationName": new_full, "was": animation_name }
561
589
  if autoplayed:
562
590
  answer["autoplay"] = new_full
563
591
  var followed: Array = []
@@ -585,9 +613,9 @@ func remove_animation(args: Dictionary) -> Dictionary:
585
613
  var player_node_path: String = str(args.get("playerNodePath", "."))
586
614
  var animation_name: String = str(args.get("animationName", ""))
587
615
  if scene_path.strip_edges() == "res://":
588
- return {"ok": false, "error": "Missing scenePath"}
616
+ return { "ok": false, "error": "Missing scenePath" }
589
617
  if animation_name.strip_edges().is_empty():
590
- return {"ok": false, "error": "Missing animationName"}
618
+ return { "ok": false, "error": "Missing animationName" }
591
619
 
592
620
  var found: Array = _animation_at(scene_path, player_node_path, animation_name)
593
621
  if found[1] == null:
@@ -598,12 +626,14 @@ func remove_animation(args: Dictionary) -> Dictionary:
598
626
  var homes: Array = _homes(scene, [[library, "animation library"]])
599
627
  if not homes[0]:
600
628
  return scene.refuse(str(homes[1]))
601
- var called: String = animation_name.get_slice("/", 1) if animation_name.contains("/") else animation_name
629
+ var called: String = (
630
+ animation_name.get_slice("/", 1) if animation_name.contains("/") else animation_name
631
+ )
602
632
  var autoplayed: bool = str(player.autoplay) == animation_name
603
633
  library.remove_animation(StringName(called))
604
634
  if player.has_animation(StringName(animation_name)):
605
635
  return scene.refuse("The library did not let go of %s." % animation_name)
606
- var answer: Dictionary = {"ok": true, "removed": animation_name}
636
+ var answer: Dictionary = { "ok": true, "removed": animation_name }
607
637
  if autoplayed:
608
638
  player.autoplay = ""
609
639
  answer["autoplayCleared"] = true
@@ -1,8 +1,7 @@
1
1
  @tool
2
2
  extends "animation_tools.gd"
3
-
4
- ## The tracks and keys of an animation, beside the players and libraries the script it extends edits,
5
- ## whose helpers it shares.
3
+ ## The tracks and keys of an animation, beside the players and libraries the script it extends
4
+ ## edits, whose helpers it shares.
6
5
 
7
6
 
8
7
  # =============================================================================
@@ -15,19 +14,19 @@ func add_animation_track(args: Dictionary) -> Dictionary:
15
14
  var given_track: Variant = args.get("track", {})
16
15
 
17
16
  if scene_path.strip_edges() == "res://":
18
- return {"ok": false, "error": "Missing scenePath"}
17
+ return { "ok": false, "error": "Missing scenePath" }
19
18
  if animation_name.strip_edges().is_empty():
20
- return {"ok": false, "error": "Missing animationName"}
19
+ return { "ok": false, "error": "Missing animationName" }
21
20
  var track: Dictionary = given_track if given_track is Dictionary else {}
22
21
  if track.is_empty():
23
- return {"ok": false, "error": "Missing track"}
24
- # The schema leaves keyframes out of what track requires, since remove_track finds a track without
25
- # them.
22
+ return { "ok": false, "error": "Missing track" }
23
+ # The schema leaves keyframes out of what track requires, since remove_track finds a track
24
+ # without them.
26
25
  if not track.has("keyframes"):
27
- return {"ok": false, "error": "Missing track.keyframes"}
26
+ return { "ok": false, "error": "Missing track.keyframes" }
28
27
  var keyed: Array = _keyframes(track)
29
28
  if not keyed[0]:
30
- return {"ok": false, "error": keyed[1]}
29
+ return { "ok": false, "error": keyed[1] }
31
30
 
32
31
  # Asked of the player, which knows every library: looking only in the default one refused
33
32
  # "moves/walk" as missing.
@@ -48,13 +47,16 @@ func add_animation_track(args: Dictionary) -> Dictionary:
48
47
  target_path = "."
49
48
  var target: Node = _animated(player, target_path)
50
49
  if target == null:
51
- return scene.refuse(
52
- (
50
+ return (
51
+ scene
52
+ . refuse(
53
53
  (
54
- "No node at %s from the player's root node, %s, which is what the track path is read "
55
- + "against."
54
+ (
55
+ "No node at %s from the player's root node, %s, which is what the track "
56
+ + "path is read against."
57
+ )
58
+ % [target_path, str(player.root_node)]
56
59
  )
57
- % [target_path, str(player.root_node)]
58
60
  )
59
61
  )
60
62
  var keyframes: Array = keyed[1]
@@ -120,7 +122,12 @@ func add_animation_track(args: Dictionary) -> Dictionary:
120
122
  ## animates: two tracks for one path both play, the later overriding the earlier, and a key meant
121
123
  ## to extend the motion was split off where reading the animation showed two halves.
122
124
  func _add_track(
123
- anim: Animation, track: Dictionary, target: Node, target_path: String, keyframes: Array, replacing: bool
125
+ anim: Animation,
126
+ track: Dictionary,
127
+ target: Node,
128
+ target_path: String,
129
+ keyframes: Array,
130
+ replacing: bool
124
131
  ) -> Array:
125
132
  var track_type: String = str(track.get("type", ""))
126
133
  var keys: Array = []
@@ -148,7 +155,7 @@ func _add_track(
148
155
  return _not_added("keyframes[%d].args must be a list." % index)
149
156
  var raw: Array = given
150
157
  var arguments: Array = _fitted(target, method_name, _parse_method_args(raw))
151
- keys.append({"method": method_name, "args": arguments})
158
+ keys.append({ "method": method_name, "args": arguments })
152
159
  if misfit.is_empty():
153
160
  misfit = _key_misfit(target, method_name, arguments, index)
154
161
  method_found = target.has_method(method_name)
@@ -156,7 +163,10 @@ func _add_track(
156
163
  else:
157
164
  return _not_added(
158
165
  (
159
- "add_track makes property and method tracks, and track.type is %s; remove_track takes any."
166
+ (
167
+ "add_track makes property and method tracks, and track.type is %s; "
168
+ + "remove_track takes any."
169
+ )
160
170
  % track_type
161
171
  )
162
172
  )
@@ -178,14 +188,16 @@ func _add_track(
178
188
  return _not_added(
179
189
  (
180
190
  (
181
- "Track %d already animates %s and has a key at %s s, which keyframes[%d] would "
182
- + "replace. Nothing was written; replaceKeys true replaces it."
191
+ "Track %d already animates %s and has a key at %s s, which "
192
+ + "keyframes[%d] would replace. Nothing was written; replaceKeys true "
193
+ + "replaces it."
183
194
  )
184
195
  % [track_idx, str(path), _seconds(time), index]
185
196
  )
186
197
  )
187
- # A method key's value is its call, {"method": ..., "args": [...]}. The time is as asked:
188
- # the key's own, read back from a scene's 32-bit times, puts 0.1 at 0.100000001490116.
198
+ # A method key's value is its call, {"method": ..., "args": [...]}. The time is as
199
+ # asked: the key's own, read back from a scene's 32-bit times, puts 0.1 at
200
+ # 0.100000001490116.
189
201
  (
190
202
  replaced
191
203
  . append(
@@ -228,7 +240,9 @@ static func _fitted(target: Node, method: String, arguments: Array) -> Array:
228
240
  declared = GdhRead.as_int(parameter.get("type", TYPE_NIL))
229
241
  if value is float and declared != TYPE_FLOAT:
230
242
  var number: float = value
231
- if is_finite(number) and number == floorf(number) and absf(number) < 9007199254740992.0:
243
+ if (is_finite(number)
244
+ and number == floorf(number)
245
+ and absf(number) < 9_007_199_254_740_992.0):
232
246
  value = int(number)
233
247
  fitted.append(value)
234
248
  return fitted
@@ -256,10 +270,16 @@ static func _key_misfit(target: Node, method: String, arguments: Array, index: i
256
270
  else ("1 argument" if arguments.size() == 1 else "%d arguments" % arguments.size())
257
271
  )
258
272
  if arguments.size() < needed:
259
- return "keyframes[%d] calls %s with %s, and it needs %d%s" % [index, method, passed, needed, fails]
273
+ return (
274
+ "keyframes[%d] calls %s with %s, and it needs %d%s"
275
+ % [index, method, passed, needed, fails]
276
+ )
260
277
  if arguments.size() > parameters.size():
261
278
  var most: String = "none" if parameters.is_empty() else "at most %d" % parameters.size()
262
- return "keyframes[%d] calls %s with %s, and it takes %s%s" % [index, method, passed, most, fails]
279
+ return (
280
+ "keyframes[%d] calls %s with %s, and it takes %s%s"
281
+ % [index, method, passed, most, fails]
282
+ )
263
283
  for at: int in arguments.size():
264
284
  var parameter: Dictionary = parameters[at]
265
285
  var taken_type: int = GdhRead.as_int(parameter.get("type", TYPE_NIL))
@@ -276,7 +296,7 @@ static func _key_misfit(target: Node, method: String, arguments: Array, index: i
276
296
  method,
277
297
  str(parameter.get("name", "")),
278
298
  type_string(taken_type),
279
- fails
299
+ fails,
280
300
  ]
281
301
  )
282
302
  return ""
@@ -293,22 +313,22 @@ func remove_animation_track(args: Dictionary) -> Dictionary:
293
313
  var animation_name: String = str(args.get("animationName", ""))
294
314
  var given_track: Variant = args.get("track", {})
295
315
  if scene_path.strip_edges() == "res://":
296
- return {"ok": false, "error": "Missing scenePath"}
316
+ return { "ok": false, "error": "Missing scenePath" }
297
317
  if animation_name.strip_edges().is_empty():
298
- return {"ok": false, "error": "Missing animationName"}
318
+ return { "ok": false, "error": "Missing animationName" }
299
319
  var track: Dictionary = given_track if given_track is Dictionary else {}
300
320
  if track.is_empty():
301
- return {"ok": false, "error": "Missing track"}
321
+ return { "ok": false, "error": "Missing track" }
302
322
  var track_type: String = str(track.get("type", ""))
303
323
  if not track_type in GdhAnimationReads.TRACK_TYPE_NAMES.values():
304
- return {"ok": false, "error": "Unsupported track.type: " + track_type}
324
+ return { "ok": false, "error": "Unsupported track.type: " + track_type }
305
325
  var node_path: String = str(track.get("nodePath", ""))
306
326
  var property: String = str(track.get("property", ""))
307
327
  var shape: Array = [track_type, node_path, property]
308
328
  var method: String = str(track.get("method", "")) if track_type == "method" else ""
309
329
  var read_times: Variant = _times_of(args.get("times"))
310
330
  if read_times is String:
311
- return {"ok": false, "error": read_times}
331
+ return { "ok": false, "error": read_times }
312
332
  var times: Array = read_times
313
333
 
314
334
  var found: Array = _animation_at(scene_path, player_node_path, animation_name)
@@ -335,7 +355,7 @@ func remove_animation_track(args: Dictionary) -> Dictionary:
335
355
  % [
336
356
  animation_name,
337
357
  track_type,
338
- node_path if property.is_empty() else "%s:%s" % [node_path, property]
358
+ node_path if property.is_empty() else "%s:%s" % [node_path, property],
339
359
  ]
340
360
  )
341
361
  if held.is_empty():
@@ -353,7 +373,9 @@ func remove_animation_track(args: Dictionary) -> Dictionary:
353
373
  var timed: Array = _keys_at(anim, calling, times)
354
374
  if timed[1] != "":
355
375
  var on: String = node_path if property.is_empty() else "%s:%s" % [node_path, property]
356
- return scene.refuse("%s's %s track on %s %s" % [animation_name, track_type, on, timed[1]])
376
+ return scene.refuse(
377
+ "%s's %s track on %s %s" % [animation_name, track_type, on, timed[1]]
378
+ )
357
379
  calling = timed[0]
358
380
  var keys: int = 0
359
381
  var tracks_removed: int = 0
@@ -383,7 +405,7 @@ func remove_animation_track(args: Dictionary) -> Dictionary:
383
405
  if loaded.get_track_count() != left or _key_total(loaded) != keys_left:
384
406
  return "the track would still be in %s when the scene loads." % animation_name
385
407
  return ""
386
- var removed: Dictionary = {"type": track_type, "nodePath": node_path}
408
+ var removed: Dictionary = { "type": track_type, "nodePath": node_path }
387
409
  if not property.is_empty():
388
410
  removed["property"] = property
389
411
  if not method.is_empty():
@@ -432,8 +454,8 @@ static func _times_of(given: Variant) -> Variant:
432
454
 
433
455
 
434
456
  ## Of the keys [param calling] names, as [method _keys_calling] answers them, the ones at
435
- ## [param times], as [[[track, key]...], ""], or with the second the words refusing a time none is at.
436
- ## Removing a key took removing its whole track, so moving one key in time rewrote every other.
457
+ ## [param times], as [[[track, key]...], ""], or with the second the words refusing a time none is
458
+ ## at. Removing a key took removing its whole track, so moving one key in time rewrote every other.
437
459
  static func _keys_at(anim: Animation, calling: Array, times: Array) -> Array:
438
460
  var at: Array = []
439
461
  var held: PackedStringArray = []
@@ -457,7 +479,10 @@ static func _keys_at(anim: Animation, calling: Array, times: Array) -> Array:
457
479
  var _named: bool = named.append(str(given))
458
480
  return [
459
481
  at,
460
- "has no key at %s s; its keys are at %s s. Nothing was removed." % [", ".join(named), ", ".join(held)]
482
+ (
483
+ "has no key at %s s; its keys are at %s s. Nothing was removed."
484
+ % [", ".join(named), ", ".join(held)]
485
+ ),
461
486
  ]
462
487
 
463
488
 
@@ -483,7 +508,9 @@ static func _key_total(anim: Animation) -> int:
483
508
  static func _track_shape(anim: Animation, index: int) -> Array:
484
509
  var path: NodePath = anim.track_get_path(index)
485
510
  return [
486
- GdhAnimationReads.TRACK_TYPE_NAMES.get(anim.track_get_type(index), str(anim.track_get_type(index))),
511
+ GdhAnimationReads.TRACK_TYPE_NAMES.get(
512
+ anim.track_get_type(index), str(anim.track_get_type(index))
513
+ ),
487
514
  str(path.get_concatenated_names()),
488
515
  str(path.get_concatenated_subnames()),
489
516
  ]
@@ -508,7 +535,8 @@ func _keyframes(track: Dictionary) -> Array:
508
535
  var seconds: float = GdhRead.as_float(time)
509
536
  if times.has(seconds):
510
537
  return [
511
- false, "keyframes[%d] and [%d] are both at %s seconds." % [times[seconds], index, seconds]
538
+ false,
539
+ "keyframes[%d] and [%d] are both at %s seconds." % [times[seconds], index, seconds],
512
540
  ]
513
541
  times[seconds] = index
514
542
  return [true, keyframes]
@@ -530,7 +558,9 @@ func _key_values(target: Node, prop_name: String, keyframes: Array) -> Array:
530
558
  # A subname such as position:x keys one component, which is a number.
531
559
  var component: Variant = _properties.parse(raw, TYPE_FLOAT)
532
560
  if not component is float:
533
- return [false, "keyframes[%d].value keys %s, which is a number." % [index, prop_name]]
561
+ return [
562
+ false, "keyframes[%d].value keys %s, which is a number." % [index, prop_name],
563
+ ]
534
564
  values.append(component)
535
565
  continue
536
566
  var value: Array = _properties.value_for(target, declared, raw)