gdharness 1.3.60 → 1.3.61

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 (77) hide show
  1. package/README.md +20 -20
  2. package/build/cli.js +2104 -1691
  3. package/build/godot/addons/auto_reload/auto_reload.gd +3 -3
  4. package/build/godot/addons/gdharness_editor/bridge_client.gd +4 -4
  5. package/build/godot/addons/gdharness_editor/declared_values.gd +13 -13
  6. package/build/godot/addons/gdharness_editor/file_reads.gd +6 -6
  7. package/build/godot/addons/gdharness_editor/headless_check.gd +9 -6
  8. package/build/godot/addons/gdharness_editor/property_paths.gd +3 -3
  9. package/build/godot/addons/gdharness_editor/property_values.gd +10 -10
  10. package/build/godot/addons/gdharness_editor/reading.gd +22 -18
  11. package/build/godot/addons/gdharness_editor/scene_file.gd +5 -5
  12. package/build/godot/addons/gdharness_editor/serialisation.gd +4 -4
  13. package/build/godot/addons/gdharness_editor/tools/animation_states.gd +5 -5
  14. package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +6 -6
  15. package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd +9 -9
  16. package/build/godot/addons/gdharness_editor/tools/class_tools.gd +3 -3
  17. package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +5 -5
  18. package/build/godot/addons/gdharness_editor/tools/navigation_bake.gd +5 -5
  19. package/build/godot/addons/gdharness_editor/tools/play_tools.gd +2 -2
  20. package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +1 -1
  21. package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +5 -5
  22. package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +3 -3
  23. package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +3 -3
  24. package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +4 -4
  25. package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +3 -3
  26. package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +10 -10
  27. package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +1 -1
  28. package/build/godot/addons/gdharness_editor/tools/tileset_tools.gd +5 -5
  29. package/build/godot/addons/gdharness_runtime/declared_values.gd +13 -13
  30. package/build/godot/addons/gdharness_runtime/reading.gd +22 -18
  31. package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +2 -2
  32. package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +89 -18
  33. package/build/godot/addons/gdharness_runtime/runtime_capture.gd +6 -6
  34. package/build/godot/addons/gdharness_runtime/runtime_changes.gd +10 -10
  35. package/build/godot/addons/gdharness_runtime/runtime_frames.gd +5 -4
  36. package/build/godot/addons/gdharness_runtime/runtime_hover.gd +3 -4
  37. package/build/godot/addons/gdharness_runtime/runtime_input.gd +8 -8
  38. package/build/godot/addons/gdharness_runtime/runtime_items.gd +1 -1
  39. package/build/godot/addons/gdharness_runtime/runtime_menus.gd +3 -3
  40. package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +5 -5
  41. package/build/godot/addons/gdharness_runtime/runtime_paths.gd +20 -20
  42. package/build/godot/addons/gdharness_runtime/runtime_queries.gd +13 -13
  43. package/build/godot/addons/gdharness_runtime/runtime_says.gd +5 -5
  44. package/build/godot/addons/gdharness_runtime/runtime_targets.gd +39 -39
  45. package/build/godot/addons/gdharness_runtime/runtime_typing.gd +3 -3
  46. package/build/godot/addons/gdharness_runtime/runtime_values.gd +7 -7
  47. package/build/godot/addons/gdharness_runtime/runtime_waits.gd +8 -8
  48. package/build/godot/addons/gdharness_runtime/runtime_words.gd +5 -5
  49. package/build/godot/addons/gdharness_runtime/serialisation.gd +4 -4
  50. package/build/godot/addons/gdharness_tests/bench.gd +1 -1
  51. package/build/godot/addons/gdharness_tests/share.gd +6 -6
  52. package/build/godot/addons/gdharness_tests/suites.gd +1 -1
  53. package/build/godot/operations/audio_buses.gd +4 -4
  54. package/build/godot/operations/class_cache.gd +3 -3
  55. package/build/godot/operations/classdb_queries.gd +1 -1
  56. package/build/godot/operations/declared_values.gd +13 -13
  57. package/build/godot/operations/dependencies.gd +6 -6
  58. package/build/godot/operations/export_presets.gd +7 -7
  59. package/build/godot/operations/file_reads.gd +6 -6
  60. package/build/godot/operations/gdscript_analysis.gd +6 -6
  61. package/build/godot/operations/gdscript_authoring.gd +11 -11
  62. package/build/godot/operations/godot_operations.gd +1 -1
  63. package/build/godot/operations/import_pipeline.gd +12 -12
  64. package/build/godot/operations/input_actions.gd +3 -3
  65. package/build/godot/operations/logger.gd +1 -1
  66. package/build/godot/operations/plugins.gd +2 -2
  67. package/build/godot/operations/project_config.gd +11 -11
  68. package/build/godot/operations/project_validation.gd +1 -1
  69. package/build/godot/operations/property_paths.gd +3 -3
  70. package/build/godot/operations/property_values.gd +10 -10
  71. package/build/godot/operations/reading.gd +22 -18
  72. package/build/godot/operations/resource_files.gd +1 -1
  73. package/build/godot/operations/script_check.gd +2 -2
  74. package/build/godot/operations/serialisation.gd +4 -4
  75. package/build/godot/tests/listed.gd +9 -9
  76. package/build/keeper.js +511 -162
  77. package/package.json +1 -1
