Cannot get rect_size of children of hBoxContainer AFTER expand

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By lamkka
func _ready():
	for n in 3:			
		var child = child_control.instance()
        print(child.rect_size)
   		child.size_flags_horizontal = SIZE_EXPAND_FILL
		self.add_child(child)
    print(get_children()[0].rect_size)

The above object is inherited from hBoxContainer and has no child.

All the above printing gets the same value: the original rect_size of the child_control instead of the rect_size of the child_control AFTER expanding. It just doesn’t make sense.

How can I get the rect_size of the child_control AFTER expanding via code instead of explicitly calculating the rect_size after expanding myself?

:bust_in_silhouette: Reply From: AlexTheRegent

New rect_size will be available in next frame. I usually do it using next code:

func _ready():
    for n in 3:         
        var child = child_control.instance()
        print(child.rect_size)
        child.size_flags_horizontal = SIZE_EXPAND_FILL
        self.add_child(child)
    yield(get_tree(), "idle_frame") # wait for next frame
    print(get_children()[0].rect_size)

Or you can try to call queue_sort on Container, but I’m not sure if it will update sizes immediately.

Thanks for the answer!
However there are still some problems with this method:
In fact my code layout is something like:

var expanded_size 
func _ready():
    create_children()
    print(get_children()[0].rect_size) #This printing is incorrect
    print(expanded_size) #The printing is incorrect
    func1() #cannot access expanded size in this method
    func2() #cannot access expanded size in this method
func create_children():
    for n in 3:         
        var child = child_control.instance()
        print(child.rect_size)
        child.size_flags_horizontal = SIZE_EXPAND_FILL
        self.add_child(child)
    yield(get_tree(), "idle_frame") # wait for next frame
    print(get_children()[0].rect_size) #This printing is correct
    expanded_size = get_children()[0].rect_size

There is still some wrong printings.
In fact I want to use the create_children() method to change some property of the object relating to the rect_size after expanding and THEN use it in func1() and func2().

lamkka | 2021-08-14 08:35

yield works inside function where it was called, because this is one of the tools to work with asynchronous code. in this layout you need to add yield(get_tree(), "idle_frame") after create_children() too:

func _ready():
    create_children()
    yield(get_tree(), "idle_frame") # wait for next frame here too
    print(get_children()[0].rect_size) #This printing is incorrect
    print(expanded_size) #The printing is incorrect
    func1() #cannot access expanded size in this method
    func2() #cannot access expanded size in this method

here yield acts as simple shorthand for (basically yield is shorthand for signals handlers):

    # ...
    get_tree().connect("idle_frame", self, "_on_idle_frame")


func _on_idle_frame():
    print(get_children()[0].rect_size) #This printing is correct
    expanded_size = get_children()[0].rect_size

if you will use it frequently, consider making wrapper around BoxContainer with custom signal, i.e. size_updated to reduce amount of lines to write.

AlexTheRegent | 2021-08-14 10:02

Thank you very much!

That works! However, it seems to me it would be quite troublesome writing yield on every related function. Would you please also demonstrate how to

make wrapper around BoxContainer with custom signal, i.e. size_updated to reduce amount of lines to write?

Many thanks!

lamkka | 2021-08-14 10:32

It depends on your situation and overall layout. Why do you need to frequently change content of Container and why do you need to know exact size of new child?

AlexTheRegent | 2021-08-14 16:50

I would like to make an object - falling mechanism like those in any standard match - 3 game, e.g. candies falling in Candy Crush.

The container object is in fact a column that contains “candy” objects (child) which will disappear upon interaction; when a child disappear, a new “candy” OF THE SAME SIZE will fall into the column with suitable animation. That is why I need to frequently add and free children of the container.

Furthermore, the main thing is that the size of these child objects depend on the “capacity” of the container, which is a variable, while the container has fixed length. That is why I need to know the exact size of the expanded new child: the size of these objects under a fixed capacity is the expanded object size.

lamkka | 2021-08-15 03:16

It probably will be easier to solve your problem if you contact me in discord: AlexTheRegent#8015

Right now I’m think it will be easier for you to make your own Container class rather than using existing BoxContainer, because it was made for different cases.

AlexTheRegent | 2021-08-15 15:12