gdharness 1.3.0 → 1.3.2
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 +322 -96
- package/build/godot/addons/gdharness_editor/animation_reads.gd +7 -19
- package/build/godot/addons/gdharness_editor/bridge_client.gd +8 -8
- package/build/godot/addons/gdharness_editor/declared_values.gd +116 -0
- package/build/godot/addons/gdharness_editor/declared_values.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/file_reads.gd +65 -25
- package/build/godot/addons/gdharness_editor/headless_check.gd +7 -7
- package/build/godot/addons/gdharness_editor/plugin.gd +6 -6
- package/build/godot/addons/gdharness_editor/property_values.gd +222 -59
- package/build/godot/addons/gdharness_editor/reading.gd +65 -0
- package/build/godot/addons/gdharness_editor/scene_file.gd +28 -23
- package/build/godot/addons/gdharness_editor/serialisation.gd +49 -94
- package/build/godot/addons/gdharness_editor/tool_executor.gd +24 -24
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +52 -41
- package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +4 -4
- package/build/godot/addons/gdharness_editor/tools/play_tools.gd +2 -2
- package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +14 -14
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +175 -74
- package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +17 -17
- package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +14 -12
- package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +7 -7
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +88 -84
- package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +4 -4
- package/build/godot/addons/gdharness_editor/value_shapes.gd +118 -0
- package/build/godot/addons/gdharness_editor/value_shapes.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/reading.gd +65 -0
- package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +18 -18
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +29 -29
- package/build/godot/addons/gdharness_runtime/runtime_capture.gd +21 -18
- package/build/godot/addons/gdharness_runtime/runtime_changes.gd +86 -80
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +65 -64
- package/build/godot/addons/gdharness_runtime/runtime_items.gd +6 -6
- package/build/godot/addons/gdharness_runtime/runtime_menus.gd +8 -8
- package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +6 -6
- package/build/godot/addons/gdharness_runtime/runtime_pad.gd +10 -10
- package/build/godot/addons/gdharness_runtime/runtime_paths.gd +7 -7
- package/build/godot/addons/gdharness_runtime/runtime_queries.gd +41 -41
- package/build/godot/addons/gdharness_runtime/runtime_says.gd +3 -3
- package/build/godot/addons/gdharness_runtime/runtime_targets.gd +33 -33
- package/build/godot/addons/gdharness_runtime/runtime_typing.gd +20 -20
- package/build/godot/addons/gdharness_runtime/runtime_values.gd +52 -25
- package/build/godot/addons/gdharness_runtime/runtime_waits.gd +56 -50
- package/build/godot/addons/gdharness_runtime/serialisation.gd +49 -94
- package/build/godot/addons/gdharness_runtime/value_shapes.gd +118 -0
- package/build/godot/addons/gdharness_runtime/value_shapes.gd.uid +1 -0
- package/build/godot/operations/animation_reads.gd +7 -19
- package/build/godot/operations/audio_buses.gd +10 -10
- package/build/godot/operations/class_cache.gd +16 -16
- package/build/godot/operations/classdb_queries.gd +25 -15
- package/build/godot/operations/declared_values.gd +116 -0
- package/build/godot/operations/dependencies.gd +141 -33
- package/build/godot/operations/editor_tools.gd +12 -12
- package/build/godot/operations/export_presets.gd +14 -14
- package/build/godot/operations/file_reads.gd +65 -25
- package/build/godot/operations/file_walk.gd +34 -0
- package/build/godot/operations/gdscript_analysis.gd +27 -22
- package/build/godot/operations/gdscript_authoring.gd +122 -17
- package/build/godot/operations/godot_operations.gd +66 -63
- package/build/godot/operations/import_pipeline.gd +59 -20
- package/build/godot/operations/input_actions.gd +90 -18
- package/build/godot/operations/logger.gd +1 -1
- package/build/godot/operations/plugins.gd +8 -8
- package/build/godot/operations/project_config.gd +83 -20
- package/build/godot/operations/project_diagnostics.gd +36 -11
- package/build/godot/operations/property_values.gd +222 -59
- package/build/godot/operations/reading.gd +65 -0
- package/build/godot/operations/rename_checks.gd +3 -3
- package/build/godot/operations/resource_files.gd +9 -6
- package/build/godot/operations/script_check.gd +23 -7
- package/build/godot/operations/serialisation.gd +49 -94
- package/build/godot/operations/value_shapes.gd +118 -0
- package/package.json +1 -1
|
@@ -3,19 +3,19 @@ extends Node
|
|
|
3
3
|
|
|
4
4
|
## Scenes and their nodes, edited in the open editor and read back from what it holds.
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
6
|
+
const GdhFileReads = preload("../file_reads.gd")
|
|
7
|
+
const GdhRead = preload("../reading.gd")
|
|
8
|
+
const GdhKin = preload("scene_kin.gd")
|
|
9
|
+
const GdhPaths = preload("scene_paths.gd")
|
|
10
|
+
const GdhPlacing = preload("scene_placing.gd")
|
|
11
|
+
const GdhPropertyValues = preload("../property_values.gd")
|
|
12
|
+
const GdhResourceTools = preload("resource_tools.gd")
|
|
13
|
+
const GdhSceneFile = preload("../scene_file.gd")
|
|
14
|
+
const GdhSerialisation = preload("../serialisation.gd")
|
|
15
15
|
|
|
16
16
|
var _editor_plugin: EditorPlugin = null
|
|
17
|
-
var _values:
|
|
18
|
-
var _properties:
|
|
17
|
+
var _values: GdhSerialisation = GdhSerialisation.new()
|
|
18
|
+
var _properties: GdhPropertyValues = GdhPropertyValues.new()
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
func set_editor_plugin(plugin: EditorPlugin) -> void:
|
|
@@ -47,7 +47,7 @@ func _to_scene_res_path(project_path: String, scene_path: String) -> String:
|
|
|
47
47
|
|
|
48
48
|
## [param scene_path] opened for a tool, as [scene, refusal]: the refusal is {} when it opened.
|
|
49
49
|
func _open(scene_path: String, for_writing: bool) -> Array:
|
|
50
|
-
var scene:
|
|
50
|
+
var scene: GdhSceneFile = GdhSceneFile.new()
|
|
51
51
|
return [scene, scene.open(scene_path, for_writing)]
|
|
52
52
|
|
|
53
53
|
|
|
@@ -60,23 +60,21 @@ func _find_node(root: Node, path: String) -> Node:
|
|
|
60
60
|
## Why the property or signal [param missing] could not be found on [param node], adding the one
|
|
61
61
|
## cause the name alone does not show: a script that does not compile leaves the editor holding a
|
|
62
62
|
## placeholder with no properties or signals at all, and the refusal named the property instead.
|
|
63
|
+
## Such a script has no engine class beneath it. Compiling a copy of the source to find out failed on
|
|
64
|
+
## every script with a class_name, since the copy hides the global class the original declares.
|
|
63
65
|
func _missing_on(node: Node, missing: String) -> String:
|
|
64
66
|
var script: Script = node.get_script()
|
|
65
|
-
if script == null or not script.
|
|
66
|
-
return missing
|
|
67
|
-
var probe: GDScript = GDScript.new()
|
|
68
|
-
probe.source_code = script.source_code
|
|
69
|
-
if probe.reload() == OK:
|
|
67
|
+
if script == null or not str(script.get_instance_base_type()).is_empty():
|
|
70
68
|
return missing
|
|
71
69
|
return (
|
|
72
70
|
"%s. Its script, %s, does not compile, so none of what it declares is known here."
|
|
73
|
-
% [missing, script.resource_path]
|
|
71
|
+
% [missing.trim_suffix("."), script.resource_path]
|
|
74
72
|
)
|
|
75
73
|
|
|
76
74
|
|
|
77
75
|
## Whether each of [param names] reads the same off [param saved] as off [param node], answering
|
|
78
76
|
## the first that does not, or "".
|
|
79
|
-
func _kept(scene:
|
|
77
|
+
func _kept(scene: GdhSceneFile, saved: Node, node: Node, names: Array) -> String:
|
|
80
78
|
var at: String = scene.path_of(node)
|
|
81
79
|
var copy: Node = saved.get_node_or_null(at)
|
|
82
80
|
if copy == null:
|
|
@@ -106,7 +104,7 @@ func _properties_of(node: Node, include_defaults: bool, set_here: Dictionary) ->
|
|
|
106
104
|
scripted[str(declared.get("name", ""))] = true
|
|
107
105
|
var props: Dictionary = {}
|
|
108
106
|
for p: Dictionary in node.get_property_list():
|
|
109
|
-
if not (
|
|
107
|
+
if not (GdhRead.as_int(p.get("usage", 0)) & PROPERTY_USAGE_STORAGE):
|
|
110
108
|
continue
|
|
111
109
|
var property: String = str(p.get("name", ""))
|
|
112
110
|
if property.is_empty():
|
|
@@ -118,7 +116,7 @@ func _properties_of(node: Node, include_defaults: bool, set_here: Dictionary) ->
|
|
|
118
116
|
if scripted.has(property)
|
|
119
117
|
else ClassDB.class_get_property_default_value(node.get_class(), property)
|
|
120
118
|
)
|
|
121
|
-
if
|
|
119
|
+
if GdhPropertyValues.same(value, default):
|
|
122
120
|
continue
|
|
123
121
|
props[property] = _readable(node, value)
|
|
124
122
|
return props
|
|
@@ -141,7 +139,7 @@ func _parse_properties_arg(raw_properties: Variant) -> Dictionary:
|
|
|
141
139
|
var text: String = str(raw_properties)
|
|
142
140
|
if text.strip_edges().is_empty():
|
|
143
141
|
return {}
|
|
144
|
-
var parsed: Variant =
|
|
142
|
+
var parsed: Variant = GdhRead.json_or_null(text)
|
|
145
143
|
if typeof(parsed) == TYPE_DICTIONARY:
|
|
146
144
|
return parsed
|
|
147
145
|
return {}
|
|
@@ -157,7 +155,7 @@ func _collect_nodes_recursive(node: Node, path: String, out_nodes: Array) -> voi
|
|
|
157
155
|
func _inherited(args: Dictionary) -> Dictionary:
|
|
158
156
|
var project_path: String = str(args.get("projectPath", ""))
|
|
159
157
|
var script_path: String = str(args.get("script", ""))
|
|
160
|
-
return
|
|
158
|
+
return GdhKin.inherited(
|
|
161
159
|
args,
|
|
162
160
|
_new_scene_path(args),
|
|
163
161
|
_to_scene_res_path(project_path, str(args.get("inherits", ""))),
|
|
@@ -191,7 +189,7 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
191
189
|
if scene_path.is_empty():
|
|
192
190
|
return {"ok": false, "error": "Missing scenePath"}
|
|
193
191
|
var asked_type: String = root_node_type
|
|
194
|
-
var made: Dictionary =
|
|
192
|
+
var made: Dictionary = GdhSceneFile.made_as(
|
|
195
193
|
root_node_type,
|
|
196
194
|
"" if script_path.is_empty() else _to_scene_res_path(project_path, script_path),
|
|
197
195
|
"Node",
|
|
@@ -209,15 +207,15 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
209
207
|
}
|
|
210
208
|
if not ClassDB.can_instantiate(root_node_type):
|
|
211
209
|
return {"ok": false, "error": "%s cannot be instantiated." % root_node_type}
|
|
212
|
-
var unfit: String =
|
|
210
|
+
var unfit: String = GdhSceneFile.unfit_name(root_node_name)
|
|
213
211
|
if not unfit.is_empty():
|
|
214
212
|
return {"ok": false, "error": unfit}
|
|
215
213
|
if FileAccess.file_exists(scene_path):
|
|
216
|
-
return
|
|
214
|
+
return GdhKin.taken(scene_path)
|
|
217
215
|
|
|
218
216
|
var root: Node = ClassDB.instantiate(root_node_type)
|
|
219
217
|
root.name = root_node_name
|
|
220
|
-
var scene:
|
|
218
|
+
var scene: GdhSceneFile = GdhSceneFile.new()
|
|
221
219
|
scene.root = root
|
|
222
220
|
scene.path = scene_path
|
|
223
221
|
scene.asked(root, ["script"])
|
|
@@ -228,7 +226,7 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
228
226
|
if script == null:
|
|
229
227
|
root.free()
|
|
230
228
|
return {"ok": false, "error": "No script loads from " + full_script_path}
|
|
231
|
-
var uncompiled: String =
|
|
229
|
+
var uncompiled: String = GdhSceneFile.uncompiled(script, full_script_path)
|
|
232
230
|
if not uncompiled.is_empty():
|
|
233
231
|
root.free()
|
|
234
232
|
return {"ok": false, "error": uncompiled}
|
|
@@ -245,7 +243,7 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
245
243
|
# name is no property the write compares.
|
|
246
244
|
root.name = root_node_name
|
|
247
245
|
|
|
248
|
-
var folder: String =
|
|
246
|
+
var folder: String = GdhSceneFile.make_folder_for(scene_path)
|
|
249
247
|
if not folder.is_empty():
|
|
250
248
|
root.free()
|
|
251
249
|
return {"ok": false, "error": folder}
|
|
@@ -259,14 +257,14 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
259
257
|
func list_scene_nodes(args: Dictionary) -> Dictionary:
|
|
260
258
|
var project_path: String = str(args.get("projectPath", ""))
|
|
261
259
|
var scene_path: String = _to_scene_res_path(project_path, str(args.get("scenePath", "")))
|
|
262
|
-
var depth: int =
|
|
263
|
-
var include_properties: bool =
|
|
260
|
+
var depth: int = GdhRead.as_int(args.get("depth", -1), -1)
|
|
261
|
+
var include_properties: bool = GdhRead.as_bool(args.get("includeProperties", false))
|
|
264
262
|
|
|
265
263
|
# Read as a headless engine reads it with no editor connected, so the answer does not depend on
|
|
266
264
|
# whether one is.
|
|
267
|
-
var read: Dictionary =
|
|
265
|
+
var read: Dictionary = GdhFileReads.scene_tree(scene_path, depth, include_properties)
|
|
268
266
|
if read.get("ok", false):
|
|
269
|
-
read["unsavedInEditor"] =
|
|
267
|
+
read["unsavedInEditor"] = GdhSceneFile.unsaved(scene_path)
|
|
270
268
|
return read
|
|
271
269
|
|
|
272
270
|
|
|
@@ -284,20 +282,20 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
284
282
|
var asked_type: String = node_type
|
|
285
283
|
var class_script: Script = null
|
|
286
284
|
if not node_type.is_empty() and not ClassDB.class_exists(node_type):
|
|
287
|
-
var declared: Dictionary =
|
|
285
|
+
var declared: Dictionary = GdhSceneFile.script_class(node_type, "Node")
|
|
288
286
|
if declared.has("error"):
|
|
289
287
|
return {"ok": false, "error": declared["error"]}
|
|
290
288
|
var held: Variant = declared.get("script")
|
|
291
289
|
if held is Script:
|
|
292
290
|
class_script = held
|
|
293
291
|
node_type = str(declared["base"])
|
|
294
|
-
var making: Array =
|
|
292
|
+
var making: Array = GdhPlacing.what_to_add(node_type, instance_path, scene_path)
|
|
295
293
|
var packed: PackedScene = making[0]
|
|
296
294
|
if not str(making[1]).is_empty():
|
|
297
295
|
return {"ok": false, "error": making[1]}
|
|
298
296
|
|
|
299
297
|
var opened: Array = _open(scene_path, true)
|
|
300
|
-
var scene:
|
|
298
|
+
var scene: GdhSceneFile = opened[0]
|
|
301
299
|
var refused: Dictionary = opened[1]
|
|
302
300
|
if not refused.is_empty():
|
|
303
301
|
return refused
|
|
@@ -313,19 +311,19 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
313
311
|
if not unusable.is_empty():
|
|
314
312
|
return scene.refuse(unusable)
|
|
315
313
|
var place: Variant = args.get("index")
|
|
316
|
-
var unplaceable: String =
|
|
314
|
+
var unplaceable: String = GdhPlacing.unplaceable(parent, null, place)
|
|
317
315
|
if not unplaceable.is_empty():
|
|
318
316
|
return scene.refuse(unplaceable)
|
|
319
317
|
|
|
320
318
|
# In the tree before its properties, so a property holding a node can find it by path.
|
|
321
|
-
var new_node: Node =
|
|
319
|
+
var new_node: Node = GdhPlacing.made(packed, node_type)
|
|
322
320
|
if class_script != null:
|
|
323
321
|
scene.asked(new_node, ["script"])
|
|
324
322
|
new_node.set_script(class_script)
|
|
325
323
|
new_node.name = node_name
|
|
326
324
|
parent.add_child(new_node)
|
|
327
|
-
|
|
328
|
-
|
|
325
|
+
GdhPlacing.place(new_node, place)
|
|
326
|
+
GdhPlacing.own(new_node, root)
|
|
329
327
|
var unsettled: String = scene.settle()
|
|
330
328
|
if not unsettled.is_empty():
|
|
331
329
|
return scene.refuse("Nothing was written: " + unsettled)
|
|
@@ -343,6 +341,7 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
343
341
|
"nodePath": new_path,
|
|
344
342
|
"index": new_node.get_index(),
|
|
345
343
|
}
|
|
344
|
+
_properties.note_write(answer, new_node)
|
|
346
345
|
var written: Dictionary = scene.write(
|
|
347
346
|
func(saved: Node) -> String:
|
|
348
347
|
return _kept(
|
|
@@ -373,7 +372,7 @@ func delete_node(args: Dictionary) -> Dictionary:
|
|
|
373
372
|
}
|
|
374
373
|
|
|
375
374
|
var opened: Array = _open(scene_path, true)
|
|
376
|
-
var scene:
|
|
375
|
+
var scene: GdhSceneFile = opened[0]
|
|
377
376
|
var refused: Dictionary = opened[1]
|
|
378
377
|
if not refused.is_empty():
|
|
379
378
|
return refused
|
|
@@ -388,7 +387,7 @@ func delete_node(args: Dictionary) -> Dictionary:
|
|
|
388
387
|
var at: String = scene.path_of(node)
|
|
389
388
|
node.get_parent().remove_child(node)
|
|
390
389
|
node.free()
|
|
391
|
-
var carried:
|
|
390
|
+
var carried: GdhPaths = GdhPaths.new()
|
|
392
391
|
var _rewritten: int = carried.carry(scene, {at: ""})
|
|
393
392
|
|
|
394
393
|
var written: Dictionary = scene.write(
|
|
@@ -401,7 +400,7 @@ func delete_node(args: Dictionary) -> Dictionary:
|
|
|
401
400
|
return written
|
|
402
401
|
|
|
403
402
|
var answer: Dictionary = {"ok": true, "deletedNodePath": at}
|
|
404
|
-
answer.merge(
|
|
403
|
+
answer.merge(GdhKin.follow(scene_path, at, "", carried))
|
|
405
404
|
return answer
|
|
406
405
|
|
|
407
406
|
|
|
@@ -416,7 +415,7 @@ func duplicate_node(args: Dictionary) -> Dictionary:
|
|
|
416
415
|
return {"ok": false, "error": "Missing nodePath or newName"}
|
|
417
416
|
|
|
418
417
|
var opened: Array = _open(scene_path, true)
|
|
419
|
-
var scene:
|
|
418
|
+
var scene: GdhSceneFile = opened[0]
|
|
420
419
|
var refused: Dictionary = opened[1]
|
|
421
420
|
if not refused.is_empty():
|
|
422
421
|
return refused
|
|
@@ -444,14 +443,14 @@ func duplicate_node(args: Dictionary) -> Dictionary:
|
|
|
444
443
|
return scene.refuse(unusable)
|
|
445
444
|
|
|
446
445
|
var copies: Dictionary = {}
|
|
447
|
-
var duplicated_node: Node =
|
|
446
|
+
var duplicated_node: Node = GdhPlacing.copied(source, root, copies)
|
|
448
447
|
if not duplicated_node:
|
|
449
448
|
return scene.refuse("Failed to duplicate node: " + node_path)
|
|
450
449
|
|
|
451
450
|
duplicated_node.name = new_name
|
|
452
451
|
target_parent.add_child(duplicated_node)
|
|
453
|
-
|
|
454
|
-
|
|
452
|
+
GdhPlacing.own(duplicated_node, root)
|
|
453
|
+
GdhPlacing.reconnect(copies, source)
|
|
455
454
|
scene.copied(copies)
|
|
456
455
|
|
|
457
456
|
var new_path: String = scene.path_of(duplicated_node)
|
|
@@ -487,7 +486,7 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
487
486
|
return {"ok": false, "error": "Missing newParentPath"}
|
|
488
487
|
|
|
489
488
|
var opened: Array = _open(scene_path, true)
|
|
490
|
-
var scene:
|
|
489
|
+
var scene: GdhSceneFile = opened[0]
|
|
491
490
|
var refused: Dictionary = opened[1]
|
|
492
491
|
if not refused.is_empty():
|
|
493
492
|
return refused
|
|
@@ -515,7 +514,7 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
515
514
|
if not unusable.is_empty():
|
|
516
515
|
return scene.refuse(unusable)
|
|
517
516
|
var place: Variant = args.get("index")
|
|
518
|
-
var unplaceable: String =
|
|
517
|
+
var unplaceable: String = GdhPlacing.unplaceable(new_parent, node, place)
|
|
519
518
|
if not unplaceable.is_empty():
|
|
520
519
|
return scene.refuse(unplaceable)
|
|
521
520
|
|
|
@@ -525,12 +524,12 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
525
524
|
node.owner = null
|
|
526
525
|
node.get_parent().remove_child(node)
|
|
527
526
|
new_parent.add_child(node)
|
|
528
|
-
|
|
529
|
-
|
|
527
|
+
GdhPlacing.place(node, place)
|
|
528
|
+
GdhPlacing.own(node, root)
|
|
530
529
|
|
|
531
530
|
var new_path: String = scene.path_of(node)
|
|
532
531
|
var index: int = node.get_index()
|
|
533
|
-
var carried:
|
|
532
|
+
var carried: GdhPaths = GdhPaths.new()
|
|
534
533
|
var _rewritten: int = carried.carry(scene, {old_path: new_path} if new_path != old_path else {})
|
|
535
534
|
var written: Dictionary = scene.write(
|
|
536
535
|
func(saved: Node) -> String:
|
|
@@ -555,7 +554,7 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
555
554
|
"index": index,
|
|
556
555
|
}
|
|
557
556
|
if new_path != old_path:
|
|
558
|
-
answer.merge(
|
|
557
|
+
answer.merge(GdhKin.follow(scene_path, old_path, new_path, carried))
|
|
559
558
|
return answer
|
|
560
559
|
|
|
561
560
|
|
|
@@ -569,7 +568,7 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
569
568
|
return {"ok": false, "error": "set takes properties, editableChildren, or both."}
|
|
570
569
|
|
|
571
570
|
var opened: Array = _open(scene_path, true)
|
|
572
|
-
var scene:
|
|
571
|
+
var scene: GdhSceneFile = opened[0]
|
|
573
572
|
var refused: Dictionary = opened[1]
|
|
574
573
|
if not refused.is_empty():
|
|
575
574
|
return refused
|
|
@@ -590,10 +589,10 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
590
589
|
|
|
591
590
|
var dropped: Dictionary = {}
|
|
592
591
|
if editable != null:
|
|
593
|
-
var not_an_instance: String =
|
|
592
|
+
var not_an_instance: String = GdhKin.set_editable(scene, node, GdhRead.as_bool(editable))
|
|
594
593
|
if not not_an_instance.is_empty():
|
|
595
594
|
return scene.refuse(not_an_instance)
|
|
596
|
-
if not
|
|
595
|
+
if not GdhRead.as_bool(editable):
|
|
597
596
|
dropped = scene.held_under(scene.path_of(node))
|
|
598
597
|
|
|
599
598
|
var old_path: String = scene.path_of(node)
|
|
@@ -606,28 +605,31 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
606
605
|
for key: Variant in properties:
|
|
607
606
|
held[str(key)] = _readable(node, _properties.read_at(node, str(key)))
|
|
608
607
|
var new_path: String = scene.path_of(node)
|
|
609
|
-
var
|
|
608
|
+
var answer: Dictionary = {"ok": true, "nodePath": new_path, "properties": held}
|
|
609
|
+
_properties.note_write(answer, node)
|
|
610
|
+
var carried: GdhPaths = GdhPaths.new()
|
|
610
611
|
var _rewritten: int = carried.carry(scene, {old_path: new_path} if new_path != old_path else {})
|
|
611
612
|
var written: Dictionary = scene.write(
|
|
612
613
|
func(saved: Node) -> String:
|
|
613
614
|
var unkept: String = _kept(scene, saved, node, properties.keys())
|
|
614
615
|
if unkept.is_empty() and editable != null:
|
|
615
|
-
if saved.is_editable_instance(saved.get_node(new_path)) !=
|
|
616
|
-
return
|
|
616
|
+
if saved.is_editable_instance(saved.get_node(new_path)) != GdhRead.as_bool(editable):
|
|
617
|
+
return (
|
|
618
|
+
"%s would load with editableChildren %s." % [new_path, not GdhRead.as_bool(editable)]
|
|
619
|
+
)
|
|
617
620
|
return unkept
|
|
618
621
|
)
|
|
619
622
|
if not written.is_empty():
|
|
620
623
|
carried.put_back(scene_path)
|
|
621
624
|
return written
|
|
622
625
|
|
|
623
|
-
var answer: Dictionary = {"ok": true, "nodePath": new_path, "properties": held}
|
|
624
626
|
if editable != null:
|
|
625
|
-
answer["editableChildren"] =
|
|
627
|
+
answer["editableChildren"] = GdhRead.as_bool(editable)
|
|
626
628
|
if not dropped.is_empty():
|
|
627
629
|
answer["droppedValues"] = dropped["values"]
|
|
628
630
|
answer["droppedNodes"] = dropped["nodes"]
|
|
629
631
|
if new_path != old_path:
|
|
630
|
-
answer.merge(
|
|
632
|
+
answer.merge(GdhKin.follow(scene_path, old_path, new_path, carried))
|
|
631
633
|
return answer
|
|
632
634
|
|
|
633
635
|
|
|
@@ -635,10 +637,10 @@ func get_node_properties(args: Dictionary) -> Dictionary:
|
|
|
635
637
|
var project_path: String = str(args.get("projectPath", ""))
|
|
636
638
|
var scene_path: String = _to_scene_res_path(project_path, str(args.get("scenePath", "")))
|
|
637
639
|
var node_path: String = str(args.get("nodePath", "."))
|
|
638
|
-
var include_defaults: bool =
|
|
640
|
+
var include_defaults: bool = GdhRead.as_bool(args.get("includeDefaults", false))
|
|
639
641
|
|
|
640
642
|
var opened: Array = _open(scene_path, false)
|
|
641
|
-
var scene:
|
|
643
|
+
var scene: GdhSceneFile = opened[0]
|
|
642
644
|
var refused: Dictionary = opened[1]
|
|
643
645
|
if not refused.is_empty():
|
|
644
646
|
return refused
|
|
@@ -652,7 +654,7 @@ func get_node_properties(args: Dictionary) -> Dictionary:
|
|
|
652
654
|
# variable read as changed; and a value this scene sets back to the default was hidden, so the
|
|
653
655
|
# names this scene's file sets are always answered.
|
|
654
656
|
var props: Dictionary = _properties_of(node, include_defaults, scene.set_here(node))
|
|
655
|
-
var cells: Dictionary =
|
|
657
|
+
var cells: Dictionary = GdhResourceTools.cells_of(node)
|
|
656
658
|
var answer: Dictionary = {"ok": true, "nodePath": node_path, "properties": props}
|
|
657
659
|
if node != scene.root and node.owner != null and not node.scene_file_path.is_empty():
|
|
658
660
|
answer["instanceOf"] = node.scene_file_path
|
|
@@ -660,7 +662,7 @@ func get_node_properties(args: Dictionary) -> Dictionary:
|
|
|
660
662
|
scene.close()
|
|
661
663
|
# Only an editor holds anything unsaved; a headless engine answering false would say it looked.
|
|
662
664
|
if Engine.is_editor_hint():
|
|
663
|
-
answer["unsavedInEditor"] =
|
|
665
|
+
answer["unsavedInEditor"] = GdhSceneFile.unsaved(scene_path)
|
|
664
666
|
answer.merge(cells)
|
|
665
667
|
# An empty answer read as a node with nothing on it, rather than one with nothing changed.
|
|
666
668
|
if props.is_empty() and not include_defaults:
|
|
@@ -680,7 +682,7 @@ func save_scene(args: Dictionary) -> Dictionary:
|
|
|
680
682
|
target_path = _to_scene_res_path(project_path, new_path_raw)
|
|
681
683
|
|
|
682
684
|
if target_path != scene_path:
|
|
683
|
-
var unsaved: String =
|
|
685
|
+
var unsaved: String = GdhSceneFile.unsaved_in_editor(target_path)
|
|
684
686
|
if not unsaved.is_empty():
|
|
685
687
|
return {"ok": false, "error": unsaved}
|
|
686
688
|
|
|
@@ -703,9 +705,9 @@ func save_scene(args: Dictionary) -> Dictionary:
|
|
|
703
705
|
var packing: Error = packed.pack(open_root)
|
|
704
706
|
if packing != OK:
|
|
705
707
|
return {"ok": false, "error": "Failed to pack %s: %s" % [scene_path, error_string(packing)]}
|
|
706
|
-
written =
|
|
708
|
+
written = GdhSceneFile.save_packed(packed, target_path)
|
|
707
709
|
else:
|
|
708
|
-
var scene:
|
|
710
|
+
var scene: GdhSceneFile = GdhSceneFile.new()
|
|
709
711
|
var refused: Dictionary = scene.open(scene_path, true)
|
|
710
712
|
if not refused.is_empty():
|
|
711
713
|
return refused
|
|
@@ -743,7 +745,7 @@ func _save_open_scene(scene_path: String) -> Dictionary:
|
|
|
743
745
|
"scenePath": scene_path,
|
|
744
746
|
"savedPath": scene_path,
|
|
745
747
|
"from": "editor",
|
|
746
|
-
"unsavedInEditor":
|
|
748
|
+
"unsavedInEditor": GdhSceneFile.unsaved(scene_path)
|
|
747
749
|
}
|
|
748
750
|
|
|
749
751
|
|
|
@@ -756,7 +758,7 @@ func connect_signal(args: Dictionary) -> Dictionary:
|
|
|
756
758
|
var method_name: String = str(args.get("methodName", ""))
|
|
757
759
|
# A connection without CONNECT_PERSIST is a runtime one, and PackedScene.pack drops those on
|
|
758
760
|
# the way out: without this the scene saves unchanged and this answers success over nothing.
|
|
759
|
-
var flags: int =
|
|
761
|
+
var flags: int = GdhRead.as_int(args.get("flags", 0)) | Object.CONNECT_PERSIST
|
|
760
762
|
|
|
761
763
|
if (
|
|
762
764
|
source_node_path.is_empty()
|
|
@@ -767,7 +769,7 @@ func connect_signal(args: Dictionary) -> Dictionary:
|
|
|
767
769
|
return {"ok": false, "error": "Missing required signal connection arguments"}
|
|
768
770
|
|
|
769
771
|
var opened: Array = _open(scene_path, true)
|
|
770
|
-
var scene:
|
|
772
|
+
var scene: GdhSceneFile = opened[0]
|
|
771
773
|
var refused: Dictionary = opened[1]
|
|
772
774
|
if not refused.is_empty():
|
|
773
775
|
return refused
|
|
@@ -785,7 +787,7 @@ func connect_signal(args: Dictionary) -> Dictionary:
|
|
|
785
787
|
var flags_before: int = -1
|
|
786
788
|
for connection: Dictionary in source.get_signal_connection_list(signal_name):
|
|
787
789
|
if connection.get("callable") == callable:
|
|
788
|
-
flags_before =
|
|
790
|
+
flags_before = GdhRead.as_int(connection.get("flags", 0))
|
|
789
791
|
if source.is_connected(signal_name, callable):
|
|
790
792
|
source.disconnect(signal_name, callable)
|
|
791
793
|
var connect_result: Error = source.connect(signal_name, callable, flags)
|
|
@@ -812,7 +814,7 @@ func connect_signal(args: Dictionary) -> Dictionary:
|
|
|
812
814
|
"targetNodePath": to,
|
|
813
815
|
"methodName": method_name,
|
|
814
816
|
"flags": saved_flags[0],
|
|
815
|
-
"flagNames":
|
|
817
|
+
"flagNames": GdhSceneFile.flag_names(GdhRead.as_int(saved_flags[0])),
|
|
816
818
|
# Connected either way, as the editor's own dialog allows, since the method may be written
|
|
817
819
|
# next; a caller told nothing learnt of a misspelt one only when the signal fired.
|
|
818
820
|
"methodFound": method_found
|
|
@@ -822,14 +824,14 @@ func connect_signal(args: Dictionary) -> Dictionary:
|
|
|
822
824
|
# looked like a lost write.
|
|
823
825
|
if flags_before >= 0:
|
|
824
826
|
answer["alreadyConnected"] = true
|
|
825
|
-
if flags_before !=
|
|
826
|
-
answer["flagsBefore"] =
|
|
827
|
+
if flags_before != GdhRead.as_int(saved_flags[0]):
|
|
828
|
+
answer["flagsBefore"] = GdhSceneFile.flag_names(flags_before)
|
|
827
829
|
return answer
|
|
828
830
|
|
|
829
831
|
|
|
830
832
|
## The two ends of a connection in [param scene], as [source, target], or [null, why not].
|
|
831
833
|
func _connection_ends(
|
|
832
|
-
scene:
|
|
834
|
+
scene: GdhSceneFile, source_node_path: String, signal_name: String, target_node_path: String
|
|
833
835
|
) -> Array:
|
|
834
836
|
var source: Node = _find_node(scene.root, source_node_path)
|
|
835
837
|
var target: Node = _find_node(scene.root, target_node_path)
|
|
@@ -844,7 +846,8 @@ func _connection_ends(
|
|
|
844
846
|
if not foreign.is_empty():
|
|
845
847
|
return [null, foreign]
|
|
846
848
|
if not source.has_signal(signal_name):
|
|
847
|
-
|
|
849
|
+
var said: String = "%s has no signal %s" % [source_node_path, signal_name]
|
|
850
|
+
return [null, _missing_on(source, GdhRead.offered(said, signal_name, GdhRead.signals_of(source)))]
|
|
848
851
|
return [source, target]
|
|
849
852
|
|
|
850
853
|
|
|
@@ -856,7 +859,7 @@ func _connection_flags(root: Node, from: String, signal_name: String, to: String
|
|
|
856
859
|
if source == null or target == null or not source.has_signal(signal_name):
|
|
857
860
|
return -1
|
|
858
861
|
for conn: Dictionary in source.get_signal_connection_list(signal_name):
|
|
859
|
-
var flags: int =
|
|
862
|
+
var flags: int = GdhRead.as_int(conn.get("flags", 0))
|
|
860
863
|
var callable: Callable = conn.get("callable", Callable())
|
|
861
864
|
if (
|
|
862
865
|
flags & Object.CONNECT_PERSIST
|
|
@@ -884,7 +887,7 @@ func disconnect_signal(args: Dictionary) -> Dictionary:
|
|
|
884
887
|
return {"ok": false, "error": "Missing required signal disconnection arguments"}
|
|
885
888
|
|
|
886
889
|
var opened: Array = _open(scene_path, true)
|
|
887
|
-
var scene:
|
|
890
|
+
var scene: GdhSceneFile = opened[0]
|
|
888
891
|
var refused: Dictionary = opened[1]
|
|
889
892
|
if not refused.is_empty():
|
|
890
893
|
return refused
|
|
@@ -916,6 +919,7 @@ func disconnect_signal(args: Dictionary) -> Dictionary:
|
|
|
916
919
|
|
|
917
920
|
return {
|
|
918
921
|
"ok": true,
|
|
922
|
+
"removed": true,
|
|
919
923
|
"sourceNodePath": from,
|
|
920
924
|
"signalName": signal_name,
|
|
921
925
|
"targetNodePath": to,
|
|
@@ -929,7 +933,7 @@ func list_connections(args: Dictionary) -> Dictionary:
|
|
|
929
933
|
var filter_path: String = str(args.get("nodePath", ""))
|
|
930
934
|
|
|
931
935
|
var opened: Array = _open(scene_path, false)
|
|
932
|
-
var scene:
|
|
936
|
+
var scene: GdhSceneFile = opened[0]
|
|
933
937
|
var refused: Dictionary = opened[1]
|
|
934
938
|
if not refused.is_empty():
|
|
935
939
|
return refused
|
|
@@ -955,7 +959,7 @@ func list_connections(args: Dictionary) -> Dictionary:
|
|
|
955
959
|
if signal_name.is_empty():
|
|
956
960
|
continue
|
|
957
961
|
for conn: Dictionary in node.get_signal_connection_list(signal_name):
|
|
958
|
-
var flags: int =
|
|
962
|
+
var flags: int = GdhRead.as_int(conn.get("flags", 0))
|
|
959
963
|
if not flags & Object.CONNECT_PERSIST:
|
|
960
964
|
continue
|
|
961
965
|
var callable: Callable = conn.get("callable", Callable())
|
|
@@ -976,7 +980,7 @@ func list_connections(args: Dictionary) -> Dictionary:
|
|
|
976
980
|
"targetNodePath": target_path,
|
|
977
981
|
"methodName": str(callable.get_method()),
|
|
978
982
|
"flags": flags,
|
|
979
|
-
"flagNames":
|
|
983
|
+
"flagNames": GdhSceneFile.flag_names(flags),
|
|
980
984
|
# False for a connection an instanced scene makes inside itself, which only that
|
|
981
985
|
# scene can change.
|
|
982
986
|
"editable": editable
|
|
@@ -987,5 +991,5 @@ func list_connections(args: Dictionary) -> Dictionary:
|
|
|
987
991
|
scene.close()
|
|
988
992
|
var listed: Dictionary = {"ok": true, "connections": connections}
|
|
989
993
|
if Engine.is_editor_hint():
|
|
990
|
-
listed["unsavedInEditor"] =
|
|
994
|
+
listed["unsavedInEditor"] = GdhSceneFile.unsaved(scene_path)
|
|
991
995
|
return listed
|
|
@@ -14,10 +14,10 @@ extends Node
|
|
|
14
14
|
## question asked of two places: a value spelled differently here would read as the editor and the
|
|
15
15
|
## file disagreeing about something they agree about.
|
|
16
16
|
|
|
17
|
-
const
|
|
18
|
-
const
|
|
17
|
+
const GdhRead = preload("../reading.gd")
|
|
18
|
+
const GdhSerialisation = preload("../serialisation.gd")
|
|
19
19
|
|
|
20
|
-
var _values:
|
|
20
|
+
var _values: GdhSerialisation = GdhSerialisation.new()
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
func get_project_setting(args: Dictionary) -> Dictionary:
|
|
@@ -47,7 +47,7 @@ func _settings_under(prefix: String) -> Dictionary:
|
|
|
47
47
|
var setting: String = str(property.get("name", ""))
|
|
48
48
|
if not setting.begins_with(prefix):
|
|
49
49
|
continue
|
|
50
|
-
var kind: int =
|
|
50
|
+
var kind: int = GdhRead.as_int(property.get("type", TYPE_NIL), TYPE_NIL)
|
|
51
51
|
var described: Dictionary = {
|
|
52
52
|
"setting": setting,
|
|
53
53
|
"type": type_string(kind),
|