@@ -3,12 +3,12 @@ extends EditorPlugin
3
3
  ## Reloads the open scene and the scripts it carries when they change on disk, without the
4
4
  ## editor's confirmation popup. Every edit made through gdharness lands on disk, and an editor
5
5
  ## that keeps showing the old file is how a change reads as one that never happened. The
6
- ## files are polled once a second; the editor's own watcher only fires on window focus.
6
+ ## files are polled once a second. The editor's own watcher only fires on window focus.
7
7
 
8
8
  const CHECK_INTERVAL_SECONDS: float = 1.0
9
9
  ## How long after a file's modification time its contents are compared as well. The time is in
10
10
  ## whole seconds, so a second write inside the second of the first leaves it as it was and changes
11
- ## only the contents; past that second any write moves the time.
11
+ ## only the contents. Past that second any write moves the time.
12
12
  const SAME_SECOND_SECONDS: int = 5
13
13
 
14
14
  var _timer: Timer
@@ -130,7 +130,7 @@ func _reload_scene(path: String) -> void:
130
130
  (
131
131
  (
132
132
  "gdharness: %s changed on disk while the editor holds unsaved changes to it, "
133
- + "so it was not reloaded; saving it writes the editor's copy over the file"
133
+ + "so it was not reloaded. Saving it writes the editor's copy over the file"
134
134
  )
135
135
  % path
136
136
  )
@@ -17,7 +17,7 @@ const DIGEST_MARKER: String = "res://addons/gdharness_editor/.gdharness-digest"
17
17
  ## step with `announcementPath` in src/bridge-announce.ts.
18
18
  const ANNOUNCEMENT: String = "res://.godot/gdharness-bridge.json"
19
19
  const ANNOUNCE_PROTOCOL: int = 1
20
- ## Where each editor of this project says which ports it serves; see [method _ports_record].
20
+ ## Where each editor of this project says which ports it serves. See [method _ports_record].
21
21
  const EDITORS_RECORDED: String = "res://.godot/gdharness-editors"
22
22
  const EDITORS_RECORDED_PROTOCOL: int = 1
23
23
  const RECONNECT_DELAY: float = 3.0
@@ -172,7 +172,7 @@ func _process(_delta: float) -> void:
172
172
  ## The file saying which ports this editor serves, named by its process id, so `gdharness lsp` can
173
173
  ## find its language server when a server moved it off the default. One for each process rather
174
174
  ## than one for the project, because a gate's `--import` loads this addon too, and its plugin is
175
- ## shown none of the options that would say so; the reader tells the two apart by command line.
175
+ ## shown none of the options that would say so. The reader tells the two apart by command line.
176
176
  ## Kept in step with `editorRecordsIn` in src/lsp-bridge.ts.
177
177
  static func _ports_record() -> String:
