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,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 }
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
@tool
|
|
2
2
|
extends "animation_tools.gd"
|
|
3
|
-
|
|
4
3
|
## The states and transitions of an AnimationTree's state machines, beside the players and tracks
|
|
5
4
|
## the script it extends edits, whose helpers it shares.
|
|
6
5
|
|
|
@@ -16,9 +15,9 @@ func add_animation_state(args: Dictionary) -> Dictionary:
|
|
|
16
15
|
var state_name: String = str(args.get("stateName", ""))
|
|
17
16
|
var animation_name: String = str(args.get("animationName", ""))
|
|
18
17
|
if state_name.is_empty():
|
|
19
|
-
return {"ok": false, "error": "Missing stateName"}
|
|
18
|
+
return { "ok": false, "error": "Missing stateName" }
|
|
20
19
|
if animation_name.is_empty():
|
|
21
|
-
return {"ok": false, "error": "Missing animationName"}
|
|
20
|
+
return { "ok": false, "error": "Missing animationName" }
|
|
22
21
|
var machine: Array = _machine_at(args)
|
|
23
22
|
if machine[1] == null:
|
|
24
23
|
return machine[3]
|
|
@@ -29,7 +28,8 @@ func add_animation_state(args: Dictionary) -> Dictionary:
|
|
|
29
28
|
# are in use in every state machine.
|
|
30
29
|
if sm.has_node(StringName(state_name)):
|
|
31
30
|
return scene.refuse("The state machine already has a state named %s." % state_name)
|
|
32
|
-
var
|
|
31
|
+
var reached: Node = anim_tree.get_node_or_null(anim_tree.anim_player)
|
|
32
|
+
var player: AnimationPlayer = reached as AnimationPlayer
|
|
33
33
|
var found: bool = player != null and player.has_animation(StringName(animation_name))
|
|
34
34
|
|
|
35
35
|
var anim_node: AnimationNodeAnimation = AnimationNodeAnimation.new()
|
|
@@ -57,7 +57,11 @@ func add_animation_state(args: Dictionary) -> Dictionary:
|
|
|
57
57
|
}
|
|
58
58
|
# Written all the same, as the editor writes one: a state machine is often laid out before its
|
|
59
59
|
# animations are made, and refusing it stopped a tree being built in that order.
|
|
60
|
-
if player
|
|
60
|
+
if player == null:
|
|
61
|
+
answer["animationMissing"] = GdhAnimationReads.no_player(
|
|
62
|
+
str(anim_tree.anim_player), reached
|
|
63
|
+
)
|
|
64
|
+
elif not found:
|
|
61
65
|
answer["animationMissing"] = GdhAnimationReads.missing_animation(
|
|
62
66
|
player, scene.path_of(player), animation_name
|
|
63
67
|
)
|
|
@@ -73,14 +77,14 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
73
77
|
var to_state: String = str(args.get("toState", ""))
|
|
74
78
|
var transition_type: String = str(args.get("transitionType", "immediate"))
|
|
75
79
|
var advance_condition: String = str(args.get("advanceCondition", ""))
|
|
76
|
-
# Auto where it is the only mode that does what was asked: a condition is checked only on an
|
|
77
|
-
# transition, and a machine leaves Start only through one. Written as the default enabled,
|
|
78
|
-
# did nothing, and the machine sat in Start with its conditions true.
|
|
80
|
+
# Auto where it is the only mode that does what was asked: a condition is checked only on an
|
|
81
|
+
# auto transition, and a machine leaves Start only through one. Written as the default enabled,
|
|
82
|
+
# both did nothing, and the machine sat in Start with its conditions true.
|
|
79
83
|
var auto: bool = not advance_condition.is_empty() or from_state == "Start"
|
|
80
84
|
var advance_mode: String = str(args.get("advanceMode", "auto" if auto else "enabled"))
|
|
81
85
|
|
|
82
86
|
if from_state.is_empty() or to_state.is_empty():
|
|
83
|
-
return {"ok": false, "error": "Missing fromState or toState"}
|
|
87
|
+
return { "ok": false, "error": "Missing fromState or toState" }
|
|
84
88
|
var advances: Dictionary = {
|
|
85
89
|
"auto": AnimationNodeStateMachineTransition.ADVANCE_MODE_AUTO,
|
|
86
90
|
"enabled": AnimationNodeStateMachineTransition.ADVANCE_MODE_ENABLED,
|
|
@@ -89,7 +93,7 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
89
93
|
if not advances.has(advance_mode):
|
|
90
94
|
return {
|
|
91
95
|
"ok": false,
|
|
92
|
-
"error": "Unsupported advanceMode: %s; it is auto, enabled or disabled" % advance_mode
|
|
96
|
+
"error": "Unsupported advanceMode: %s; it is auto, enabled or disabled" % advance_mode,
|
|
93
97
|
}
|
|
94
98
|
if not advance_condition.is_empty() and advance_mode != "auto":
|
|
95
99
|
return {
|
|
@@ -97,11 +101,12 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
97
101
|
"error":
|
|
98
102
|
(
|
|
99
103
|
(
|
|
100
|
-
"advanceCondition %s would never advance a transition whose advanceMode is %s:
|
|
101
|
-
+ " checks a condition only on an auto one. Leave advanceMode out,
|
|
104
|
+
"advanceCondition %s would never advance a transition whose advanceMode is %s: "
|
|
105
|
+
+ "the engine checks a condition only on an auto one. Leave advanceMode out, "
|
|
106
|
+
+ "or give auto"
|
|
102
107
|
)
|
|
103
108
|
% [advance_condition, advance_mode]
|
|
104
|
-
)
|
|
109
|
+
),
|
|
105
110
|
}
|
|
106
111
|
var modes: Dictionary = {
|
|
107
112
|
"sync": AnimationNodeStateMachineTransition.SWITCH_MODE_SYNC,
|
|
@@ -109,7 +114,7 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
109
114
|
"immediate": AnimationNodeStateMachineTransition.SWITCH_MODE_IMMEDIATE,
|
|
110
115
|
}
|
|
111
116
|
if not modes.has(transition_type):
|
|
112
|
-
return {"ok": false, "error": "Unsupported transitionType: " + transition_type}
|
|
117
|
+
return { "ok": false, "error": "Unsupported transitionType: " + transition_type }
|
|
113
118
|
var transition: AnimationNodeStateMachineTransition = AnimationNodeStateMachineTransition.new()
|
|
114
119
|
transition.switch_mode = (
|
|
115
120
|
GdhRead.as_int(modes[transition_type]) as AnimationNodeStateMachineTransition.SwitchMode
|
|
@@ -137,14 +142,16 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
137
142
|
scene,
|
|
138
143
|
Callable(),
|
|
139
144
|
files,
|
|
140
|
-
{"ok": true, "from": from_state, "to": to_state, "advanceMode": advance_mode}
|
|
145
|
+
{ "ok": true, "from": from_state, "to": to_state, "advanceMode": advance_mode }
|
|
141
146
|
)
|
|
142
147
|
|
|
143
148
|
|
|
144
149
|
## Why [param sm] cannot take a transition from [param from_state] to [param to_state], or "".
|
|
145
150
|
## Each is a condition add_transition fails on with only a line in the editor's log, and the
|
|
146
151
|
## transition was answered as made.
|
|
147
|
-
func _transition_problem(
|
|
152
|
+
func _transition_problem(
|
|
153
|
+
sm: AnimationNodeStateMachine, from_state: String, to_state: String
|
|
154
|
+
) -> String:
|
|
148
155
|
for state: String in [from_state, to_state]:
|
|
149
156
|
if not sm.has_node(StringName(state)):
|
|
150
157
|
return _no_state(sm, state)
|
|
@@ -169,7 +176,8 @@ static func _no_state(sm: AnimationNodeStateMachine, state_name: String) -> Stri
|
|
|
169
176
|
var close: PackedStringArray = GdhRead.nearest(state_name, states)
|
|
170
177
|
if not close.is_empty():
|
|
171
178
|
return (
|
|
172
|
-
"%s; the nearest it has %s %s."
|
|
179
|
+
"%s; the nearest it has %s %s."
|
|
180
|
+
% [said, "is" if close.size() == 1 else "are", ", ".join(close)]
|
|
173
181
|
)
|
|
174
182
|
return "%s; its states are %s." % [said, ", ".join(states)]
|
|
175
183
|
|
|
@@ -180,9 +188,9 @@ func _machine_at(args: Dictionary) -> Array:
|
|
|
180
188
|
var scene_path: String = GdhSceneFile.res_path("", str(args.get("scenePath", "")))
|
|
181
189
|
var anim_tree_path: String = str(args.get("animTreePath", ""))
|
|
182
190
|
if scene_path.strip_edges() == "res://":
|
|
183
|
-
return [null, null, {}, {"ok": false, "error": "Missing scenePath"}]
|
|
191
|
+
return [null, null, {}, { "ok": false, "error": "Missing scenePath" }]
|
|
184
192
|
if anim_tree_path.is_empty():
|
|
185
|
-
return [null, null, {}, {"ok": false, "error": "Missing animTreePath"}]
|
|
193
|
+
return [null, null, {}, { "ok": false, "error": "Missing animTreePath" }]
|
|
186
194
|
var opened: Array = _open_at(scene_path, anim_tree_path, "AnimationTree")
|
|
187
195
|
var scene: GdhSceneFile = opened[0]
|
|
188
196
|
if opened[1] == null:
|
|
@@ -203,14 +211,16 @@ func _machine_at(args: Dictionary) -> Array:
|
|
|
203
211
|
func remove_animation_state(args: Dictionary) -> Dictionary:
|
|
204
212
|
var state_name: String = str(args.get("stateName", ""))
|
|
205
213
|
if state_name.is_empty():
|
|
206
|
-
return {"ok": false, "error": "Missing stateName"}
|
|
214
|
+
return { "ok": false, "error": "Missing stateName" }
|
|
207
215
|
var found: Array = _machine_at(args)
|
|
208
216
|
if found[1] == null:
|
|
209
217
|
return found[3]
|
|
210
218
|
var scene: GdhSceneFile = found[0]
|
|
211
219
|
var sm: AnimationNodeStateMachine = found[1]
|
|
212
220
|
if state_name in ["Start", "End"]:
|
|
213
|
-
return scene.refuse(
|
|
221
|
+
return scene.refuse(
|
|
222
|
+
"%s is part of every state machine, so it cannot be removed." % state_name
|
|
223
|
+
)
|
|
214
224
|
if not sm.has_node(StringName(state_name)):
|
|
215
225
|
return scene.refuse(_no_state(sm, state_name))
|
|
216
226
|
var dropped: Array = []
|
|
@@ -218,7 +228,7 @@ func remove_animation_state(args: Dictionary) -> Dictionary:
|
|
|
218
228
|
var from: String = str(sm.get_transition_from(index))
|
|
219
229
|
var to: String = str(sm.get_transition_to(index))
|
|
220
230
|
if state_name in [from, to]:
|
|
221
|
-
dropped.append({"from": from, "to": to})
|
|
231
|
+
dropped.append({ "from": from, "to": to })
|
|
222
232
|
sm.remove_node(StringName(state_name))
|
|
223
233
|
if sm.has_node(StringName(state_name)):
|
|
224
234
|
return scene.refuse("The state machine did not let go of %s." % state_name)
|
|
@@ -228,9 +238,8 @@ func remove_animation_state(args: Dictionary) -> Dictionary:
|
|
|
228
238
|
"The state machine kept a transition of %s after the state went." % state_name
|
|
229
239
|
)
|
|
230
240
|
var files: Dictionary = found[2]
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
)
|
|
241
|
+
var answer: Dictionary = { "ok": true, "removed": state_name, "transitionsRemoved": dropped }
|
|
242
|
+
return _finish(scene, Callable(), files, answer)
|
|
234
243
|
|
|
235
244
|
|
|
236
245
|
## Takes out the transition from one state to another.
|
|
@@ -238,7 +247,7 @@ func disconnect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
238
247
|
var from_state: String = str(args.get("fromState", ""))
|
|
239
248
|
var to_state: String = str(args.get("toState", ""))
|
|
240
249
|
if from_state.is_empty() or to_state.is_empty():
|
|
241
|
-
return {"ok": false, "error": "Missing fromState or toState"}
|
|
250
|
+
return { "ok": false, "error": "Missing fromState or toState" }
|
|
242
251
|
var found: Array = _machine_at(args)
|
|
243
252
|
if found[1] == null:
|
|
244
253
|
return found[3]
|
|
@@ -255,9 +264,13 @@ func disconnect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
255
264
|
var said: String = "There is no transition from %s to %s" % [from_state, to_state]
|
|
256
265
|
if leaving.is_empty():
|
|
257
266
|
return scene.refuse("%s; none leaves %s." % [said, from_state])
|
|
258
|
-
return scene.refuse(
|
|
267
|
+
return scene.refuse(
|
|
268
|
+
"%s; the ones leaving %s go to %s." % [said, from_state, ", ".join(leaving)]
|
|
269
|
+
)
|
|
259
270
|
sm.remove_transition(StringName(from_state), StringName(to_state))
|
|
260
271
|
if sm.has_transition(StringName(from_state), StringName(to_state)):
|
|
261
272
|
return scene.refuse("The state machine did not let go of the transition.")
|
|
262
273
|
var files: Dictionary = found[2]
|
|
263
|
-
return _finish(
|
|
274
|
+
return _finish(
|
|
275
|
+
scene, Callable(), files, { "ok": true, "removed": { "from": from_state, "to": to_state } }
|
|
276
|
+
)
|