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
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
@tool
|
|
2
2
|
extends RefCounted
|
|
3
|
-
|
|
4
3
|
## How a scene or resource a tool saves keeps naming files by uid, as the editor's saves do.
|
|
5
4
|
|
|
6
5
|
## The files a headless save named by path alone because the uid cache holds no uid for them,
|
|
@@ -84,12 +83,17 @@ static func note_by_path(named: String) -> void:
|
|
|
84
83
|
|
|
85
84
|
## The uid attribute a reference to [param named] is written with, as ' uid="uid://..."', or "".
|
|
86
85
|
##
|
|
87
|
-
## Only a uid the uid cache gives that path, which is what the loader resolves it by. A uid the
|
|
88
|
-
## does not know (a file made with no editor since the last scan) is answered with a warning
|
|
89
|
-
## load, and one it gives another file (a scene copied whole keeps its original's) loads
|
|
86
|
+
## Only a uid the uid cache gives that path, which is what the loader resolves it by. A uid the
|
|
87
|
+
## cache does not know (a file made with no editor since the last scan) is answered with a warning
|
|
88
|
+
## on every load, and one it gives another file (a scene copied whole keeps its original's) loads
|
|
89
|
+
## that file.
|
|
90
90
|
static func uid_attribute(named: String) -> String:
|
|
91
91
|
var id: int = ResourceLoader.get_resource_uid(named)
|
|
92
|
-
if
|
|
92
|
+
if (
|
|
93
|
+
id == ResourceUID.INVALID_ID
|
|
94
|
+
or not ResourceUID.has_id(id)
|
|
95
|
+
or ResourceUID.get_id_path(id) != named
|
|
96
|
+
):
|
|
93
97
|
return ""
|
|
94
98
|
return ' uid="%s"' % ResourceUID.id_to_text(id)
|
|
95
99
|
|
|
@@ -100,7 +104,9 @@ static func uid_in(file_path: String) -> int:
|
|
|
100
104
|
return ResourceUID.INVALID_ID
|
|
101
105
|
var file: FileAccess = FileAccess.open(file_path, FileAccess.READ)
|
|
102
106
|
if file != null:
|
|
103
|
-
var header: RegExMatch = RegEx.create_from_string('uid="(uid://[a-z0-9]+)"').search(
|
|
107
|
+
var header: RegExMatch = RegEx.create_from_string('uid="(uid://[a-z0-9]+)"').search(
|
|
108
|
+
file.get_line()
|
|
109
|
+
)
|
|
104
110
|
file.close()
|
|
105
111
|
if header != null:
|
|
106
112
|
return ResourceUID.text_to_id(header.get_string(1))
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
extends RefCounted
|
|
2
|
-
|
|
3
2
|
## Godot values as JSON can carry them, and JSON back into the values the engine wants.
|
|
4
3
|
##
|
|
5
4
|
## This file is the one beside the operations, and `bun run sync:gd` copies it into each addon,
|
|
@@ -10,17 +9,14 @@ extends RefCounted
|
|
|
10
9
|
|
|
11
10
|
const GdhRead = preload("reading.gd")
|
|
12
11
|
const GdhShapes = preload("value_shapes.gd")
|
|
13
|
-
|
|
14
12
|
# What the engine carries from one to another without complaint, which is what a value written to a
|
|
15
13
|
# property or handed to a parameter may arrive as. Numbers include bool because the engine counts it
|
|
16
14
|
# as one, and the three text types are one string wearing three hats.
|
|
17
15
|
const NUMBERS: Array[int] = [TYPE_BOOL, TYPE_INT, TYPE_FLOAT]
|
|
18
16
|
const TEXTS: Array[int] = [TYPE_STRING, TYPE_STRING_NAME, TYPE_NODE_PATH]
|
|
19
|
-
|
|
20
17
|
# 2^53. A JSON number is a double, and every whole number below this one in size has a double of
|
|
21
18
|
# its own; from here on two or more share each double, so one arriving tells nobody which was sent.
|
|
22
|
-
const EXACT: int =
|
|
23
|
-
|
|
19
|
+
const EXACT: int = 9_007_199_254_740_992
|
|
24
20
|
# The types that cross as a plain JSON list and have to be built back into themselves. A list is
|
|
25
21
|
# what a caller can write by hand and what the serialiser answers with, and the parameter or
|
|
26
22
|
# property being written is the only thing that knows which of these it wanted.
|
|
@@ -35,7 +31,6 @@ const LIST_TYPES: Array[int] = [
|
|
|
35
31
|
TYPE_PACKED_VECTOR4_ARRAY,
|
|
36
32
|
TYPE_PACKED_COLOR_ARRAY,
|
|
37
33
|
]
|
|
38
|
-
|
|
39
34
|
# What each Godot type becomes on the wire, as one table you can read rather than an order you
|
|
40
35
|
# have to trust. Keyed on typeof() rather than written as a chain of `is` tests, because the
|
|
41
36
|
# order mattered: Resource had to be tested before Object or every resource came back as a bare
|
|
@@ -92,7 +87,6 @@ const SERIALISERS: Dictionary = {
|
|
|
92
87
|
TYPE_PACKED_VECTOR4_ARRAY: "_serialize_vector4s",
|
|
93
88
|
TYPE_PACKED_COLOR_ARRAY: "_serialize_colors",
|
|
94
89
|
}
|
|
95
|
-
|
|
96
90
|
# What each tag builds back into. The other half of the table above, and separate from it because
|
|
97
91
|
# they are keyed differently: one by the type of a value in hand, the other by the name in a
|
|
98
92
|
# dictionary that arrived from somewhere else.
|
|
@@ -144,7 +138,11 @@ func serialize_value(value: Variant) -> Variant:
|
|
|
144
138
|
# The fixed shapes carry their components as bare floats, so an infinite one in a Vector2 is
|
|
145
139
|
# tagged here, and a 32-bit one shortened; containers reach their members through this already.
|
|
146
140
|
var type: int = typeof(value)
|
|
147
|
-
return
|
|
141
|
+
return (
|
|
142
|
+
carried
|
|
143
|
+
if type in [TYPE_ARRAY, TYPE_DICTIONARY]
|
|
144
|
+
else _finite(carried, GdhRead.holds_singles(type))
|
|
145
|
+
)
|
|
148
146
|
|
|
149
147
|
|
|
150
148
|
# [param carried] with every non-finite float in it tagged. JSON has no spelling for infinity or
|
|
@@ -172,7 +170,10 @@ func _finite(carried: Variant, single: bool = false) -> Variant:
|
|
|
172
170
|
func _serialize_float(value: float) -> Variant:
|
|
173
171
|
if is_finite(value):
|
|
174
172
|
return value
|
|
175
|
-
return {
|
|
173
|
+
return {
|
|
174
|
+
"_type": "float",
|
|
175
|
+
"value": "nan" if is_nan(value) else ("inf" if value > 0 else "-inf"),
|
|
176
|
+
}
|
|
176
177
|
|
|
177
178
|
|
|
178
179
|
# A packed float array stays the JSON list it is unless something in it has no JSON spelling.
|
|
@@ -400,8 +401,9 @@ func fitted(value: Variant, type: int) -> Variant:
|
|
|
400
401
|
var simple: Array[int] = [TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING]
|
|
401
402
|
if not simple.has(type) or not simple.has(typeof(rebuilt)):
|
|
402
403
|
return rebuilt
|
|
403
|
-
# A number or a truth value stays as sent where text is wanted, for the refusal to name.
|
|
404
|
-
# 1 arrived as the double it is in JSON and was saved as "1.0", which is not the text
|
|
404
|
+
# A number or a truth value stays as sent where text is wanted, for the refusal to name.
|
|
405
|
+
# Converted, 1 arrived as the double it is in JSON and was saved as "1.0", which is not the text
|
|
406
|
+
# anyone sends.
|
|
405
407
|
if type == TYPE_STRING and not rebuilt is String:
|
|
406
408
|
return rebuilt
|
|
407
409
|
|
|
@@ -426,9 +428,10 @@ func fitted(value: Variant, type: int) -> Variant:
|
|
|
426
428
|
|
|
427
429
|
|
|
428
430
|
## Why [param given], meant for an int, may not be the number that was sent, or "" when it is. A
|
|
429
|
-
## JSON number is a double wherever it is read, so a whole number from 2^53 on arrives as the
|
|
430
|
-
## double to the one written: 9007199254740993 sent as a number arrives as 9007199254740992,
|
|
431
|
-
## seed written that way would be stored as its neighbour with the answer saying it was
|
|
431
|
+
## JSON number is a double wherever it is read, so a whole number from 2^53 on arrives as the
|
|
432
|
+
## nearest double to the one written: 9007199254740993 sent as a number arrives as 9007199254740992,
|
|
433
|
+
## and a seed written that way would be stored as its neighbour with the answer saying it was
|
|
434
|
+
## written.
|
|
432
435
|
static func inexact(given: Variant, type: int) -> String:
|
|
433
436
|
if type != TYPE_INT or (typeof(given) != TYPE_FLOAT and typeof(given) != TYPE_INT):
|
|
434
437
|
return ""
|
|
@@ -437,9 +440,9 @@ static func inexact(given: Variant, type: int) -> String:
|
|
|
437
440
|
return ""
|
|
438
441
|
return (
|
|
439
442
|
(
|
|
440
|
-
"%s is 2^53 or more, where a JSON number holds a whole number only to the nearest
|
|
441
|
-
+ ' so it may not be the number sent: send the digits as {"_type": "int",
|
|
442
|
-
+ ", the form a read answers with
|
|
443
|
+
"%s is 2^53 or more, where a JSON number holds a whole number only to the nearest "
|
|
444
|
+
+ 'double, so it may not be the number sent: send the digits as {"_type": "int", '
|
|
445
|
+
+ '"value": "..."}, the form a read answers with'
|
|
443
446
|
)
|
|
444
447
|
% String.num(number, 0)
|
|
445
448
|
)
|
|
@@ -450,51 +453,59 @@ func _serialize_nil(_value: Variant) -> Variant:
|
|
|
450
453
|
|
|
451
454
|
|
|
452
455
|
func _serialize_vector2(value: Vector2) -> Dictionary:
|
|
453
|
-
return {"x": value.x, "y": value.y, "_type": "Vector2"}
|
|
456
|
+
return { "x": value.x, "y": value.y, "_type": "Vector2" }
|
|
454
457
|
|
|
455
458
|
|
|
456
459
|
func _serialize_vector2i(value: Vector2i) -> Dictionary:
|
|
457
|
-
return {"x": value.x, "y": value.y, "_type": "Vector2i"}
|
|
460
|
+
return { "x": value.x, "y": value.y, "_type": "Vector2i" }
|
|
458
461
|
|
|
459
462
|
|
|
460
463
|
func _serialize_vector3(value: Vector3) -> Dictionary:
|
|
461
|
-
return {"x": value.x, "y": value.y, "z": value.z, "_type": "Vector3"}
|
|
464
|
+
return { "x": value.x, "y": value.y, "z": value.z, "_type": "Vector3" }
|
|
462
465
|
|
|
463
466
|
|
|
464
467
|
func _serialize_vector3i(value: Vector3i) -> Dictionary:
|
|
465
|
-
return {"x": value.x, "y": value.y, "z": value.z, "_type": "Vector3i"}
|
|
468
|
+
return { "x": value.x, "y": value.y, "z": value.z, "_type": "Vector3i" }
|
|
466
469
|
|
|
467
470
|
|
|
468
471
|
func _serialize_vector4(value: Vector4) -> Dictionary:
|
|
469
|
-
return {"x": value.x, "y": value.y, "z": value.z, "w": value.w, "_type": "Vector4"}
|
|
472
|
+
return { "x": value.x, "y": value.y, "z": value.z, "w": value.w, "_type": "Vector4" }
|
|
470
473
|
|
|
471
474
|
|
|
472
475
|
func _serialize_vector4i(value: Vector4i) -> Dictionary:
|
|
473
|
-
return {"x": value.x, "y": value.y, "z": value.z, "w": value.w, "_type": "Vector4i"}
|
|
476
|
+
return { "x": value.x, "y": value.y, "z": value.z, "w": value.w, "_type": "Vector4i" }
|
|
474
477
|
|
|
475
478
|
|
|
476
479
|
func _serialize_rect2(value: Rect2) -> Dictionary:
|
|
477
480
|
return {
|
|
478
|
-
"position": serialize_value(value.position),
|
|
481
|
+
"position": serialize_value(value.position),
|
|
482
|
+
"size": serialize_value(value.size),
|
|
483
|
+
"_type": "Rect2",
|
|
479
484
|
}
|
|
480
485
|
|
|
481
486
|
|
|
482
487
|
func _serialize_rect2i(value: Rect2i) -> Dictionary:
|
|
483
488
|
return {
|
|
484
|
-
"position": serialize_value(value.position),
|
|
489
|
+
"position": serialize_value(value.position),
|
|
490
|
+
"size": serialize_value(value.size),
|
|
491
|
+
"_type": "Rect2i",
|
|
485
492
|
}
|
|
486
493
|
|
|
487
494
|
|
|
488
495
|
func _serialize_plane(value: Plane) -> Dictionary:
|
|
489
|
-
return {"normal": serialize_value(value.normal), "d": value.d, "_type": "Plane"}
|
|
496
|
+
return { "normal": serialize_value(value.normal), "d": value.d, "_type": "Plane" }
|
|
490
497
|
|
|
491
498
|
|
|
492
499
|
func _serialize_quaternion(value: Quaternion) -> Dictionary:
|
|
493
|
-
return {"x": value.x, "y": value.y, "z": value.z, "w": value.w, "_type": "Quaternion"}
|
|
500
|
+
return { "x": value.x, "y": value.y, "z": value.z, "w": value.w, "_type": "Quaternion" }
|
|
494
501
|
|
|
495
502
|
|
|
496
503
|
func _serialize_aabb(value: AABB) -> Dictionary:
|
|
497
|
-
return {
|
|
504
|
+
return {
|
|
505
|
+
"position": serialize_value(value.position),
|
|
506
|
+
"size": serialize_value(value.size),
|
|
507
|
+
"_type": "AABB",
|
|
508
|
+
}
|
|
498
509
|
|
|
499
510
|
|
|
500
511
|
func _serialize_basis(value: Basis) -> Dictionary:
|
|
@@ -502,7 +513,7 @@ func _serialize_basis(value: Basis) -> Dictionary:
|
|
|
502
513
|
"x": serialize_value(value.x),
|
|
503
514
|
"y": serialize_value(value.y),
|
|
504
515
|
"z": serialize_value(value.z),
|
|
505
|
-
"_type": "Basis"
|
|
516
|
+
"_type": "Basis",
|
|
506
517
|
}
|
|
507
518
|
|
|
508
519
|
|
|
@@ -511,13 +522,15 @@ func _serialize_transform2d(value: Transform2D) -> Dictionary:
|
|
|
511
522
|
"origin": serialize_value(value.origin),
|
|
512
523
|
"x": serialize_value(value.x),
|
|
513
524
|
"y": serialize_value(value.y),
|
|
514
|
-
"_type": "Transform2D"
|
|
525
|
+
"_type": "Transform2D",
|
|
515
526
|
}
|
|
516
527
|
|
|
517
528
|
|
|
518
529
|
func _serialize_transform3d(value: Transform3D) -> Dictionary:
|
|
519
530
|
return {
|
|
520
|
-
"origin": serialize_value(value.origin),
|
|
531
|
+
"origin": serialize_value(value.origin),
|
|
532
|
+
"basis": serialize_value(value.basis),
|
|
533
|
+
"_type": "Transform3D",
|
|
521
534
|
}
|
|
522
535
|
|
|
523
536
|
|
|
@@ -527,22 +540,22 @@ func _serialize_projection(value: Projection) -> Dictionary:
|
|
|
527
540
|
"y": serialize_value(value.y),
|
|
528
541
|
"z": serialize_value(value.z),
|
|
529
542
|
"w": serialize_value(value.w),
|
|
530
|
-
"_type": "Projection"
|
|
543
|
+
"_type": "Projection",
|
|
531
544
|
}
|
|
532
545
|
|
|
533
546
|
|
|
534
547
|
func _serialize_color(value: Color) -> Dictionary:
|
|
535
|
-
return {"r": value.r, "g": value.g, "b": value.b, "a": value.a, "_type": "Color"}
|
|
548
|
+
return { "r": value.r, "g": value.g, "b": value.b, "a": value.a, "_type": "Color" }
|
|
536
549
|
|
|
537
550
|
|
|
538
551
|
func _serialize_node_path(value: NodePath) -> Dictionary:
|
|
539
|
-
return {"path": str(value), "_type": "NodePath"}
|
|
552
|
+
return { "path": str(value), "_type": "NodePath" }
|
|
540
553
|
|
|
541
554
|
|
|
542
555
|
# By its id, which is all an RID is from outside the server holding it, and which builds it back:
|
|
543
556
|
# a viewport's RID read off one call is what RenderingServer's render timing takes in the next.
|
|
544
557
|
func _serialize_rid(value: RID) -> Dictionary:
|
|
545
|
-
return {"id": _serialize_int(value.get_id()), "_type": "RID"}
|
|
558
|
+
return { "id": _serialize_int(value.get_id()), "_type": "RID" }
|
|
546
559
|
|
|
547
560
|
|
|
548
561
|
# A whole number from 2^53 on as its digits, because JSON numbers are doubles on the server's side
|
|
@@ -552,7 +565,7 @@ func _serialize_rid(value: RID) -> Dictionary:
|
|
|
552
565
|
func _serialize_int(value: int) -> Variant:
|
|
553
566
|
if value > -EXACT and value < EXACT:
|
|
554
567
|
return value
|
|
555
|
-
return {"_type": "int", "value": str(value)}
|
|
568
|
+
return { "_type": "int", "value": str(value) }
|
|
556
569
|
|
|
557
570
|
|
|
558
571
|
# A packed list of 64-bit numbers stays the JSON list it is unless something in it is too large for
|
|
@@ -570,7 +583,7 @@ func _serialize_ints(value: PackedInt64Array) -> Variant:
|
|
|
570
583
|
# A bound method, said in the terms a caller could act on: what it is on, and what it is called.
|
|
571
584
|
# It cannot be rebuilt from here, and saying so is the answer rather than a silent null.
|
|
572
585
|
func _serialize_callable(value: Callable) -> Dictionary:
|
|
573
|
-
var described: Dictionary = {"method": str(value.get_method()), "_type": "Callable"}
|
|
586
|
+
var described: Dictionary = { "method": str(value.get_method()), "_type": "Callable" }
|
|
574
587
|
var holder: Object = value.get_object()
|
|
575
588
|
if holder != null:
|
|
576
589
|
described["object"] = _describe_object(holder)
|
|
@@ -578,7 +591,7 @@ func _serialize_callable(value: Callable) -> Dictionary:
|
|
|
578
591
|
|
|
579
592
|
|
|
580
593
|
func _serialize_signal(value: Signal) -> Dictionary:
|
|
581
|
-
var described: Dictionary = {"name": str(value.get_name()), "_type": "Signal"}
|
|
594
|
+
var described: Dictionary = { "name": str(value.get_name()), "_type": "Signal" }
|
|
582
595
|
var holder: Object = value.get_object()
|
|
583
596
|
if holder != null:
|
|
584
597
|
described["object"] = _describe_object(holder)
|
|
@@ -589,12 +602,14 @@ func _serialize_signal(value: Signal) -> Dictionary:
|
|
|
589
602
|
## int or Vector2 key was answered as its text, and a dictionary read and written back had its keys
|
|
590
603
|
## replaced by words: `{1: "a"}` came back as `{"1": "a"}`.
|
|
591
604
|
func _serialize_dictionary(value: Dictionary) -> Dictionary:
|
|
592
|
-
var texts: bool = value.keys().all(
|
|
605
|
+
var texts: bool = value.keys().all(
|
|
606
|
+
func(key: Variant) -> bool: return key is String or key is StringName
|
|
607
|
+
)
|
|
593
608
|
if not texts:
|
|
594
609
|
var entries: Array = []
|
|
595
610
|
for key: Variant in value:
|
|
596
611
|
entries.append([serialize_value(key), serialize_value(value[key])])
|
|
597
|
-
return {"_type": "Dictionary", "entries": entries}
|
|
612
|
+
return { "_type": "Dictionary", "entries": entries }
|
|
598
613
|
var serialised: Dictionary = {}
|
|
599
614
|
for key: Variant in value:
|
|
600
615
|
serialised[str(key)] = serialize_value(value[key])
|
|
@@ -612,7 +627,7 @@ func _serialize_array(value: Array) -> Array:
|
|
|
612
627
|
# TileMapLayer with nothing painted yet, so a read of one carried an engine error in its answer.
|
|
613
628
|
func _serialize_bytes(value: PackedByteArray) -> Dictionary:
|
|
614
629
|
var text: String = "" if value.is_empty() else Marshalls.raw_to_base64(value)
|
|
615
|
-
return {"base64": text, "size": value.size(), "_type": "PackedByteArray"}
|
|
630
|
+
return { "base64": text, "size": value.size(), "_type": "PackedByteArray" }
|
|
616
631
|
|
|
617
632
|
|
|
618
633
|
# The packed vector and colour arrays, each element serialised the way one of them on its own is.
|
|
@@ -660,7 +675,7 @@ func _serialize_object(value: Object) -> Variant:
|
|
|
660
675
|
if resource.resource_path.is_empty() or resource.resource_path.contains("::"):
|
|
661
676
|
return _describe_built_in(resource)
|
|
662
677
|
var filed: Dictionary = {
|
|
663
|
-
"path": resource.resource_path, "class": resource.get_class(), "_type": "Resource"
|
|
678
|
+
"path": resource.resource_path, "class": resource.get_class(), "_type": "Resource",
|
|
664
679
|
}
|
|
665
680
|
# The engine class of a resource with a script is the one its script extends, so a Stats
|
|
666
681
|
# file read as a Resource and nothing said it was a Stats.
|
|
@@ -673,7 +688,7 @@ func _serialize_object(value: Object) -> Variant:
|
|
|
673
688
|
if value is Node:
|
|
674
689
|
var node: Node = value
|
|
675
690
|
if node.is_inside_tree():
|
|
676
|
-
return {"path": str(node.get_path()), "class": node.get_class(), "_type": "Node"}
|
|
691
|
+
return { "path": str(node.get_path()), "class": node.get_class(), "_type": "Node" }
|
|
677
692
|
return _describe_object(value)
|
|
678
693
|
|
|
679
694
|
|
|
@@ -683,16 +698,16 @@ func _serialize_object(value: Object) -> Variant:
|
|
|
683
698
|
## written back.
|
|
684
699
|
func _describe_built_in(resource: Resource) -> Dictionary:
|
|
685
700
|
if _describing.has(resource):
|
|
686
|
-
return {"class": resource.get_class(), "_type": "Resource"}
|
|
701
|
+
return { "class": resource.get_class(), "_type": "Resource" }
|
|
687
702
|
_describing.append(resource)
|
|
688
|
-
var described: Dictionary = {"_type": resource.get_class()}
|
|
703
|
+
var described: Dictionary = { "_type": resource.get_class() }
|
|
689
704
|
var attached: Variant = resource.get_script()
|
|
690
705
|
var script: Script = null
|
|
691
706
|
if attached is Script:
|
|
692
707
|
script = attached
|
|
693
708
|
# By the class its script declares, which a write takes as the _type and which says what it
|
|
694
|
-
# is: as Resource with the script beside it, one answer named a Shop's built-in item that
|
|
695
|
-
# and the file item beside it as an Item.
|
|
709
|
+
# is: as Resource with the script beside it, one answer named a Shop's built-in item that
|
|
710
|
+
# way and the file item beside it as an Item.
|
|
696
711
|
if script.get_global_name().is_empty():
|
|
697
712
|
described["script"] = serialize_value(script)
|
|
698
713
|
else:
|
|
@@ -741,11 +756,17 @@ static func _fresh(script: Script) -> Object:
|
|
|
741
756
|
## away from its default. As a bare resource it was its class and nothing else, so an input action
|
|
742
757
|
## read back from project.godot could not say whether it was bound to Space or to a joypad button.
|
|
743
758
|
func _describe_input_event(event: InputEvent) -> Dictionary:
|
|
744
|
-
var described: Dictionary = {
|
|
759
|
+
var described: Dictionary = {
|
|
760
|
+
"class": event.get_class(), "_type": "Resource", "text": event.as_text(),
|
|
761
|
+
}
|
|
745
762
|
for property: Dictionary in event.get_property_list():
|
|
746
763
|
var usage: int = property.get("usage", 0)
|
|
747
764
|
var name: String = str(property.get("name", ""))
|
|
748
|
-
if
|
|
765
|
+
if (
|
|
766
|
+
not (usage & PROPERTY_USAGE_STORAGE)
|
|
767
|
+
or name.begins_with("resource_")
|
|
768
|
+
or name == "script"
|
|
769
|
+
):
|
|
749
770
|
continue
|
|
750
771
|
var held: Variant = event.get(name)
|
|
751
772
|
if held == ClassDB.class_get_property_default_value(event.get_class(), name):
|
|
@@ -764,7 +785,7 @@ func _describe_input_event(event: InputEvent) -> Dictionary:
|
|
|
764
785
|
## different per object. None of it is invented: every field is left out when there is nothing to
|
|
765
786
|
## put in it, because a key holding "" is a worse answer than a key that is not there.
|
|
766
787
|
func _describe_object(value: Object) -> Dictionary:
|
|
767
|
-
var described: Dictionary = {"class": value.get_class(), "_type": "Object"}
|
|
788
|
+
var described: Dictionary = { "class": value.get_class(), "_type": "Object" }
|
|
768
789
|
# Asked as a Variant and narrowed, because get_script answers one and an object without a
|
|
769
790
|
# script answers null: casting that to Script is the unsafe cast the engine refuses to compile.
|
|
770
791
|
var attached: Variant = value.get_script()
|
|
@@ -892,7 +913,10 @@ func _build_transform3d(fields: Dictionary) -> Transform3D:
|
|
|
892
913
|
|
|
893
914
|
func _build_projection(fields: Dictionary) -> Projection:
|
|
894
915
|
return Projection(
|
|
895
|
-
_vector4_at(fields, "x"),
|
|
916
|
+
_vector4_at(fields, "x"),
|
|
917
|
+
_vector4_at(fields, "y"),
|
|
918
|
+
_vector4_at(fields, "z"),
|
|
919
|
+
_vector4_at(fields, "w")
|
|
896
920
|
)
|
|
897
921
|
|
|
898
922
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
extends RefCounted
|
|
2
|
-
|
|
3
2
|
## Project settings read the same way headless and from the open editor, because the two are one
|
|
4
3
|
## question asked of two places: a field one of them left out read as the editor and the file
|
|
5
4
|
## disagreeing about something they agree about.
|
|
@@ -12,7 +11,7 @@ const GdhSerialisation = preload("serialisation.gd")
|
|
|
12
11
|
## the feature overrides that replace it in some builds.
|
|
13
12
|
static func one(setting_path: String, values: GdhSerialisation) -> Dictionary:
|
|
14
13
|
var result: Dictionary = {
|
|
15
|
-
"setting_path": setting_path, "exists": ProjectSettings.has_setting(setting_path)
|
|
14
|
+
"setting_path": setting_path, "exists": ProjectSettings.has_setting(setting_path),
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
if result["exists"]:
|
|
@@ -66,8 +65,8 @@ static func under(prefix: String, values: GdhSerialisation) -> Dictionary:
|
|
|
66
65
|
"type": type_string(kind),
|
|
67
66
|
"value": values.serialize_value(value),
|
|
68
67
|
}
|
|
69
|
-
# As a single get says it, so a family read can be told apart into what the project sets
|
|
70
|
-
#
|
|
68
|
+
# As a single get says it, so a family read can be told apart into what the project sets and
|
|
69
|
+
# the engine's defaults: "input/" is ninety actions the engine ships and the project's few.
|
|
71
70
|
var default_value: Variant = ProjectSettings.property_get_revert(name)
|
|
72
71
|
if default_value != null:
|
|
73
72
|
described["at_default"] = value == default_value
|
|
@@ -76,8 +75,10 @@ static func under(prefix: String, values: GdhSerialisation) -> Dictionary:
|
|
|
76
75
|
described["override_of"] = base
|
|
77
76
|
found.append(described)
|
|
78
77
|
|
|
79
|
-
found.sort_custom(
|
|
80
|
-
|
|
78
|
+
found.sort_custom(
|
|
79
|
+
func(a: Dictionary, b: Dictionary) -> bool: return a["setting"] < b["setting"]
|
|
80
|
+
)
|
|
81
|
+
return { "prefix": prefix, "count": found.size(), "settings": found }
|
|
81
82
|
|
|
82
83
|
|
|
83
84
|
## The setting [param setting_path] overrides for builds with one feature, as
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
@tool
|
|
2
2
|
extends Node
|
|
3
|
-
|
|
4
3
|
## Routes each command the server sends to the tool module that answers it. The modules are
|
|
5
4
|
## preloaded rather than looked up on disk at runtime, so a missing one fails to parse here
|
|
6
5
|
## instead of leaving a command silently unanswered.
|
|
@@ -20,7 +19,6 @@ const GdhFilesystemTools = preload("tools/filesystem_tools.gd")
|
|
|
20
19
|
const GdhProfileTools = preload("tools/profile_tools.gd")
|
|
21
20
|
|
|
22
21
|
var _editor_plugin: EditorPlugin = null
|
|
23
|
-
|
|
24
22
|
var _scene_tools: GdhSceneTools = null
|
|
25
23
|
var _signal_tools: GdhSignalTools = null
|
|
26
24
|
var _resource_tools: GdhResourceTools = null
|
|
@@ -33,7 +31,6 @@ var _class_tools: GdhClassTools = null
|
|
|
33
31
|
var _settings_tools: GdhSettingsTools = null
|
|
34
32
|
var _filesystem_tools: GdhFilesystemTools = null
|
|
35
33
|
var _profile_tools: GdhProfileTools = null
|
|
36
|
-
|
|
37
34
|
var _tool_map: Dictionary = {}
|
|
38
35
|
var _initialized: bool = false
|
|
39
36
|
|
|
@@ -169,14 +166,14 @@ func _init_tools() -> void:
|
|
|
169
166
|
|
|
170
167
|
func execute_tool(tool_name: String, args: Dictionary) -> Dictionary:
|
|
171
168
|
if not _tool_map.has(tool_name):
|
|
172
|
-
return {"ok": false, "error": "Unknown tool: " + tool_name}
|
|
169
|
+
return { "ok": false, "error": "Unknown tool: " + tool_name }
|
|
173
170
|
|
|
174
171
|
var handler: Array = _tool_map[tool_name]
|
|
175
172
|
var node: Node = handler[0]
|
|
176
173
|
var method: String = handler[1]
|
|
177
174
|
|
|
178
175
|
if not node.has_method(method):
|
|
179
|
-
return {"ok": false, "error": "Tool method not found: %s.%s" % [node.name, method]}
|
|
176
|
+
return { "ok": false, "error": "Tool method not found: %s.%s" % [node.name, method] }
|
|
180
177
|
|
|
181
178
|
GdhSceneFile.also_saved.clear()
|
|
182
179
|
var result: Variant = node.call(method, args)
|
|
@@ -187,4 +184,4 @@ func execute_tool(tool_name: String, args: Dictionary) -> Dictionary:
|
|
|
187
184
|
GdhSceneFile.also_saved.clear()
|
|
188
185
|
return answered
|
|
189
186
|
|
|
190
|
-
return {"ok": false, "error": "Invalid tool result from: " + tool_name}
|
|
187
|
+
return { "ok": false, "error": "Invalid tool result from: " + tool_name }
|