178
178
  return ProjectSettings.globalize_path(EDITORS_RECORDED).path_join(
@@ -265,7 +265,7 @@ func _resolve_server_url(explicit_url: String) -> String:
265
265
  if raw != "":
266
266
  if raw.is_valid_int() and int(raw) >= 1 and int(raw) <= 65535:
267
267
  return "ws://127.0.0.1:%d/godot" % int(raw)
268
- push_error("GDHARNESS_BRIDGE_PORT is %s, not a port; using %s" % [raw, DEFAULT_URL])
268
+ push_error("GDHARNESS_BRIDGE_PORT is %s, not a port, so %s is used" % [raw, DEFAULT_URL])
269
269
 
270
270
  return DEFAULT_URL
271
271
 
@@ -411,7 +411,7 @@ static func _asked_for(variable: String) -> int:
411
411
  ## Turns breakpoint syncing on, so a debug session opening does not clear the editor's breakpoints.
412
412
  ##
413
413
  ## With the setting off, Godot's adapter answers `initialize` by clearing every breakpoint in the
414
- ## script editor, open and cached, and telling every session so; with it on, it tells the new
414
+ ## script editor, open and cached, and telling every session so. With it on, it tells the new
415
415
  ## session what is set and clears nothing. A server opens a session for its first breakpoint or
416
416
  ## its first stack read, so off meant a harness session took the user's breakpoints away on its
417
417
  ## first debug call, silently. The adapter reads the setting again the moment it changes, so this
@@ -288,7 +288,7 @@ static func outside(target: Object, declared: Dictionary, value: Variant, shown:
288
288
  return ""
289
289
  return (
290
290
  (
291
- "%s is none of the names %s lists: %s, which the inspector holds it to; the engine "
291
+ "%s is none of the names %s lists: %s, which the inspector holds it to. The engine "
292
292
  + "stores it as given."
293
293
  )
294
294
  % [shown, property, ", ".join(names)]
@@ -311,7 +311,7 @@ static func outside(target: Object, declared: Dictionary, value: Variant, shown:
311
311
  if flags.is_empty() or stray == 0:
312
312
  return ""
313
313
  return (
314
- "%d holds bits no flag of %s has (%d): its flags are %s; the engine stores it as given."
314
+ "%d holds bits no flag of %s has (%d): its flags are %s. The engine stores it as given."
315
315
  % [whole, property, stray, _listed(flags)]
316
316
  )
317
317
  if hint != PROPERTY_HINT_RANGE:
@@ -327,7 +327,7 @@ static func outside(target: Object, declared: Dictionary, value: Variant, shown:
327
327
  return ""
328
328
  return (
329
329
  (
330
- "%s is outside the range %s declares, %s to %s, which the inspector holds it to; the "
330
+ "%s is outside the range %s declares, %s to %s, which the inspector holds it to. The "
331
331
  + "engine stores it as given."
332
332
  )
333
333
  % [shown, property, _bound(low), _bound(high)]
@@ -544,7 +544,7 @@ static func not_held(
544
544
  return (
545
545
  (
546
546
  "%s.bus takes the name of one of the project's audio buses, and %s is none of "
547
- + "them, so it would play on %s; %s. project_info include audio_buses lists them, "
547
+ + "them, so it would play on %s. %s. project_info include audio_buses lists them, "
548
548
  + "and project_settings add_audio_bus adds one. Nothing was written."
549
549
  )
550
550
  % [
@@ -552,21 +552,21 @@ static func not_held(
552
552
  given[1],
553
553
  AudioServer.get_bus_name(0),
554
554
  (
555
- "the buses are " + ", ".join(names)
555
+ "The buses are " + ", ".join(names)
556
556
  if nearest.is_empty()
557
- else "the nearest " + nearest
557
+ else "The nearest " + nearest
558
558
  ),
559
559
  ]
560
560
  )
561
561
  return (
562
- "%s: it takes one of the names it lists, and %s is none of them; %s. Nothing was written."
562
+ "%s: it takes one of the names it lists, and %s is none of them. %s. Nothing was written."
563
563
  % [
564
564
  said,
565
565
  given[1],
566
566
  (
567
- "it lists " + ", ".join(names)
567
+ "It lists " + ", ".join(names)
568
568
  if nearest.is_empty()
569
- else "the nearest it lists " + nearest
569
+ else "The nearest it lists " + nearest
570
570
  ),
571
571
  ]
572
572
  )
@@ -593,7 +593,7 @@ static func held_by_children(node: Node, property: String) -> String:
593
593
 
594
594
  ## A sentence for each node path in [param given], by property, that names no node from
595
595
  ## [param node]. A path is written whatever it names, as the inspector writes one, since the node
596
- ## may be added next; a joint whose node_a named nothing then joined nothing, and no answer said so.
596
+ ## may be added next. A joint whose node_a named nothing then joined nothing, and no answer said so.
597
597
  static func naming_nothing(node: Node, given: Dictionary) -> Dictionary:
598
598
  var said: Dictionary = {}
599
599
  for property: String in given:
@@ -610,7 +610,7 @@ static func naming_nothing(node: Node, given: Dictionary) -> Dictionary:
610
610
  said[property] = (
611
611
  (
612
612
  "%s names no node from %s. It is written, as the editor writes one, since that "
613
- + "node may be added next; until it is, %s finds nothing."
613
+ + "node may be added next. Until it is, %s finds nothing."
614
614
  )
615
615
  % [str(named), node.name, property]
616
616
  )
@@ -624,7 +624,7 @@ static func no_uniform(material: ShaderMaterial, property: String) -> String:
624
624
  var uniform: String = property.trim_prefix("shader_parameter/")
625
625
  if material.shader == null:
626
626
  return (
627
- "The ShaderMaterial has no shader, so it has no parameter %s yet; set shader first."
627
+ "The ShaderMaterial has no shader, so it has no parameter %s yet. Set shader first."
628
628
  % uniform
629
629
  )
630
630
  var shader: String = material.shader.resource_path
@@ -634,5 +634,5 @@ static func no_uniform(material: ShaderMaterial, property: String) -> String:
634
634
  uniforms.append(str(entry["name"]))
635
635
  var said: String = "%s declares no uniform %s, which %s would set" % [named, uniform, property]
636
636
  if uniforms.is_empty():
637
- return said + "; it declares no uniforms."
637
+ return said + ". It declares no uniforms."
638
638
  return GdhRead.offered(said, uniform, uniforms) + "."
@@ -4,7 +4,7 @@ extends RefCounted
4
4
  ##
5
5
  ## A scene is read off its SceneState rather than instantiated. Instantiating outside the editor
6
6
  ## runs every script's member initialisers and _init (measured on 4.7.2, with or without -e), so a
7
- ## read with no editor would have run the game's code on every node; the editor gets placeholders
7
+ ## read with no editor would have run the game's code on every node. The editor gets placeholders
8
8
  ## and runs none. The state holds everything the file says, and the scenes it instances theirs,
9
9
  ## without making a node. Loading the file still does what loading does in the game: static
10
10
  ## initialisers run, and a resource with a script is made with it.
@@ -53,7 +53,7 @@ static func scene_node(scene_path: String, node_path: String) -> Dictionary:
53
53
 
54
54
 
55
55
  ## The node at [param node_path] in [param scene_path] as [method scene_node] answers it, when it is
56
- ## a [param kind]; otherwise a refusal saying what the scene has there and where its nodes of that
56
+ ## a [param kind]. Otherwise a refusal saying what the scene has there and where its nodes of that
57
57
  ## kind are, so the caller has the path to pass. The file is read once, because every load prints
58
58
  ## the engine's warnings about it again.
59
59
  static func scene_node_of_kind(scene_path: String, node_path: String, kind: String) -> Dictionary:
@@ -143,7 +143,7 @@ static func _laid(scene_path: String) -> Dictionary:
143
143
  ## file's own entries for it applied over it. Answers a refusal, or "".
144
144
  ##
145
145
  ## [param within] is the files being laid, outermost first, so a scene that instances one of them
146
- ## is refused rather than laid forever; the engine refuses to load such a scene, so this is only
146
+ ## is refused rather than laid forever. The engine refuses to load such a scene, so this is only
147
147
  ## reached through a state built some other way. [param loaded] is the scene [param state] is read
148
148
  ## from, when the caller has it loaded already.
149
149
  static func _lay(
@@ -200,7 +200,7 @@ static func _lay(
200
200
  if prefix == "." and loaded == null:
201
201
  nodes[path]["inheritedFrom"] = state.get_path()
202
202
  # The name is the state's even for an entry laid already, since an inherited scene names its
203
- # root itself; a root instanced inside another scene is renamed by that scene once laid.
203
+ # root itself. A root instanced inside another scene is renamed by that scene once laid.
204
204
  if not recovered:
205
205
  nodes[path]["name"] = str(state.get_node_name(index))
206
206
  if fresh:
@@ -229,7 +229,7 @@ static func _lay(
229
229
  if loaded != null and not set_here.has(named):
230
230
  set_here.append(named)
231
231
  # Only the scene being read and the scenes it inherits share its root, the owner whose editable
232
- # instances a write here sets; a file instanced below makes its own owner's editable.
232
+ # instances a write here sets. A file instanced below makes its own owner's editable.
233
233
  if prefix == ".":
234
234
  for editable: String in _editable_in(state.get_path(), loaded):
235
235
  var at: String = _joined(prefix, editable)
@@ -558,7 +558,7 @@ static func resource(res_path: String, include_defaults: bool) -> Dictionary:
558
558
  var serialiser: GdhSerialisation = GdhSerialisation.new()
559
559
  var properties: Dictionary = {}
560
560
  # A headless engine runs a script that is not a tool as the file loads, so what its _init and
561
- # setters gave other properties read as values the file sets; the file's own lines say which it
561
+ # setters gave other properties read as values the file sets. The file's own lines say which it
562
562
  # does. The editor runs no such script.
563
563
  var untooled: bool = script != null and not script.is_tool() and not Engine.is_editor_hint()
564
564
  var from_file: bool = (
@@ -80,7 +80,7 @@ static func kept_by_engine(object: Object, name: String, wanted: Variant, held:
80
80
 
81
81
  ## The stored properties of [param object] that are not in [param names] and no longer hold what
82
82
  ## [param before] recorded. One the object did not have before, which a script set on it declares,
83
- ## counts once it holds anything but its default; one it no longer has went with the old script.
83
+ ## counts once it holds anything but its default. One it no longer has went with the old script.
84
84
  static func differing(object: Object, before: Dictionary, names: Dictionary) -> Array[String]:
85
85
  var changed: Array[String] = []
86
86
  var now: Dictionary = stored(object)
@@ -111,7 +111,7 @@ static func default_of(object: Object, name: String) -> Variant:
111
111
  ## What the declaration of [param name] in [param script] or a script it extends initialises it to,
112
112
  ## when that is a value written out, such as [code]PackedStringArray()[/code], or null. The engine
113
113
  ## reports a default only for an initializer it folded into a constant, and it folds no constructor
114
- ## call, so it gives none for such a property; the saver then writes it whatever it holds, and the
114
+ ## call, so it gives none for such a property. The saver then writes it whatever it holds, and the
115
115
  ## line read as a change some script had made.
116
116
  static func _initialised(script: Script, name: String, type: int) -> Variant:
117
117
  var declaration: RegEx = RegEx.create_from_string(
@@ -157,7 +157,7 @@ static func reached(object: Object, property: String) -> Dictionary:
157
157
  return ids
158
158
 
159
159
 
160
- ## Adds what [param more] spares to [param into], both as [method reached] answers them; true for an
160
+ ## Adds what [param more] spares to [param into], both as [method reached] answers them. True for an
161
161
  ## id spares the whole resource, as one a tool rebuilt.
162
162
  static func spare(into: Dictionary, more: Dictionary) -> void:
163
163
  for id: Variant in more:
@@ -507,7 +507,7 @@ static func setter_ran(object: Object, property: String, refused: String) -> Str
507
507
  (
508
508
  (
509
509
  "%s %s is not a tool script, so its setter ran in the headless engine writing this "
510
- + "as it runs in the game; an editor runs none and would have saved the value "
510
+ + "as it runs in the game. An editor runs none and would have saved the value "
511
511
  + "given. "
512
512
  )
513
513
  % [refused, named]
@@ -539,7 +539,7 @@ static func move_script_set(answer: Dictionary, names: Array, owner: String) ->
539
539
  (
540
540
  "%s's script is not a tool, so it ran in the headless engine that wrote the file, and "
541
541
  + "set %s as it did. The file does not hold %s, as a save from the editor, where the "
542
- + "script does not run, would not; the script sets %s again when it runs in the game."
542
+ + "script does not run, would not. The script sets %s again when it runs in the game."
543
543
  )
544
544
  % [owner, ", ".join(listed), pronoun, pronoun]
545
545
  )
@@ -547,6 +547,9 @@ static func move_script_set(answer: Dictionary, names: Array, owner: String) ->
547
547
 
548
548
  ## Why [param name] on [param what] cannot be saved as the file held it.
549
549
  static func unasked(what: String, name: String, why: String = "") -> String:
550
+ var told: String = why.trim_suffix(".")
551
+ if not told.is_empty():
552
+ told = ". " + told.left(1).to_upper() + told.substr(1)
550
553
  return (
551
554
  (
552
555
  (
@@ -554,7 +557,7 @@ static func unasked(what: String, name: String, why: String = "") -> String:
554
557
  + "ask for it: its script ran when a headless engine loaded or set it, as it does "
555
558
  + "in the game and not in an editor%s. "
556
559
  )
557
- % [what, name, "" if why.is_empty() else "; " + why.trim_suffix(".")]
560
+ % [what, name, told]
558
561
  )
559
562
  + REMEDY
560
563
  )
@@ -75,7 +75,7 @@ static func _stepped(target: Object, name: String, at: int) -> Array:
75
75
 
76
76
 
77
77
  ## The refusal for [param name], which [param target] does not declare, when a step of it indexes a
78
- ## list [param target] holds and names no resource in it; or "".
78
+ ## list [param target] holds and names no resource in it, or "".
79
79
  static func unlisted(target: Object, name: String) -> String:
80
80
  var at: int = name.find("/")
81
81
  while at > 0:
@@ -163,7 +163,7 @@ static func held_at(target: Object, property: String) -> Resource:
163
163
  ## only once the element exists, so a TileSet with no physics layer had no
164
164
  ## physics_layer_0/collision_layer to write. A list the engine declares as an array grows through
165
165
  ## the method named after its elements, add_physics_layer for physics_layer_, given the indices of
166
- ## the lists around it; a list counted by a property, as a tile's polygons are by polygons_count,
166
+ ## the lists around it. A list counted by a property, as a tile's polygons are by polygons_count,
167
167
  ## grows by raising the count.
168
168
  static func grow(target: Object, name: String, called: String) -> String:
169
169
  var steps: PackedStringArray = name.split("/")
@@ -255,7 +255,7 @@ static func class_called(target: Object) -> String:
255
255
 
256
256
 
257
257
  ## The refusal for [param name], which [param target] does not declare, when it runs through a
258
- ## resource saved in a file other than [param home], the one [param target] is saved in; or "". The
258
+ ## resource saved in a file other than [param home], the one [param target] is saved in, or "". The
259
259
  ## write belongs in that file, since this one would be saved and that one left as it was: through a
260
260
  ## TileMapLayer's tile_set kept in a file of its own, or through the mesh of an instance's editable
261
261
  ## child, which is built into the scene the instance comes from.
@@ -20,7 +20,7 @@ const GdhRead = preload("reading.gd")
20
20
  const GdhSame = preload("same_values.gd")
21
21
  const GdhSerialisation = preload("serialisation.gd")
22
22
  const GdhShapes = preload("value_shapes.gd")
23
- # The data types a Theme names its items by, as in "Button/colors/font_color", and what each holds.
23
+ # The data types a Theme names its items by, as in `Button/colors/font_color`, and what each holds.
24
24
  const THEME_ITEMS: Dictionary[String, Array] = {
25
25
  "colors": [TYPE_COLOR, ""],
26
26
  "constants": [TYPE_INT, ""],
@@ -75,7 +75,7 @@ var _names_no_node: Dictionary = {}
75
75
  ##
76
76
  ## Three separate questions, asked in order, because a caller may say what it means in three
77
77
  ## ways: a dictionary that names its own type, a dictionary shaped like the type the property
78
- ## declares, or a bare array positional for a vector. Each is its own function; asking all three
78
+ ## declares, or a bare array positional for a vector. Each is its own function. Asking all three
79
79
  ## in one was twenty-four exits deep and impossible to follow.
80
80
  ##
81
81
  ## [param elements] is what a typed Array or Dictionary holds, as [method GdhDeclared.elements_of]
@@ -216,8 +216,8 @@ func write_all(target: Object, properties: Dictionary) -> String:
216
216
  var written_at: Dictionary[String, int] = {}
217
217
  var writes: int = 0
218
218
  # Which other property's write last changed each one already written, by name. A Gradient keeps
219
- # one offset for each colour, so offsets given after colors cut them back, and the refusal said
220
- # only that the engine had changed the colours.
219
+ # one offset for each colour, so offsets given after `colors` cut them back, and the refusal
220
+ # said only that the engine had changed the colours.
221
221
  var undone_by: Dictionary[String, String] = {}
222
222
  # A refusal of one of several leaves the others unwritten too, which a refusal naming only the
223
223
  # one it refused left a caller to guess.
@@ -350,7 +350,7 @@ func _note_undone(
350
350
  ## sizes its children and the scene keeps none of that for them, so their anchors, offsets, position
351
351
  ## and size are refused with what a child does set. A control in Position mode ignores an anchor
352
352
  ## preset, and the inspector offers anchors only in Anchors mode, so writing one puts it there
353
- ## first, as picking a preset in the editor does; alsoChanged then names layout_mode.
353
+ ## first, as picking a preset in the editor does, and alsoChanged then names layout_mode.
354
354
  func _laid_out(control: Control, name: String) -> String:
355
355
  var base: String = name.get_slice(":", 0)
356
356
  var anchoring: bool = base == "anchors_preset" or base.begins_with("anchor_")
@@ -454,7 +454,7 @@ func _write(target: Object, key: String, value: Variant) -> void:
454
454
 
455
455
 
456
456
  ## The declaration the last step of [param path] would have, typed as the component it reaches, so
457
- ## a fraction for an integer vector's axis is refused as one for an int property is; or
457
+ ## a fraction for an integer vector's axis is refused as one for an int property is, or
458
458
  ## {"refused": why} for the first step that is not there.
459
459
  func _component_slot(target: Object, path: String) -> Dictionary:
460
460
  var steps: PackedStringArray = path.split(":")
@@ -494,7 +494,7 @@ func _component_slot(target: Object, path: String) -> Dictionary:
494
494
  return {
495
495
  "refused":
496
496
  (
497
- "%s.%s is %s, so it has no %s; it has %s."
497
+ "%s.%s is %s, so it has no %s. It has %s."
498
498
  % [owner, walked, sort, step, ", ".join(has)]
499
499
  ),
500
500
  }
@@ -569,7 +569,7 @@ func value_for(target: Object, declared: Dictionary, raw: Variant) -> Array:
569
569
 
570
570
 
571
571
  ## A property holding a Node is given the node the path leads to from [param target], as the
572
- ## editor's inspector gives it; the scene is saved with the path. A res:// path could never name a
572
+ ## editor's inspector gives it. The scene is saved with the path. A res:// path could never name a
573
573
  ## node, so the remedy a caller is given is a node path.
574
574
  func _node_reference(target: Object, property: String, raw: Variant) -> Array:
575
575
  if raw == null:
@@ -746,7 +746,7 @@ func colour_from(raw: Variant, named: String) -> Array:
746
746
  (
747
747
  (
748
748
  '%s is {"r": .., "g": .., "b": .., "a": ..} from 0 to 1, a optional, or an html '
749
- + 'code such as "#ff8000" or "#ff800080"; %s is neither.'
749
+ + 'code such as "#ff8000" or "#ff800080". %s is neither.'
750
750
  )
751
751
  % [named, JSON.stringify(raw)]
752
752
  ),
@@ -898,7 +898,7 @@ func _parse_resource_tag(value: Dictionary) -> Array:
898
898
  )
899
899
  return [true, null]
900
900
  # A plain Resource with a script or values of its own, as a read answers one built into a scene,
901
- # is one to build; taken as nothing, writing such a read back cleared the property.
901
+ # is one to build. Taken as nothing, writing such a read back cleared the property.
902
902
  if value.size() > 1:
903
903
  return _parse_new_resource("Resource", value)
904
904
  return [true, null]
@@ -139,7 +139,7 @@ static func from_the_root(said: String, node_path: String, root_name: String) ->
139
139
 
140
140
  ## [param said], the refusal for a path a scene does not have, with where the path leaves it: the
141
141
  ## last node of the path it has, [param reached] from the root, called [param root_name], when that
142
- ## is empty; the name below it that is missing; and [param children], the names that node has, as
142
+ ## is empty, the name below it that is missing, and [param children], the names that node has, as
143
143
  ## after a node was moved or renamed. Names up to [constant NAMED_CHILDREN] of them.
144
144
  static func missing_below(
145
145
  said: String,
@@ -152,17 +152,21 @@ static func missing_below(
152
152
  if children.size() > NAMED_CHILDREN:
153
153
  shown += " and %d more" % (children.size() - NAMED_CHILDREN)
154
154
  return (
155
- "%s%s %s has no %s; %s."
155
+ "%s %s has no %s. %s."
156
156
  % [
157
- said,
158
- "" if said.ends_with(".") else ".",
157
+ ended(said),
159
158
  "The root, %s," % root_name if reached.is_empty() else "/".join(reached),
160
159
  missing,
161
- "its children are " + shown if not children.is_empty() else "it has no children",
160
+ "Its children are " + shown if not children.is_empty() else "It has no children",
162
161
  ]
163
162
  )
164
163
 
165
164
 
165
+ ## [param said] with a full stop at its end, so another sentence can follow it.
166
+ static func ended(said: String) -> String:
167
+ return said if said.ends_with(".") else said + "."
168
+
169
+
166
170
  ## [param said], the refusal for a [param kind] the scene does not have at [param node_path], with
167
171
  ## what is there when the scene has a node there, [param found] its class, and [param holders], the
168
172
  ## paths of the nodes in the scene that are one, so the caller has the path to pass. Names up to
@@ -180,7 +184,7 @@ static func not_of_kind(
180
184
  return (
181
185
  told
182
186
  + (
183
- " The scene holds no %s; scene_node add with nodeType %s puts one in it."
187
+ " The scene holds no %s. scene_node add with nodeType %s puts one in it."
184
188
  % [kind, kind]
185
189
  )
186
190
  )
@@ -222,17 +226,17 @@ static func offered(said: String, word: String, names: Array) -> String:
222
226
  var every: PackedStringArray = PackedStringArray(names)
223
227
  var close: PackedStringArray = nearest(word, every)
224
228
  if close.is_empty():
225
- return "%s; it has %s" % [said, ", ".join(every)]
229
+ return "%s It has %s" % [ended(said), ", ".join(every)]
226
230
  return (
227
- "%s; the nearest it has %s %s"
228
- % [said, "is" if close.size() == 1 else "are", ", ".join(close)]
231
+ "%s The nearest it has %s %s"
232
+ % [ended(said), "is" if close.size() == 1 else "are", ", ".join(close)]
229
233
  )
230
234
 
231
235
 
232
236
  ## [param said], the refusal for [param property], which [param target] does not declare, with the
233
237
  ## names it declares nearest it when any are, as a misspelt one is usually one of them, or else the
234
238
  ## variables its script declares. The engine's own are not listed when none is near, since an object
235
- ## has a hundred, while a script's are the few a caller most likely meant; an object with no script
239
+ ## has a hundred, while a script's are the few a caller most likely meant. An object with no script
236
240
  ## is told where they are listed instead, since the refusal alone left nothing to try.
237
241
  static func near_property(said: String, target: Object, property: String) -> String:
238
242
  var headings: int = PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP
@@ -243,7 +247,7 @@ static func near_property(said: String, target: Object, property: String) -> Str
243
247
  if usage & PROPERTY_USAGE_ARRAY:
244
248
  var listed: String = _list_called(target, declared, property)
245
249
  if not listed.is_empty():
246
- return "%s; %s" % [said, listed]
250
+ return "%s %s" % [ended(said), listed]
247
251
  if not usage & headings:
248
252
  names.append(str(declared.get("name", "")))
249
253
  if usage & PROPERTY_USAGE_SCRIPT_VARIABLE and not usage & headings:
@@ -251,8 +255,8 @@ static func near_property(said: String, target: Object, property: String) -> Str
251
255
  var close: PackedStringArray = nearest(property, PackedStringArray(names))
252
256
  if not close.is_empty():
253
257
  return (
254
- "%s; the nearest it has %s %s"
255
- % [said, "is" if close.size() == 1 else "are", ", ".join(close)]
258
+ "%s The nearest it has %s %s"
259
+ % [ended(said), "is" if close.size() == 1 else "are", ", ".join(close)]
256
260
  )
257
261
  # With a script that declares nothing readable, as one that does not compile, the name is
258
262
  # likelier the script's than the class's, so the class's list would point the wrong way.
@@ -261,17 +265,17 @@ static func near_property(said: String, target: Object, property: String) -> Str
261
265
  if scripted.is_empty():
262
266
  return (
263
267
  (
264
- "%s; editor_classes info with className %s and includeInherited true lists the "
268
+ "%s editor_classes info with className %s and includeInherited true lists the "
265
269
  + "ones it has"
266
270
  )
267
- % [said, target.get_class()]
271
+ % [ended(said), target.get_class()]
268
272
  )
269
273
  scripted.sort()
270
- return "%s; its script declares %s" % [said, ", ".join(PackedStringArray(scripted))]
274
+ return "%s Its script declares %s" % [ended(said), ", ".join(PackedStringArray(scripted))]
271
275
 
272
276
 
273
277
  ## How [param target] keeps the list [param property] names, when that is the label of one of the
274
- ## engine's numbered lists, such as an OptionButton's Items; empty when it is not. The engine has no
278
+ ## engine's numbered lists, such as an OptionButton's Items. Empty when it is not. The engine has no
275
279
  ## property by that name, only a count and each entry's fields under a numbered prefix, so "items"
276
280
  ## was refused with nothing near it to offer.
277
281
  static func _list_called(target: Object, count: Dictionary, property: String) -> String:
@@ -292,7 +296,7 @@ static func _list_called(target: Object, count: Dictionary, property: String) ->
292
296
  )
293
297
  return (
294
298
  (
295
- "it keeps its %s as %s, how many there are, and %s under %s for the first, %s for the "
299
+ "It keeps its %s as %s, how many there are, and %s under %s for the first, %s for the "
296
300
  + "second and so on: give %s before the fields of the entries it makes"
297
301
  )
298
302
  % [parts[0].to_lower(), counted, each, first, parts[1] + "1/", counted]
@@ -599,7 +599,7 @@ func fixed(node: Node, deleting: bool = false) -> String:
599
599
  if node.owner == null:
600
600
  return foreign(node)
601
601
  if node.owner != root:
602
- # Editable children keep values here and no more; the scene instanced may have the node from
602
+ # Editable children keep values here and no more. The scene instanced may have the node from
603
603
  # a scene it inherits, which is the one to edit.
604
604
  var instanced: String = node.owner.scene_file_path
605
605
  var packed: PackedScene = load(instanced) as PackedScene
@@ -624,7 +624,7 @@ func fixed(node: Node, deleting: bool = false) -> String:
624
624
 
625
625
 
626
626
  ## Each node the scenes [param state] inherits give it, by path, with the deepest file making it
627
- ## more than values; a node [param state] makes itself is not in it.
627
+ ## more than values. A node [param state] makes itself is not in it.
628
628
  static func makers(state: SceneState) -> Dictionary:
629
629
  var made_by: Dictionary = {}
630
630
  var at: SceneState = state.get_base_scene_state()
@@ -764,7 +764,7 @@ static func unfit_name(node_name: String) -> String:
764
764
  if valid != node_name:
765
765
  return (
766
766
  (
767
- "%s is not a name a node can have; Godot would save it as %s. The characters "
767
+ "%s is not a name a node can have. Godot would save it as %s. The characters "
768
768
  + '. : @ / " %% cannot be in a node name.'
769
769
  )
770
770
  % [node_name, valid]
@@ -784,7 +784,7 @@ func unusable_name(parent: Node, child_name: String, moving: Node = null) -> Str
784
784
  # The root by its name, since its path is ".", and ". already has a child" read as a typo.
785
785
  var holder: String = "The root, %s," % parent.name if parent == root else path_of(parent)
786
786
  return (
787
- "%s already has a child named %s; %s is free there."
787
+ "%s already has a child named %s. %s is free there."
788
788
  % [holder, child_name, _free_name(parent, child_name)]
789
789
  )
790
790
  return ""
@@ -1210,7 +1210,7 @@ func _stray_text(node: Node, name: String) -> String:
1210
1210
  (
1211
1211
  (
1212
1212
  "the script of %s did not start when a headless engine instanced %s, so the "
1213
- + "node would be saved without it; the engine's messages give its errors. "
1213
+ + "node would be saved without it. The engine's messages give its errors. "
1214
1214
  )
1215
1215
  % [at, path]
1216
1216
  )
@@ -15,7 +15,7 @@ const GdhShapes = preload("value_shapes.gd")
15
15
  const NUMBERS: Array[int] = [TYPE_BOOL, TYPE_INT, TYPE_FLOAT]
16
16
  const TEXTS: Array[int] = [TYPE_STRING, TYPE_STRING_NAME, TYPE_NODE_PATH]
17
17
  # 2^53. A JSON number is a double, and every whole number below this one in size has a double of
18
- # its own; from here on two or more share each double, so one arriving tells nobody which was sent.
18
+ # its own. From here on two or more share each double, so one arriving tells nobody which was sent.
19
19
  const EXACT: int = 9_007_199_254_740_992
20
20
  # The types that cross as a plain JSON list and have to be built back into themselves. A list is
21
21
  # what a caller can write by hand and what the serialiser answers with, and the parameter or
@@ -136,7 +136,7 @@ func serialize_value(value: Variant) -> Variant:
136
136
  return value
137
137
  var carried: Variant = call(serialiser, value)
138
138
  # The fixed shapes carry their components as bare floats, so an infinite one in a Vector2 is
139
- # tagged here, and a 32-bit one shortened; containers reach their members through this already.
139
+ # tagged here, and a 32-bit one shortened. Containers reach their members through this already.
140
140
  var type: int = typeof(value)
141
141
  return (
142
142
  carried
@@ -345,7 +345,7 @@ static func comparable(one: Variant, other: Variant) -> bool:
345
345
  ##
346
346
  ## A list of what is accepted rather than of what is refused, which is the way round that errs
347
347
  ## safely. The engine's own conversion table is not readable from GDScript, so either list is a
348
- ## guess at it; guessing narrow costs a caller a refusal naming both types, and guessing wide costs
348
+ ## guess at it. Guessing narrow costs a caller a refusal naming both types, and guessing wide costs
349
349
  ## them the damage above. A refusal is the cheaper mistake, and it is the one they can act on.
350
350
  static func acceptable(value: Variant, type: int) -> bool:
351
351
  if type == TYPE_NIL:
@@ -560,7 +560,7 @@ func _serialize_rid(value: RID) -> Dictionary:
560
560
 
561
561
  # A whole number from 2^53 on as its digits, because JSON numbers are doubles on the server's side
562
562
  # and on the engine's, and from there on neighbouring whole numbers share a double. A RefCounted's
563
- # instance id is one, with its top bit set, and a resource uid another; read as numbers they came
563
+ # instance id is one, with its top bit set, and a resource uid another. Read as numbers they came
564
564
  # back as a neighbouring id, which named nothing or something else.
565
565
  func _serialize_int(value: int) -> Variant:
566
566
  if value > -EXACT and value < EXACT:
@@ -93,7 +93,7 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
93
93
  if not advances.has(advance_mode):
94
94
  return {
95
95
  "ok": false,
96
- "error": "Unsupported advanceMode: %s; it is auto, enabled or disabled" % advance_mode,
96
+ "error": "Unsupported advanceMode: %s. It is auto, enabled or disabled" % advance_mode,
97
97
  }
98
98
  if not advance_condition.is_empty() and advance_mode != "auto":
99
99
  return {
@@ -189,10 +189,10 @@ static func _no_state(sm: AnimationNodeStateMachine, state_name: String) -> Stri
189
189
  var close: PackedStringArray = GdhRead.nearest(state_name, states)
190
190
  if not close.is_empty():
191
191
  return (
192
- "%s; the nearest it has %s %s."
192
+ "%s. The nearest it has %s %s."
193
193
  % [said, "is" if close.size() == 1 else "are", ", ".join(close)]
194
194
  )
195
- return "%s; its states are %s." % [said, ", ".join(states)]
195
+ return "%s. Its states are %s." % [said, ", ".join(states)]
196
196
 
197
197
 
198
198
  ## The state machine [param args] names, as [scene, machine, files, refusal, tree]: the machine is
@@ -276,9 +276,9 @@ func disconnect_animation_states(args: Dictionary) -> Dictionary:
276
276
  var _listed: bool = leaving.append(str(sm.get_transition_to(index)))
277
277
  var said: String = "There is no transition from %s to %s" % [from_state, to_state]
278
278
  if leaving.is_empty():
279
- return scene.refuse("%s; none leaves %s." % [said, from_state])
279
+ return scene.refuse("%s. None leaves %s." % [said, from_state])
280
280
  return scene.refuse(
281
- "%s; the ones leaving %s go to %s." % [said, from_state, ", ".join(leaving)]
281
+ "%s. The ones leaving %s go to %s." % [said, from_state, ", ".join(leaving)]
282
282
  )
283
283
  sm.remove_transition(StringName(from_state), StringName(to_state))
284
284
  if sm.has_transition(StringName(from_state), StringName(to_state)):