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 "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]
|
|
@@ -59,7 +58,9 @@ func add_animation_state(args: Dictionary) -> Dictionary:
|
|
|
59
58
|
# Written all the same, as the editor writes one: a state machine is often laid out before its
|
|
60
59
|
# animations are made, and refusing it stopped a tree being built in that order.
|
|
61
60
|
if player == null:
|
|
62
|
-
answer["animationMissing"] = GdhAnimationReads.no_player(
|
|
61
|
+
answer["animationMissing"] = GdhAnimationReads.no_player(
|
|
62
|
+
str(anim_tree.anim_player), reached
|
|
63
|
+
)
|
|
63
64
|
elif not found:
|
|
64
65
|
answer["animationMissing"] = GdhAnimationReads.missing_animation(
|
|
65
66
|
player, scene.path_of(player), animation_name
|
|
@@ -76,14 +77,14 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
76
77
|
var to_state: String = str(args.get("toState", ""))
|
|
77
78
|
var transition_type: String = str(args.get("transitionType", "immediate"))
|
|
78
79
|
var advance_condition: String = str(args.get("advanceCondition", ""))
|
|
79
|
-
# Auto where it is the only mode that does what was asked: a condition is checked only on an
|
|
80
|
-
# transition, and a machine leaves Start only through one. Written as the default enabled,
|
|
81
|
-
# 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.
|
|
82
83
|
var auto: bool = not advance_condition.is_empty() or from_state == "Start"
|
|
83
84
|
var advance_mode: String = str(args.get("advanceMode", "auto" if auto else "enabled"))
|
|
84
85
|
|
|
85
86
|
if from_state.is_empty() or to_state.is_empty():
|
|
86
|
-
return {"ok": false, "error": "Missing fromState or toState"}
|
|
87
|
+
return { "ok": false, "error": "Missing fromState or toState" }
|
|
87
88
|
var advances: Dictionary = {
|
|
88
89
|
"auto": AnimationNodeStateMachineTransition.ADVANCE_MODE_AUTO,
|
|
89
90
|
"enabled": AnimationNodeStateMachineTransition.ADVANCE_MODE_ENABLED,
|
|
@@ -92,7 +93,7 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
92
93
|
if not advances.has(advance_mode):
|
|
93
94
|
return {
|
|
94
95
|
"ok": false,
|
|
95
|
-
"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,
|
|
96
97
|
}
|
|
97
98
|
if not advance_condition.is_empty() and advance_mode != "auto":
|
|
98
99
|
return {
|
|
@@ -100,11 +101,12 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
100
101
|
"error":
|
|
101
102
|
(
|
|
102
103
|
(
|
|
103
|
-
"advanceCondition %s would never advance a transition whose advanceMode is %s:
|
|
104
|
-
+ " 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"
|
|
105
107
|
)
|
|
106
108
|
% [advance_condition, advance_mode]
|
|
107
|
-
)
|
|
109
|
+
),
|
|
108
110
|
}
|
|
109
111
|
var modes: Dictionary = {
|
|
110
112
|
"sync": AnimationNodeStateMachineTransition.SWITCH_MODE_SYNC,
|
|
@@ -112,7 +114,7 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
112
114
|
"immediate": AnimationNodeStateMachineTransition.SWITCH_MODE_IMMEDIATE,
|
|
113
115
|
}
|
|
114
116
|
if not modes.has(transition_type):
|
|
115
|
-
return {"ok": false, "error": "Unsupported transitionType: " + transition_type}
|
|
117
|
+
return { "ok": false, "error": "Unsupported transitionType: " + transition_type }
|
|
116
118
|
var transition: AnimationNodeStateMachineTransition = AnimationNodeStateMachineTransition.new()
|
|
117
119
|
transition.switch_mode = (
|
|
118
120
|
GdhRead.as_int(modes[transition_type]) as AnimationNodeStateMachineTransition.SwitchMode
|
|
@@ -140,14 +142,16 @@ func connect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
140
142
|
scene,
|
|
141
143
|
Callable(),
|
|
142
144
|
files,
|
|
143
|
-
{"ok": true, "from": from_state, "to": to_state, "advanceMode": advance_mode}
|
|
145
|
+
{ "ok": true, "from": from_state, "to": to_state, "advanceMode": advance_mode }
|
|
144
146
|
)
|
|
145
147
|
|
|
146
148
|
|
|
147
149
|
## Why [param sm] cannot take a transition from [param from_state] to [param to_state], or "".
|
|
148
150
|
## Each is a condition add_transition fails on with only a line in the editor's log, and the
|
|
149
151
|
## transition was answered as made.
|
|
150
|
-
func _transition_problem(
|
|
152
|
+
func _transition_problem(
|
|
153
|
+
sm: AnimationNodeStateMachine, from_state: String, to_state: String
|
|
154
|
+
) -> String:
|
|
151
155
|
for state: String in [from_state, to_state]:
|
|
152
156
|
if not sm.has_node(StringName(state)):
|
|
153
157
|
return _no_state(sm, state)
|
|
@@ -172,7 +176,8 @@ static func _no_state(sm: AnimationNodeStateMachine, state_name: String) -> Stri
|
|
|
172
176
|
var close: PackedStringArray = GdhRead.nearest(state_name, states)
|
|
173
177
|
if not close.is_empty():
|
|
174
178
|
return (
|
|
175
|
-
"%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)]
|
|
176
181
|
)
|
|
177
182
|
return "%s; its states are %s." % [said, ", ".join(states)]
|
|
178
183
|
|
|
@@ -183,9 +188,9 @@ func _machine_at(args: Dictionary) -> Array:
|
|
|
183
188
|
var scene_path: String = GdhSceneFile.res_path("", str(args.get("scenePath", "")))
|
|
184
189
|
var anim_tree_path: String = str(args.get("animTreePath", ""))
|
|
185
190
|
if scene_path.strip_edges() == "res://":
|
|
186
|
-
return [null, null, {}, {"ok": false, "error": "Missing scenePath"}]
|
|
191
|
+
return [null, null, {}, { "ok": false, "error": "Missing scenePath" }]
|
|
187
192
|
if anim_tree_path.is_empty():
|
|
188
|
-
return [null, null, {}, {"ok": false, "error": "Missing animTreePath"}]
|
|
193
|
+
return [null, null, {}, { "ok": false, "error": "Missing animTreePath" }]
|
|
189
194
|
var opened: Array = _open_at(scene_path, anim_tree_path, "AnimationTree")
|
|
190
195
|
var scene: GdhSceneFile = opened[0]
|
|
191
196
|
if opened[1] == null:
|
|
@@ -206,14 +211,16 @@ func _machine_at(args: Dictionary) -> Array:
|
|
|
206
211
|
func remove_animation_state(args: Dictionary) -> Dictionary:
|
|
207
212
|
var state_name: String = str(args.get("stateName", ""))
|
|
208
213
|
if state_name.is_empty():
|
|
209
|
-
return {"ok": false, "error": "Missing stateName"}
|
|
214
|
+
return { "ok": false, "error": "Missing stateName" }
|
|
210
215
|
var found: Array = _machine_at(args)
|
|
211
216
|
if found[1] == null:
|
|
212
217
|
return found[3]
|
|
213
218
|
var scene: GdhSceneFile = found[0]
|
|
214
219
|
var sm: AnimationNodeStateMachine = found[1]
|
|
215
220
|
if state_name in ["Start", "End"]:
|
|
216
|
-
return scene.refuse(
|
|
221
|
+
return scene.refuse(
|
|
222
|
+
"%s is part of every state machine, so it cannot be removed." % state_name
|
|
223
|
+
)
|
|
217
224
|
if not sm.has_node(StringName(state_name)):
|
|
218
225
|
return scene.refuse(_no_state(sm, state_name))
|
|
219
226
|
var dropped: Array = []
|
|
@@ -221,7 +228,7 @@ func remove_animation_state(args: Dictionary) -> Dictionary:
|
|
|
221
228
|
var from: String = str(sm.get_transition_from(index))
|
|
222
229
|
var to: String = str(sm.get_transition_to(index))
|
|
223
230
|
if state_name in [from, to]:
|
|
224
|
-
dropped.append({"from": from, "to": to})
|
|
231
|
+
dropped.append({ "from": from, "to": to })
|
|
225
232
|
sm.remove_node(StringName(state_name))
|
|
226
233
|
if sm.has_node(StringName(state_name)):
|
|
227
234
|
return scene.refuse("The state machine did not let go of %s." % state_name)
|
|
@@ -231,9 +238,8 @@ func remove_animation_state(args: Dictionary) -> Dictionary:
|
|
|
231
238
|
"The state machine kept a transition of %s after the state went." % state_name
|
|
232
239
|
)
|
|
233
240
|
var files: Dictionary = found[2]
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
)
|
|
241
|
+
var answer: Dictionary = { "ok": true, "removed": state_name, "transitionsRemoved": dropped }
|
|
242
|
+
return _finish(scene, Callable(), files, answer)
|
|
237
243
|
|
|
238
244
|
|
|
239
245
|
## Takes out the transition from one state to another.
|
|
@@ -241,7 +247,7 @@ func disconnect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
241
247
|
var from_state: String = str(args.get("fromState", ""))
|
|
242
248
|
var to_state: String = str(args.get("toState", ""))
|
|
243
249
|
if from_state.is_empty() or to_state.is_empty():
|
|
244
|
-
return {"ok": false, "error": "Missing fromState or toState"}
|
|
250
|
+
return { "ok": false, "error": "Missing fromState or toState" }
|
|
245
251
|
var found: Array = _machine_at(args)
|
|
246
252
|
if found[1] == null:
|
|
247
253
|
return found[3]
|
|
@@ -258,9 +264,13 @@ func disconnect_animation_states(args: Dictionary) -> Dictionary:
|
|
|
258
264
|
var said: String = "There is no transition from %s to %s" % [from_state, to_state]
|
|
259
265
|
if leaving.is_empty():
|
|
260
266
|
return scene.refuse("%s; none leaves %s." % [said, from_state])
|
|
261
|
-
return scene.refuse(
|
|
267
|
+
return scene.refuse(
|
|
268
|
+
"%s; the ones leaving %s go to %s." % [said, from_state, ", ".join(leaving)]
|
|
269
|
+
)
|
|
262
270
|
sm.remove_transition(StringName(from_state), StringName(to_state))
|
|
263
271
|
if sm.has_transition(StringName(from_state), StringName(to_state)):
|
|
264
272
|
return scene.refuse("The state machine did not let go of the transition.")
|
|
265
273
|
var files: Dictionary = found[2]
|
|
266
|
-
return _finish(
|
|
274
|
+
return _finish(
|
|
275
|
+
scene, Callable(), files, { "ok": true, "removed": { "from": from_state, "to": to_state } }
|
|
276
|
+
)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
@tool
|
|
2
2
|
extends Node
|
|
3
|
-
|
|
4
|
-
##
|
|
5
|
-
## headless engine.
|
|
3
|
+
## Animations and animation trees, edited in the open editor or, for a project no editor serves, by
|
|
4
|
+
## a headless engine.
|
|
6
5
|
|
|
7
6
|
const GdhAnimationReads = preload("../animation_reads.gd")
|
|
8
7
|
const GdhHeadlessCheck = preload("../headless_check.gd")
|
|
@@ -11,9 +10,10 @@ const GdhRead = preload("../reading.gd")
|
|
|
11
10
|
const GdhSceneFile = preload("../scene_file.gd")
|
|
12
11
|
const GdhSceneUids = preload("../scene_uids.gd")
|
|
13
12
|
const GdhSerialisation = preload("../serialisation.gd")
|
|
14
|
-
|
|
15
13
|
const LOOP_MODES: Dictionary = {
|
|
16
|
-
"none": Animation.LOOP_NONE,
|
|
14
|
+
"none": Animation.LOOP_NONE,
|
|
15
|
+
"linear": Animation.LOOP_LINEAR,
|
|
16
|
+
"pingpong": Animation.LOOP_PINGPONG,
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
var _editor_plugin: EditorPlugin = null
|
|
@@ -74,7 +74,9 @@ func _not_of_kind(scene: GdhSceneFile, node: Node, node_path: String, kind: Stri
|
|
|
74
74
|
|
|
75
75
|
## Writes [param scene] once [param check] passes, then the files of [param homes], answering
|
|
76
76
|
## [param answer] or a refusal.
|
|
77
|
-
func _finish(
|
|
77
|
+
func _finish(
|
|
78
|
+
scene: GdhSceneFile, check: Callable, homes: Dictionary, answer: Dictionary
|
|
79
|
+
) -> Dictionary:
|
|
78
80
|
if not Engine.is_editor_hint():
|
|
79
81
|
for file: Variant in homes:
|
|
80
82
|
var home: Resource = homes[file]
|
|
@@ -85,9 +87,9 @@ func _finish(scene: GdhSceneFile, check: Callable, homes: Dictionary, answer: Di
|
|
|
85
87
|
(
|
|
86
88
|
(
|
|
87
89
|
(
|
|
88
|
-
"Nothing was written: %s holds a resource with a script that
|
|
89
|
-
+ "
|
|
90
|
-
+ "edit. "
|
|
90
|
+
"Nothing was written: %s holds a resource with a script that "
|
|
91
|
+
+ "is not a tool, and what that script changed when a headless "
|
|
92
|
+
+ "engine loaded it cannot be told apart from the edit. "
|
|
91
93
|
)
|
|
92
94
|
% file
|
|
93
95
|
)
|
|
@@ -102,7 +104,7 @@ func _finish(scene: GdhSceneFile, check: Callable, homes: Dictionary, answer: Di
|
|
|
102
104
|
var resource: Resource = homes[file]
|
|
103
105
|
var saving: Error = GdhSceneUids.save_keeping_uid(resource, str(file))
|
|
104
106
|
if saving != OK:
|
|
105
|
-
return {"ok": false, "error": "Failed to save %s: %s" % [file, error_string(saving)]}
|
|
107
|
+
return { "ok": false, "error": "Failed to save %s: %s" % [file, error_string(saving)] }
|
|
106
108
|
if Engine.is_editor_hint():
|
|
107
109
|
EditorInterface.get_resource_filesystem().update_file(str(file))
|
|
108
110
|
return answer
|
|
@@ -112,7 +114,10 @@ func _finish(scene: GdhSceneFile, check: Callable, homes: Dictionary, answer: Di
|
|
|
112
114
|
## engine ran as it loaded the file.
|
|
113
115
|
func _scripted(resource: Resource) -> bool:
|
|
114
116
|
var script: Script = resource.get_script()
|
|
115
|
-
return (
|
|
117
|
+
return (
|
|
118
|
+
(script != null and not script.is_tool())
|
|
119
|
+
or GdhHeadlessCheck.holds_scripted_embedded(resource, {})
|
|
120
|
+
)
|
|
116
121
|
|
|
117
122
|
|
|
118
123
|
func _parse_json_maybe(value: Variant) -> Variant:
|
|
@@ -160,11 +165,11 @@ func _homes(scene: GdhSceneFile, held: Array) -> Array:
|
|
|
160
165
|
false,
|
|
161
166
|
(
|
|
162
167
|
(
|
|
163
|
-
"The %s is kept in %s, not in %s, and an edit here would not be saved there.
|
|
164
|
-
+ "where it is kept instead."
|
|
168
|
+
"The %s is kept in %s, not in %s, and an edit here would not be saved there. "
|
|
169
|
+
+ "Edit it where it is kept instead."
|
|
165
170
|
)
|
|
166
171
|
% [entry[1], at.get_slice("::", 0), scene.path]
|
|
167
|
-
)
|
|
172
|
+
),
|
|
168
173
|
]
|
|
169
174
|
return [true, homes]
|
|
170
175
|
|
|
@@ -198,7 +203,9 @@ func _library_of(player: AnimationPlayer, animation_name: String) -> AnimationLi
|
|
|
198
203
|
## The state machine at [param state_machine_path] in [param anim_tree], with the files it is kept
|
|
199
204
|
## in, as [machine, homes, why not].
|
|
200
205
|
func _machine(scene: GdhSceneFile, anim_tree: AnimationTree, state_machine_path: String) -> Array:
|
|
201
|
-
var sm: AnimationNodeStateMachine = GdhAnimationReads.state_machine(
|
|
206
|
+
var sm: AnimationNodeStateMachine = GdhAnimationReads.state_machine(
|
|
207
|
+
anim_tree, state_machine_path
|
|
208
|
+
)
|
|
202
209
|
if not sm:
|
|
203
210
|
return [null, {}, GdhAnimationReads.no_machine(anim_tree, state_machine_path)]
|
|
204
211
|
var homes: Array = _homes(scene, [[sm, "state machine"]])
|
|
@@ -225,7 +232,7 @@ func read_animations(args: Dictionary) -> Dictionary:
|
|
|
225
232
|
var player_node_path: String = str(args.get("playerNodePath", "."))
|
|
226
233
|
var animation_name: String = str(args.get("animationName", ""))
|
|
227
234
|
if scene_path.strip_edges() == "res://":
|
|
228
|
-
return {"ok": false, "error": "Missing scenePath"}
|
|
235
|
+
return { "ok": false, "error": "Missing scenePath" }
|
|
229
236
|
|
|
230
237
|
var opened: Array = _read_at(scene_path, player_node_path, "AnimationPlayer")
|
|
231
238
|
var scene: GdhSceneFile = opened[0]
|
|
@@ -250,9 +257,9 @@ func read_animation_states(args: Dictionary) -> Dictionary:
|
|
|
250
257
|
var anim_tree_path: String = str(args.get("animTreePath", ""))
|
|
251
258
|
var state_machine_path: String = str(args.get("stateMachinePath", ""))
|
|
252
259
|
if scene_path.strip_edges() == "res://":
|
|
253
|
-
return {"ok": false, "error": "Missing scenePath"}
|
|
260
|
+
return { "ok": false, "error": "Missing scenePath" }
|
|
254
261
|
if anim_tree_path.is_empty():
|
|
255
|
-
return {"ok": false, "error": "Missing animTreePath"}
|
|
262
|
+
return { "ok": false, "error": "Missing animTreePath" }
|
|
256
263
|
|
|
257
264
|
var opened: Array = _read_at(scene_path, anim_tree_path, "AnimationTree")
|
|
258
265
|
var scene: GdhSceneFile = opened[0]
|
|
@@ -264,7 +271,8 @@ func read_animation_states(args: Dictionary) -> Dictionary:
|
|
|
264
271
|
var player_path: String = "" if player == null else scene.path_of(player)
|
|
265
272
|
var unplayed: String = GdhAnimationReads.no_player(str(anim_tree.anim_player), reached)
|
|
266
273
|
return _read_in(
|
|
267
|
-
scene,
|
|
274
|
+
scene,
|
|
275
|
+
GdhAnimationReads.states(anim_tree, state_machine_path, player, player_path, unplayed)
|
|
268
276
|
)
|
|
269
277
|
|
|
270
278
|
|
|
@@ -278,18 +286,18 @@ func create_animation(args: Dictionary) -> Dictionary:
|
|
|
278
286
|
var loop_mode_name: String = str(args.get("loopMode", "none"))
|
|
279
287
|
|
|
280
288
|
if scene_path.strip_edges() == "res://":
|
|
281
|
-
return {"ok": false, "error": "Missing scenePath"}
|
|
289
|
+
return { "ok": false, "error": "Missing scenePath" }
|
|
282
290
|
if animation_name.strip_edges().is_empty():
|
|
283
|
-
return {"ok": false, "error": "Missing animationName"}
|
|
291
|
+
return { "ok": false, "error": "Missing animationName" }
|
|
284
292
|
var named: String = _name_refusal(animation_name)
|
|
285
293
|
if not named.is_empty():
|
|
286
|
-
return {"ok": false, "error": named}
|
|
294
|
+
return { "ok": false, "error": named }
|
|
287
295
|
var loop_modes: Dictionary = LOOP_MODES
|
|
288
296
|
if not loop_modes.has(loop_mode_name):
|
|
289
|
-
return {"ok": false, "error": "Unsupported loopMode: " + loop_mode_name}
|
|
297
|
+
return { "ok": false, "error": "Unsupported loopMode: " + loop_mode_name }
|
|
290
298
|
var timing: String = _timing_refusal(args)
|
|
291
299
|
if not timing.is_empty():
|
|
292
|
-
return {"ok": false, "error": timing}
|
|
300
|
+
return { "ok": false, "error": timing }
|
|
293
301
|
|
|
294
302
|
var opened: Array = _open_at(scene_path, player_node_path, "AnimationPlayer")
|
|
295
303
|
var scene: GdhSceneFile = opened[0]
|
|
@@ -310,7 +318,9 @@ func create_animation(args: Dictionary) -> Dictionary:
|
|
|
310
318
|
anim.length = GdhRead.as_float(args.get("length", 1.0), 1.0)
|
|
311
319
|
anim.loop_mode = GdhRead.as_int(loop_modes[loop_mode_name]) as Animation.LoopMode
|
|
312
320
|
anim.step = GdhRead.as_float(args.get("step", 0.1), 0.1)
|
|
313
|
-
var called: String =
|
|
321
|
+
var called: String = (
|
|
322
|
+
animation_name.get_slice("/", 1) if animation_name.contains("/") else animation_name
|
|
323
|
+
)
|
|
314
324
|
# As the editor names a new one: the file keeps it as resource_name, which the inspector shows.
|
|
315
325
|
anim.resource_name = called
|
|
316
326
|
var add_err: Error = anim_lib.add_animation(StringName(called), anim)
|
|
@@ -327,10 +337,12 @@ func create_animation(args: Dictionary) -> Dictionary:
|
|
|
327
337
|
"ok": true,
|
|
328
338
|
"animationName": animation_name,
|
|
329
339
|
"length": GdhAnimationReads.held_seconds(anim.length),
|
|
330
|
-
"loopMode": loop_mode_name
|
|
340
|
+
"loopMode": loop_mode_name,
|
|
331
341
|
}
|
|
332
342
|
if library[2]:
|
|
333
|
-
answer["libraryMade"] =
|
|
343
|
+
answer["libraryMade"] = (
|
|
344
|
+
animation_name.get_slice("/", 0) if animation_name.contains("/") else ""
|
|
345
|
+
)
|
|
334
346
|
var files: Dictionary = homes[1]
|
|
335
347
|
return _finish(scene, check, files, answer)
|
|
336
348
|
|
|
@@ -341,8 +353,8 @@ static func _name_refusal(animation_name: String) -> String:
|
|
|
341
353
|
if animation_name.count("/") > 1:
|
|
342
354
|
return (
|
|
343
355
|
(
|
|
344
|
-
"%s names a library and an animation in it with one slash, as moves/walk; a
|
|
345
|
-
+ "libraries."
|
|
356
|
+
"%s names a library and an animation in it with one slash, as moves/walk; a "
|
|
357
|
+
+ "library holds no libraries."
|
|
346
358
|
)
|
|
347
359
|
% animation_name
|
|
348
360
|
)
|
|
@@ -372,7 +384,9 @@ static func _past_length(anim: Animation, animation_name: String) -> String:
|
|
|
372
384
|
|
|
373
385
|
## The pastLength sentence for [param past], keys of [param anim] each named by its track's path and
|
|
374
386
|
## time, or "" for none.
|
|
375
|
-
static func _past_sentence(
|
|
387
|
+
static func _past_sentence(
|
|
388
|
+
anim: Animation, animation_name: String, past: PackedStringArray
|
|
389
|
+
) -> String:
|
|
376
390
|
if past.is_empty():
|
|
377
391
|
return ""
|
|
378
392
|
return (
|
|
@@ -407,7 +421,10 @@ static func _timing_refusal(args: Dictionary) -> String:
|
|
|
407
421
|
if args.has("length"):
|
|
408
422
|
var length: Variant = args["length"]
|
|
409
423
|
if not (length is float or length is int) or GdhRead.as_float(length) <= 0.0:
|
|
410
|
-
return
|
|
424
|
+
return (
|
|
425
|
+
"length is the animation's length in seconds, more than 0, and %s is not."
|
|
426
|
+
% _given(length)
|
|
427
|
+
)
|
|
411
428
|
if args.has("step"):
|
|
412
429
|
var step: Variant = args["step"]
|
|
413
430
|
if not (step is float or step is int) or GdhRead.as_float(step) < 0.0:
|
|
@@ -443,16 +460,19 @@ func set_animation(args: Dictionary) -> Dictionary:
|
|
|
443
460
|
var animation_name: String = str(args.get("animationName", ""))
|
|
444
461
|
var loop_mode_name: String = str(args.get("loopMode", ""))
|
|
445
462
|
if scene_path.strip_edges() == "res://":
|
|
446
|
-
return {"ok": false, "error": "Missing scenePath"}
|
|
463
|
+
return { "ok": false, "error": "Missing scenePath" }
|
|
447
464
|
if animation_name.strip_edges().is_empty():
|
|
448
|
-
return {"ok": false, "error": "Missing animationName"}
|
|
465
|
+
return { "ok": false, "error": "Missing animationName" }
|
|
449
466
|
if not (args.has("length") or args.has("loopMode") or args.has("step")):
|
|
450
|
-
return {
|
|
467
|
+
return {
|
|
468
|
+
"ok": false,
|
|
469
|
+
"error": "set changes length, loopMode or step, and was given none of them.",
|
|
470
|
+
}
|
|
451
471
|
if args.has("loopMode") and not LOOP_MODES.has(loop_mode_name):
|
|
452
|
-
return {"ok": false, "error": "Unsupported loopMode: " + loop_mode_name}
|
|
472
|
+
return { "ok": false, "error": "Unsupported loopMode: " + loop_mode_name }
|
|
453
473
|
var timing: String = _timing_refusal(args)
|
|
454
474
|
if not timing.is_empty():
|
|
455
|
-
return {"ok": false, "error": timing}
|
|
475
|
+
return { "ok": false, "error": timing }
|
|
456
476
|
|
|
457
477
|
var found: Array = _animation_at(scene_path, player_node_path, animation_name)
|
|
458
478
|
if found[1] == null:
|
|
@@ -479,7 +499,10 @@ func set_animation(args: Dictionary) -> Dictionary:
|
|
|
479
499
|
if copy == null or not copy.has_animation(StringName(animation_name)):
|
|
480
500
|
return "%s would not be in the scene when it loads." % animation_name
|
|
481
501
|
if not is_equal_approx(copy.get_animation(StringName(animation_name)).length, length):
|
|
482
|
-
return
|
|
502
|
+
return (
|
|
503
|
+
"%s would not be %s s long when the scene loads."
|
|
504
|
+
% [animation_name, _seconds(length)]
|
|
505
|
+
)
|
|
483
506
|
return ""
|
|
484
507
|
var answer: Dictionary = {
|
|
485
508
|
"ok": true,
|
|
@@ -504,12 +527,14 @@ func rename_animation(args: Dictionary) -> Dictionary:
|
|
|
504
527
|
var animation_name: String = str(args.get("animationName", ""))
|
|
505
528
|
var new_name: String = str(args.get("newName", "")).strip_edges()
|
|
506
529
|
if scene_path.strip_edges() == "res://":
|
|
507
|
-
return {"ok": false, "error": "Missing scenePath"}
|
|
530
|
+
return { "ok": false, "error": "Missing scenePath" }
|
|
508
531
|
if animation_name.strip_edges().is_empty():
|
|
509
|
-
return {"ok": false, "error": "Missing animationName"}
|
|
532
|
+
return { "ok": false, "error": "Missing animationName" }
|
|
510
533
|
if new_name.is_empty():
|
|
511
|
-
return {"ok": false, "error": "Missing newName"}
|
|
512
|
-
var library_name: String =
|
|
534
|
+
return { "ok": false, "error": "Missing newName" }
|
|
535
|
+
var library_name: String = (
|
|
536
|
+
animation_name.get_slice("/", 0) if animation_name.contains("/") else ""
|
|
537
|
+
)
|
|
513
538
|
var prefix: String = "" if library_name.is_empty() else library_name + "/"
|
|
514
539
|
if not prefix.is_empty() and new_name.begins_with(prefix):
|
|
515
540
|
new_name = new_name.trim_prefix(prefix)
|
|
@@ -519,15 +544,18 @@ func rename_animation(args: Dictionary) -> Dictionary:
|
|
|
519
544
|
"error":
|
|
520
545
|
(
|
|
521
546
|
(
|
|
522
|
-
"rename keeps an animation in its library (%s), so newName is its name there,
|
|
523
|
-
+ "no library before a slash."
|
|
547
|
+
"rename keeps an animation in its library (%s), so newName is its name there, "
|
|
548
|
+
+ "with no library before a slash."
|
|
524
549
|
)
|
|
525
550
|
% ("the default one" if library_name.is_empty() else library_name)
|
|
526
551
|
),
|
|
527
552
|
}
|
|
528
553
|
for forbidden: String in [":", ",", "["]:
|
|
529
554
|
if new_name.contains(forbidden):
|
|
530
|
-
return {
|
|
555
|
+
return {
|
|
556
|
+
"ok": false,
|
|
557
|
+
"error": "An animation's name cannot hold : , or [, and %s does." % new_name,
|
|
558
|
+
}
|
|
531
559
|
var new_full: String = prefix + new_name
|
|
532
560
|
|
|
533
561
|
var found: Array = _animation_at(scene_path, player_node_path, animation_name)
|
|
@@ -557,7 +585,7 @@ func rename_animation(args: Dictionary) -> Dictionary:
|
|
|
557
585
|
# As the editor's rename sets it: the library's key alone left the file's resource_name, which
|
|
558
586
|
# the inspector shows, on the old name.
|
|
559
587
|
player.get_animation(StringName(new_full)).resource_name = new_name
|
|
560
|
-
var answer: Dictionary = {"ok": true, "animationName": new_full, "was": animation_name}
|
|
588
|
+
var answer: Dictionary = { "ok": true, "animationName": new_full, "was": animation_name }
|
|
561
589
|
if autoplayed:
|
|
562
590
|
answer["autoplay"] = new_full
|
|
563
591
|
var followed: Array = []
|
|
@@ -585,9 +613,9 @@ func remove_animation(args: Dictionary) -> Dictionary:
|
|
|
585
613
|
var player_node_path: String = str(args.get("playerNodePath", "."))
|
|
586
614
|
var animation_name: String = str(args.get("animationName", ""))
|
|
587
615
|
if scene_path.strip_edges() == "res://":
|
|
588
|
-
return {"ok": false, "error": "Missing scenePath"}
|
|
616
|
+
return { "ok": false, "error": "Missing scenePath" }
|
|
589
617
|
if animation_name.strip_edges().is_empty():
|
|
590
|
-
return {"ok": false, "error": "Missing animationName"}
|
|
618
|
+
return { "ok": false, "error": "Missing animationName" }
|
|
591
619
|
|
|
592
620
|
var found: Array = _animation_at(scene_path, player_node_path, animation_name)
|
|
593
621
|
if found[1] == null:
|
|
@@ -598,12 +626,14 @@ func remove_animation(args: Dictionary) -> Dictionary:
|
|
|
598
626
|
var homes: Array = _homes(scene, [[library, "animation library"]])
|
|
599
627
|
if not homes[0]:
|
|
600
628
|
return scene.refuse(str(homes[1]))
|
|
601
|
-
var called: String =
|
|
629
|
+
var called: String = (
|
|
630
|
+
animation_name.get_slice("/", 1) if animation_name.contains("/") else animation_name
|
|
631
|
+
)
|
|
602
632
|
var autoplayed: bool = str(player.autoplay) == animation_name
|
|
603
633
|
library.remove_animation(StringName(called))
|
|
604
634
|
if player.has_animation(StringName(animation_name)):
|
|
605
635
|
return scene.refuse("The library did not let go of %s." % animation_name)
|
|
606
|
-
var answer: Dictionary = {"ok": true, "removed": animation_name}
|
|
636
|
+
var answer: Dictionary = { "ok": true, "removed": animation_name }
|
|
607
637
|
if autoplayed:
|
|
608
638
|
player.autoplay = ""
|
|
609
639
|
answer["autoplayCleared"] = true
|