|
|
|
|
Reply From: |
takaturre |
Actually all the children nodes are duplicated recursively automatically. * However, they will not be saved along the packed scene unless their owner is set accordingly. So, the solution is to run a recursive loop on the kids and “own” each one by their grandpa - ie. the original node to be duplicated: kid_node.owner = grandpa_node
.
Here is a general static method for this purpose:
# Own recursively - supporting ignoring nested instanced scenes (.filename).
static func own(node, new_owner):
if not node == new_owner and (not node.owner or node.filename):
node.owner = new_owner
if node.get_child_count():
for kid in node.get_children():
own(kid, new_owner)
And using above, the solution to the original problem:
own(grandpa_node, grandpa_node)
_ * I don’t know if there is a way to not duplicate all the children with duplicate
. Thought thatduplicate(8)
flag (see Node.DuplicateFlags) would be needed to duplicate all the kids, but seems duplicate(0)
also does this.
Edit:
If you are working within the editor (tool script) and want to see your nodes immediately in the scene tree, own them by the editor scene instead: get_tree().get_edited_scene_root()
.
thanks a lot for this tip, here is the code i’ve used with to generate packedscenes, it works like a charm!!
# your method
static func own(node, new_owner):
if not node == new_owner and (not node.owner or node.filename):
node.owner = new_owner
if node.get_child_count():
for kid in node.get_children():
own(kid, new_owner)
further in the code:
for i in range( 0, 10 ):
var board = load("res://models/board.tscn").instance()
board.depth = i
add_child( board )
# this is a tool func of the board to regenerate all objects
board.do_generate()
own( board, board )
var path = str( i )
while len( path ) < 3:
path = "0" + path
path = "res://models/boards/board_" + path + ".tscn"
var ps = PackedScene.new()
var result = ps.pack(board)
if result == OK:
ResourceSaver.save(path, ps)
print( "board saved at " + path )
frankiezafe | 2020-01-09 16:35
The recursive re-parenting is making problems when the scene is containing imported scenes. My board has this structure:
board
– buttons
---- button.tscn
---- button.tscn
---- button.tscn
---- button.tscn
---- …
– slots
---- slot.tscn
---- slot.tscn
---- slot.tscn
---- …
when running own()
on board
, all elements contained in button.tscn
and slot.tscn
gets duplicated
Due to my hierarchy, it is easy to limit to re-parenting at a specified depth:
func own( node, new_owner, lvl, max_lvl ):
if lvl >= max_lvl:
return
if not node == new_owner and (not node.owner or node.filename):
node.set_owner( new_owner )
lvl += 1
for c in node.get_children():
c.set_owner( new_owner )
own( c, new_owner, lvl, max_lvl )
And calling it like this:
own( board, board, 0, 2 )
This prevents the imported scenes to be duplicated…
frankiezafe | 2020-01-09 17:20
For Godot 4, node.filename
has been renamed to node.scene_file_path
(link)