Hi,
I use GUI nodes for a puzzle game, where a “block” can have a “selected” state, visualized by another child node with a texture.
All block nodes are created dynamically without assigning an individual id to them. I store only the reference to each node in an array.
Now I want to clone a block node with gui.clone_tree( block_node ).
Since I don’t have any ids to access the resulting table of this function, I use next() for getting the first node (the root I assume).
The block is then cloned a the same position but without showing the “selected” state texture.
When I then assign a position to the root node reference, nothing changes visually, even though internally the correct position is stored, if I print out gui.get_position():
local new_pos = vmath.vector3(100, 100, 0)
local node_tree = gui.clone_tree(node)
local _, root_block_node = next(node_tree)
gui.set_position(root_block_node, new_pos)
print(gui.get_position(root_block_node)) -- correct position
Things become even less comprehensible (to me) when I test assigning a parent node to the root block like so:
local blocks_node = gui.get_node("blocks") -- the parent of all created blocks
gui.set_parent(root_block_node, blocks_node, true)
Then the child node (the node for state “selected”) will be set to the position I want instead. But the cloned block node remains in its position!
The examples and code in the forum I have found of clone_tree() always involve the use of the id string. But it would be great if you could solve it without.
How can this behavior be explained and how can I solve the problem? Thanks!
local node_tree = gui.clone_tree(node)
local cloned_node_tree = node_tree[hash("root_node")] -- you need this one
gui.set_position(cloned_node_tree, new_pos)
Try printing out the results of gui.clone_tree with pprint() to see what it contains. That should make it more clear.
I don’t think you’re getting the right node. Rama’s code should be correct, only you should replace “root_node” with the actual name of your root node (the one you cloned).
next() will not give you anything that could be considered the “first” value, and the “first” value won’t necessarily be the root node, since they are keyed by the original node names (hashed). If you look at the Lua manual entry for next(), you will see:
The order in which the indices are enumerated is not specified, even for numeric indices.
In other words: next() gives you an essentially random key and value. It’s main use is just to check if a table is empty or not.
Aha, interesting. Are you cloning a node that you created dynamically? (such as with gui.new_box_node()?) They get an “empty” id, which is a hashed empty string: hash(""). That’s what you’re seeing as the key.
But anyway, since there is only one node and no child nodes, that should eliminate the possibility that you are getting the wrong node, leaving the problem still a mystery…
Is the project small? Could you zip it up (without the “.internal” or “build” folders) and post it here?
Ohhh, good point, that really throws a wrench in the works if you clone a dynamically created tree of nodes. All the IDs used for keys are the same, so the table returned from clone_tree has only one node in it.
Just did a quick test. If you don’t set the IDs before cloning, you just get a table with one node in it, with no way to tell which one it is.
local _pos = vmath.vector3()
local _size = vmath.vector3(100, 100, 0)
local function box(w, h, x, y)
_pos.x, _pos.y = x or 0, y or 0
_size.x, _size.y = w or 100, h or 100
return gui.new_box_node(_pos, _size)
end
function init(self)
local parent = box()
local child = box()
gui.set_parent(child, parent)
-- gui.set_id(parent, "parent") -- Without these, 'nodes' has only one node in it.
-- gui.set_id(child, "child")
local nodes = gui.clone_tree(parent)
pprint(nodes)
end
Oh, that’s odd, but I think I will build a simple workaround by creating the game object as a new node.
This is not so hard in my case, since there is only one more child node.
PS: Here in the docs I had found the following quote:
Dynamically created nodes do not have an id assigned to them. This is by design. The references that are returned from gui.new_[type]_node(), gui.clone() and gui.clone_tree() are the only thing necessary to be able to access the nodes and you should keep track of that reference. GUI scripts in Defold
It sounded to me like I actually didn’t need to manually assign ids.