gdharness 1.3.41 → 1.3.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cli.js +131 -47
- package/build/godot/addons/auto_reload/auto_reload.gd +18 -19
- package/build/godot/addons/gdharness_editor/animation_reads.gd +84 -35
- 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 +114 -39
- package/build/godot/addons/gdharness_editor/file_walk.gd +12 -5
- package/build/godot/addons/gdharness_editor/headless_check.gd +94 -41
- 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 +37 -12
- package/build/godot/addons/gdharness_editor/same_values.gd +4 -4
- package/build/godot/addons/gdharness_editor/scene_file.gd +136 -79
- 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 +41 -28
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +84 -50
- package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd +70 -40
- package/build/godot/addons/gdharness_editor/tools/class_tools.gd +34 -30
- 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 +181 -107
- package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +16 -9
- package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +75 -43
- 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 +66 -0
- package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +171 -62
- 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 +37 -12
- package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +84 -63
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +153 -148
- 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 +38 -20
- 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 +211 -0
- package/build/godot/addons/gdharness_runtime/runtime_touch.gd.uid +1 -0
- 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 +84 -35
- 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 +139 -93
- package/build/godot/operations/editor_tools.gd +9 -10
- package/build/godot/operations/export_presets.gd +100 -54
- package/build/godot/operations/file_reads.gd +114 -39
- package/build/godot/operations/file_walk.gd +12 -5
- package/build/godot/operations/gdscript_analysis.gd +105 -66
- package/build/godot/operations/gdscript_authoring.gd +138 -39
- 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 +63 -39
- package/build/godot/operations/patterns.gd +3 -1
- package/build/godot/operations/plugins.gd +36 -16
- package/build/godot/operations/project_config.gd +144 -27
- 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 +37 -12
- 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/package.json +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
@tool
|
|
2
2
|
extends RefCounted
|
|
3
|
-
|
|
4
3
|
## What a caller writes for a property, read against the type that property declares, and the
|
|
5
4
|
## question of whether it can be written at all.
|
|
6
5
|
##
|
|
@@ -21,7 +20,6 @@ const GdhRead = preload("reading.gd")
|
|
|
21
20
|
const GdhSame = preload("same_values.gd")
|
|
22
21
|
const GdhSerialisation = preload("serialisation.gd")
|
|
23
22
|
const GdhShapes = preload("value_shapes.gd")
|
|
24
|
-
|
|
25
23
|
# The data types a Theme names its items by, as in "Button/colors/font_color", and what each holds.
|
|
26
24
|
const THEME_ITEMS: Dictionary[String, Array] = {
|
|
27
25
|
"colors": [TYPE_COLOR, ""],
|
|
@@ -31,13 +29,11 @@ const THEME_ITEMS: Dictionary[String, Array] = {
|
|
|
31
29
|
"icons": [TYPE_OBJECT, "Texture2D"],
|
|
32
30
|
"styles": [TYPE_OBJECT, "StyleBox"],
|
|
33
31
|
}
|
|
34
|
-
|
|
35
32
|
# What each packed array holds, for the four whose elements are not types JSON has. A polygon is
|
|
36
33
|
# written as a list of pairs, and only the property knows that each pair is a Vector2 rather than a
|
|
37
34
|
# list of two numbers: without being told, every element was read as itself and the engine turned
|
|
38
35
|
# the lot into zeroes on the way into the property.
|
|
39
36
|
const PACKED_ELEMENTS: Dictionary = GdhShapes.PACKED_ELEMENTS
|
|
40
|
-
|
|
41
37
|
# Entries in a property list that only head a section of the inspector. Object.set ignores their
|
|
42
38
|
# names, so a write to "Visibility" or "Transform" changed nothing and was answered as made.
|
|
43
39
|
const HEADINGS: int = PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP
|
|
@@ -49,7 +45,6 @@ const PLACED_BY_A_CONTAINER: Array[String] = ["position", "size", "global_positi
|
|
|
49
45
|
|
|
50
46
|
## The property the last write_all refused because it did not hold what it was given, or "".
|
|
51
47
|
var unheld: String = ""
|
|
52
|
-
|
|
53
48
|
## The stored properties the last write_all's own writes moved beside the ones they were given, as a
|
|
54
49
|
## set: the Anchors mode an anchor needs, and what an engine setter keeps in step, such as the
|
|
55
50
|
## anchors an anchor preset sets. Only writes no script code runs for count. A headless write that
|
|
@@ -57,24 +52,19 @@ var unheld: String = ""
|
|
|
57
52
|
## doing, which put a panel given a script and a bottom-wide preset back in Position mode, where its
|
|
58
53
|
## anchors are not stored.
|
|
59
54
|
var moved_by_engine: Dictionary = {}
|
|
60
|
-
|
|
61
55
|
var _values: GdhSerialisation = GdhSerialisation.new()
|
|
62
|
-
|
|
63
56
|
# Why the value being parsed cannot be written, when the parse is what found out. A resource is
|
|
64
57
|
# built inside the parse and there is nowhere in a parsed value to put the reason it is wrong.
|
|
65
58
|
var _refused: String = ""
|
|
66
|
-
|
|
67
59
|
# The stored properties the last write_all changed without being given them, by name, as [what it
|
|
68
60
|
# held before, what it holds now]. A setter keeps other properties in step with the one it is given:
|
|
69
61
|
# a Gradient given a third colour gives that point an offset of 0, a Control given a size moves its
|
|
70
62
|
# offsets. An answer naming only what was given leaves the caller to guess the rest.
|
|
71
63
|
var _also_changed: Dictionary = {}
|
|
72
|
-
|
|
73
64
|
# The values the last write_all wrote outside what their property declares, by name, as a sentence
|
|
74
65
|
# saying so: a number past an export range, or one no enum value has. The engine stores either, and
|
|
75
66
|
# the inspector would not have let it be entered, so a write answered as made said nothing of it.
|
|
76
67
|
var _outside_declared: Dictionary = {}
|
|
77
|
-
|
|
78
68
|
# The node paths the last write_all wrote that name no node from the node written, by property, as
|
|
79
69
|
# a sentence saying so.
|
|
80
70
|
var _names_no_node: Dictionary = {}
|
|
@@ -94,7 +84,10 @@ func parse(value: Variant, expected_type: int = TYPE_NIL, elements: Array = [])
|
|
|
94
84
|
var fields: Dictionary = value
|
|
95
85
|
# A dictionary with keys that are not text arrives as its entries, and is read against the
|
|
96
86
|
# declared element types like any other.
|
|
97
|
-
if
|
|
87
|
+
if (
|
|
88
|
+
str(fields.get("_type", "")) == "Dictionary"
|
|
89
|
+
and GdhSerialisation.pairs(fields.get("entries"))
|
|
90
|
+
):
|
|
98
91
|
var built: Dictionary = _values.deserialize_value(fields)
|
|
99
92
|
return _parse_entries(built, elements)
|
|
100
93
|
var tagged: Array = _parse_tagged_dictionary(fields)
|
|
@@ -128,8 +121,8 @@ func cannot_hold(
|
|
|
128
121
|
return shape % [holder, property, held, _kind(value)] + remedy + cost
|
|
129
122
|
|
|
130
123
|
# And the same question of each element, because a list is accepted for a packed or typed array
|
|
131
|
-
# whatever is in it: a polygon written as [{"x": 1}] passes the check above and lands as one
|
|
132
|
-
# vector, and [1.5, "x"] for a PackedInt32Array as [1, 0].
|
|
124
|
+
# whatever is in it: a polygon written as [{"x": 1}] passes the check above and lands as one
|
|
125
|
+
# zero vector, and [1.5, "x"] for a PackedInt32Array as [1, 0].
|
|
133
126
|
var element: int = GdhRead.as_int(PACKED_ELEMENTS.get(expected_type, TYPE_NIL), TYPE_NIL)
|
|
134
127
|
if expected_type == TYPE_ARRAY and not elements.is_empty():
|
|
135
128
|
element = GdhRead.as_int(elements[0], TYPE_NIL)
|
|
@@ -138,7 +131,9 @@ func cannot_hold(
|
|
|
138
131
|
for index: int in items.size():
|
|
139
132
|
if not GdhSerialisation.acceptable(items[index], element):
|
|
140
133
|
var shape: String = "%s.%s is %s and item %d of the list given is %s, not %s."
|
|
141
|
-
var named: Array = [
|
|
134
|
+
var named: Array = [
|
|
135
|
+
holder, property, held, index, _kind(items[index]), type_string(element),
|
|
136
|
+
]
|
|
142
137
|
return shape % named + GdhShapes.remedy(items[index], element) + cost
|
|
143
138
|
# A list of polygons is a list of lists of points, and each point is read as one too.
|
|
144
139
|
var inner: int = GdhRead.as_int(PACKED_ELEMENTS.get(element, TYPE_NIL), TYPE_NIL)
|
|
@@ -147,9 +142,17 @@ func cannot_hold(
|
|
|
147
142
|
var points: Array = items[index]
|
|
148
143
|
for at: int in points.size():
|
|
149
144
|
if not GdhSerialisation.acceptable(points[at], inner):
|
|
150
|
-
var nested: String =
|
|
145
|
+
var nested: String = (
|
|
146
|
+
"%s.%s holds lists of %s, and item %d of list %d given is %s, not %s."
|
|
147
|
+
)
|
|
151
148
|
var said: Array = [
|
|
152
|
-
holder,
|
|
149
|
+
holder,
|
|
150
|
+
property,
|
|
151
|
+
type_string(inner),
|
|
152
|
+
at,
|
|
153
|
+
index,
|
|
154
|
+
_kind(points[at]),
|
|
155
|
+
type_string(inner),
|
|
153
156
|
]
|
|
154
157
|
return nested % said + GdhShapes.remedy(points[at], inner) + cost
|
|
155
158
|
if expected_type == TYPE_DICTIONARY and elements.size() == 2 and value is Dictionary:
|
|
@@ -163,13 +166,15 @@ func cannot_hold(
|
|
|
163
166
|
var entry: Variant = entries[key]
|
|
164
167
|
if not GdhSerialisation.acceptable(entry, value_type):
|
|
165
168
|
var shape: String = "%s.%s holds %s values, and the one given for %s is %s."
|
|
166
|
-
var named: Array = [
|
|
169
|
+
var named: Array = [
|
|
170
|
+
holder, property, type_string(value_type), shown(key), shown(entry),
|
|
171
|
+
]
|
|
167
172
|
return shape % named + GdhShapes.remedy(entry, value_type) + cost
|
|
168
173
|
return ""
|
|
169
174
|
|
|
170
175
|
|
|
171
|
-
## What [param value] is, as a refusal names it. A number arrives from JSON as a float whether or
|
|
172
|
-
## it has a fraction, so [1, 2] given for a list of words was called a list of floats.
|
|
176
|
+
## What [param value] is, as a refusal names it. A number arrives from JSON as a float whether or
|
|
177
|
+
## not it has a fraction, so [1, 2] given for a list of words was called a list of floats.
|
|
173
178
|
static func _kind(value: Variant) -> String:
|
|
174
179
|
if value is int or value is float:
|
|
175
180
|
return "a number"
|
|
@@ -219,7 +224,9 @@ func write_all(target: Object, properties: Dictionary) -> String:
|
|
|
219
224
|
# A refusal of one of several leaves the others unwritten too, which a refusal naming only the
|
|
220
225
|
# one it refused left a caller to guess.
|
|
221
226
|
var unwritten: String = (
|
|
222
|
-
""
|
|
227
|
+
""
|
|
228
|
+
if properties.size() < 2
|
|
229
|
+
else " None of the %d properties given was written." % properties.size()
|
|
223
230
|
)
|
|
224
231
|
# The script first, wherever the caller put it, since the properties it declares exist only once
|
|
225
232
|
# it is attached.
|
|
@@ -241,7 +248,9 @@ func write_all(target: Object, properties: Dictionary) -> String:
|
|
|
241
248
|
var unlisted: String = GdhPropertyPaths.unlisted(holder, name)
|
|
242
249
|
if not unlisted.is_empty():
|
|
243
250
|
return unlisted + unwritten
|
|
244
|
-
var ungrown: String = GdhPropertyPaths.grow(
|
|
251
|
+
var ungrown: String = GdhPropertyPaths.grow(
|
|
252
|
+
holder, name, GdhPropertyPaths.class_called(holder)
|
|
253
|
+
)
|
|
245
254
|
if not ungrown.is_empty():
|
|
246
255
|
return ungrown + unwritten
|
|
247
256
|
declared = declaration(holder, name)
|
|
@@ -249,7 +258,11 @@ func write_all(target: Object, properties: Dictionary) -> String:
|
|
|
249
258
|
declared = _component_slot(holder, name)
|
|
250
259
|
if declared.has("refused"):
|
|
251
260
|
return str(declared["refused"]) + unwritten
|
|
252
|
-
if
|
|
261
|
+
if (
|
|
262
|
+
declared.is_empty()
|
|
263
|
+
and holder is ShaderMaterial
|
|
264
|
+
and name.begins_with("shader_parameter/")
|
|
265
|
+
):
|
|
253
266
|
return GdhDeclared.no_uniform(holder as ShaderMaterial, name) + unwritten
|
|
254
267
|
if declared.is_empty():
|
|
255
268
|
return no_property(holder, name) + unwritten
|
|
@@ -280,7 +293,10 @@ func write_all(target: Object, properties: Dictionary) -> String:
|
|
|
280
293
|
declarations[property] = declared
|
|
281
294
|
|
|
282
295
|
for property: String in given:
|
|
283
|
-
if
|
|
296
|
+
if (
|
|
297
|
+
written_at[property] < writes
|
|
298
|
+
and not GdhSame.same(read_at(target, property), given[property])
|
|
299
|
+
):
|
|
284
300
|
_write(target, property, given[property])
|
|
285
301
|
writes += 1
|
|
286
302
|
written_at[property] = writes
|
|
@@ -292,15 +308,16 @@ func write_all(target: Object, properties: Dictionary) -> String:
|
|
|
292
308
|
if undone_by.has(property):
|
|
293
309
|
return (
|
|
294
310
|
(
|
|
295
|
-
"%s.%s was given %s and holds %s once %s was set as well: the engine keeps
|
|
296
|
-
+ "in step, so they cannot hold these values together. Nothing was
|
|
311
|
+
"%s.%s was given %s and holds %s once %s was set as well: the engine keeps "
|
|
312
|
+
+ "the two in step, so they cannot hold these values together. Nothing was "
|
|
313
|
+
+ "written."
|
|
297
314
|
)
|
|
298
315
|
% [
|
|
299
316
|
GdhPropertyPaths.class_called(target),
|
|
300
317
|
property,
|
|
301
318
|
shown(given[property]),
|
|
302
319
|
shown(held),
|
|
303
|
-
undone_by[property]
|
|
320
|
+
undone_by[property],
|
|
304
321
|
]
|
|
305
322
|
)
|
|
306
323
|
var declared: Dictionary = declarations[property]
|
|
@@ -334,17 +351,20 @@ func _note_undone(
|
|
|
334
351
|
## Why [param name] cannot be written on [param control], or "" once it can. A container places and
|
|
335
352
|
## sizes its children and the scene keeps none of that for them, so their anchors, offsets, position
|
|
336
353
|
## and size are refused with what a child does set. A control in Position mode ignores an anchor
|
|
337
|
-
## preset, and the inspector offers anchors only in Anchors mode, so writing one puts it there
|
|
338
|
-
## as picking a preset in the editor does; alsoChanged then names layout_mode.
|
|
354
|
+
## preset, and the inspector offers anchors only in Anchors mode, so writing one puts it there
|
|
355
|
+
## first, as picking a preset in the editor does; alsoChanged then names layout_mode.
|
|
339
356
|
func _laid_out(control: Control, name: String) -> String:
|
|
340
357
|
var base: String = name.get_slice(":", 0)
|
|
341
358
|
var anchoring: bool = base == "anchors_preset" or base.begins_with("anchor_")
|
|
342
359
|
var parent: Node = control.get_parent()
|
|
343
|
-
if
|
|
360
|
+
if (
|
|
361
|
+
parent is Container
|
|
362
|
+
and (anchoring or base.begins_with("offset_") or base in PLACED_BY_A_CONTAINER)
|
|
363
|
+
):
|
|
344
364
|
return (
|
|
345
365
|
(
|
|
346
|
-
"%s's parent, %s, is a %s, which places and sizes it, so its %s is the container's
|
|
347
|
-
+ "and the scene keeps none of it. A child of a container is laid out with "
|
|
366
|
+
"%s's parent, %s, is a %s, which places and sizes it, so its %s is the container's "
|
|
367
|
+
+ "to set and the scene keeps none of it. A child of a container is laid out with "
|
|
348
368
|
+ "size_flags_horizontal, size_flags_vertical and custom_minimum_size."
|
|
349
369
|
)
|
|
350
370
|
% [control.name, parent.name, parent.get_class(), base]
|
|
@@ -369,7 +389,9 @@ func note_write(answer: Dictionary, relative_to: Node = null) -> void:
|
|
|
369
389
|
var noted: Dictionary = {}
|
|
370
390
|
for property: Variant in _also_changed:
|
|
371
391
|
var pair: Array = _also_changed[property]
|
|
372
|
-
noted[property] = {
|
|
392
|
+
noted[property] = {
|
|
393
|
+
"was": _readable(pair[0], relative_to), "now": _readable(pair[1], relative_to),
|
|
394
|
+
}
|
|
373
395
|
answer["alsoChanged"] = noted
|
|
374
396
|
|
|
375
397
|
|
|
@@ -384,9 +406,9 @@ func _readable(value: Variant, relative_to: Node) -> Variant:
|
|
|
384
406
|
|
|
385
407
|
|
|
386
408
|
## What [param target] stores, by name, but its script and the properties in [param leave], in the
|
|
387
|
-
## names a read answers with: a Curve's points as point_0/position and the rest rather than the
|
|
388
|
-
## list every point write changes. A list or a map is copied, since a setter can change the
|
|
389
|
-
## holds in place.
|
|
409
|
+
## names a read answers with: a Curve's points as point_0/position and the rest rather than the
|
|
410
|
+
## _data list every point write changes. A list or a map is copied, since a setter can change the
|
|
411
|
+
## one it holds in place.
|
|
390
412
|
func _stored(target: Object, leave: Dictionary) -> Dictionary:
|
|
391
413
|
var held: Dictionary = {}
|
|
392
414
|
for entry: Dictionary in GdhShapes.read_properties(target):
|
|
@@ -434,7 +456,7 @@ func _component_slot(target: Object, path: String) -> Dictionary:
|
|
|
434
456
|
var steps: PackedStringArray = path.split(":")
|
|
435
457
|
var owner: String = GdhPropertyPaths.class_called(target)
|
|
436
458
|
if declaration(target, steps[0]).is_empty():
|
|
437
|
-
return {"refused": no_property(target, steps[0])}
|
|
459
|
+
return { "refused": no_property(target, steps[0]) }
|
|
438
460
|
var value: Variant = target.get(steps[0])
|
|
439
461
|
var walked: String = steps[0]
|
|
440
462
|
for index: int in range(1, steps.size()):
|
|
@@ -444,8 +466,8 @@ func _component_slot(target: Object, path: String) -> Dictionary:
|
|
|
444
466
|
if has.is_empty():
|
|
445
467
|
var refused: String = (
|
|
446
468
|
(
|
|
447
|
-
"%s.%s is %s, which a path does not step into: a path reaches the components
|
|
448
|
-
+ "vector, a colour, a rectangle or a transform."
|
|
469
|
+
"%s.%s is %s, which a path does not step into: a path reaches the components "
|
|
470
|
+
+ "of a vector, a colour, a rectangle or a transform."
|
|
449
471
|
)
|
|
450
472
|
% [owner, walked, sort]
|
|
451
473
|
)
|
|
@@ -457,18 +479,24 @@ func _component_slot(target: Object, path: String) -> Dictionary:
|
|
|
457
479
|
)
|
|
458
480
|
elif value is Array and index + 1 < steps.size():
|
|
459
481
|
refused += (
|
|
460
|
-
|
|
482
|
+
(
|
|
483
|
+
" A property of a resource in it is reached with slashes and the element's "
|
|
484
|
+
+ "index: %s/%s/%s."
|
|
485
|
+
)
|
|
461
486
|
% [walked, step, ":".join(steps.slice(index + 1))]
|
|
462
487
|
)
|
|
463
|
-
return {"refused": refused}
|
|
488
|
+
return { "refused": refused }
|
|
464
489
|
if not step in has:
|
|
465
490
|
return {
|
|
466
491
|
"refused":
|
|
467
|
-
|
|
492
|
+
(
|
|
493
|
+
"%s.%s is %s, so it has no %s; it has %s."
|
|
494
|
+
% [owner, walked, sort, step, ", ".join(has)]
|
|
495
|
+
),
|
|
468
496
|
}
|
|
469
497
|
value = value[step]
|
|
470
498
|
walked += ":" + step
|
|
471
|
-
return {"name": path, "type": typeof(value), "usage": PROPERTY_USAGE_DEFAULT}
|
|
499
|
+
return { "name": path, "type": typeof(value), "usage": PROPERTY_USAGE_DEFAULT }
|
|
472
500
|
|
|
473
501
|
|
|
474
502
|
## [param raw] as the value [param declared] takes, as [ok, value] or [false, why not].
|
|
@@ -509,7 +537,8 @@ func value_for(target: Object, declared: Dictionary, raw: Variant) -> Array:
|
|
|
509
537
|
var rounded: String = GdhSerialisation.inexact(raw, expected_type)
|
|
510
538
|
if not rounded.is_empty():
|
|
511
539
|
return [
|
|
512
|
-
false,
|
|
540
|
+
false,
|
|
541
|
+
"%s.%s holds int: %s." % [GdhPropertyPaths.class_called(target), property, rounded],
|
|
513
542
|
]
|
|
514
543
|
_refused = ""
|
|
515
544
|
value = parse(raw, expected_type, elements)
|
|
@@ -559,12 +588,13 @@ func _node_reference(target: Object, property: String, raw: Variant) -> Array:
|
|
|
559
588
|
+ '"../Player", not %s.'
|
|
560
589
|
)
|
|
561
590
|
% [property, shown(raw)]
|
|
562
|
-
)
|
|
591
|
+
),
|
|
563
592
|
]
|
|
564
593
|
var found: Node = node.get_node_or_null(path)
|
|
565
594
|
if found == null:
|
|
566
595
|
return [
|
|
567
|
-
false,
|
|
596
|
+
false,
|
|
597
|
+
"%s names %s, and there is no node at that path from %s." % [property, path, node.name],
|
|
568
598
|
]
|
|
569
599
|
return [true, found]
|
|
570
600
|
|
|
@@ -587,16 +617,20 @@ func _wrong_class(value: Object, declared: Dictionary) -> String:
|
|
|
587
617
|
)
|
|
588
618
|
|
|
589
619
|
|
|
590
|
-
## [param value] as the typed list of objects that [param declared] holds on [param target], as
|
|
591
|
-
##
|
|
620
|
+
## [param value] as the typed list of objects that [param declared] holds on [param target], as [ok,
|
|
621
|
+
## list or why not]. Measured on 4.7.2, a scene's node whose script exports Array[Item] holds []
|
|
592
622
|
## after being given an untyped list of Items, and keeps a list typed as its own is.
|
|
593
623
|
func _object_list(target: Object, declared: Dictionary, value: Array) -> Array:
|
|
594
624
|
var property: String = str(declared.get("name", ""))
|
|
595
625
|
var kind: Array = GdhDeclared.object_kind(declared, 0)
|
|
596
|
-
var holding: String =
|
|
626
|
+
var holding: String = (
|
|
627
|
+
"%s.%s holds %s" % [GdhPropertyPaths.class_called(target), property, kind[0]]
|
|
628
|
+
)
|
|
597
629
|
var items: Array = []
|
|
598
630
|
for index: int in value.size():
|
|
599
|
-
var place: Array = [
|
|
631
|
+
var place: Array = [
|
|
632
|
+
"item %d of the list given" % index, "item %d of %s" % [index, property],
|
|
633
|
+
]
|
|
600
634
|
var item: Array = _object_item(target, value[index], kind, holding, place)
|
|
601
635
|
if not item[0]:
|
|
602
636
|
return item
|
|
@@ -607,8 +641,11 @@ func _object_list(target: Object, declared: Dictionary, value: Array) -> Array:
|
|
|
607
641
|
return [
|
|
608
642
|
true,
|
|
609
643
|
Array(
|
|
610
|
-
items,
|
|
611
|
-
|
|
644
|
+
items,
|
|
645
|
+
current.get_typed_builtin(),
|
|
646
|
+
current.get_typed_class_name(),
|
|
647
|
+
current.get_typed_script()
|
|
648
|
+
),
|
|
612
649
|
]
|
|
613
650
|
var typing: Array = GdhDeclared.object_typing(str(kind[0]))
|
|
614
651
|
if typing.is_empty():
|
|
@@ -623,7 +660,9 @@ func _object_list(target: Object, declared: Dictionary, value: Array) -> Array:
|
|
|
623
660
|
func _object_entries(target: Object, declared: Dictionary, value: Dictionary) -> Array:
|
|
624
661
|
var property: String = str(declared.get("name", ""))
|
|
625
662
|
var kind: Array = GdhDeclared.object_kind(declared, 1)
|
|
626
|
-
var holding: String =
|
|
663
|
+
var holding: String = (
|
|
664
|
+
"%s.%s holds %s values" % [GdhPropertyPaths.class_called(target), property, kind[0]]
|
|
665
|
+
)
|
|
627
666
|
var entries: Dictionary = {}
|
|
628
667
|
for key: Variant in value:
|
|
629
668
|
var place: Array = ["the one given for %s" % shown(key), "%s[%s]" % [property, shown(key)]]
|
|
@@ -644,7 +683,7 @@ func _object_entries(target: Object, declared: Dictionary, value: Dictionary) ->
|
|
|
644
683
|
current.get_typed_value_builtin(),
|
|
645
684
|
current.get_typed_value_class_name(),
|
|
646
685
|
current.get_typed_value_script()
|
|
647
|
-
)
|
|
686
|
+
),
|
|
648
687
|
]
|
|
649
688
|
var typing: Array = GdhDeclared.object_typing(str(kind[0]))
|
|
650
689
|
var key_type: int = GdhRead.as_int(GdhDeclared.elements_of(declared)[0], TYPE_NIL)
|
|
@@ -659,7 +698,9 @@ func _object_entries(target: Object, declared: Dictionary, value: Dictionary) ->
|
|
|
659
698
|
## res:// path is the resource, and for nodes a path from [param target] is the node there.
|
|
660
699
|
## [param holding] says what the list or map holds, and [param place] is [where the value sits in
|
|
661
700
|
## what was given, what it is called in the property].
|
|
662
|
-
func _object_item(
|
|
701
|
+
func _object_item(
|
|
702
|
+
target: Object, given: Variant, kind: Array, holding: String, place: Array
|
|
703
|
+
) -> Array:
|
|
663
704
|
var item: Variant = given
|
|
664
705
|
if typeof(item) == TYPE_STRING:
|
|
665
706
|
var found: Array = (
|
|
@@ -680,8 +721,8 @@ func _object_item(target: Object, given: Variant, kind: Array, holding: String,
|
|
|
680
721
|
func _fraction_refusal(target: Object, property: String, raw: Variant) -> String:
|
|
681
722
|
return (
|
|
682
723
|
(
|
|
683
|
-
"%s.%s holds whole numbers, and %s would be cut to fit. Setting it would save a
|
|
684
|
-
+ "value than the one asked for."
|
|
724
|
+
"%s.%s holds whole numbers, and %s would be cut to fit. Setting it would save a "
|
|
725
|
+
+ "different value than the one asked for."
|
|
685
726
|
)
|
|
686
727
|
% [GdhPropertyPaths.class_called(target), property, shown(raw)]
|
|
687
728
|
)
|
|
@@ -700,11 +741,11 @@ func colour_from(raw: Variant, named: String) -> Array:
|
|
|
700
741
|
false,
|
|
701
742
|
(
|
|
702
743
|
(
|
|
703
|
-
'%s is {"r": .., "g": .., "b": .., "a": ..} from 0 to 1, a optional, or an html
|
|
704
|
-
+ '"#ff8000" or "#ff800080"; %s is neither.'
|
|
744
|
+
'%s is {"r": .., "g": .., "b": .., "a": ..} from 0 to 1, a optional, or an html '
|
|
745
|
+
+ 'code such as "#ff8000" or "#ff800080"; %s is neither.'
|
|
705
746
|
)
|
|
706
747
|
% [named, JSON.stringify(raw)]
|
|
707
|
-
)
|
|
748
|
+
),
|
|
708
749
|
]
|
|
709
750
|
|
|
710
751
|
|
|
@@ -713,7 +754,9 @@ func colour_from(raw: Variant, named: String) -> Array:
|
|
|
713
754
|
static func no_property(target: Object, property: String) -> String:
|
|
714
755
|
var said: String = (
|
|
715
756
|
GdhRead.near_property(
|
|
716
|
-
"%s has no property %s" % [GdhPropertyPaths.class_called(target), property],
|
|
757
|
+
"%s has no property %s" % [GdhPropertyPaths.class_called(target), property],
|
|
758
|
+
target,
|
|
759
|
+
property
|
|
717
760
|
)
|
|
718
761
|
+ "."
|
|
719
762
|
)
|
|
@@ -738,11 +781,11 @@ func _resource_at(path: String, property: String) -> Array:
|
|
|
738
781
|
false,
|
|
739
782
|
(
|
|
740
783
|
(
|
|
741
|
-
"%s is a resource built into %s, and only that file can refer to it. Build a
|
|
742
|
-
+ 'for %s with "_type" set to its class and its properties beside it.'
|
|
784
|
+
"%s is a resource built into %s, and only that file can refer to it. Build a "
|
|
785
|
+
+ 'new one for %s with "_type" set to its class and its properties beside it.'
|
|
743
786
|
)
|
|
744
787
|
% [path, path.get_slice("::", 0), property]
|
|
745
|
-
)
|
|
788
|
+
),
|
|
746
789
|
]
|
|
747
790
|
if not ResourceLoader.exists(path):
|
|
748
791
|
# An image or a sound nobody has imported is a file the engine has no loader for, and "No
|
|
@@ -752,16 +795,20 @@ func _resource_at(path: String, property: String) -> Array:
|
|
|
752
795
|
false,
|
|
753
796
|
(
|
|
754
797
|
(
|
|
755
|
-
"%s is there, but it has never been imported, so the engine has no
|
|
756
|
-
+ " from it for %s. project_import reimport with
|
|
798
|
+
"%s is there, but it has never been imported, so the engine has no "
|
|
799
|
+
+ "resource to load from it for %s. project_import reimport with "
|
|
800
|
+
+ "resourcePath %s imports it."
|
|
757
801
|
)
|
|
758
802
|
% [path, property, path]
|
|
759
|
-
)
|
|
803
|
+
),
|
|
760
804
|
]
|
|
761
805
|
if path.begins_with("uid://"):
|
|
762
806
|
return [false, "No resource at %s for %s" % [path, property]]
|
|
763
807
|
return [
|
|
764
|
-
false,
|
|
808
|
+
false,
|
|
809
|
+
GdhFileWalk.new().with_nearest_files(
|
|
810
|
+
"No resource at %s for %s" % [path, property], path
|
|
811
|
+
),
|
|
765
812
|
]
|
|
766
813
|
return [true, load(path)]
|
|
767
814
|
|
|
@@ -782,11 +829,16 @@ func declaration(target: Object, property: String) -> Dictionary:
|
|
|
782
829
|
## item a read of one theme answered with was refused when written into another that lacked it.
|
|
783
830
|
static func _theme_item(property: String) -> Dictionary:
|
|
784
831
|
var parts: PackedStringArray = property.split("/")
|
|
785
|
-
if
|
|
832
|
+
if (
|
|
833
|
+
parts.size() != 3
|
|
834
|
+
or parts[0].is_empty()
|
|
835
|
+
or parts[2].is_empty()
|
|
836
|
+
or not THEME_ITEMS.has(parts[1])
|
|
837
|
+
):
|
|
786
838
|
return {}
|
|
787
839
|
var item: Array = THEME_ITEMS[parts[1]]
|
|
788
840
|
var kind: int = item[0]
|
|
789
|
-
var made: Dictionary = {"name": property, "type": kind, "usage": PROPERTY_USAGE_DEFAULT}
|
|
841
|
+
var made: Dictionary = { "name": property, "type": kind, "usage": PROPERTY_USAGE_DEFAULT }
|
|
790
842
|
if kind == TYPE_OBJECT:
|
|
791
843
|
made["hint"] = PROPERTY_HINT_RESOURCE_TYPE
|
|
792
844
|
made["hint_string"] = item[1]
|
|
@@ -835,8 +887,8 @@ func _parse_resource_tag(value: Dictionary) -> Array:
|
|
|
835
887
|
_refused = (
|
|
836
888
|
(
|
|
837
889
|
"The %s given has no path: a read names a resource built into a scene by its class "
|
|
838
|
-
+ "alone where it recurs inside itself, and nothing elsewhere can refer to it.
|
|
839
|
-
+ 'a new one with "_type" set to its class and its properties beside it.'
|
|
890
|
+
+ "alone where it recurs inside itself, and nothing elsewhere can refer to it. "
|
|
891
|
+
+ 'Build a new one with "_type" set to its class and its properties beside it.'
|
|
840
892
|
)
|
|
841
893
|
% str(value["class"])
|
|
842
894
|
)
|
|
@@ -929,7 +981,9 @@ func _typed_dictionary(entries: Dictionary, key_type: int, value_type: int) -> D
|
|
|
929
981
|
return entries
|
|
930
982
|
var fitted: Dictionary = {}
|
|
931
983
|
for key: Variant in entries:
|
|
932
|
-
fitted[key] =
|
|
984
|
+
fitted[key] = (
|
|
985
|
+
type_convert(entries[key], value_type) if value_type != TYPE_NIL else entries[key]
|
|
986
|
+
)
|
|
933
987
|
return Dictionary(fitted, key_type, &"", null, value_type, &"", null)
|
|
934
988
|
|
|
935
989
|
|
|
@@ -952,11 +1006,15 @@ func _parse_array(value: Array, expected_type: int, elements: Array) -> Variant:
|
|
|
952
1006
|
TYPE_VECTOR3:
|
|
953
1007
|
if value.size() == 3:
|
|
954
1008
|
return Vector3(
|
|
955
|
-
GdhRead.as_float(value[0]),
|
|
1009
|
+
GdhRead.as_float(value[0]),
|
|
1010
|
+
GdhRead.as_float(value[1]),
|
|
1011
|
+
GdhRead.as_float(value[2])
|
|
956
1012
|
)
|
|
957
1013
|
TYPE_VECTOR3I:
|
|
958
1014
|
if value.size() == 3:
|
|
959
|
-
return Vector3i(
|
|
1015
|
+
return Vector3i(
|
|
1016
|
+
GdhRead.as_int(value[0]), GdhRead.as_int(value[1]), GdhRead.as_int(value[2])
|
|
1017
|
+
)
|
|
960
1018
|
TYPE_VECTOR4:
|
|
961
1019
|
if value.size() == 4:
|
|
962
1020
|
return Vector4(
|
|
@@ -980,14 +1038,21 @@ func _parse_array(value: Array, expected_type: int, elements: Array) -> Variant:
|
|
|
980
1038
|
var items: Array = value.map(func(item: Variant) -> Variant: return parse(item, element_type))
|
|
981
1039
|
if element_type == TYPE_NIL or element_type == TYPE_OBJECT:
|
|
982
1040
|
return items
|
|
983
|
-
if not items.all(
|
|
1041
|
+
if not items.all(
|
|
1042
|
+
func(item: Variant) -> bool: return GdhSerialisation.acceptable(item, element_type)
|
|
1043
|
+
):
|
|
984
1044
|
return items
|
|
985
|
-
# Converted, a list of points holding a word became a packed list of zeroes before anything read
|
|
1045
|
+
# Converted, a list of points holding a word became a packed list of zeroes before anything read
|
|
1046
|
+
# it.
|
|
986
1047
|
var inner: int = GdhRead.as_int(PACKED_ELEMENTS.get(element_type, TYPE_NIL), TYPE_NIL)
|
|
987
1048
|
if inner != TYPE_NIL:
|
|
988
1049
|
for item: Variant in items:
|
|
989
1050
|
var points: Array = item if item is Array else []
|
|
990
|
-
if not points.all(
|
|
1051
|
+
if not points.all(
|
|
1052
|
+
func(point: Variant) -> bool: return GdhSerialisation.acceptable(point, inner)
|
|
1053
|
+
):
|
|
991
1054
|
return items
|
|
992
|
-
var fitted: Array = items.map(
|
|
1055
|
+
var fitted: Array = items.map(
|
|
1056
|
+
func(item: Variant) -> Variant: return type_convert(item, element_type)
|
|
1057
|
+
)
|
|
993
1058
|
return Array(fitted, element_type, &"", null)
|
|
@@ -124,7 +124,8 @@ static func json_or_null(text: String) -> Variant:
|
|
|
124
124
|
## [param said], the refusal for [param node_path] found nowhere in a scene whose root is called
|
|
125
125
|
## [param root_name], with how paths are read when the path starts with that name and the root has
|
|
126
126
|
## no child called that. Paths go from the root, so its own name there names a child of it, and a
|
|
127
|
-
## caller who read the root as Main in a tree wrote Main/Body and was told only that nothing is
|
|
127
|
+
## caller who read the root as Main in a tree wrote Main/Body and was told only that nothing is
|
|
128
|
+
## there.
|
|
128
129
|
static func from_the_root(said: String, node_path: String, root_name: String) -> String:
|
|
129
130
|
var first: String = node_path.get_slice("/", 0)
|
|
130
131
|
if root_name.is_empty() or first != root_name:
|
|
@@ -141,7 +142,11 @@ static func from_the_root(said: String, node_path: String, root_name: String) ->
|
|
|
141
142
|
## is empty; the name below it that is missing; and [param children], the names that node has, as
|
|
142
143
|
## after a node was moved or renamed. Names up to [constant NAMED_CHILDREN] of them.
|
|
143
144
|
static func missing_below(
|
|
144
|
-
said: String,
|
|
145
|
+
said: String,
|
|
146
|
+
root_name: String,
|
|
147
|
+
reached: PackedStringArray,
|
|
148
|
+
missing: String,
|
|
149
|
+
children: PackedStringArray
|
|
145
150
|
) -> String:
|
|
146
151
|
var shown: String = ", ".join(children.slice(0, NAMED_CHILDREN))
|
|
147
152
|
if children.size() > NAMED_CHILDREN:
|
|
@@ -167,9 +172,18 @@ static func not_of_kind(
|
|
|
167
172
|
) -> String:
|
|
168
173
|
var told: String = said + ("" if said.ends_with(".") else ".")
|
|
169
174
|
if not found.is_empty():
|
|
170
|
-
told +=
|
|
175
|
+
told += (
|
|
176
|
+
' The node at "%s" is %s, not %s.'
|
|
177
|
+
% [node_path, with_article(found), with_article(kind)]
|
|
178
|
+
)
|
|
171
179
|
if holders.is_empty():
|
|
172
|
-
return
|
|
180
|
+
return (
|
|
181
|
+
told
|
|
182
|
+
+ (
|
|
183
|
+
" The scene holds no %s; scene_node add with nodeType %s puts one in it."
|
|
184
|
+
% [kind, kind]
|
|
185
|
+
)
|
|
186
|
+
)
|
|
173
187
|
var quoted: PackedStringArray = []
|
|
174
188
|
for holder: String in holders.slice(0, NAMED_CHILDREN):
|
|
175
189
|
var _quoted: bool = quoted.append('"%s"' % holder)
|
|
@@ -209,7 +223,10 @@ static func offered(said: String, word: String, names: Array) -> String:
|
|
|
209
223
|
var close: PackedStringArray = nearest(word, every)
|
|
210
224
|
if close.is_empty():
|
|
211
225
|
return "%s; it has %s" % [said, ", ".join(every)]
|
|
212
|
-
return
|
|
226
|
+
return (
|
|
227
|
+
"%s; the nearest it has %s %s"
|
|
228
|
+
% [said, "is" if close.size() == 1 else "are", ", ".join(close)]
|
|
229
|
+
)
|
|
213
230
|
|
|
214
231
|
|
|
215
232
|
## [param said], the refusal for [param property], which [param target] does not declare, with the
|
|
@@ -233,14 +250,20 @@ static func near_property(said: String, target: Object, property: String) -> Str
|
|
|
233
250
|
scripted.append(str(declared.get("name", "")))
|
|
234
251
|
var close: PackedStringArray = nearest(property, PackedStringArray(names))
|
|
235
252
|
if not close.is_empty():
|
|
236
|
-
return
|
|
237
|
-
|
|
238
|
-
|
|
253
|
+
return (
|
|
254
|
+
"%s; the nearest it has %s %s"
|
|
255
|
+
% [said, "is" if close.size() == 1 else "are", ", ".join(close)]
|
|
256
|
+
)
|
|
257
|
+
# With a script that declares nothing readable, as one that does not compile, the name is
|
|
258
|
+
# likelier the script's than the class's, so the class's list would point the wrong way.
|
|
239
259
|
if scripted.is_empty() and target.get_script() != null:
|
|
240
260
|
return said
|
|
241
261
|
if scripted.is_empty():
|
|
242
262
|
return (
|
|
243
|
-
|
|
263
|
+
(
|
|
264
|
+
"%s; editor_classes info with className %s and includeInherited true lists the "
|
|
265
|
+
+ "ones it has"
|
|
266
|
+
)
|
|
244
267
|
% [said, target.get_class()]
|
|
245
268
|
)
|
|
246
269
|
scripted.sort()
|
|
@@ -264,11 +287,13 @@ static func _list_called(target: Object, count: Dictionary, property: String) ->
|
|
|
264
287
|
fields = _fields_at(fresh, first)
|
|
265
288
|
if not fresh is RefCounted:
|
|
266
289
|
fresh.free()
|
|
267
|
-
var each: String =
|
|
290
|
+
var each: String = (
|
|
291
|
+
"each one's fields" if fields.is_empty() else "each one's %s" % ", ".join(fields)
|
|
292
|
+
)
|
|
268
293
|
return (
|
|
269
294
|
(
|
|
270
|
-
"it keeps its %s as %s, how many there are, and %s under %s for the first, %s for the
|
|
271
|
-
+ "give %s before the fields of the entries it makes"
|
|
295
|
+
"it keeps its %s as %s, how many there are, and %s under %s for the first, %s for the "
|
|
296
|
+
+ "second and so on: give %s before the fields of the entries it makes"
|
|
272
297
|
)
|
|
273
298
|
% [parts[0].to_lower(), counted, each, first, parts[1] + "1/", counted]
|
|
274
299
|
)
|