gdharness 1.3.2 → 1.3.4
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 +163 -85
- package/build/godot/addons/gdharness_editor/animation_reads.gd +14 -11
- package/build/godot/addons/gdharness_editor/declared_values.gd +157 -4
- package/build/godot/addons/gdharness_editor/file_reads.gd +15 -3
- package/build/godot/addons/gdharness_editor/file_walk.gd +134 -0
- package/build/godot/addons/gdharness_editor/file_walk.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/headless_check.gd +44 -23
- package/build/godot/addons/gdharness_editor/property_paths.gd +225 -0
- package/build/godot/addons/gdharness_editor/property_paths.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/property_values.gd +249 -227
- package/build/godot/addons/gdharness_editor/reading.gd +15 -0
- package/build/godot/addons/gdharness_editor/same_values.gd +177 -0
- package/build/godot/addons/gdharness_editor/same_values.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/scene_file.gd +100 -15
- package/build/godot/addons/gdharness_editor/serialisation.gd +75 -3
- package/build/godot/addons/gdharness_editor/tool_executor.gd +12 -3
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +402 -55
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +3 -2
- package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +91 -0
- package/build/godot/addons/gdharness_editor/tools/scene_groups.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +88 -5
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +102 -337
- package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +363 -0
- package/build/godot/addons/gdharness_editor/tools/signal_tools.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/reading.gd +15 -0
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +10 -26
- package/build/godot/addons/gdharness_runtime/runtime_pad.gd +3 -2
- package/build/godot/addons/gdharness_runtime/runtime_paths.gd +2 -1
- package/build/godot/addons/gdharness_runtime/runtime_values.gd +30 -0
- package/build/godot/addons/gdharness_runtime/serialisation.gd +75 -3
- package/build/godot/operations/animation_reads.gd +14 -11
- package/build/godot/operations/declared_values.gd +157 -4
- package/build/godot/operations/dependencies.gd +14 -39
- package/build/godot/operations/editor_tools.gd +7 -3
- package/build/godot/operations/file_reads.gd +15 -3
- package/build/godot/operations/file_walk.gd +1 -0
- package/build/godot/operations/gdscript_analysis.gd +229 -75
- package/build/godot/operations/gdscript_authoring.gd +142 -34
- package/build/godot/operations/import_pipeline.gd +17 -6
- package/build/godot/operations/logger.gd +7 -0
- package/build/godot/operations/property_paths.gd +225 -0
- package/build/godot/operations/property_values.gd +249 -227
- package/build/godot/operations/reading.gd +15 -0
- package/build/godot/operations/same_values.gd +177 -0
- package/build/godot/operations/serialisation.gd +75 -3
- package/package.json +1 -1
|
@@ -5,11 +5,13 @@ extends Node
|
|
|
5
5
|
|
|
6
6
|
const GdhFileReads = preload("../file_reads.gd")
|
|
7
7
|
const GdhRead = preload("../reading.gd")
|
|
8
|
+
const GdhGroups = preload("scene_groups.gd")
|
|
8
9
|
const GdhKin = preload("scene_kin.gd")
|
|
9
10
|
const GdhPaths = preload("scene_paths.gd")
|
|
10
11
|
const GdhPlacing = preload("scene_placing.gd")
|
|
11
12
|
const GdhPropertyValues = preload("../property_values.gd")
|
|
12
13
|
const GdhResourceTools = preload("resource_tools.gd")
|
|
14
|
+
const GdhSame = preload("../same_values.gd")
|
|
13
15
|
const GdhSceneFile = preload("../scene_file.gd")
|
|
14
16
|
const GdhSerialisation = preload("../serialisation.gd")
|
|
15
17
|
|
|
@@ -22,56 +24,12 @@ func set_editor_plugin(plugin: EditorPlugin) -> void:
|
|
|
22
24
|
_editor_plugin = plugin
|
|
23
25
|
|
|
24
26
|
|
|
25
|
-
func _ensure_res_path(path: String) -> String:
|
|
26
|
-
if not path.begins_with("res://"):
|
|
27
|
-
return "res://" + path
|
|
28
|
-
return path
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
func _to_scene_res_path(project_path: String, scene_path: String) -> String:
|
|
32
|
-
var p: String = scene_path.strip_edges()
|
|
33
|
-
if p.begins_with("res://"):
|
|
34
|
-
return p
|
|
35
|
-
|
|
36
|
-
if project_path.strip_edges() != "":
|
|
37
|
-
var normalized_project: String = project_path.replace("\\", "/")
|
|
38
|
-
var normalized_scene: String = p.replace("\\", "/")
|
|
39
|
-
if normalized_scene.begins_with(normalized_project):
|
|
40
|
-
var rel: String = normalized_scene.substr(normalized_project.length())
|
|
41
|
-
if rel.begins_with("/"):
|
|
42
|
-
rel = rel.substr(1)
|
|
43
|
-
return _ensure_res_path(rel)
|
|
44
|
-
|
|
45
|
-
return _ensure_res_path(p)
|
|
46
|
-
|
|
47
|
-
|
|
48
27
|
## [param scene_path] opened for a tool, as [scene, refusal]: the refusal is {} when it opened.
|
|
49
28
|
func _open(scene_path: String, for_writing: bool) -> Array:
|
|
50
29
|
var scene: GdhSceneFile = GdhSceneFile.new()
|
|
51
30
|
return [scene, scene.open(scene_path, for_writing)]
|
|
52
31
|
|
|
53
32
|
|
|
54
|
-
func _find_node(root: Node, path: String) -> Node:
|
|
55
|
-
if path == "." or path.is_empty():
|
|
56
|
-
return root
|
|
57
|
-
return root.get_node_or_null(path)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
## Why the property or signal [param missing] could not be found on [param node], adding the one
|
|
61
|
-
## cause the name alone does not show: a script that does not compile leaves the editor holding a
|
|
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.
|
|
65
|
-
func _missing_on(node: Node, missing: String) -> String:
|
|
66
|
-
var script: Script = node.get_script()
|
|
67
|
-
if script == null or not str(script.get_instance_base_type()).is_empty():
|
|
68
|
-
return missing
|
|
69
|
-
return (
|
|
70
|
-
"%s. Its script, %s, does not compile, so none of what it declares is known here."
|
|
71
|
-
% [missing.trim_suffix("."), script.resource_path]
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
|
|
75
33
|
## Whether each of [param names] reads the same off [param saved] as off [param node], answering
|
|
76
34
|
## the first that does not, or "".
|
|
77
35
|
func _kept(scene: GdhSceneFile, saved: Node, node: Node, names: Array) -> String:
|
|
@@ -116,7 +74,7 @@ func _properties_of(node: Node, include_defaults: bool, set_here: Dictionary) ->
|
|
|
116
74
|
if scripted.has(property)
|
|
117
75
|
else ClassDB.class_get_property_default_value(node.get_class(), property)
|
|
118
76
|
)
|
|
119
|
-
if
|
|
77
|
+
if GdhSame.same(value, default):
|
|
120
78
|
continue
|
|
121
79
|
props[property] = _readable(node, value)
|
|
122
80
|
return props
|
|
@@ -145,27 +103,20 @@ func _parse_properties_arg(raw_properties: Variant) -> Dictionary:
|
|
|
145
103
|
return {}
|
|
146
104
|
|
|
147
105
|
|
|
148
|
-
func _collect_nodes_recursive(node: Node, path: String, out_nodes: Array) -> void:
|
|
149
|
-
out_nodes.append({"path": path, "node": node})
|
|
150
|
-
for child: Node in node.get_children():
|
|
151
|
-
var child_path: String = str(child.name) if path == "." else path + "/" + str(child.name)
|
|
152
|
-
_collect_nodes_recursive(child, child_path, out_nodes)
|
|
153
|
-
|
|
154
|
-
|
|
155
106
|
func _inherited(args: Dictionary) -> Dictionary:
|
|
156
107
|
var project_path: String = str(args.get("projectPath", ""))
|
|
157
108
|
var script_path: String = str(args.get("script", ""))
|
|
158
109
|
return GdhKin.inherited(
|
|
159
110
|
args,
|
|
160
111
|
_new_scene_path(args),
|
|
161
|
-
|
|
162
|
-
"" if script_path.is_empty() else
|
|
112
|
+
GdhSceneFile.res_path(project_path, str(args.get("inherits", ""))),
|
|
113
|
+
"" if script_path.is_empty() else GdhSceneFile.res_path(project_path, script_path)
|
|
163
114
|
)
|
|
164
115
|
|
|
165
116
|
|
|
166
117
|
## The res:// path a create in [param args] writes, given .tscn when it has no extension, or "".
|
|
167
118
|
func _new_scene_path(args: Dictionary) -> String:
|
|
168
|
-
var scene_path: String =
|
|
119
|
+
var scene_path: String = GdhSceneFile.res_path(
|
|
169
120
|
str(args.get("projectPath", "")), str(args.get("scenePath", ""))
|
|
170
121
|
)
|
|
171
122
|
if scene_path == "res://":
|
|
@@ -191,7 +142,7 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
191
142
|
var asked_type: String = root_node_type
|
|
192
143
|
var made: Dictionary = GdhSceneFile.made_as(
|
|
193
144
|
root_node_type,
|
|
194
|
-
"" if script_path.is_empty() else
|
|
145
|
+
"" if script_path.is_empty() else GdhSceneFile.res_path(project_path, script_path),
|
|
195
146
|
"Node",
|
|
196
147
|
"rootNodeType"
|
|
197
148
|
)
|
|
@@ -202,9 +153,7 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
202
153
|
# A class that is not a node went into a Node variable, which is a runtime error the caller
|
|
203
154
|
# heard about only as "Invalid tool result".
|
|
204
155
|
if not ClassDB.class_exists(root_node_type) or not ClassDB.is_parent_class(root_node_type, "Node"):
|
|
205
|
-
return {
|
|
206
|
-
"ok": false, "error": "rootNodeType must be a node class, and %s is not one." % root_node_type
|
|
207
|
-
}
|
|
156
|
+
return {"ok": false, "error": GdhPlacing.not_a_node_class("rootNodeType", root_node_type)}
|
|
208
157
|
if not ClassDB.can_instantiate(root_node_type):
|
|
209
158
|
return {"ok": false, "error": "%s cannot be instantiated." % root_node_type}
|
|
210
159
|
var unfit: String = GdhSceneFile.unfit_name(root_node_name)
|
|
@@ -221,7 +170,7 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
221
170
|
scene.asked(root, ["script"])
|
|
222
171
|
|
|
223
172
|
if not script_path.is_empty():
|
|
224
|
-
var full_script_path: String =
|
|
173
|
+
var full_script_path: String = GdhSceneFile.res_path(project_path, script_path)
|
|
225
174
|
var script: Script = load(full_script_path) as Script
|
|
226
175
|
if script == null:
|
|
227
176
|
root.free()
|
|
@@ -243,6 +192,7 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
243
192
|
# name is no property the write compares.
|
|
244
193
|
root.name = root_node_name
|
|
245
194
|
|
|
195
|
+
var had_folder: bool = DirAccess.dir_exists_absolute(scene_path.get_base_dir())
|
|
246
196
|
var folder: String = GdhSceneFile.make_folder_for(scene_path)
|
|
247
197
|
if not folder.is_empty():
|
|
248
198
|
root.free()
|
|
@@ -251,12 +201,17 @@ func _create_of_a_class(args: Dictionary) -> Dictionary:
|
|
|
251
201
|
if not written.is_empty():
|
|
252
202
|
return written
|
|
253
203
|
|
|
254
|
-
|
|
204
|
+
var answer: Dictionary = {
|
|
205
|
+
"ok": true, "scenePath": scene_path, "rootNodeType": asked_type, "rootNodeName": root_node_name
|
|
206
|
+
}
|
|
207
|
+
if not had_folder:
|
|
208
|
+
answer["madeFolder"] = scene_path.get_base_dir()
|
|
209
|
+
return answer
|
|
255
210
|
|
|
256
211
|
|
|
257
212
|
func list_scene_nodes(args: Dictionary) -> Dictionary:
|
|
258
213
|
var project_path: String = str(args.get("projectPath", ""))
|
|
259
|
-
var scene_path: String =
|
|
214
|
+
var scene_path: String = GdhSceneFile.res_path(project_path, str(args.get("scenePath", "")))
|
|
260
215
|
var depth: int = GdhRead.as_int(args.get("depth", -1), -1)
|
|
261
216
|
var include_properties: bool = GdhRead.as_bool(args.get("includeProperties", false))
|
|
262
217
|
|
|
@@ -270,12 +225,13 @@ func list_scene_nodes(args: Dictionary) -> Dictionary:
|
|
|
270
225
|
|
|
271
226
|
func add_node(args: Dictionary) -> Dictionary:
|
|
272
227
|
var project_path: String = str(args.get("projectPath", ""))
|
|
273
|
-
var scene_path: String =
|
|
228
|
+
var scene_path: String = GdhSceneFile.res_path(project_path, str(args.get("scenePath", "")))
|
|
274
229
|
var node_type: String = str(args.get("nodeType", ""))
|
|
275
230
|
var instance_path: String = str(args.get("instancePath", ""))
|
|
276
231
|
var node_name: String = str(args.get("nodeName", ""))
|
|
277
232
|
var parent_node_path: String = str(args.get("parentNodePath", "."))
|
|
278
233
|
var properties: Dictionary = _parse_properties_arg(args.get("properties", {}))
|
|
234
|
+
var adding: Array = GdhGroups.asked(args, "addGroups")
|
|
279
235
|
|
|
280
236
|
if node_name.is_empty():
|
|
281
237
|
return {"ok": false, "error": "Missing nodeName"}
|
|
@@ -301,7 +257,7 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
301
257
|
return refused
|
|
302
258
|
|
|
303
259
|
var root: Node = scene.root
|
|
304
|
-
var parent: Node =
|
|
260
|
+
var parent: Node = GdhSceneFile.node_at(root, parent_node_path)
|
|
305
261
|
if not parent:
|
|
306
262
|
return scene.refuse(scene.not_found("Parent node not found: " + parent_node_path, parent_node_path))
|
|
307
263
|
var foreign: String = scene.foreign(parent)
|
|
@@ -328,9 +284,11 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
328
284
|
if not unsettled.is_empty():
|
|
329
285
|
return scene.refuse("Nothing was written: " + unsettled)
|
|
330
286
|
scene.asked(new_node, properties.keys())
|
|
331
|
-
var
|
|
332
|
-
if
|
|
333
|
-
|
|
287
|
+
var unwritten: String = _properties.write_all(new_node, properties)
|
|
288
|
+
if unwritten.is_empty():
|
|
289
|
+
unwritten = GdhGroups.change(scene, new_node, adding, [])
|
|
290
|
+
if not unwritten.is_empty():
|
|
291
|
+
return scene.refuse(unwritten)
|
|
334
292
|
|
|
335
293
|
var new_path: String = scene.path_of(new_node)
|
|
336
294
|
# Read before the write, which frees the scene it was added to.
|
|
@@ -342,11 +300,16 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
342
300
|
"index": new_node.get_index(),
|
|
343
301
|
}
|
|
344
302
|
_properties.note_write(answer, new_node)
|
|
303
|
+
if not adding.is_empty():
|
|
304
|
+
answer.merge(GdhGroups.read(scene, new_node))
|
|
345
305
|
var written: Dictionary = scene.write(
|
|
346
306
|
func(saved: Node) -> String:
|
|
347
|
-
|
|
307
|
+
var unkept: String = _kept(
|
|
348
308
|
scene, saved, new_node, properties.keys() + (["script"] if class_script != null else [])
|
|
349
309
|
)
|
|
310
|
+
if unkept.is_empty() and saved.get_node_or_null(new_path) != null:
|
|
311
|
+
unkept = GdhGroups.unkept(saved.get_node(new_path), adding, [])
|
|
312
|
+
return unkept
|
|
350
313
|
)
|
|
351
314
|
if not written.is_empty():
|
|
352
315
|
return written
|
|
@@ -358,7 +321,7 @@ func add_node(args: Dictionary) -> Dictionary:
|
|
|
358
321
|
|
|
359
322
|
func delete_node(args: Dictionary) -> Dictionary:
|
|
360
323
|
var project_path: String = str(args.get("projectPath", ""))
|
|
361
|
-
var scene_path: String =
|
|
324
|
+
var scene_path: String = GdhSceneFile.res_path(project_path, str(args.get("scenePath", "")))
|
|
362
325
|
var node_path: String = str(args.get("nodePath", ""))
|
|
363
326
|
|
|
364
327
|
if node_path.is_empty() or node_path == ".":
|
|
@@ -377,14 +340,18 @@ func delete_node(args: Dictionary) -> Dictionary:
|
|
|
377
340
|
if not refused.is_empty():
|
|
378
341
|
return refused
|
|
379
342
|
|
|
380
|
-
var node: Node =
|
|
343
|
+
var node: Node = GdhSceneFile.node_at(scene.root, node_path)
|
|
381
344
|
if not node:
|
|
382
345
|
return scene.refuse(scene.not_found("Node not found: " + node_path, node_path))
|
|
383
|
-
var fixed: String = scene.fixed(node)
|
|
346
|
+
var fixed: String = scene.fixed(node, true)
|
|
384
347
|
if not fixed.is_empty():
|
|
385
348
|
return scene.refuse(fixed)
|
|
386
349
|
|
|
387
350
|
var at: String = scene.path_of(node)
|
|
351
|
+
var went: Array[String] = []
|
|
352
|
+
for under: Node in node.find_children("*", "", true, false):
|
|
353
|
+
if under.owner == scene.root:
|
|
354
|
+
went.append(scene.path_of(under))
|
|
388
355
|
node.get_parent().remove_child(node)
|
|
389
356
|
node.free()
|
|
390
357
|
var carried: GdhPaths = GdhPaths.new()
|
|
@@ -400,13 +367,15 @@ func delete_node(args: Dictionary) -> Dictionary:
|
|
|
400
367
|
return written
|
|
401
368
|
|
|
402
369
|
var answer: Dictionary = {"ok": true, "deletedNodePath": at}
|
|
370
|
+
if not went.is_empty():
|
|
371
|
+
answer["deletedWithIt"] = went
|
|
403
372
|
answer.merge(GdhKin.follow(scene_path, at, "", carried))
|
|
404
373
|
return answer
|
|
405
374
|
|
|
406
375
|
|
|
407
376
|
func duplicate_node(args: Dictionary) -> Dictionary:
|
|
408
377
|
var project_path: String = str(args.get("projectPath", ""))
|
|
409
|
-
var scene_path: String =
|
|
378
|
+
var scene_path: String = GdhSceneFile.res_path(project_path, str(args.get("scenePath", "")))
|
|
410
379
|
var node_path: String = str(args.get("nodePath", ""))
|
|
411
380
|
var new_name: String = str(args.get("newName", ""))
|
|
412
381
|
var parent_path: String = str(args.get("parentNodePath", ""))
|
|
@@ -421,7 +390,7 @@ func duplicate_node(args: Dictionary) -> Dictionary:
|
|
|
421
390
|
return refused
|
|
422
391
|
|
|
423
392
|
var root: Node = scene.root
|
|
424
|
-
var source: Node =
|
|
393
|
+
var source: Node = GdhSceneFile.node_at(root, node_path)
|
|
425
394
|
if not source:
|
|
426
395
|
return scene.refuse(scene.not_found("Node not found: " + node_path, node_path))
|
|
427
396
|
if source == root:
|
|
@@ -432,7 +401,7 @@ func duplicate_node(args: Dictionary) -> Dictionary:
|
|
|
432
401
|
|
|
433
402
|
var target_parent: Node = source.get_parent()
|
|
434
403
|
if not parent_path.is_empty():
|
|
435
|
-
target_parent =
|
|
404
|
+
target_parent = GdhSceneFile.node_at(root, parent_path)
|
|
436
405
|
if not target_parent:
|
|
437
406
|
return scene.refuse(scene.not_found("Parent not found: " + parent_path, parent_path))
|
|
438
407
|
foreign = scene.foreign(target_parent)
|
|
@@ -441,6 +410,13 @@ func duplicate_node(args: Dictionary) -> Dictionary:
|
|
|
441
410
|
var unusable: String = scene.unusable_name(target_parent, new_name)
|
|
442
411
|
if not unusable.is_empty():
|
|
443
412
|
return scene.refuse(unusable)
|
|
413
|
+
var place: Variant = args.get("index")
|
|
414
|
+
var unplaceable: String = GdhPlacing.unplaceable(target_parent, null, place)
|
|
415
|
+
if not unplaceable.is_empty():
|
|
416
|
+
return scene.refuse(unplaceable)
|
|
417
|
+
# The editor's Duplicate puts the copy right after the original.
|
|
418
|
+
if place == null and target_parent == source.get_parent():
|
|
419
|
+
place = source.get_index() + 1
|
|
444
420
|
|
|
445
421
|
var copies: Dictionary = {}
|
|
446
422
|
var duplicated_node: Node = GdhPlacing.copied(source, root, copies)
|
|
@@ -449,6 +425,7 @@ func duplicate_node(args: Dictionary) -> Dictionary:
|
|
|
449
425
|
|
|
450
426
|
duplicated_node.name = new_name
|
|
451
427
|
target_parent.add_child(duplicated_node)
|
|
428
|
+
GdhPlacing.place(duplicated_node, place)
|
|
452
429
|
GdhPlacing.own(duplicated_node, root)
|
|
453
430
|
GdhPlacing.reconnect(copies, source)
|
|
454
431
|
scene.copied(copies)
|
|
@@ -457,8 +434,11 @@ func duplicate_node(args: Dictionary) -> Dictionary:
|
|
|
457
434
|
var placed: Array = [scene.path_of(target_parent), duplicated_node.get_index()]
|
|
458
435
|
var written: Dictionary = scene.write(
|
|
459
436
|
func(saved: Node) -> String:
|
|
460
|
-
|
|
437
|
+
var copy: Node = saved.get_node_or_null(new_path)
|
|
438
|
+
if copy == null:
|
|
461
439
|
return "the copy would not be in the scene when it loads."
|
|
440
|
+
if copy.get_index() != placed[1]:
|
|
441
|
+
return "%s would load at index %d, not %d." % [new_path, copy.get_index(), placed[1]]
|
|
462
442
|
return ""
|
|
463
443
|
)
|
|
464
444
|
if not written.is_empty():
|
|
@@ -476,7 +456,7 @@ func duplicate_node(args: Dictionary) -> Dictionary:
|
|
|
476
456
|
|
|
477
457
|
func reparent_node(args: Dictionary) -> Dictionary:
|
|
478
458
|
var project_path: String = str(args.get("projectPath", ""))
|
|
479
|
-
var scene_path: String =
|
|
459
|
+
var scene_path: String = GdhSceneFile.res_path(project_path, str(args.get("scenePath", "")))
|
|
480
460
|
var node_path: String = str(args.get("nodePath", ""))
|
|
481
461
|
var new_parent_path: String = str(args.get("newParentPath", ""))
|
|
482
462
|
|
|
@@ -492,8 +472,8 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
492
472
|
return refused
|
|
493
473
|
|
|
494
474
|
var root: Node = scene.root
|
|
495
|
-
var node: Node =
|
|
496
|
-
var new_parent: Node =
|
|
475
|
+
var node: Node = GdhSceneFile.node_at(root, node_path)
|
|
476
|
+
var new_parent: Node = GdhSceneFile.node_at(root, new_parent_path)
|
|
497
477
|
if not node:
|
|
498
478
|
return scene.refuse(scene.not_found("Node not found: " + node_path, node_path))
|
|
499
479
|
if not new_parent:
|
|
@@ -519,13 +499,24 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
519
499
|
return scene.refuse(unplaceable)
|
|
520
500
|
|
|
521
501
|
var old_path: String = scene.path_of(node)
|
|
502
|
+
var old_parent: Node = node.get_parent()
|
|
503
|
+
var drawn_at: Dictionary = {}
|
|
504
|
+
for property: String in GdhPlacing.placing(node):
|
|
505
|
+
drawn_at[property] = _properties.read_at(node, property)
|
|
522
506
|
# Unowned while it moves: a node taken out of the tree keeps its owner, and adding it under the new
|
|
523
507
|
# parent warned that the owner was not above it. Node.reparent warns the same way.
|
|
524
508
|
node.owner = null
|
|
525
|
-
|
|
509
|
+
old_parent.remove_child(node)
|
|
526
510
|
new_parent.add_child(node)
|
|
527
511
|
GdhPlacing.place(node, place)
|
|
528
512
|
GdhPlacing.own(node, root)
|
|
513
|
+
if GdhRead.as_bool(args.get("keepGlobalTransform", true)):
|
|
514
|
+
GdhPlacing.keep_in_place(node, old_parent)
|
|
515
|
+
var also_changed: Dictionary = {}
|
|
516
|
+
for property: String in drawn_at:
|
|
517
|
+
var now: Variant = _properties.read_at(node, property)
|
|
518
|
+
if not GdhSame.same(now, drawn_at[property]):
|
|
519
|
+
also_changed[property] = {"was": _readable(node, drawn_at[property]), "now": _readable(node, now)}
|
|
529
520
|
|
|
530
521
|
var new_path: String = scene.path_of(node)
|
|
531
522
|
var index: int = node.get_index()
|
|
@@ -540,7 +531,7 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
540
531
|
return "%s would still be in the scene as well when it loads." % old_path
|
|
541
532
|
if copy.get_index() != index:
|
|
542
533
|
return "%s would load at index %d, not %d." % [new_path, copy.get_index(), index]
|
|
543
|
-
return
|
|
534
|
+
return _kept(scene, saved, node, also_changed.keys())
|
|
544
535
|
)
|
|
545
536
|
if not written.is_empty():
|
|
546
537
|
carried.put_back(scene_path)
|
|
@@ -553,6 +544,8 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
553
544
|
"newNodePath": new_path,
|
|
554
545
|
"index": index,
|
|
555
546
|
}
|
|
547
|
+
if not also_changed.is_empty():
|
|
548
|
+
answer["alsoChanged"] = also_changed
|
|
556
549
|
if new_path != old_path:
|
|
557
550
|
answer.merge(GdhKin.follow(scene_path, old_path, new_path, carried))
|
|
558
551
|
return answer
|
|
@@ -560,12 +553,14 @@ func reparent_node(args: Dictionary) -> Dictionary:
|
|
|
560
553
|
|
|
561
554
|
func set_node_properties(args: Dictionary) -> Dictionary:
|
|
562
555
|
var project_path: String = str(args.get("projectPath", ""))
|
|
563
|
-
var scene_path: String =
|
|
556
|
+
var scene_path: String = GdhSceneFile.res_path(project_path, str(args.get("scenePath", "")))
|
|
564
557
|
var node_path: String = str(args.get("nodePath", "."))
|
|
565
558
|
var properties: Dictionary = _parse_properties_arg(args.get("properties", {}))
|
|
566
559
|
var editable: Variant = args.get("editableChildren")
|
|
567
|
-
|
|
568
|
-
|
|
560
|
+
var adding: Array = GdhGroups.asked(args, "addGroups")
|
|
561
|
+
var removing: Array = GdhGroups.asked(args, "removeGroups")
|
|
562
|
+
if properties.is_empty() and editable == null and adding.is_empty() and removing.is_empty():
|
|
563
|
+
return {"ok": false, "error": "set takes properties, editableChildren, addGroups or removeGroups."}
|
|
569
564
|
|
|
570
565
|
var opened: Array = _open(scene_path, true)
|
|
571
566
|
var scene: GdhSceneFile = opened[0]
|
|
@@ -573,7 +568,7 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
573
568
|
if not refused.is_empty():
|
|
574
569
|
return refused
|
|
575
570
|
|
|
576
|
-
var node: Node =
|
|
571
|
+
var node: Node = GdhSceneFile.node_at(scene.root, node_path)
|
|
577
572
|
if not node:
|
|
578
573
|
return scene.refuse(scene.not_found("Node not found: " + node_path, node_path))
|
|
579
574
|
var foreign: String = scene.foreign(node)
|
|
@@ -599,7 +594,10 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
599
594
|
scene.asked(node, properties.keys())
|
|
600
595
|
var refused_property: String = _properties.write_all(node, properties)
|
|
601
596
|
if not refused_property.is_empty():
|
|
602
|
-
return scene.refuse(
|
|
597
|
+
return scene.refuse(GdhSceneFile.missing_on(node, refused_property))
|
|
598
|
+
var ungrouped: String = GdhGroups.change(scene, node, adding, removing)
|
|
599
|
+
if not ungrouped.is_empty():
|
|
600
|
+
return scene.refuse(ungrouped)
|
|
603
601
|
|
|
604
602
|
var held: Dictionary = {}
|
|
605
603
|
for key: Variant in properties:
|
|
@@ -607,11 +605,15 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
607
605
|
var new_path: String = scene.path_of(node)
|
|
608
606
|
var answer: Dictionary = {"ok": true, "nodePath": new_path, "properties": held}
|
|
609
607
|
_properties.note_write(answer, node)
|
|
608
|
+
if not adding.is_empty() or not removing.is_empty():
|
|
609
|
+
answer["groups"] = GdhGroups.read(scene, node).get("groups", [])
|
|
610
610
|
var carried: GdhPaths = GdhPaths.new()
|
|
611
611
|
var _rewritten: int = carried.carry(scene, {old_path: new_path} if new_path != old_path else {})
|
|
612
612
|
var written: Dictionary = scene.write(
|
|
613
613
|
func(saved: Node) -> String:
|
|
614
614
|
var unkept: String = _kept(scene, saved, node, properties.keys())
|
|
615
|
+
if unkept.is_empty():
|
|
616
|
+
unkept = GdhGroups.unkept(saved.get_node(new_path), adding, removing)
|
|
615
617
|
if unkept.is_empty() and editable != null:
|
|
616
618
|
if saved.is_editable_instance(saved.get_node(new_path)) != GdhRead.as_bool(editable):
|
|
617
619
|
return (
|
|
@@ -635,7 +637,7 @@ func set_node_properties(args: Dictionary) -> Dictionary:
|
|
|
635
637
|
|
|
636
638
|
func get_node_properties(args: Dictionary) -> Dictionary:
|
|
637
639
|
var project_path: String = str(args.get("projectPath", ""))
|
|
638
|
-
var scene_path: String =
|
|
640
|
+
var scene_path: String = GdhSceneFile.res_path(project_path, str(args.get("scenePath", "")))
|
|
639
641
|
var node_path: String = str(args.get("nodePath", "."))
|
|
640
642
|
var include_defaults: bool = GdhRead.as_bool(args.get("includeDefaults", false))
|
|
641
643
|
|
|
@@ -645,7 +647,7 @@ func get_node_properties(args: Dictionary) -> Dictionary:
|
|
|
645
647
|
if not refused.is_empty():
|
|
646
648
|
return refused
|
|
647
649
|
|
|
648
|
-
var node: Node =
|
|
650
|
+
var node: Node = GdhSceneFile.node_at(scene.root, node_path)
|
|
649
651
|
if not node:
|
|
650
652
|
return scene.refuse(scene.not_found("Node not found: " + node_path, node_path))
|
|
651
653
|
|
|
@@ -653,9 +655,18 @@ func get_node_properties(args: Dictionary) -> Dictionary:
|
|
|
653
655
|
# declares, the class's for the rest. Compared with a bare instance of the class, every exported
|
|
654
656
|
# variable read as changed; and a value this scene sets back to the default was hidden, so the
|
|
655
657
|
# names this scene's file sets are always answered.
|
|
656
|
-
var
|
|
658
|
+
var set_here: Dictionary = scene.set_here(node)
|
|
659
|
+
var props: Dictionary = _properties_of(node, include_defaults, set_here)
|
|
657
660
|
var cells: Dictionary = GdhResourceTools.cells_of(node)
|
|
658
|
-
var
|
|
661
|
+
var at: String = scene.path_of(node)
|
|
662
|
+
var here: Array = set_here.keys()
|
|
663
|
+
here.sort()
|
|
664
|
+
var answer: Dictionary = {"ok": true, "nodePath": at, "properties": props, "setHere": here}
|
|
665
|
+
answer.merge(GdhSceneFile.class_of(node))
|
|
666
|
+
answer.merge(GdhGroups.read(scene, node))
|
|
667
|
+
var from: String = scene.values_from(node, at)
|
|
668
|
+
if not from.is_empty():
|
|
669
|
+
answer["valuesFrom"] = from
|
|
659
670
|
if node != scene.root and node.owner != null and not node.scene_file_path.is_empty():
|
|
660
671
|
answer["instanceOf"] = node.scene_file_path
|
|
661
672
|
answer["editableChildren"] = scene.root.is_editable_instance(node)
|
|
@@ -675,11 +686,11 @@ func get_node_properties(args: Dictionary) -> Dictionary:
|
|
|
675
686
|
|
|
676
687
|
func save_scene(args: Dictionary) -> Dictionary:
|
|
677
688
|
var project_path: String = str(args.get("projectPath", ""))
|
|
678
|
-
var scene_path: String =
|
|
689
|
+
var scene_path: String = GdhSceneFile.res_path(project_path, str(args.get("scenePath", "")))
|
|
679
690
|
var new_path_raw: String = str(args.get("newPath", ""))
|
|
680
691
|
var target_path: String = scene_path
|
|
681
692
|
if not new_path_raw.is_empty():
|
|
682
|
-
target_path =
|
|
693
|
+
target_path = GdhSceneFile.res_path(project_path, new_path_raw)
|
|
683
694
|
|
|
684
695
|
if target_path != scene_path:
|
|
685
696
|
var unsaved: String = GdhSceneFile.unsaved_in_editor(target_path)
|
|
@@ -747,249 +758,3 @@ func _save_open_scene(scene_path: String) -> Dictionary:
|
|
|
747
758
|
"from": "editor",
|
|
748
759
|
"unsavedInEditor": GdhSceneFile.unsaved(scene_path)
|
|
749
760
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
func connect_signal(args: Dictionary) -> Dictionary:
|
|
753
|
-
var project_path: String = str(args.get("projectPath", ""))
|
|
754
|
-
var scene_path: String = _to_scene_res_path(project_path, str(args.get("scenePath", "")))
|
|
755
|
-
var source_node_path: String = str(args.get("sourceNodePath", ""))
|
|
756
|
-
var signal_name: String = str(args.get("signalName", ""))
|
|
757
|
-
var target_node_path: String = str(args.get("targetNodePath", ""))
|
|
758
|
-
var method_name: String = str(args.get("methodName", ""))
|
|
759
|
-
# A connection without CONNECT_PERSIST is a runtime one, and PackedScene.pack drops those on
|
|
760
|
-
# the way out: without this the scene saves unchanged and this answers success over nothing.
|
|
761
|
-
var flags: int = GdhRead.as_int(args.get("flags", 0)) | Object.CONNECT_PERSIST
|
|
762
|
-
|
|
763
|
-
if (
|
|
764
|
-
source_node_path.is_empty()
|
|
765
|
-
or signal_name.is_empty()
|
|
766
|
-
or target_node_path.is_empty()
|
|
767
|
-
or method_name.is_empty()
|
|
768
|
-
):
|
|
769
|
-
return {"ok": false, "error": "Missing required signal connection arguments"}
|
|
770
|
-
|
|
771
|
-
var opened: Array = _open(scene_path, true)
|
|
772
|
-
var scene: GdhSceneFile = opened[0]
|
|
773
|
-
var refused: Dictionary = opened[1]
|
|
774
|
-
if not refused.is_empty():
|
|
775
|
-
return refused
|
|
776
|
-
|
|
777
|
-
var ends: Array = _connection_ends(scene, source_node_path, signal_name, target_node_path)
|
|
778
|
-
if ends[0] == null:
|
|
779
|
-
return scene.refuse(str(ends[1]))
|
|
780
|
-
var source: Node = ends[0]
|
|
781
|
-
var target: Node = ends[1]
|
|
782
|
-
|
|
783
|
-
# Reconnected rather than left alone when the flags differ, so the connection saved is the one
|
|
784
|
-
# asked for. Left alone, the answer gave the flags asked for and the file kept the old ones.
|
|
785
|
-
var callable: Callable = Callable(target, method_name)
|
|
786
|
-
var method_found: bool = target.has_method(method_name)
|
|
787
|
-
var flags_before: int = -1
|
|
788
|
-
for connection: Dictionary in source.get_signal_connection_list(signal_name):
|
|
789
|
-
if connection.get("callable") == callable:
|
|
790
|
-
flags_before = GdhRead.as_int(connection.get("flags", 0))
|
|
791
|
-
if source.is_connected(signal_name, callable):
|
|
792
|
-
source.disconnect(signal_name, callable)
|
|
793
|
-
var connect_result: Error = source.connect(signal_name, callable, flags)
|
|
794
|
-
if connect_result != OK:
|
|
795
|
-
return scene.refuse("Failed to connect signal: " + error_string(connect_result))
|
|
796
|
-
|
|
797
|
-
var from: String = scene.path_of(source)
|
|
798
|
-
var to: String = scene.path_of(target)
|
|
799
|
-
var saved_flags: Array = [-1]
|
|
800
|
-
var written: Dictionary = scene.write(
|
|
801
|
-
func(saved: Node) -> String:
|
|
802
|
-
saved_flags[0] = _connection_flags(saved, from, signal_name, to, method_name)
|
|
803
|
-
if saved_flags[0] < 0:
|
|
804
|
-
return "the connection would not be in the scene when it loads."
|
|
805
|
-
return ""
|
|
806
|
-
)
|
|
807
|
-
if not written.is_empty():
|
|
808
|
-
return written
|
|
809
|
-
|
|
810
|
-
var answer: Dictionary = {
|
|
811
|
-
"ok": true,
|
|
812
|
-
"sourceNodePath": from,
|
|
813
|
-
"signalName": signal_name,
|
|
814
|
-
"targetNodePath": to,
|
|
815
|
-
"methodName": method_name,
|
|
816
|
-
"flags": saved_flags[0],
|
|
817
|
-
"flagNames": GdhSceneFile.flag_names(GdhRead.as_int(saved_flags[0])),
|
|
818
|
-
# Connected either way, as the editor's own dialog allows, since the method may be written
|
|
819
|
-
# next; a caller told nothing learnt of a misspelt one only when the signal fired.
|
|
820
|
-
"methodFound": method_found
|
|
821
|
-
}
|
|
822
|
-
# A second connect of the same pair read exactly like the first, so a caller could not tell a
|
|
823
|
-
# connection made from one that was already there, and a list showing one where two were made
|
|
824
|
-
# looked like a lost write.
|
|
825
|
-
if flags_before >= 0:
|
|
826
|
-
answer["alreadyConnected"] = true
|
|
827
|
-
if flags_before != GdhRead.as_int(saved_flags[0]):
|
|
828
|
-
answer["flagsBefore"] = GdhSceneFile.flag_names(flags_before)
|
|
829
|
-
return answer
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
## The two ends of a connection in [param scene], as [source, target], or [null, why not].
|
|
833
|
-
func _connection_ends(
|
|
834
|
-
scene: GdhSceneFile, source_node_path: String, signal_name: String, target_node_path: String
|
|
835
|
-
) -> Array:
|
|
836
|
-
var source: Node = _find_node(scene.root, source_node_path)
|
|
837
|
-
var target: Node = _find_node(scene.root, target_node_path)
|
|
838
|
-
if not source:
|
|
839
|
-
return [null, scene.not_found("Source node not found: " + source_node_path, source_node_path)]
|
|
840
|
-
if not target:
|
|
841
|
-
return [null, scene.not_found("Target node not found: " + target_node_path, target_node_path)]
|
|
842
|
-
# pack drops a connection with either end inside an instanced scene, and the answer said it was
|
|
843
|
-
# made or removed.
|
|
844
|
-
for end: Node in [source, target]:
|
|
845
|
-
var foreign: String = scene.foreign(end)
|
|
846
|
-
if not foreign.is_empty():
|
|
847
|
-
return [null, foreign]
|
|
848
|
-
if not source.has_signal(signal_name):
|
|
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)))]
|
|
851
|
-
return [source, target]
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
## The flags of the persistent connection from [param from]'s [param signal_name] to
|
|
855
|
-
## [param method] on [param to] in the tree under [param root], or -1 when there is none.
|
|
856
|
-
func _connection_flags(root: Node, from: String, signal_name: String, to: String, method: String) -> int:
|
|
857
|
-
var source: Node = root.get_node_or_null(from)
|
|
858
|
-
var target: Node = root.get_node_or_null(to)
|
|
859
|
-
if source == null or target == null or not source.has_signal(signal_name):
|
|
860
|
-
return -1
|
|
861
|
-
for conn: Dictionary in source.get_signal_connection_list(signal_name):
|
|
862
|
-
var flags: int = GdhRead.as_int(conn.get("flags", 0))
|
|
863
|
-
var callable: Callable = conn.get("callable", Callable())
|
|
864
|
-
if (
|
|
865
|
-
flags & Object.CONNECT_PERSIST
|
|
866
|
-
and callable.get_object() == target
|
|
867
|
-
and str(callable.get_method()) == method
|
|
868
|
-
):
|
|
869
|
-
return flags
|
|
870
|
-
return -1
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
func disconnect_signal(args: Dictionary) -> Dictionary:
|
|
874
|
-
var project_path: String = str(args.get("projectPath", ""))
|
|
875
|
-
var scene_path: String = _to_scene_res_path(project_path, str(args.get("scenePath", "")))
|
|
876
|
-
var source_node_path: String = str(args.get("sourceNodePath", ""))
|
|
877
|
-
var signal_name: String = str(args.get("signalName", ""))
|
|
878
|
-
var target_node_path: String = str(args.get("targetNodePath", ""))
|
|
879
|
-
var method_name: String = str(args.get("methodName", ""))
|
|
880
|
-
|
|
881
|
-
if (
|
|
882
|
-
source_node_path.is_empty()
|
|
883
|
-
or signal_name.is_empty()
|
|
884
|
-
or target_node_path.is_empty()
|
|
885
|
-
or method_name.is_empty()
|
|
886
|
-
):
|
|
887
|
-
return {"ok": false, "error": "Missing required signal disconnection arguments"}
|
|
888
|
-
|
|
889
|
-
var opened: Array = _open(scene_path, true)
|
|
890
|
-
var scene: GdhSceneFile = opened[0]
|
|
891
|
-
var refused: Dictionary = opened[1]
|
|
892
|
-
if not refused.is_empty():
|
|
893
|
-
return refused
|
|
894
|
-
|
|
895
|
-
var ends: Array = _connection_ends(scene, source_node_path, signal_name, target_node_path)
|
|
896
|
-
if ends[0] == null:
|
|
897
|
-
return scene.refuse(str(ends[1]))
|
|
898
|
-
var source: Node = ends[0]
|
|
899
|
-
var target: Node = ends[1]
|
|
900
|
-
|
|
901
|
-
var from: String = scene.path_of(source)
|
|
902
|
-
var to: String = scene.path_of(target)
|
|
903
|
-
# A connection that was never there saved the scene unchanged and answered as removed, so a
|
|
904
|
-
# typo in either name read as success.
|
|
905
|
-
if _connection_flags(scene.root, from, signal_name, to, method_name) < 0:
|
|
906
|
-
return scene.refuse(
|
|
907
|
-
"%s has no connection from %s.%s to %s.%s." % [scene_path, from, signal_name, to, method_name]
|
|
908
|
-
)
|
|
909
|
-
source.disconnect(signal_name, Callable(target, method_name))
|
|
910
|
-
|
|
911
|
-
var written: Dictionary = scene.write(
|
|
912
|
-
func(saved: Node) -> String:
|
|
913
|
-
if _connection_flags(saved, from, signal_name, to, method_name) >= 0:
|
|
914
|
-
return "the connection would still be in the scene when it loads."
|
|
915
|
-
return ""
|
|
916
|
-
)
|
|
917
|
-
if not written.is_empty():
|
|
918
|
-
return written
|
|
919
|
-
|
|
920
|
-
return {
|
|
921
|
-
"ok": true,
|
|
922
|
-
"removed": true,
|
|
923
|
-
"sourceNodePath": from,
|
|
924
|
-
"signalName": signal_name,
|
|
925
|
-
"targetNodePath": to,
|
|
926
|
-
"methodName": method_name
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
func list_connections(args: Dictionary) -> Dictionary:
|
|
931
|
-
var project_path: String = str(args.get("projectPath", ""))
|
|
932
|
-
var scene_path: String = _to_scene_res_path(project_path, str(args.get("scenePath", "")))
|
|
933
|
-
var filter_path: String = str(args.get("nodePath", ""))
|
|
934
|
-
|
|
935
|
-
var opened: Array = _open(scene_path, false)
|
|
936
|
-
var scene: GdhSceneFile = opened[0]
|
|
937
|
-
var refused: Dictionary = opened[1]
|
|
938
|
-
if not refused.is_empty():
|
|
939
|
-
return refused
|
|
940
|
-
|
|
941
|
-
var root: Node = scene.root
|
|
942
|
-
var filtered: Node = null
|
|
943
|
-
if not filter_path.is_empty():
|
|
944
|
-
filtered = _find_node(root, filter_path)
|
|
945
|
-
if filtered == null:
|
|
946
|
-
return scene.refuse(scene.not_found("Node not found: " + filter_path, filter_path))
|
|
947
|
-
var nodes: Array = []
|
|
948
|
-
_collect_nodes_recursive(root, ".", nodes)
|
|
949
|
-
|
|
950
|
-
# Only persistent connections, which are the ones a scene file holds: a Container connects
|
|
951
|
-
# signals of each child to itself as the child is added, and those were answered as if the file
|
|
952
|
-
# held them. Matched on either end, since the filter is for connections involving the node.
|
|
953
|
-
var connections: Array = []
|
|
954
|
-
for entry: Dictionary in nodes:
|
|
955
|
-
var path: String = str(entry["path"])
|
|
956
|
-
var node: Node = entry["node"]
|
|
957
|
-
for signal_info: Dictionary in node.get_signal_list():
|
|
958
|
-
var signal_name: String = str(signal_info.get("name", ""))
|
|
959
|
-
if signal_name.is_empty():
|
|
960
|
-
continue
|
|
961
|
-
for conn: Dictionary in node.get_signal_connection_list(signal_name):
|
|
962
|
-
var flags: int = GdhRead.as_int(conn.get("flags", 0))
|
|
963
|
-
if not flags & Object.CONNECT_PERSIST:
|
|
964
|
-
continue
|
|
965
|
-
var callable: Callable = conn.get("callable", Callable())
|
|
966
|
-
var target_obj: Object = callable.get_object()
|
|
967
|
-
if filtered != null and node != filtered and target_obj != filtered:
|
|
968
|
-
continue
|
|
969
|
-
var target_path: String = ""
|
|
970
|
-
var editable: bool = scene.foreign(node).is_empty()
|
|
971
|
-
if target_obj is Node:
|
|
972
|
-
target_path = str(root.get_path_to(target_obj as Node))
|
|
973
|
-
editable = editable and scene.foreign(target_obj as Node).is_empty()
|
|
974
|
-
(
|
|
975
|
-
connections
|
|
976
|
-
. append(
|
|
977
|
-
{
|
|
978
|
-
"sourceNodePath": path,
|
|
979
|
-
"signalName": signal_name,
|
|
980
|
-
"targetNodePath": target_path,
|
|
981
|
-
"methodName": str(callable.get_method()),
|
|
982
|
-
"flags": flags,
|
|
983
|
-
"flagNames": GdhSceneFile.flag_names(flags),
|
|
984
|
-
# False for a connection an instanced scene makes inside itself, which only that
|
|
985
|
-
# scene can change.
|
|
986
|
-
"editable": editable
|
|
987
|
-
}
|
|
988
|
-
)
|
|
989
|
-
)
|
|
990
|
-
|
|
991
|
-
scene.close()
|
|
992
|
-
var listed: Dictionary = {"ok": true, "connections": connections}
|
|
993
|
-
if Engine.is_editor_hint():
|
|
994
|
-
listed["unsavedInEditor"] = GdhSceneFile.unsaved(scene_path)
|
|
995
|
-
return listed
|