gdharness 1.3.42 → 1.3.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cli.js +383 -243
- package/build/godot/addons/auto_reload/auto_reload.gd +18 -19
- package/build/godot/addons/gdharness_editor/animation_reads.gd +55 -33
- package/build/godot/addons/gdharness_editor/bridge_client.gd +53 -58
- package/build/godot/addons/gdharness_editor/declared_values.gd +68 -32
- package/build/godot/addons/gdharness_editor/file_reads.gd +83 -42
- package/build/godot/addons/gdharness_editor/file_walk.gd +12 -5
- package/build/godot/addons/gdharness_editor/headless_check.gd +68 -44
- package/build/godot/addons/gdharness_editor/plugin.gd +2 -3
- package/build/godot/addons/gdharness_editor/property_paths.gd +22 -12
- package/build/godot/addons/gdharness_editor/property_values.gd +143 -78
- package/build/godot/addons/gdharness_editor/reading.gd +51 -17
- package/build/godot/addons/gdharness_editor/same_values.gd +4 -4
- package/build/godot/addons/gdharness_editor/scene_file.gd +127 -80
- package/build/godot/addons/gdharness_editor/scene_uids.gd +12 -6
- package/build/godot/addons/gdharness_editor/serialisation.gd +75 -51
- package/build/godot/addons/gdharness_editor/setting_reads.gd +7 -6
- package/build/godot/addons/gdharness_editor/tool_executor.gd +3 -6
- package/build/godot/addons/gdharness_editor/tools/animation_states.gd +37 -27
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +79 -49
- package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd +70 -40
- package/build/godot/addons/gdharness_editor/tools/class_tools.gd +65 -42
- package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +24 -22
- package/build/godot/addons/gdharness_editor/tools/navigation_bake.gd +49 -29
- package/build/godot/addons/gdharness_editor/tools/play_tools.gd +26 -21
- package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +40 -40
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +166 -107
- package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +16 -9
- package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +68 -41
- package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +35 -20
- package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +28 -13
- package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd +12 -5
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +113 -67
- package/build/godot/addons/gdharness_editor/tools/script_paths.gd +20 -8
- package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +11 -8
- package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +47 -34
- package/build/godot/addons/gdharness_editor/tools/tileset_tools.gd +77 -50
- package/build/godot/addons/gdharness_editor/value_shapes.gd +5 -6
- package/build/godot/addons/gdharness_runtime/call_errors.gd +1 -2
- package/build/godot/addons/gdharness_runtime/declared_values.gd +68 -32
- package/build/godot/addons/gdharness_runtime/error_report.gd +1 -2
- package/build/godot/addons/gdharness_runtime/reading.gd +51 -17
- package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +84 -63
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +149 -147
- package/build/godot/addons/gdharness_runtime/runtime_capture.gd +64 -42
- package/build/godot/addons/gdharness_runtime/runtime_changes.gd +184 -122
- package/build/godot/addons/gdharness_runtime/runtime_frames.gd +2 -2
- package/build/godot/addons/gdharness_runtime/runtime_hover.gd +24 -20
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +134 -92
- package/build/godot/addons/gdharness_runtime/runtime_items.gd +29 -13
- package/build/godot/addons/gdharness_runtime/runtime_menus.gd +0 -1
- package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +34 -17
- package/build/godot/addons/gdharness_runtime/runtime_pad.gd +17 -13
- package/build/godot/addons/gdharness_runtime/runtime_paths.gd +84 -46
- package/build/godot/addons/gdharness_runtime/runtime_queries.gd +117 -79
- package/build/godot/addons/gdharness_runtime/runtime_says.gd +14 -17
- package/build/godot/addons/gdharness_runtime/runtime_screen.gd +23 -16
- package/build/godot/addons/gdharness_runtime/runtime_targets.gd +117 -66
- package/build/godot/addons/gdharness_runtime/runtime_touch.gd +15 -15
- package/build/godot/addons/gdharness_runtime/runtime_typing.gd +44 -27
- package/build/godot/addons/gdharness_runtime/runtime_values.gd +108 -73
- package/build/godot/addons/gdharness_runtime/runtime_waits.gd +111 -84
- package/build/godot/addons/gdharness_runtime/runtime_words.gd +10 -7
- package/build/godot/addons/gdharness_runtime/serialisation.gd +75 -51
- package/build/godot/addons/gdharness_runtime/value_shapes.gd +5 -6
- package/build/godot/addons/gdharness_tests/bench.gd +4 -5
- package/build/godot/addons/gdharness_tests/event.gd +10 -5
- package/build/godot/addons/gdharness_tests/share.gd +38 -18
- package/build/godot/addons/gdharness_tests/suites.gd +3 -3
- package/build/godot/addons/gdharness_tests/wait.gd +3 -2
- package/build/godot/loader/loader.gd +9 -9
- package/build/godot/operations/animation_reads.gd +55 -33
- package/build/godot/operations/audio_buses.gd +48 -19
- package/build/godot/operations/class_cache.gd +16 -11
- package/build/godot/operations/classdb_queries.gd +89 -44
- package/build/godot/operations/declared_values.gd +68 -32
- package/build/godot/operations/dependencies.gd +190 -109
- package/build/godot/operations/editor_tools.gd +10 -10
- package/build/godot/operations/export_presets.gd +100 -54
- package/build/godot/operations/file_reads.gd +83 -42
- package/build/godot/operations/file_walk.gd +12 -5
- package/build/godot/operations/gdscript_analysis.gd +86 -65
- package/build/godot/operations/gdscript_authoring.gd +83 -36
- package/build/godot/operations/godot_operations.gd +17 -11
- package/build/godot/operations/import_pipeline.gd +110 -59
- package/build/godot/operations/input_actions.gd +62 -39
- package/build/godot/operations/patterns.gd +3 -1
- package/build/godot/operations/plugins.gd +36 -16
- package/build/godot/operations/project_config.gd +61 -32
- package/build/godot/operations/project_diagnostics.gd +24 -11
- package/build/godot/operations/project_file.gd +16 -16
- package/build/godot/operations/project_validation.gd +71 -44
- package/build/godot/operations/property_paths.gd +22 -12
- package/build/godot/operations/property_values.gd +143 -78
- package/build/godot/operations/reading.gd +51 -17
- package/build/godot/operations/rename_checks.gd +2 -2
- package/build/godot/operations/resource_files.gd +11 -9
- package/build/godot/operations/same_values.gd +4 -4
- package/build/godot/operations/scene_connections.gd +27 -13
- package/build/godot/operations/script_check.gd +52 -49
- package/build/godot/operations/serialisation.gd +75 -51
- package/build/godot/operations/setting_reads.gd +7 -6
- package/build/godot/operations/value_shapes.gd +5 -6
- package/build/godot/tests/listed.gd +321 -268
- package/build/keeper.js +43 -43
- package/package.json +1 -1
|
@@ -3,10 +3,8 @@ extends RefCounted
|
|
|
3
3
|
const GdhRead = preload("reading.gd")
|
|
4
4
|
const GdhLog = preload("logger.gd")
|
|
5
5
|
const GdhSerialisation = preload("serialisation.gd")
|
|
6
|
-
|
|
7
6
|
# How far below the closest name another may score and still be offered beside it.
|
|
8
7
|
const CLOSE_TO_THE_BEST: float = 0.2
|
|
9
|
-
|
|
10
8
|
# The base classes each category name stands for. Kept to the list the tool's schema offers, which
|
|
11
9
|
# a case holds: the schema offered physics3d and ui, which this refused, and physics answered the 3D
|
|
12
10
|
# bodies alone beside physics2d and physics3d.
|
|
@@ -74,7 +72,9 @@ func query_classes(params: Dictionary) -> Dictionary:
|
|
|
74
72
|
if not category.is_empty():
|
|
75
73
|
bases = CATEGORY_BASES.get(category.to_lower(), [])
|
|
76
74
|
if bases.is_empty():
|
|
77
|
-
return _log.failure(
|
|
75
|
+
return _log.failure(
|
|
76
|
+
"Unknown category: " + category + ". Valid: " + str(CATEGORY_BASES.keys())
|
|
77
|
+
)
|
|
78
78
|
|
|
79
79
|
var all_classes: PackedStringArray = ClassDB.get_class_list()
|
|
80
80
|
all_classes.sort()
|
|
@@ -107,7 +107,13 @@ func query_classes(params: Dictionary) -> Dictionary:
|
|
|
107
107
|
own.append(_project_entry(name, declared))
|
|
108
108
|
|
|
109
109
|
_log.info(
|
|
110
|
-
|
|
110
|
+
(
|
|
111
|
+
"Found "
|
|
112
|
+
+ str(filtered_classes.size())
|
|
113
|
+
+ " classes (out of "
|
|
114
|
+
+ str(all_classes.size())
|
|
115
|
+
+ " total)"
|
|
116
|
+
)
|
|
111
117
|
)
|
|
112
118
|
|
|
113
119
|
return {
|
|
@@ -127,7 +133,13 @@ func query_class_info(params: Dictionary) -> Dictionary:
|
|
|
127
133
|
var include_inherited: bool = GdhRead.as_bool(params.get("include_inherited", false))
|
|
128
134
|
|
|
129
135
|
_log.info(
|
|
130
|
-
|
|
136
|
+
(
|
|
137
|
+
"Querying class info for: "
|
|
138
|
+
+ class_name_str
|
|
139
|
+
+ " (include_inherited: "
|
|
140
|
+
+ str(include_inherited)
|
|
141
|
+
+ ")"
|
|
142
|
+
)
|
|
131
143
|
)
|
|
132
144
|
|
|
133
145
|
if not ClassDB.class_exists(class_name_str):
|
|
@@ -171,7 +183,7 @@ func query_class_info(params: Dictionary) -> Dictionary:
|
|
|
171
183
|
"properties": properties,
|
|
172
184
|
"signals_count": signals.size(),
|
|
173
185
|
"signals": signals,
|
|
174
|
-
"enums": enums
|
|
186
|
+
"enums": enums,
|
|
175
187
|
}
|
|
176
188
|
if include_inherited:
|
|
177
189
|
answer["inherited"] = _inherited_names(class_name_str)
|
|
@@ -283,24 +295,28 @@ static func _project_entry(name: String, declared: Dictionary) -> Dictionary:
|
|
|
283
295
|
|
|
284
296
|
## Why [param wanted] has no answer here. A class_name a project script declares is not in ClassDB,
|
|
285
297
|
## and "Class not found" for one read as though the project had no such class. [param declared] is
|
|
286
|
-
## what the project's scripts declare on disk, class to path, rather than the engine's list, which
|
|
287
|
-
## the class cache: that lags the scripts, and a class written a moment ago was refused as
|
|
288
|
-
## nowhere.
|
|
298
|
+
## what the project's scripts declare on disk, class to path, rather than the engine's list, which
|
|
299
|
+
## is the class cache: that lags the scripts, and a class written a moment ago was refused as
|
|
300
|
+
## declared nowhere.
|
|
289
301
|
func _not_found(wanted: String, declared: Dictionary, answers_own: bool = false) -> Dictionary:
|
|
290
302
|
if declared.has(wanted):
|
|
291
|
-
return
|
|
292
|
-
|
|
303
|
+
return (
|
|
304
|
+
_log
|
|
305
|
+
. failure(
|
|
293
306
|
(
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
307
|
+
(
|
|
308
|
+
"%s is not an engine class: it is the class_name %s declares, and "
|
|
309
|
+
+ "editor_classes reads the engine's ClassDB only. script_info structure "
|
|
310
|
+
+ "on that script, with includeInherited, answers what it declares and "
|
|
311
|
+
+ "what it inherits."
|
|
312
|
+
)
|
|
313
|
+
% [wanted, str(_entry_of(wanted, declared).get("path", ""))]
|
|
297
314
|
)
|
|
298
|
-
% [wanted, str(_entry_of(wanted, declared).get("path", ""))]
|
|
299
315
|
)
|
|
300
316
|
)
|
|
301
|
-
# The usual miss is a spelling, one letter off a class the engine has or one the project
|
|
302
|
-
# Ranked as one pool and kept near the best, since a project class a letter off came
|
|
303
|
-
# engine classes that shared only "Texture" with it.
|
|
317
|
+
# The usual miss is a spelling, one letter off a class the engine has or one the project
|
|
318
|
+
# declares. Ranked as one pool and kept near the best, since a project class a letter off came
|
|
319
|
+
# behind three engine classes that shared only "Texture" with it.
|
|
304
320
|
var pool: PackedStringArray = ClassDB.get_class_list()
|
|
305
321
|
pool.append_array(PackedStringArray(declared.keys()))
|
|
306
322
|
var close: PackedStringArray = GdhRead.nearest(wanted, pool)
|
|
@@ -310,8 +326,9 @@ func _not_found(wanted: String, declared: Dictionary, answers_own: bool = false)
|
|
|
310
326
|
for name: String in close:
|
|
311
327
|
if name.to_lower().similarity(wanted.to_lower()) < best - CLOSE_TO_THE_BEST:
|
|
312
328
|
continue
|
|
313
|
-
# Similarity counts shared letter pairs, so a word the two names share passes it:
|
|
314
|
-
# was offered ClassDB. A spelling is a few letters off, a swap of two among
|
|
329
|
+
# Similarity counts shared letter pairs, so a word the two names share passes it:
|
|
330
|
+
# NoSuchClass was offered ClassDB. A spelling is a few letters off, a swap of two among
|
|
331
|
+
# them.
|
|
315
332
|
if _edits(name.to_lower(), wanted.to_lower()) > maxi(2, floori(wanted.length() / 3.0)):
|
|
316
333
|
continue
|
|
317
334
|
if declared.has(name):
|
|
@@ -338,15 +355,22 @@ func _not_found(wanted: String, declared: Dictionary, answers_own: bool = false)
|
|
|
338
355
|
)
|
|
339
356
|
if answers_own:
|
|
340
357
|
return _log.failure(
|
|
341
|
-
|
|
358
|
+
(
|
|
359
|
+
"Class not found: %s.%s Neither the engine nor a project script declares it."
|
|
360
|
+
% [wanted, offered]
|
|
361
|
+
)
|
|
342
362
|
)
|
|
343
|
-
return
|
|
344
|
-
|
|
363
|
+
return (
|
|
364
|
+
_log
|
|
365
|
+
. failure(
|
|
345
366
|
(
|
|
346
|
-
|
|
347
|
-
|
|
367
|
+
(
|
|
368
|
+
"Class not found: %s.%s editor_classes reads the engine's ClassDB, so a "
|
|
369
|
+
+ "class_name a project script declares is not in it either; script_info "
|
|
370
|
+
+ "structure reads one."
|
|
371
|
+
)
|
|
372
|
+
% [wanted, offered]
|
|
348
373
|
)
|
|
349
|
-
% [wanted, offered]
|
|
350
374
|
)
|
|
351
375
|
)
|
|
352
376
|
|
|
@@ -358,7 +382,9 @@ static func _edits(from: String, to: String) -> int:
|
|
|
358
382
|
var here: PackedInt32Array = PackedInt32Array([row])
|
|
359
383
|
for column: int in range(1, to.length() + 1):
|
|
360
384
|
var changed: int = above[column - 1] + (0 if from[row - 1] == to[column - 1] else 1)
|
|
361
|
-
var _added: bool = here.append(
|
|
385
|
+
var _added: bool = here.append(
|
|
386
|
+
mini(changed, mini(above[column] + 1, here[column - 1] + 1))
|
|
387
|
+
)
|
|
362
388
|
above = here
|
|
363
389
|
return above[to.length()]
|
|
364
390
|
|
|
@@ -376,39 +402,49 @@ func _member_of(class_name_str: String, member: String) -> Dictionary:
|
|
|
376
402
|
while not current.is_empty():
|
|
377
403
|
for m: Dictionary in _methods_of(current):
|
|
378
404
|
if m["name"] == member:
|
|
379
|
-
found.append({"kind": "method", "declared_in": current, "member": m})
|
|
405
|
+
found.append({ "kind": "method", "declared_in": current, "member": m })
|
|
380
406
|
for p: Dictionary in _properties_of(current):
|
|
381
407
|
if p["name"] == member:
|
|
382
|
-
found.append({"kind": "property", "declared_in": current, "member": p})
|
|
408
|
+
found.append({ "kind": "property", "declared_in": current, "member": p })
|
|
383
409
|
for s: Dictionary in _signals_of(current):
|
|
384
410
|
if s["name"] == member:
|
|
385
|
-
found.append({"kind": "signal", "declared_in": current, "member": s})
|
|
411
|
+
found.append({ "kind": "signal", "declared_in": current, "member": s })
|
|
386
412
|
for e: String in ClassDB.class_get_enum_list(current, true):
|
|
387
413
|
if e == member:
|
|
388
414
|
var values: Dictionary = {}
|
|
389
415
|
for c: String in ClassDB.class_get_enum_constants(current, e, true):
|
|
390
416
|
values[c] = ClassDB.class_get_integer_constant(current, c)
|
|
391
417
|
found.append(
|
|
392
|
-
{
|
|
418
|
+
{
|
|
419
|
+
"kind": "enum",
|
|
420
|
+
"declared_in": current,
|
|
421
|
+
"member": { "name": e, "values": values },
|
|
422
|
+
}
|
|
393
423
|
)
|
|
394
424
|
for c: String in ClassDB.class_get_integer_constant_list(current, true):
|
|
395
425
|
if c == member:
|
|
396
426
|
var value: int = ClassDB.class_get_integer_constant(current, c)
|
|
397
427
|
found.append(
|
|
398
|
-
{
|
|
428
|
+
{
|
|
429
|
+
"kind": "constant",
|
|
430
|
+
"declared_in": current,
|
|
431
|
+
"member": { "name": c, "value": value },
|
|
432
|
+
}
|
|
399
433
|
)
|
|
400
434
|
current = ClassDB.get_parent_class(current)
|
|
401
435
|
|
|
402
436
|
if found.is_empty():
|
|
403
437
|
var alike: Array[String] = _members_alike(class_name_str, member)
|
|
404
438
|
var hint: String = (
|
|
405
|
-
""
|
|
439
|
+
""
|
|
440
|
+
if alike.is_empty()
|
|
441
|
+
else " Members with names containing it: " + ", ".join(alike) + "."
|
|
406
442
|
)
|
|
407
443
|
return _log.failure(
|
|
408
444
|
"%s and its ancestors declare no member named %s.%s" % [class_name_str, member, hint]
|
|
409
445
|
)
|
|
410
446
|
|
|
411
|
-
return {"class_name": class_name_str, "member": member, "found": found}
|
|
447
|
+
return { "class_name": class_name_str, "member": member, "found": found }
|
|
412
448
|
|
|
413
449
|
|
|
414
450
|
# The names, across a class and its ancestors, that contain the asked-for one, case-insensitively.
|
|
@@ -531,7 +567,7 @@ func _methods_of(class_name_str: String) -> Array[Dictionary]:
|
|
|
531
567
|
"type": a.get("type", 0),
|
|
532
568
|
"type_name": _type_name(a, "Variant"),
|
|
533
569
|
"class_name": a.get("class_name", ""),
|
|
534
|
-
"hint_string": a.get("hint_string", "")
|
|
570
|
+
"hint_string": a.get("hint_string", ""),
|
|
535
571
|
}
|
|
536
572
|
)
|
|
537
573
|
var return_info: Dictionary = m.get("return", {})
|
|
@@ -545,13 +581,14 @@ func _methods_of(class_name_str: String) -> Array[Dictionary]:
|
|
|
545
581
|
{
|
|
546
582
|
"type": return_info.get("type", 0),
|
|
547
583
|
"type_name": _type_name(return_info, "void"),
|
|
548
|
-
"class_name": return_info.get("class_name", "")
|
|
584
|
+
"class_name": return_info.get("class_name", ""),
|
|
549
585
|
},
|
|
550
586
|
"flags": m.get("flags", 0),
|
|
551
587
|
"flag_names": _flag_names(GdhRead.as_int(m.get("flags", 0))),
|
|
552
|
-
# As values, tagged the way every other answer tags one: JSON writes a Vector2i
|
|
553
|
-
# handed as its text, so TileMapLayer.set_cell's default atlas coords read
|
|
554
|
-
"
|
|
588
|
+
# As values, tagged the way every other answer tags one: JSON writes a Vector2i
|
|
589
|
+
# it is handed as its text, so TileMapLayer.set_cell's default atlas coords read
|
|
590
|
+
# "(-1, -1)".
|
|
591
|
+
"default_args": _values.serialize_value(m.get("default_args", [])),
|
|
555
592
|
}
|
|
556
593
|
)
|
|
557
594
|
)
|
|
@@ -579,7 +616,11 @@ static func _type_name(info: Dictionary, nil_name: String) -> String:
|
|
|
579
616
|
if type == TYPE_OBJECT and not named.is_empty():
|
|
580
617
|
return named
|
|
581
618
|
if type == TYPE_NIL:
|
|
582
|
-
return
|
|
619
|
+
return (
|
|
620
|
+
"Variant"
|
|
621
|
+
if GdhRead.as_int(info.get("usage", 0)) & PROPERTY_USAGE_NIL_IS_VARIANT
|
|
622
|
+
else nil_name
|
|
623
|
+
)
|
|
583
624
|
return type_string(type)
|
|
584
625
|
|
|
585
626
|
|
|
@@ -589,7 +630,11 @@ func _properties_of(class_name_str: String) -> Array[Dictionary]:
|
|
|
589
630
|
for p: Dictionary in ClassDB.class_get_property_list(class_name_str, true):
|
|
590
631
|
# A category, group or subgroup is an editor heading rather than a property.
|
|
591
632
|
var usage: int = GdhRead.as_int(p.get("usage", 0))
|
|
592
|
-
if
|
|
633
|
+
if (
|
|
634
|
+
usage & PROPERTY_USAGE_CATEGORY
|
|
635
|
+
or usage & PROPERTY_USAGE_GROUP
|
|
636
|
+
or usage & PROPERTY_USAGE_SUBGROUP
|
|
637
|
+
):
|
|
593
638
|
continue
|
|
594
639
|
properties.append(
|
|
595
640
|
{
|
|
@@ -599,7 +644,7 @@ func _properties_of(class_name_str: String) -> Array[Dictionary]:
|
|
|
599
644
|
"class_name": p.get("class_name", ""),
|
|
600
645
|
"hint": p.get("hint", 0),
|
|
601
646
|
"hint_string": p.get("hint_string", ""),
|
|
602
|
-
"usage": usage
|
|
647
|
+
"usage": usage,
|
|
603
648
|
}
|
|
604
649
|
)
|
|
605
650
|
|
|
@@ -618,9 +663,9 @@ func _signals_of(class_name_str: String) -> Array[Dictionary]:
|
|
|
618
663
|
"name": a.get("name", ""),
|
|
619
664
|
"type": a.get("type", 0),
|
|
620
665
|
"type_name": _type_name(a, "Variant"),
|
|
621
|
-
"class_name": a.get("class_name", "")
|
|
666
|
+
"class_name": a.get("class_name", ""),
|
|
622
667
|
}
|
|
623
668
|
)
|
|
624
|
-
signals.append({"name": s.get("name", ""), "args": sig_args})
|
|
669
|
+
signals.append({ "name": s.get("name", ""), "args": sig_args })
|
|
625
670
|
|
|
626
671
|
return signals
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
@tool
|
|
2
2
|
extends RefCounted
|
|
3
|
-
|
|
4
3
|
## What a property declares beyond its type: the values of its enum and the range it is exported
|
|
5
4
|
## with, for taking a value by name and for saying when a value written lies outside them.
|
|
6
5
|
|
|
7
6
|
const GdhRead = preload("reading.gd")
|
|
8
|
-
|
|
9
7
|
## The section of layer_names in project.godot naming the layers of each layers hint.
|
|
10
8
|
const LAYER_NAMES: Dictionary[int, String] = {
|
|
11
9
|
PROPERTY_HINT_LAYERS_2D_PHYSICS: "2d_physics",
|
|
@@ -27,7 +25,7 @@ static func layers_in(hint: int, mask: int) -> Array[Dictionary]:
|
|
|
27
25
|
for layer: int in range(1, MASK_LAYERS + 1):
|
|
28
26
|
if mask & (1 << (layer - 1)) == 0:
|
|
29
27
|
continue
|
|
30
|
-
var entry: Dictionary = {"layer": layer}
|
|
28
|
+
var entry: Dictionary = { "layer": layer }
|
|
31
29
|
var name: String = str(
|
|
32
30
|
ProjectSettings.get_setting("layer_names/%s/layer_%d" % [LAYER_NAMES[hint], layer], "")
|
|
33
31
|
)
|
|
@@ -119,10 +117,12 @@ static func engine_constants(target: Object, property: String) -> Dictionary:
|
|
|
119
117
|
## names by it, as [true, number], or [false, why] naming the values, with [param holder] naming the
|
|
120
118
|
## target in the refusal. [false, ""] for a word that is a number, which converts as one.
|
|
121
119
|
##
|
|
122
|
-
## An enum is written by the name of a value as well as its number, since the name is what the
|
|
123
|
-
## and the inspector show and the number is only where the value happens to sit. Tried as the
|
|
124
|
-
## spells it, then as the hint does, then as the engine's constant.
|
|
125
|
-
static func enum_by_name(
|
|
120
|
+
## An enum is written by the name of a value as well as its number, since the name is what the
|
|
121
|
+
## script and the inspector show and the number is only where the value happens to sit. Tried as the
|
|
122
|
+
## script spells it, then as the hint does, then as the engine's constant.
|
|
123
|
+
static func enum_by_name(
|
|
124
|
+
target: Object, declared: Dictionary, word: String, holder: String
|
|
125
|
+
) -> Array:
|
|
126
126
|
var property: String = str(declared.get("name", ""))
|
|
127
127
|
var choices: Dictionary = enum_of(target, declared)
|
|
128
128
|
var chosen: Variant = enum_named(choices, word)
|
|
@@ -144,7 +144,9 @@ static func enum_refusal(
|
|
|
144
144
|
) -> String:
|
|
145
145
|
var ways: String = "by name or by number"
|
|
146
146
|
if not constants.is_empty():
|
|
147
|
-
ways =
|
|
147
|
+
ways = (
|
|
148
|
+
"by name, by number or by the engine's constant, such as %s" % str(constants.keys()[0])
|
|
149
|
+
)
|
|
148
150
|
var said: String = (
|
|
149
151
|
"%s.%s is an enum, and %s is none of its values: send %s %s"
|
|
150
152
|
% [holder, property, word, _listed(choices), ways]
|
|
@@ -163,7 +165,10 @@ static func enum_argument_refusal(
|
|
|
163
165
|
called: String, index: int, named: String, word: String, choices: Dictionary
|
|
164
166
|
) -> String:
|
|
165
167
|
var said: String = (
|
|
166
|
-
|
|
168
|
+
(
|
|
169
|
+
"%s takes the enum %s as argument %d, and %s is none of its values: send %s by name or "
|
|
170
|
+
+ "by number"
|
|
171
|
+
)
|
|
167
172
|
% [called, named, index + 1, word, _listed(choices)]
|
|
168
173
|
)
|
|
169
174
|
var close: PackedStringArray = GdhRead.nearest(word, PackedStringArray(choices.keys()))
|
|
@@ -174,7 +179,9 @@ static func enum_argument_refusal(
|
|
|
174
179
|
|
|
175
180
|
## Why [param value], given as argument [param index] for the enum [param named], is none of its
|
|
176
181
|
## [param choices], or "" when it is one. The engine passes any number on.
|
|
177
|
-
static func outside_enum_argument(
|
|
182
|
+
static func outside_enum_argument(
|
|
183
|
+
index: int, named: String, value: Variant, choices: Dictionary
|
|
184
|
+
) -> String:
|
|
178
185
|
if typeof(value) != TYPE_INT or choices.values().has(value):
|
|
179
186
|
return ""
|
|
180
187
|
return (
|
|
@@ -235,7 +242,10 @@ static func outside(target: Object, declared: Dictionary, value: Variant, shown:
|
|
|
235
242
|
var hint: int = GdhRead.as_int(declared.get("hint", PROPERTY_HINT_NONE))
|
|
236
243
|
var hint_string: String = str(declared.get("hint_string", ""))
|
|
237
244
|
var property: String = str(declared.get("name", ""))
|
|
238
|
-
if
|
|
245
|
+
if (
|
|
246
|
+
hint == PROPERTY_HINT_ENUM
|
|
247
|
+
and (typeof(value) == TYPE_STRING or typeof(value) == TYPE_STRING_NAME)
|
|
248
|
+
):
|
|
239
249
|
var names: PackedStringArray = PackedStringArray(enum_values(hint_string).keys())
|
|
240
250
|
if names.is_empty() or names.has(str(value)):
|
|
241
251
|
return ""
|
|
@@ -308,15 +318,17 @@ static func _listed(choices: Dictionary) -> String:
|
|
|
308
318
|
return ", ".join(listed)
|
|
309
319
|
|
|
310
320
|
|
|
311
|
-
## A range's end as the script wrote it: the engine's hint gives @export_range(0, 10) as 0.0 and
|
|
321
|
+
## A range's end as the script wrote it: the engine's hint gives @export_range(0, 10) as 0.0 and
|
|
322
|
+
## 10.0.
|
|
312
323
|
static func _bound(end: float) -> String:
|
|
313
324
|
return str(int(end)) if end == floorf(end) and absf(end) < 1e15 else str(end)
|
|
314
325
|
|
|
315
326
|
|
|
316
327
|
## Puts back on [param built] what its script set as it was attached and was not among
|
|
317
|
-
## [param wanted], to the defaults it declares, outside the editor. Attaching runs the script's
|
|
318
|
-
## there, which the editor never runs for a script that is not a tool, so a resource_name
|
|
319
|
-
## was saved as if asked for. A property whose default the engine cannot report is left
|
|
328
|
+
## [param wanted], to the defaults it declares, outside the editor. Attaching runs the script's
|
|
329
|
+
## _init there, which the editor never runs for a script that is not a tool, so a resource_name
|
|
330
|
+
## _init chose was saved as if asked for. A property whose default the engine cannot report is left
|
|
331
|
+
## as made.
|
|
320
332
|
static func unmade(built: Resource, wanted: Dictionary) -> void:
|
|
321
333
|
var attached: Variant = built.get_script()
|
|
322
334
|
if Engine.is_editor_hint() or not attached is Script:
|
|
@@ -445,17 +457,25 @@ static func runs_script_code(target: Object, name: String) -> bool:
|
|
|
445
457
|
## the buses are read from the AudioServer, which holds the project's layout; "the engine changed or
|
|
446
458
|
## refused the value" left a caller to guess the bus did not exist.
|
|
447
459
|
static func not_held(
|
|
448
|
-
holder: String,
|
|
460
|
+
holder: String,
|
|
461
|
+
engine_class: String,
|
|
462
|
+
property: String,
|
|
463
|
+
declared: Dictionary,
|
|
464
|
+
given: Array,
|
|
465
|
+
held: String
|
|
449
466
|
) -> String:
|
|
450
467
|
var value: Variant = given[0]
|
|
451
|
-
var said: String =
|
|
468
|
+
var said: String = (
|
|
469
|
+
"%s.%s was given %s and holds %s after it was set" % [holder, property, given[1], held]
|
|
470
|
+
)
|
|
452
471
|
var type: int = GdhRead.as_int(declared.get("type", TYPE_NIL))
|
|
453
472
|
var hint: int = GdhRead.as_int(declared.get("hint", PROPERTY_HINT_NONE))
|
|
454
473
|
if hint in LAYER_NAMES and typeof(value) == TYPE_INT:
|
|
455
474
|
return (
|
|
456
475
|
(
|
|
457
|
-
"%s: it is a mask of the %s layers, one bit each from layer 1 (1) to layer %d
|
|
458
|
-
+ "takes 0 to %d and the engine keeps only those bits. Nothing was
|
|
476
|
+
"%s: it is a mask of the %s layers, one bit each from layer 1 (1) to layer %d "
|
|
477
|
+
+ "(%d), so it takes 0 to %d and the engine keeps only those bits. Nothing was "
|
|
478
|
+
+ "written."
|
|
459
479
|
)
|
|
460
480
|
% [
|
|
461
481
|
said,
|
|
@@ -477,22 +497,28 @@ static func not_held(
|
|
|
477
497
|
return said + ": the engine changed or refused the value, so nothing was written."
|
|
478
498
|
var close: PackedStringArray = GdhRead.nearest(str(value), names)
|
|
479
499
|
var nearest: String = (
|
|
480
|
-
"%s %s" % ["is" if close.size() == 1 else "are", ", ".join(close)]
|
|
500
|
+
"%s %s" % ["is" if close.size() == 1 else "are", ", ".join(close)]
|
|
501
|
+
if not close.is_empty()
|
|
502
|
+
else ""
|
|
481
503
|
)
|
|
482
504
|
if bus:
|
|
483
505
|
# Not "holds Master after it was set": the getter answers the first bus for any name the
|
|
484
506
|
# layout lacks, and nothing was kept.
|
|
485
507
|
return (
|
|
486
508
|
(
|
|
487
|
-
"%s.bus takes the name of one of the project's audio buses, and %s is none of
|
|
488
|
-
+ "would play on %s; %s. project_info include audio_buses lists them,
|
|
489
|
-
+ "project_settings add_audio_bus adds one. Nothing was written."
|
|
509
|
+
"%s.bus takes the name of one of the project's audio buses, and %s is none of "
|
|
510
|
+
+ "them, so it would play on %s; %s. project_info include audio_buses lists them, "
|
|
511
|
+
+ "and project_settings add_audio_bus adds one. Nothing was written."
|
|
490
512
|
)
|
|
491
513
|
% [
|
|
492
514
|
holder,
|
|
493
515
|
given[1],
|
|
494
516
|
AudioServer.get_bus_name(0),
|
|
495
|
-
|
|
517
|
+
(
|
|
518
|
+
"the buses are " + ", ".join(names)
|
|
519
|
+
if nearest.is_empty()
|
|
520
|
+
else "the nearest " + nearest
|
|
521
|
+
),
|
|
496
522
|
]
|
|
497
523
|
)
|
|
498
524
|
return (
|
|
@@ -500,7 +526,11 @@ static func not_held(
|
|
|
500
526
|
% [
|
|
501
527
|
said,
|
|
502
528
|
given[1],
|
|
503
|
-
|
|
529
|
+
(
|
|
530
|
+
"it lists " + ", ".join(names)
|
|
531
|
+
if nearest.is_empty()
|
|
532
|
+
else "the nearest it lists " + nearest
|
|
533
|
+
),
|
|
504
534
|
]
|
|
505
535
|
)
|
|
506
536
|
|
|
@@ -513,7 +543,9 @@ static func held_by_children(node: Node, property: String) -> String:
|
|
|
513
543
|
var holders: PackedStringArray = []
|
|
514
544
|
for child: Node in node.get_children():
|
|
515
545
|
if property in child:
|
|
516
|
-
var _added: bool = holders.append(
|
|
546
|
+
var _added: bool = holders.append(
|
|
547
|
+
"%s (a %s)" % [root.get_path_to(child), child.get_class()]
|
|
548
|
+
)
|
|
517
549
|
if holders.is_empty():
|
|
518
550
|
return ""
|
|
519
551
|
if holders.size() == 1:
|
|
@@ -523,14 +555,15 @@ static func held_by_children(node: Node, property: String) -> String:
|
|
|
523
555
|
|
|
524
556
|
|
|
525
557
|
## A sentence for each node path in [param given], by property, that names no node from
|
|
526
|
-
## [param node]. A path is written whatever it names, as the inspector writes one, since the node
|
|
527
|
-
## be added next; a joint whose node_a named nothing then joined nothing, and no answer said so.
|
|
558
|
+
## [param node]. A path is written whatever it names, as the inspector writes one, since the node
|
|
559
|
+
## may be added next; a joint whose node_a named nothing then joined nothing, and no answer said so.
|
|
528
560
|
static func naming_nothing(node: Node, given: Dictionary) -> Dictionary:
|
|
529
561
|
var said: Dictionary = {}
|
|
530
562
|
for property: String in given:
|
|
531
563
|
if "/" in property or ":" in property:
|
|
532
564
|
continue
|
|
533
|
-
# What the node holds, since a path given as text is held as text until the engine stores
|
|
565
|
+
# What the node holds, since a path given as text is held as text until the engine stores
|
|
566
|
+
# it.
|
|
534
567
|
var path: Variant = node.get(property)
|
|
535
568
|
if not path is NodePath:
|
|
536
569
|
continue
|
|
@@ -539,8 +572,8 @@ static func naming_nothing(node: Node, given: Dictionary) -> Dictionary:
|
|
|
539
572
|
continue
|
|
540
573
|
said[property] = (
|
|
541
574
|
(
|
|
542
|
-
"%s names no node from %s. It is written, as the editor writes one, since that
|
|
543
|
-
+ "be added next; until it is, %s finds nothing."
|
|
575
|
+
"%s names no node from %s. It is written, as the editor writes one, since that "
|
|
576
|
+
+ "node may be added next; until it is, %s finds nothing."
|
|
544
577
|
)
|
|
545
578
|
% [str(named), node.name, property]
|
|
546
579
|
)
|
|
@@ -553,7 +586,10 @@ static func naming_nothing(node: Node, given: Dictionary) -> Dictionary:
|
|
|
553
586
|
static func no_uniform(material: ShaderMaterial, property: String) -> String:
|
|
554
587
|
var uniform: String = property.trim_prefix("shader_parameter/")
|
|
555
588
|
if material.shader == null:
|
|
556
|
-
return
|
|
589
|
+
return (
|
|
590
|
+
"The ShaderMaterial has no shader, so it has no parameter %s yet; set shader first."
|
|
591
|
+
% uniform
|
|
592
|
+
)
|
|
557
593
|
var shader: String = material.shader.resource_path
|
|
558
594
|
var named: String = shader if not shader.is_empty() else "Its shader"
|
|
559
595
|
var uniforms: Array = []
|