Custom GUI control: rect_size and anchorage

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By TaaTT4

I’m trying to create a custom control like the one in the image below:

Basically, it is a rectangle positioned at viewport center with a label inside it. The label must be anchored at top left corner of the rectangle.
So, I’ve created a scene with an empty Control node and I’ve added a Label child node to it. I’ve attached a script to the control node which takes care to draw the rectangle and set its size. Here is the code:

extends Control


func _draw():
	draw_rect(Rect2(-100, -100, 200, 200), Color(0.0, 0.0, 0.0), false)

func _ready():
	set_size(Vector2(200, 200))

Just for sake of simplicity, in the code above the rectangle has a fixed size of 200x200, but in a real scenario it would have a dynamic size. My problem is the label node doesn’t take in account the rectangle dimension, set with the set_size method, in calculating its anchorage. I guess I have to inform the label node about the real rectangle size… but how?

:bust_in_silhouette: Reply From: clarkejm

Assuming I understand your goal and your scene is structured like this:
<Some_parent>
+Control ↔ Control.gd
±Label

The this does what I think you’re asking (plus some time based changes for visual):

extends Control

var time =0
export var box_size = Vector2(200,200) setget set_boxsize, boxsize

func set_boxsize(v):
    box_size = v
    set_size(box_size)
    if $Label:
        $Label.rect_position = Vector2(-box_size.x/2, -box_size.y/2)
    
func boxsize():
    return box_size

func _process(delta):
    time += delta
    set_boxsize( Vector2(200+(cos(time)*50),200+(sin(time)*50)))   

func _draw():
    draw_rect(Rect2(-box_size.x/2, -box_size.y/2, box_size.x, box_size.y), Color(0.0, 0.0, 0.0), false)

func _ready():
    set_boxsize(box_size)

Yep, your solution works perfectly, but it is a way too specific. What about if the rectangle would have many child nodes with different anchoration settings? Doesn’t exist a function to recalculate rect/transform of all child nodes?

TaaTT4 | 2018-07-24 08:14

I answered what you asked, there isn’t a global child recalculation. You will have to write your own taking into account how you would want the scaling/sizing to affect each child.
In the original case is straightforward because it is anchored at the top left corner but other children could be positioned elsewhere and a global function would have to know how the child is to be repositioned:

  • Is it a fixed offset from a side/corner/pivot of the parent?
  • Is it positioned relative to another child?
  • Are relative scales to be maintained
  • Does the position and size of the child scale with the parent?

you might consider adapting the above code so that each the last_size is recorded before box_size is set and then use the rect_position / size of each child + some other variables stored with the child or parent to determine how each one should be repositioned and/or scaled

clarkejm | 2018-07-25 00:53

I’m not saying your answer isn’t correct, at all. I wrote this super-simple example just to not have to provide all the context details.
I hoped that position settings choose for a child node (e.g. anchor at top left with 40px of margin) would have been automatically kept after a parent resize. Or at least, that a function would have been existed to automatically repos child nodes.

TaaTT4 | 2018-07-26 22:10