I have a simple controlscene used as a UI element and its shape is that of a regular kite (a square rotated 45deg).
I’m progressively adding these under a GridContainer (but could be any other type) at runtime and its default settings correctly put them in this arrangement:
The only solution I can think of is to avoid relying in the prefab logic of containers and every time I instance one, placing it on the right spot via script.
Would there be any container (or combination thereof) that could allow me to just do
I don’t think there is anything built-in that allows to do that easily. You could try building a custom container.
I got it working in a bit of a hacky way. I have 2 “node types”:
TextureControl - a Control that contains the actual TextureRect, or Button, or whatever you want to display. Important: It needs to be half of your desired size.
FillerControl - a Control that is just the same size as the TextureControl, but has nothing inside and just fills the space between the TextureControls.
These 2 types then fill the GridContainer in an interlocking pattern, like so:
So every time you add a TextureControl, you need to add the FillerControl as well. You can add it before or after the TextureControl, depending which pattern you want.
As long as the GridContainer has an odd number of columns, it will form this nice diamond grid pattern.
@tool
extends Container
@export var x_padding:float = 10:
set(value):
x_padding=value; queue_sort()
@export var y_padding:float = 10:
set(value):
y_padding=value; queue_sort()
func _notification(what):
if what == NOTIFICATION_SORT_CHILDREN:
update_layout()
func update_layout():
var num_children:int = get_child_count()
var flip:bool = false
for i in num_children:
var child := get_child(i)
var child_size:Vector2 = child.size
var x_pos:float = i * (child_size.x + x_padding) * 0.5
var y_pos:float = 0
if flip:
y_pos = (child_size.y * 0.5) + y_padding
flip = not flip
fit_child_in_rect(child, Rect2(Vector2(x_pos,y_pos),Vector2.ZERO))