Desired behavior
I have a custom Control
node with a Label
as its child. I have many instances of the Control
node in my UI in and I would like each to have different text in its child Label
.
Solution 1
One way of doing this would be to enable Editable Children
for the Control
node, but since I have many instances of the node (and Label
is nested far in the child nodes) I would like the Control
node to change the Label
text without cluttering the scene tree with editable children.
Solution 2
class_name CustomControl
extends Control
@export var label_text: String
func _ready():
$.../Label.text = label_text
A solution to this would be to have an export variable label_text
and then change Label.text
in the _ready()
function. The problem with doing it like this is that changes to the exported label_text
variable do not show up in editor.
Solution 3
@tool
class_name CustomControl
extends Control
@export var label_text: String:
set(new_text):
label_text = new_text
update_label()
func update_label():
$.../Label.text = label_text
I can use the @tool
annotation to update the Label
in the setter of the exported variable. The problem with this approach is that the code will not work if you run the scene, as the setter will be called before the Control
node’s children are initialized. This can be fixed by adding a check in the update_label
function
func update_label():
var label = get_node_or_null(".../Label")
if label:
$.../Label.text = label_text
which produces the desired behavior.
Question
I’m mostly wondering why this code works and if there is a better way of achieving the desired behavior. The thing I’m most confused about is when the setter of the exported variable is being called in node initialization? From my testing it seems that the initialization sequence is
_init
is calledset
is called the first time (node has no children)set
is called the second time (node has children)- node enters tree
_ready
is called
but I cannot find any official documentation telling me when setters of exported variables are called. Will the second call of set
always occur after the children of the node have been initialized?