gdharness 1.3.41 → 1.3.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cli.js +131 -47
- package/build/godot/addons/auto_reload/auto_reload.gd +18 -19
- package/build/godot/addons/gdharness_editor/animation_reads.gd +84 -35
- package/build/godot/addons/gdharness_editor/bridge_client.gd +53 -58
- package/build/godot/addons/gdharness_editor/declared_values.gd +68 -32
- package/build/godot/addons/gdharness_editor/file_reads.gd +114 -39
- package/build/godot/addons/gdharness_editor/file_walk.gd +12 -5
- package/build/godot/addons/gdharness_editor/headless_check.gd +94 -41
- package/build/godot/addons/gdharness_editor/plugin.gd +2 -3
- package/build/godot/addons/gdharness_editor/property_paths.gd +22 -12
- package/build/godot/addons/gdharness_editor/property_values.gd +143 -78
- package/build/godot/addons/gdharness_editor/reading.gd +37 -12
- package/build/godot/addons/gdharness_editor/same_values.gd +4 -4
- package/build/godot/addons/gdharness_editor/scene_file.gd +136 -79
- package/build/godot/addons/gdharness_editor/scene_uids.gd +12 -6
- package/build/godot/addons/gdharness_editor/serialisation.gd +75 -51
- package/build/godot/addons/gdharness_editor/setting_reads.gd +7 -6
- package/build/godot/addons/gdharness_editor/tool_executor.gd +3 -6
- package/build/godot/addons/gdharness_editor/tools/animation_states.gd +41 -28
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +84 -50
- package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd +70 -40
- package/build/godot/addons/gdharness_editor/tools/class_tools.gd +34 -30
- package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +24 -22
- package/build/godot/addons/gdharness_editor/tools/navigation_bake.gd +49 -29
- package/build/godot/addons/gdharness_editor/tools/play_tools.gd +26 -21
- package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +40 -40
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +181 -107
- package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +16 -9
- package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +75 -43
- package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +35 -20
- package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +28 -13
- package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd +66 -0
- package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +171 -62
- package/build/godot/addons/gdharness_editor/tools/script_paths.gd +20 -8
- package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +11 -8
- package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +47 -34
- package/build/godot/addons/gdharness_editor/tools/tileset_tools.gd +77 -50
- package/build/godot/addons/gdharness_editor/value_shapes.gd +5 -6
- package/build/godot/addons/gdharness_runtime/call_errors.gd +1 -2
- package/build/godot/addons/gdharness_runtime/declared_values.gd +68 -32
- package/build/godot/addons/gdharness_runtime/error_report.gd +1 -2
- package/build/godot/addons/gdharness_runtime/reading.gd +37 -12
- package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +84 -63
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +153 -148
- package/build/godot/addons/gdharness_runtime/runtime_capture.gd +64 -42
- package/build/godot/addons/gdharness_runtime/runtime_changes.gd +184 -122
- package/build/godot/addons/gdharness_runtime/runtime_frames.gd +2 -2
- package/build/godot/addons/gdharness_runtime/runtime_hover.gd +24 -20
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +134 -92
- package/build/godot/addons/gdharness_runtime/runtime_items.gd +29 -13
- package/build/godot/addons/gdharness_runtime/runtime_menus.gd +0 -1
- package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +38 -20
- package/build/godot/addons/gdharness_runtime/runtime_pad.gd +17 -13
- package/build/godot/addons/gdharness_runtime/runtime_paths.gd +84 -46
- package/build/godot/addons/gdharness_runtime/runtime_queries.gd +117 -79
- package/build/godot/addons/gdharness_runtime/runtime_says.gd +14 -17
- package/build/godot/addons/gdharness_runtime/runtime_screen.gd +23 -16
- package/build/godot/addons/gdharness_runtime/runtime_targets.gd +117 -66
- package/build/godot/addons/gdharness_runtime/runtime_touch.gd +211 -0
- package/build/godot/addons/gdharness_runtime/runtime_touch.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/runtime_typing.gd +44 -27
- package/build/godot/addons/gdharness_runtime/runtime_values.gd +108 -73
- package/build/godot/addons/gdharness_runtime/runtime_waits.gd +111 -84
- package/build/godot/addons/gdharness_runtime/runtime_words.gd +10 -7
- package/build/godot/addons/gdharness_runtime/serialisation.gd +75 -51
- package/build/godot/addons/gdharness_runtime/value_shapes.gd +5 -6
- package/build/godot/addons/gdharness_tests/bench.gd +4 -5
- package/build/godot/addons/gdharness_tests/event.gd +10 -5
- package/build/godot/addons/gdharness_tests/share.gd +38 -18
- package/build/godot/addons/gdharness_tests/suites.gd +3 -3
- package/build/godot/addons/gdharness_tests/wait.gd +3 -2
- package/build/godot/loader/loader.gd +9 -9
- package/build/godot/operations/animation_reads.gd +84 -35
- package/build/godot/operations/audio_buses.gd +48 -19
- package/build/godot/operations/class_cache.gd +16 -11
- package/build/godot/operations/classdb_queries.gd +89 -44
- package/build/godot/operations/declared_values.gd +68 -32
- package/build/godot/operations/dependencies.gd +139 -93
- package/build/godot/operations/editor_tools.gd +9 -10
- package/build/godot/operations/export_presets.gd +100 -54
- package/build/godot/operations/file_reads.gd +114 -39
- package/build/godot/operations/file_walk.gd +12 -5
- package/build/godot/operations/gdscript_analysis.gd +105 -66
- package/build/godot/operations/gdscript_authoring.gd +138 -39
- package/build/godot/operations/godot_operations.gd +17 -11
- package/build/godot/operations/import_pipeline.gd +110 -59
- package/build/godot/operations/input_actions.gd +63 -39
- package/build/godot/operations/patterns.gd +3 -1
- package/build/godot/operations/plugins.gd +36 -16
- package/build/godot/operations/project_config.gd +144 -27
- package/build/godot/operations/project_diagnostics.gd +24 -11
- package/build/godot/operations/project_file.gd +16 -16
- package/build/godot/operations/project_validation.gd +71 -44
- package/build/godot/operations/property_paths.gd +22 -12
- package/build/godot/operations/property_values.gd +143 -78
- package/build/godot/operations/reading.gd +37 -12
- package/build/godot/operations/rename_checks.gd +2 -2
- package/build/godot/operations/resource_files.gd +11 -9
- package/build/godot/operations/same_values.gd +4 -4
- package/build/godot/operations/scene_connections.gd +27 -13
- package/build/godot/operations/script_check.gd +52 -49
- package/build/godot/operations/serialisation.gd +75 -51
- package/build/godot/operations/setting_reads.gd +7 -6
- package/build/godot/operations/value_shapes.gd +5 -6
- package/build/godot/tests/listed.gd +321 -268
- package/package.json +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
@tool
|
|
2
2
|
extends Node
|
|
3
|
-
|
|
4
3
|
## Scenes and their nodes, edited in the open editor and read back from what it holds.
|
|
5
4
|
|
|
6
5
|
const GdhDeclared = preload("../declared_values.gd")
|
|
@@ -15,6 +14,7 @@ const GdhPlacing = preload("scene_placing.gd")
|
|
|
15
14
|
const GdhPropertyValues = preload("../property_values.gd")
|
|
16
15
|
const GdhSame = preload("../same_values.gd")
|
|
17
16
|
const GdhSceneFile = preload("../scene_file.gd")
|
|
17
|
+
const GdhSceneSharing = preload("scene_sharing.gd")
|
|
18
18
|
const GdhSerialisation = preload("../serialisation.gd")
|
|
19
19
|
const GdhTilesetTools = preload("tileset_tools.gd")
|
|
20
20
|
|
|
@@ -43,11 +43,20 @@ func _kept(scene: GdhSceneFile, saved: Node, node: Node, names: Array) -> String
|
|
|
43
43
|
for key: Variant in names:
|
|
44
44
|
var property: String = str(key)
|
|
45
45
|
var loaded: Variant = _properties.read_at(copy, property)
|
|
46
|
-
|
|
46
|
+
var given: Variant = _properties.read_at(node, property)
|
|
47
|
+
if not scene.kept(saved, loaded, given):
|
|
48
|
+
# The file holds it, and the copy's own script set it again as the copy loaded, as it
|
|
49
|
+
# will wherever the scene loads; an editor saves the same.
|
|
50
|
+
if scene.stores(at, property, given):
|
|
51
|
+
var on: Dictionary = scene.loads_as.get_or_add(at, {})
|
|
52
|
+
if GdhHeadlessCheck.untooled(copy.get_script()):
|
|
53
|
+
scene.loads_untooled[at] = true
|
|
54
|
+
on[property] = _values.serialize_value(loaded)
|
|
55
|
+
continue
|
|
47
56
|
return (
|
|
48
57
|
(
|
|
49
|
-
"%s.%s would load from the file as %s: the scene does not keep it, because the
|
|
50
|
-
+ "is not one a scene stores or the node belongs to another scene."
|
|
58
|
+
"%s.%s would load from the file as %s: the scene does not keep it, because the "
|
|
59
|
+
+ "property is not one a scene stores or the node belongs to another scene."
|
|
51
60
|
)
|
|
52
61
|
% [at, property, JSON.stringify(_values.serialize_value(loaded), "", false)]
|
|
53
62
|
)
|
|
@@ -141,7 +150,7 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
141
150
|
var script_path: String = str(args.get("script", ""))
|
|
142
151
|
|
|
143
152
|
if scene_path.is_empty():
|
|
144
|
-
return {"ok": false, "error": "Missing scenePath"}
|
|
153
|
+
return { "ok": false, "error": "Missing scenePath" }
|
|
145
154
|
var made: Dictionary = GdhSceneFile.made_as(
|
|
146
155
|
root_node_type,
|
|
147
156
|
"" if script_path.is_empty() else GdhSceneFile.res_path(project_path, script_path),
|
|
@@ -149,18 +158,21 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
149
158
|
"rootNodeType"
|
|
150
159
|
)
|
|
151
160
|
if made.has("error"):
|
|
152
|
-
return {"ok": false, "error": made["error"]}
|
|
161
|
+
return { "ok": false, "error": made["error"] }
|
|
153
162
|
root_node_type = str(made["type"])
|
|
154
163
|
script_path = str(made["script"])
|
|
155
164
|
# A class that is not a node went into a Node variable, which is a runtime error the caller
|
|
156
165
|
# heard about only as "Invalid tool result".
|
|
157
|
-
if
|
|
158
|
-
|
|
166
|
+
if (
|
|
167
|
+
not ClassDB.class_exists(root_node_type)
|
|
168
|
+
or not ClassDB.is_parent_class(root_node_type, "Node")
|
|
169
|
+
):
|
|
170
|
+
return { "ok": false, "error": GdhPlacing.not_a_node_class("rootNodeType", root_node_type) }
|
|
159
171
|
if not ClassDB.can_instantiate(root_node_type):
|
|
160
|
-
return {"ok": false, "error": "%s cannot be instantiated." % root_node_type}
|
|
172
|
+
return { "ok": false, "error": "%s cannot be instantiated." % root_node_type }
|
|
161
173
|
var unfit: String = GdhSceneFile.unfit_name(root_node_name)
|
|
162
174
|
if not unfit.is_empty():
|
|
163
|
-
return {"ok": false, "error": unfit}
|
|
175
|
+
return { "ok": false, "error": unfit }
|
|
164
176
|
if FileAccess.file_exists(scene_path):
|
|
165
177
|
return GdhKin.taken(scene_path)
|
|
166
178
|
|
|
@@ -176,29 +188,32 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
176
188
|
var script: Script = load(full_script_path) as Script
|
|
177
189
|
if script == null:
|
|
178
190
|
root.free()
|
|
179
|
-
return {"ok": false, "error": "No script loads from " + full_script_path}
|
|
191
|
+
return { "ok": false, "error": "No script loads from " + full_script_path }
|
|
180
192
|
var uncompiled: String = GdhSceneFile.uncompiled(script, full_script_path)
|
|
181
193
|
if not uncompiled.is_empty():
|
|
182
194
|
root.free()
|
|
183
|
-
return {"ok": false, "error": uncompiled}
|
|
195
|
+
return { "ok": false, "error": uncompiled }
|
|
184
196
|
var base: String = str(script.get_instance_base_type())
|
|
185
197
|
if not ClassDB.is_parent_class(root_node_type, base):
|
|
186
198
|
root.free()
|
|
187
199
|
return {
|
|
188
200
|
"ok": false,
|
|
189
201
|
"error":
|
|
190
|
-
|
|
202
|
+
(
|
|
203
|
+
"%s extends %s, so it cannot be on a %s root."
|
|
204
|
+
% [full_script_path, base, root_node_type]
|
|
205
|
+
),
|
|
191
206
|
}
|
|
192
207
|
root.set_script(script)
|
|
193
|
-
# Named again, since a headless engine runs the script's _init as it is attached, and a
|
|
194
|
-
# name is no property the write compares.
|
|
208
|
+
# Named again, since a headless engine runs the script's _init as it is attached, and a
|
|
209
|
+
# node's name is no property the write compares.
|
|
195
210
|
root.name = root_node_name
|
|
196
211
|
|
|
197
212
|
var had_folder: bool = DirAccess.dir_exists_absolute(scene_path.get_base_dir())
|
|
198
213
|
var folder: String = GdhSceneFile.make_folder_for(scene_path)
|
|
199
214
|
if not folder.is_empty():
|
|
200
215
|
root.free()
|
|
201
|
-
return {"ok": false, "error": folder}
|
|
216
|
+
return { "ok": false, "error": folder }
|
|
202
217
|
# Read before the write, which frees the root.
|
|
203
218
|
var root_class: Dictionary = GdhSceneFile.class_of(root)
|
|
204
219
|
var written: Dictionary = scene.write()
|
|
@@ -209,7 +224,7 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
209
224
|
"ok": true,
|
|
210
225
|
"scenePath": scene_path,
|
|
211
226
|
"rootNodeType": root_class["nodeType"],
|
|
212
|
-
"rootNodeName": root_node_name
|
|
227
|
+
"rootNodeName": root_node_name,
|
|
213
228
|
}
|
|
214
229
|
if root_class.has("scriptClass"):
|
|
215
230
|
answer["scriptClass"] = root_class["scriptClass"]
|
|
@@ -229,7 +244,9 @@ func list_scene_nodes(args: Dictionary) -> Dictionary:
|
|
|
229
244
|
|
|
230
245
|
# Read as a headless engine reads it with no editor connected, so the answer does not depend on
|
|
231
246
|
# whether one is.
|
|
232
|
-
var read: Dictionary = GdhFileReads.scene_tree(
|
|
247
|
+
var read: Dictionary = GdhFileReads.scene_tree(
|
|
248
|
+
scene_path, depth, include_properties, include_defaults
|
|
249
|
+
)
|
|
233
250
|
if read.get("ok", false):
|
|
234
251
|
read["unsavedInEditor"] = GdhSceneFile.unsaved(scene_path)
|
|
235
252
|
return read
|
|
@@ -246,12 +263,12 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
246
263
|
var adding: Array = GdhGroups.asked(args, "addGroups")
|
|
247
264
|
|
|
248
265
|
if node_name.is_empty():
|
|
249
|
-
return {"ok": false, "error": "Missing nodeName"}
|
|
266
|
+
return { "ok": false, "error": "Missing nodeName" }
|
|
250
267
|
var class_script: Script = null
|
|
251
268
|
if not node_type.is_empty() and not ClassDB.class_exists(node_type):
|
|
252
269
|
var declared: Dictionary = GdhSceneFile.script_class(node_type, "Node")
|
|
253
270
|
if declared.has("error"):
|
|
254
|
-
return {"ok": false, "error": declared["error"]}
|
|
271
|
+
return { "ok": false, "error": declared["error"] }
|
|
255
272
|
var held: Variant = declared.get("script")
|
|
256
273
|
if held is Script:
|
|
257
274
|
class_script = held
|
|
@@ -259,7 +276,7 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
259
276
|
var making: Array = GdhPlacing.what_to_add(node_type, instance_path, scene_path)
|
|
260
277
|
var packed: PackedScene = making[0]
|
|
261
278
|
if not str(making[1]).is_empty():
|
|
262
|
-
return {"ok": false, "error": making[1]}
|
|
279
|
+
return { "ok": false, "error": making[1] }
|
|
263
280
|
|
|
264
281
|
var opened: Array = _open(scene_path, true)
|
|
265
282
|
var scene: GdhSceneFile = opened[0]
|
|
@@ -270,7 +287,9 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
270
287
|
var root: Node = scene.root
|
|
271
288
|
var parent: Node = GdhSceneFile.node_at(root, parent_node_path)
|
|
272
289
|
if not parent:
|
|
273
|
-
return scene.refuse(
|
|
290
|
+
return scene.refuse(
|
|
291
|
+
scene.not_found("Parent node not found: " + parent_node_path, parent_node_path)
|
|
292
|
+
)
|
|
274
293
|
var foreign: String = scene.foreign(parent)
|
|
275
294
|
if not foreign.is_empty():
|
|
276
295
|
return scene.refuse(foreign)
|
|
@@ -306,9 +325,9 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
306
325
|
|
|
307
326
|
var new_path: String = scene.path_of(new_node)
|
|
308
327
|
# Read before the write, which frees the scene it was added to.
|
|
309
|
-
var answer: Dictionary = {"ok": true, "nodeName": node_name}
|
|
328
|
+
var answer: Dictionary = { "ok": true, "nodeName": node_name }
|
|
310
329
|
answer.merge(GdhSceneFile.class_of(new_node))
|
|
311
|
-
answer.merge({"nodePath": new_path, "index": new_node.get_index()})
|
|
330
|
+
answer.merge({ "nodePath": new_path, "index": new_node.get_index() })
|
|
312
331
|
if not properties.is_empty():
|
|
313
332
|
var held: Dictionary = {}
|
|
314
333
|
for key: Variant in properties:
|
|
@@ -317,10 +336,14 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
317
336
|
_properties.note_write(answer, new_node)
|
|
318
337
|
if not adding.is_empty():
|
|
319
338
|
answer.merge(GdhGroups.read_added(new_node, adding))
|
|
339
|
+
var id: int = new_node.get_instance_id()
|
|
320
340
|
var written: Dictionary = scene.write(
|
|
321
341
|
func(saved: Node) -> String:
|
|
322
342
|
var unkept: String = _kept(
|
|
323
|
-
scene,
|
|
343
|
+
scene,
|
|
344
|
+
saved,
|
|
345
|
+
new_node,
|
|
346
|
+
properties.keys() + (["script"] if class_script != null else [])
|
|
324
347
|
)
|
|
325
348
|
if unkept.is_empty() and saved.get_node_or_null(new_path) != null:
|
|
326
349
|
unkept = GdhGroups.unkept(saved.get_node(new_path), adding, [])
|
|
@@ -329,6 +352,8 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
329
352
|
if not written.is_empty():
|
|
330
353
|
return written
|
|
331
354
|
|
|
355
|
+
_note_put_back(answer, scene, id, new_path)
|
|
356
|
+
_note_loads_as(answer, scene, new_path)
|
|
332
357
|
if packed != null:
|
|
333
358
|
answer["instanceOf"] = instance_path
|
|
334
359
|
return answer
|
|
@@ -344,9 +369,9 @@ func delete_node(args: Dictionary) -> Dictionary:
|
|
|
344
369
|
"ok": false,
|
|
345
370
|
"error":
|
|
346
371
|
(
|
|
347
|
-
"The root cannot be deleted, since a scene has exactly one. Delete the nodes under
|
|
348
|
-
+ "make a scene with another root with scene_create."
|
|
349
|
-
)
|
|
372
|
+
"The root cannot be deleted, since a scene has exactly one. Delete the nodes under "
|
|
373
|
+
+ "it, or make a scene with another root with scene_create."
|
|
374
|
+
),
|
|
350
375
|
}
|
|
351
376
|
|
|
352
377
|
var opened: Array = _open(scene_path, true)
|
|
@@ -370,7 +395,7 @@ func delete_node(args: Dictionary) -> Dictionary:
|
|
|
370
395
|
node.get_parent().remove_child(node)
|
|
371
396
|
node.free()
|
|
372
397
|
var carried: GdhPaths = GdhPaths.new()
|
|
373
|
-
var _rewritten: int = carried.carry(scene, {at: ""})
|
|
398
|
+
var _rewritten: int = carried.carry(scene, { at: "" })
|
|
374
399
|
|
|
375
400
|
var written: Dictionary = scene.write(
|
|
376
401
|
func(saved: Node) -> String:
|
|
@@ -381,7 +406,7 @@ func delete_node(args: Dictionary) -> Dictionary:
|
|
|
381
406
|
if not written.is_empty():
|
|
382
407
|
return written
|
|
383
408
|
|
|
384
|
-
var answer: Dictionary = {"ok": true, "deletedNodePath": at}
|
|
409
|
+
var answer: Dictionary = { "ok": true, "deletedNodePath": at }
|
|
385
410
|
if not went.is_empty():
|
|
386
411
|
answer["deletedWithIt"] = went
|
|
387
412
|
answer.merge(GdhKin.follow(scene_path, at, "", carried))
|
|
@@ -396,7 +421,7 @@ func duplicate_node(args: Dictionary) -> Dictionary:
|
|
|
396
421
|
var parent_path: String = str(args.get("parentNodePath", ""))
|
|
397
422
|
|
|
398
423
|
if node_path.is_empty() or new_name.is_empty():
|
|
399
|
-
return {"ok": false, "error": "Missing nodePath or newName"}
|
|
424
|
+
return { "ok": false, "error": "Missing nodePath or newName" }
|
|
400
425
|
|
|
401
426
|
var opened: Array = _open(scene_path, true)
|
|
402
427
|
var scene: GdhSceneFile = opened[0]
|
|
@@ -453,7 +478,9 @@ func duplicate_node(args: Dictionary) -> Dictionary:
|
|
|
453
478
|
if copy == null:
|
|
454
479
|
return "the copy would not be in the scene when it loads."
|
|
455
480
|
if copy.get_index() != placed[1]:
|
|
456
|
-
return
|
|
481
|
+
return (
|
|
482
|
+
"%s would load at index %d, not %d." % [new_path, copy.get_index(), placed[1]]
|
|
483
|
+
)
|
|
457
484
|
return ""
|
|
458
485
|
)
|
|
459
486
|
if not written.is_empty():
|
|
@@ -476,9 +503,9 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
476
503
|
var new_parent_path: String = str(args.get("newParentPath", ""))
|
|
477
504
|
|
|
478
505
|
if node_path.is_empty() or node_path == ".":
|
|
479
|
-
return {"ok": false, "error": "Cannot reparent root node"}
|
|
506
|
+
return { "ok": false, "error": "Cannot reparent root node" }
|
|
480
507
|
if new_parent_path.is_empty():
|
|
481
|
-
return {"ok": false, "error": "Missing newParentPath"}
|
|
508
|
+
return { "ok": false, "error": "Missing newParentPath" }
|
|
482
509
|
|
|
483
510
|
var opened: Array = _open(scene_path, true)
|
|
484
511
|
var scene: GdhSceneFile = opened[0]
|
|
@@ -492,7 +519,9 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
492
519
|
if not node:
|
|
493
520
|
return scene.refuse(scene.not_found("Node not found: " + node_path, node_path))
|
|
494
521
|
if not new_parent:
|
|
495
|
-
return scene.refuse(
|
|
522
|
+
return scene.refuse(
|
|
523
|
+
scene.not_found("New parent not found: " + new_parent_path, new_parent_path)
|
|
524
|
+
)
|
|
496
525
|
var fixed: String = scene.fixed(node)
|
|
497
526
|
if not fixed.is_empty():
|
|
498
527
|
return scene.refuse(fixed)
|
|
@@ -518,9 +547,12 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
518
547
|
var drawn_at: Dictionary = {}
|
|
519
548
|
for property: String in GdhPlacing.placing(node):
|
|
520
549
|
drawn_at[property] = _properties.read_at(node, property)
|
|
521
|
-
var held_at: Transform3D = (
|
|
522
|
-
|
|
523
|
-
|
|
550
|
+
var held_at: Transform3D = (
|
|
551
|
+
(node as Node3D).transform if node is Node3D else Transform3D.IDENTITY
|
|
552
|
+
)
|
|
553
|
+
var stored_before: Dictionary = GdhHeadlessCheck.stored(node)
|
|
554
|
+
# Unowned while it moves: a node taken out of the tree keeps its owner, and adding it under the
|
|
555
|
+
# new parent warned that the owner was not above it. Node.reparent warns the same way.
|
|
524
556
|
node.owner = null
|
|
525
557
|
old_parent.remove_child(node)
|
|
526
558
|
new_parent.add_child(node)
|
|
@@ -528,22 +560,30 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
528
560
|
GdhPlacing.own(node, root)
|
|
529
561
|
if GdhRead.as_bool(args.get("keepGlobalTransform", true)):
|
|
530
562
|
GdhPlacing.keep_in_place(node, old_parent)
|
|
563
|
+
# Unasked, a headless write takes the move on a node whose script is not a tool for the
|
|
564
|
+
# script's doing and puts the node back as the file held it.
|
|
565
|
+
var placed: Array[String] = GdhHeadlessCheck.differing(node, stored_before, {})
|
|
566
|
+
if not placed.is_empty():
|
|
567
|
+
scene.asked(node, placed)
|
|
531
568
|
var also_changed: Dictionary = {}
|
|
532
569
|
for property: String in drawn_at:
|
|
533
570
|
var now: Variant = _properties.read_at(node, property)
|
|
534
571
|
if not GdhSame.same(now, drawn_at[property]):
|
|
535
|
-
also_changed[property] = {
|
|
572
|
+
also_changed[property] = {
|
|
573
|
+
"was": _readable(node, drawn_at[property]), "now": _readable(node, now),
|
|
574
|
+
}
|
|
536
575
|
var sheared: String = ""
|
|
537
576
|
if node is Node3D and GdhPlacing.sheared((node as Node3D).basis):
|
|
538
577
|
var spatial: Node3D = node
|
|
539
578
|
also_changed["transform"] = {
|
|
540
|
-
"was": _readable(node, held_at), "now": _readable(node, spatial.transform)
|
|
579
|
+
"was": _readable(node, held_at), "now": _readable(node, spatial.transform),
|
|
541
580
|
}
|
|
542
581
|
sheared = (
|
|
543
582
|
(
|
|
544
|
-
"%s keeps where it is drawn under %s, which is scaled unevenly across the way it
|
|
545
|
-
+ " so its basis is sheared: no position, rotation and scale describe
|
|
546
|
-
+ " what it holds. keepGlobalTransform false keeps its own
|
|
583
|
+
"%s keeps where it is drawn under %s, which is scaled unevenly across the way it "
|
|
584
|
+
+ "is turned, so its basis is sheared: no position, rotation and scale describe "
|
|
585
|
+
+ "it, and transform is what it holds. keepGlobalTransform false keeps its own "
|
|
586
|
+
+ "transform instead."
|
|
547
587
|
)
|
|
548
588
|
% [str(node.name), new_parent_path]
|
|
549
589
|
)
|
|
@@ -551,7 +591,10 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
551
591
|
var new_path: String = scene.path_of(node)
|
|
552
592
|
var index: int = node.get_index()
|
|
553
593
|
var carried: GdhPaths = GdhPaths.new()
|
|
554
|
-
var _rewritten: int = carried.carry(
|
|
594
|
+
var _rewritten: int = carried.carry(
|
|
595
|
+
scene,
|
|
596
|
+
{ old_path: new_path } if new_path != old_path else {},
|
|
597
|
+
)
|
|
555
598
|
var written: Dictionary = scene.write(
|
|
556
599
|
func(saved: Node) -> String:
|
|
557
600
|
var copy: Node = saved.get_node_or_null(new_path)
|
|
@@ -592,7 +635,10 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
592
635
|
var adding: Array = GdhGroups.asked(args, "addGroups")
|
|
593
636
|
var removing: Array = GdhGroups.asked(args, "removeGroups")
|
|
594
637
|
if properties.is_empty() and editable == null and adding.is_empty() and removing.is_empty():
|
|
595
|
-
return {
|
|
638
|
+
return {
|
|
639
|
+
"ok": false,
|
|
640
|
+
"error": "set takes properties, editableChildren, addGroups or removeGroups.",
|
|
641
|
+
}
|
|
596
642
|
|
|
597
643
|
var opened: Array = _open(scene_path, true)
|
|
598
644
|
var scene: GdhSceneFile = opened[0]
|
|
@@ -642,8 +688,15 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
642
688
|
for key: Variant in properties:
|
|
643
689
|
held[str(key)] = _readable(node, _properties.read_at(node, str(key)))
|
|
644
690
|
var new_path: String = scene.path_of(node)
|
|
645
|
-
var answer: Dictionary = {"ok": true, "nodePath": new_path, "properties": held}
|
|
691
|
+
var answer: Dictionary = { "ok": true, "nodePath": new_path, "properties": held }
|
|
646
692
|
_properties.note_write(answer, node)
|
|
693
|
+
var shared: Dictionary = {}
|
|
694
|
+
for key: Variant in properties:
|
|
695
|
+
var holders: Array[Dictionary] = GdhSceneSharing.holders(scene, node, str(key))
|
|
696
|
+
if not holders.is_empty():
|
|
697
|
+
shared[str(key)] = holders
|
|
698
|
+
if not shared.is_empty():
|
|
699
|
+
answer["sharedWith"] = shared
|
|
647
700
|
if not adding.is_empty() or not removing.is_empty():
|
|
648
701
|
answer["groups"] = GdhGroups.read(scene, node).get("groups", [])
|
|
649
702
|
var named: Array[String] = []
|
|
@@ -653,16 +706,24 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
653
706
|
named.append(property)
|
|
654
707
|
var source: String = scene.values_from(node, old_path)
|
|
655
708
|
var carried: GdhPaths = GdhPaths.new()
|
|
656
|
-
var _rewritten: int = carried.carry(
|
|
709
|
+
var _rewritten: int = carried.carry(
|
|
710
|
+
scene,
|
|
711
|
+
{ old_path: new_path } if new_path != old_path else {},
|
|
712
|
+
)
|
|
713
|
+
var id: int = node.get_instance_id()
|
|
657
714
|
var written: Dictionary = scene.write(
|
|
658
715
|
func(saved: Node) -> String:
|
|
659
716
|
var unkept: String = _kept(scene, saved, node, properties.keys())
|
|
660
717
|
if unkept.is_empty():
|
|
661
718
|
unkept = GdhGroups.unkept(saved.get_node(new_path), adding, removing)
|
|
662
719
|
if unkept.is_empty() and editable != null:
|
|
663
|
-
if
|
|
720
|
+
if (
|
|
721
|
+
saved.is_editable_instance(saved.get_node(new_path))
|
|
722
|
+
!= GdhRead.as_bool(editable)
|
|
723
|
+
):
|
|
664
724
|
return (
|
|
665
|
-
"%s would load with editableChildren %s."
|
|
725
|
+
"%s would load with editableChildren %s."
|
|
726
|
+
% [new_path, not GdhRead.as_bool(editable)]
|
|
666
727
|
)
|
|
667
728
|
return unkept
|
|
668
729
|
)
|
|
@@ -675,12 +736,48 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
675
736
|
if not dropped.is_empty():
|
|
676
737
|
answer["droppedValues"] = dropped["values"]
|
|
677
738
|
answer["droppedNodes"] = dropped["nodes"]
|
|
739
|
+
_note_put_back(answer, scene, id, new_path)
|
|
740
|
+
_note_loads_as(answer, scene, new_path)
|
|
678
741
|
_note_left_out(answer, scene.written_pack, new_path, named, source)
|
|
679
742
|
if new_path != old_path:
|
|
680
743
|
answer.merge(GdhKin.follow(scene_path, old_path, new_path, carried))
|
|
681
744
|
return answer
|
|
682
745
|
|
|
683
746
|
|
|
747
|
+
## Puts under loadsAs in [param answer] each value given that the file holds and the script of the
|
|
748
|
+
## node at [param at] changes as the scene loads, as it loads.
|
|
749
|
+
static func _note_loads_as(answer: Dictionary, scene: GdhSceneFile, at: String) -> void:
|
|
750
|
+
var on: Dictionary = scene.loads_as.get(at, {})
|
|
751
|
+
if on.is_empty():
|
|
752
|
+
return
|
|
753
|
+
answer["loadsAs"] = on
|
|
754
|
+
var names: Array = on.keys()
|
|
755
|
+
var pronoun: String = "it" if names.size() == 1 else "them"
|
|
756
|
+
if scene.loads_untooled.has(at):
|
|
757
|
+
answer["loadsAsNote"] = (
|
|
758
|
+
(
|
|
759
|
+
"The file holds %s as given, which the editor shows. %s's script is not a tool, so "
|
|
760
|
+
+ "in the game it runs as the scene loads and changes %s to what loadsAs gives."
|
|
761
|
+
)
|
|
762
|
+
% [", ".join(names), at, pronoun]
|
|
763
|
+
)
|
|
764
|
+
else:
|
|
765
|
+
answer["loadsAsNote"] = (
|
|
766
|
+
(
|
|
767
|
+
"The file holds %s as given. %s's script runs as the scene loads, in the editor "
|
|
768
|
+
+ "and in the game, and changes %s to what loadsAs gives."
|
|
769
|
+
)
|
|
770
|
+
% [", ".join(names), at, pronoun]
|
|
771
|
+
)
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
## Moves out of alsoChanged in [param answer] what the last write of [param scene] put back on the
|
|
775
|
+
## node with instance id [param id], at [param at], to setByScript.
|
|
776
|
+
static func _note_put_back(answer: Dictionary, scene: GdhSceneFile, id: int, at: String) -> void:
|
|
777
|
+
var restored: Dictionary = scene.restored_by_write.get(id, {})
|
|
778
|
+
GdhHeadlessCheck.move_script_set(answer, restored.keys(), at)
|
|
779
|
+
|
|
780
|
+
|
|
684
781
|
## Notes under notStored each of [param named] the file saved from [param pack] does not set on the
|
|
685
782
|
## node at [param at]: a set gave it the value the node has without it, so the packer leaves it out,
|
|
686
783
|
## as the editor does, and it follows [param source], or its default, from then on.
|
|
@@ -710,8 +807,8 @@ static func _note_left_out(
|
|
|
710
807
|
else:
|
|
711
808
|
answer["notStoredNote"] = (
|
|
712
809
|
(
|
|
713
|
-
"%s now %s what %s gives this node, so the file does not store %s, and a change
|
|
714
|
-
+ "this node."
|
|
810
|
+
"%s now %s what %s gives this node, so the file does not store %s, and a change "
|
|
811
|
+
+ "there reaches this node."
|
|
715
812
|
)
|
|
716
813
|
% [names, verb, source, pronoun]
|
|
717
814
|
)
|
|
@@ -743,7 +840,7 @@ func get_node_properties(args: Dictionary) -> Dictionary:
|
|
|
743
840
|
var at: String = scene.path_of(node)
|
|
744
841
|
var here: Array = set_here.keys()
|
|
745
842
|
here.sort()
|
|
746
|
-
var answer: Dictionary = {"ok": true, "nodePath": at, "properties": props, "setHere": here}
|
|
843
|
+
var answer: Dictionary = { "ok": true, "nodePath": at, "properties": props, "setHere": here }
|
|
747
844
|
# A Node3D stores only its transform, a matrix, while a set takes the position, rotation and
|
|
748
845
|
# scale the inspector shows, so a node turned 45 degrees down read back as nine numbers. A
|
|
749
846
|
# sheared one has no such three, and is left to its transform.
|
|
@@ -764,7 +861,9 @@ func get_node_properties(args: Dictionary) -> Dictionary:
|
|
|
764
861
|
# A player's getter answers Master for a bus the layout does not have, while the file keeps the
|
|
765
862
|
# name, so a player left on a renamed or removed bus read as one put on Master.
|
|
766
863
|
var bus: String = str(set_here.get("bus", ""))
|
|
767
|
-
var plays: bool =
|
|
864
|
+
var plays: bool = (
|
|
865
|
+
node is AudioStreamPlayer or node is AudioStreamPlayer2D or node is AudioStreamPlayer3D
|
|
866
|
+
)
|
|
768
867
|
if plays and not bus.is_empty() and AudioServer.get_bus_index(bus) == -1:
|
|
769
868
|
props["bus"] = bus
|
|
770
869
|
var buses: PackedStringArray = []
|
|
@@ -772,10 +871,15 @@ func get_node_properties(args: Dictionary) -> Dictionary:
|
|
|
772
871
|
var _added: bool = buses.append(AudioServer.get_bus_name(index))
|
|
773
872
|
answer["busNote"] = (
|
|
774
873
|
(
|
|
775
|
-
"%s names the bus %s, which the project's bus layout does not have, so it plays on
|
|
776
|
-
+ "the buses are %s."
|
|
874
|
+
"%s names the bus %s, which the project's bus layout does not have, so it plays on "
|
|
875
|
+
+ "%s; the buses are %s."
|
|
777
876
|
)
|
|
778
|
-
% [
|
|
877
|
+
% [
|
|
878
|
+
str(node.name) if at == "." else at,
|
|
879
|
+
bus,
|
|
880
|
+
AudioServer.get_bus_name(0),
|
|
881
|
+
", ".join(buses),
|
|
882
|
+
]
|
|
779
883
|
)
|
|
780
884
|
# A mask reads as a number, and which layers it holds, under the names the project gives them,
|
|
781
885
|
# is what a caller reads it for.
|
|
@@ -839,7 +943,7 @@ func save_scene(args: Dictionary) -> Dictionary:
|
|
|
839
943
|
if target_path != scene_path:
|
|
840
944
|
var unsaved: String = GdhSceneFile.unsaved_in_editor(target_path)
|
|
841
945
|
if not unsaved.is_empty():
|
|
842
|
-
return {"ok": false, "error": unsaved}
|
|
946
|
+
return { "ok": false, "error": unsaved }
|
|
843
947
|
|
|
844
948
|
var open_root: Node = null
|
|
845
949
|
var open_roots: Array[Node] = []
|
|
@@ -859,7 +963,9 @@ func save_scene(args: Dictionary) -> Dictionary:
|
|
|
859
963
|
var packed: PackedScene = PackedScene.new()
|
|
860
964
|
var packing: Error = packed.pack(open_root)
|
|
861
965
|
if packing != OK:
|
|
862
|
-
return {
|
|
966
|
+
return {
|
|
967
|
+
"ok": false, "error": "Failed to pack %s: %s" % [scene_path, error_string(packing)],
|
|
968
|
+
}
|
|
863
969
|
written = GdhSceneFile.save_packed(packed, target_path)
|
|
864
970
|
else:
|
|
865
971
|
var scene: GdhSceneFile = GdhSceneFile.new()
|
|
@@ -875,7 +981,7 @@ func save_scene(args: Dictionary) -> Dictionary:
|
|
|
875
981
|
"ok": true,
|
|
876
982
|
"scenePath": scene_path,
|
|
877
983
|
"savedPath": target_path,
|
|
878
|
-
"from": "editor" if open_root != null else "file"
|
|
984
|
+
"from": "editor" if open_root != null else "file",
|
|
879
985
|
}
|
|
880
986
|
|
|
881
987
|
|
|
@@ -889,16 +995,19 @@ func _save_open_scene(scene_path: String) -> Dictionary:
|
|
|
889
995
|
EditorInterface.open_scene_from_path(scene_path)
|
|
890
996
|
var now: Node = EditorInterface.get_edited_scene_root()
|
|
891
997
|
if now == null or now.scene_file_path != scene_path:
|
|
892
|
-
return {"ok": false, "error": "The editor did not switch to %s to save it." % scene_path}
|
|
998
|
+
return { "ok": false, "error": "The editor did not switch to %s to save it." % scene_path }
|
|
893
999
|
var saving: Error = EditorInterface.save_scene()
|
|
894
1000
|
if not previous.is_empty() and previous != scene_path:
|
|
895
1001
|
EditorInterface.open_scene_from_path(previous)
|
|
896
1002
|
if saving != OK:
|
|
897
|
-
return {
|
|
1003
|
+
return {
|
|
1004
|
+
"ok": false,
|
|
1005
|
+
"error": "The editor failed to save %s: %s" % [scene_path, error_string(saving)],
|
|
1006
|
+
}
|
|
898
1007
|
return {
|
|
899
1008
|
"ok": true,
|
|
900
1009
|
"scenePath": scene_path,
|
|
901
1010
|
"savedPath": scene_path,
|
|
902
1011
|
"from": "editor",
|
|
903
|
-
"unsavedInEditor": GdhSceneFile.unsaved(scene_path)
|
|
1012
|
+
"unsavedInEditor": GdhSceneFile.unsaved(scene_path),
|
|
904
1013
|
}
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
@tool
|
|
2
2
|
extends RefCounted
|
|
3
|
-
|
|
4
3
|
## The node paths a GDScript names in its own source, from the node it is on: `$Path`, `%Unique`,
|
|
5
4
|
## and a string handed to get_node, get_node_or_null or has_node called on itself. Read from the
|
|
6
5
|
## tokens rather than the lines, so a `$` or a `%` inside a string or a comment names nothing, and
|
|
7
6
|
## a `%` after an operand is the remainder of a division rather than a unique name.
|
|
8
7
|
|
|
9
|
-
enum {
|
|
8
|
+
enum {
|
|
9
|
+
NAME,
|
|
10
|
+
STRING,
|
|
11
|
+
MARK,
|
|
12
|
+
}
|
|
10
13
|
|
|
11
14
|
## The calls that take a path from the node they are called on.
|
|
12
15
|
const CALLS: Array[String] = ["get_node", "get_node_or_null", "has_node"]
|
|
13
16
|
## The words after which a `%` starts an operand.
|
|
14
17
|
const OPERAND_AFTER: Array[String] = [
|
|
15
|
-
"return", "and", "or", "not", "in", "if", "elif", "while", "await", "match", "when", "else"
|
|
18
|
+
"return", "and", "or", "not", "in", "if", "elif", "while", "await", "match", "when", "else",
|
|
16
19
|
]
|
|
17
20
|
## The marks after which a `%` starts an operand: an opening bracket, a separator or an operator.
|
|
18
21
|
const OPERAND_AFTER_MARKS: String = "([{,=:;+-*/<>!&|^~%"
|
|
@@ -33,10 +36,14 @@ static func named(source: String) -> Array[Dictionary]:
|
|
|
33
36
|
elif _is_mark(token, "%") and _starts_operand(tokens, at):
|
|
34
37
|
path = _path_from(tokens, at)
|
|
35
38
|
elif token[0] == NAME and CALLS.has(str(token[1])) and _on_itself(tokens, at):
|
|
36
|
-
if
|
|
39
|
+
if (
|
|
40
|
+
at + 2 < tokens.size()
|
|
41
|
+
and _is_mark(tokens[at + 1], "(")
|
|
42
|
+
and tokens[at + 2][0] == STRING
|
|
43
|
+
):
|
|
37
44
|
path = str(tokens[at + 2][1])
|
|
38
45
|
if not path.is_empty():
|
|
39
|
-
found.append({"line": token[2], "path": path})
|
|
46
|
+
found.append({ "line": token[2], "path": path })
|
|
40
47
|
return found
|
|
41
48
|
|
|
42
49
|
|
|
@@ -58,7 +65,8 @@ static func _path_from(tokens: Array[Array], at: int) -> String:
|
|
|
58
65
|
return "/".join(parts)
|
|
59
66
|
|
|
60
67
|
|
|
61
|
-
## The name of a path at [param at], as [its text, where the next token is], or [] when there is
|
|
68
|
+
## The name of a path at [param at], as [its text, where the next token is], or [] when there is
|
|
69
|
+
## none.
|
|
62
70
|
static func _part_at(tokens: Array[Array], at: int) -> Array:
|
|
63
71
|
var unique: String = ""
|
|
64
72
|
if at < tokens.size() and _is_mark(tokens[at], "%"):
|
|
@@ -112,7 +120,10 @@ static func _tokens(source: String) -> Array[Array]:
|
|
|
112
120
|
at += 1
|
|
113
121
|
elif c in " \t\r":
|
|
114
122
|
at += 1
|
|
115
|
-
elif
|
|
123
|
+
elif (
|
|
124
|
+
QUOTES.contains(c)
|
|
125
|
+
or ("r^&".contains(c) and QUOTES.contains(next) and not next.is_empty())
|
|
126
|
+
):
|
|
116
127
|
var quoted: Array = _string(source, at if QUOTES.contains(c) else at + 1)
|
|
117
128
|
tokens.append([STRING, quoted[0], line])
|
|
118
129
|
line += str(quoted[0]).count("\n")
|
|
@@ -133,7 +144,8 @@ static func _tokens(source: String) -> Array[Array]:
|
|
|
133
144
|
|
|
134
145
|
|
|
135
146
|
## The string whose opening quote is at [param at], as [what is between its quotes, where it ends].
|
|
136
|
-
## A backslash keeps the character after it inside the string, raw or not, as the tokenizer reads
|
|
147
|
+
## A backslash keeps the character after it inside the string, raw or not, as the tokenizer reads
|
|
148
|
+
## it.
|
|
137
149
|
static func _string(source: String, at: int) -> Array:
|
|
138
150
|
var quote: String = source[at]
|
|
139
151
|
var closing: String = quote.repeat(3) if source.substr(at, 3) == quote.repeat(3) else quote
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
@tool
|
|
2
2
|
extends Node
|
|
3
|
-
|
|
4
3
|
## Project settings read from the open editor, for a caller that asked for the editor's answer, and
|
|
5
4
|
## taken up by it after a write to the file.
|
|
6
5
|
##
|
|
@@ -29,7 +28,9 @@ func get_project_setting(args: Dictionary) -> Dictionary:
|
|
|
29
28
|
|
|
30
29
|
var setting: String = str(args.get("setting", ""))
|
|
31
30
|
if setting.is_empty():
|
|
32
|
-
return {
|
|
31
|
+
return {
|
|
32
|
+
"ok": false, "error": "setting is required, or prefix to read every setting under one",
|
|
33
|
+
}
|
|
33
34
|
|
|
34
35
|
var result: Dictionary = GdhSettingReads.one(setting, _values)
|
|
35
36
|
result["ok"] = true
|
|
@@ -46,11 +47,11 @@ func adopt_project_settings(args: Dictionary) -> Dictionary:
|
|
|
46
47
|
var file: ConfigFile = ConfigFile.new()
|
|
47
48
|
var loaded: Error = file.load("res://project.godot")
|
|
48
49
|
if loaded != OK:
|
|
49
|
-
return {"ok": false, "error": "Could not read project.godot: " + error_string(loaded)}
|
|
50
|
+
return { "ok": false, "error": "Could not read project.godot: " + error_string(loaded) }
|
|
50
51
|
var adopted: Array[String] = []
|
|
51
52
|
var named: Variant = args.get("settings", [])
|
|
52
53
|
if not named is Array:
|
|
53
|
-
return {"ok": false, "error": "settings must be a list of setting names"}
|
|
54
|
+
return { "ok": false, "error": "settings must be a list of setting names" }
|
|
54
55
|
var settings: Array = named
|
|
55
56
|
for entry: Variant in settings:
|
|
56
57
|
var setting: String = str(entry)
|
|
@@ -66,19 +67,21 @@ func adopt_project_settings(args: Dictionary) -> Dictionary:
|
|
|
66
67
|
else:
|
|
67
68
|
ProjectSettings.set_setting(setting, null)
|
|
68
69
|
adopted.append(setting)
|
|
69
|
-
return {"ok": true, "adopted": adopted}
|
|
70
|
+
return { "ok": true, "adopted": adopted }
|
|
70
71
|
|
|
71
72
|
|
|
72
73
|
## Loads the bus layout the project names into the editor's audio server, after something else
|
|
73
74
|
## wrote it: the editor holds the layout it loaded and saves that one when its audio panel changes.
|
|
74
75
|
func adopt_audio_bus_layout(_args: Dictionary) -> Dictionary:
|
|
75
76
|
var path: String = str(
|
|
76
|
-
ProjectSettings.get_setting(
|
|
77
|
+
ProjectSettings.get_setting(
|
|
78
|
+
"audio/buses/default_bus_layout", "res://default_bus_layout.tres"
|
|
79
|
+
)
|
|
77
80
|
)
|
|
78
81
|
var layout: AudioBusLayout = ResourceLoader.load(
|
|
79
82
|
path, "AudioBusLayout", ResourceLoader.CACHE_MODE_REPLACE
|
|
80
83
|
)
|
|
81
84
|
if layout == null:
|
|
82
|
-
return {"ok": false, "error": "Could not load the bus layout at " + path}
|
|
85
|
+
return { "ok": false, "error": "Could not load the bus layout at " + path }
|
|
83
86
|
AudioServer.set_bus_layout(layout)
|
|
84
|
-
return {"ok": true, "layout": path}
|
|
87
|
+
return { "ok": true, "layout": path }
|