godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.46k stars 21.07k forks source link

Setting scale of a control node inside of a container doesn't work if set immediately #98200

Open miv391 opened 1 week ago

miv391 commented 1 week ago

Tested versions

System information

v4.4.dev3.mono.official [f4af8201b]

Issue description

When control node is contained by a container (eg. VBoxContainer) and its scale is set immediately after node's creation, the scale value doesn't have any effect. If the scale is set afterwards or it is set using a tween with 0 second duration, the scale works as expected.

Steps to reproduce

Scene: kuva

Code:

extends Node2D

@onready var label: Label = $VBoxContainer/Label
@onready var v_box_container: VBoxContainer = $VBoxContainer

var label_2

func _ready() -> void:
    # this doesn't work:
    label.scale = Vector2(0.4, 1.0)

    label_2 = Label.new()
    v_box_container.add_child(label_2)
    label_2.text = "Another label with some text"
    # this doesn't work:
    label_2.scale = Vector2(1.0, 2.0)

    # setting scale using a tween with zero duration works:
    #create_tween().tween_property(label, "scale", Vector2(0.4, 1.0), 0.0)
    #create_tween().tween_property(label_2, "scale", Vector2(1.0, 2.0), 0.0)

func _on_button_pressed() -> void:
    # this works:
    label.scale = Vector2(0.4, 1.0)
    label_2.scale = Vector2(1.0, 2.0)

If the button is clicked or if the two create_tween() lines are uncommented, scales are working as expected.

Minimal reproduction project (MRP)

scale_test.zip

syntaxerror247 commented 1 week ago

This is an expected behaviour.

If the Control node is a child of a Container node, the scale will be reset to Vector2(1, 1) when the scene is instantiated. To set the Control's scale when it's instantiated, wait for one frame using await get_tree().process_frame then set its scale property.

EDIT: The real issue is that, after creating label_2 node in MRP , it resets label node's scale to Vector2(1,1) even if you use await in start of function.

@miv391 update your ready function like this, this will work until you un-comment label_2 code.

func _ready() -> void:
    # this does work:
    await get_tree().process_frame
    label.scale = Vector2(0.4, 1.0)

    #label_2 = Label.new()
    #v_box_container.add_child(label_2)
    #label_2.text = "Another label with some text"
    # this doesn't work:
    #label_2.scale = Vector2(1.0, 2.0)
miv391 commented 1 week ago

I have to admit I didn't read documentation about how scale works with containers. In debug mode it could be nice if a warning were displayed if non-Vector(1,1) scale value is reset because of the container.