immersive-home/app/content/ui/components/flex_container/flex_container.gd

100 lines
2.4 KiB
GDScript3
Raw Normal View History

2024-04-23 23:11:18 +03:00
@tool
extends Container3D
class_name FlexContainer3D
enum Justification {
START,
CENTER,
END,
SPACE_BETWEEN,
SPACE_AROUND,
SPACE_EVENLY,
}
@export var justification: Justification = Justification.START:
set(value):
justification = value
_update()
@export var vertical: bool = false:
set(value):
vertical = value
_update()
@export var gap: float = 0.0:
set(value):
gap = value
_update()
func _ready():
_update()
func _update():
var width = size.y if vertical else size.x
2024-04-25 14:19:12 +03:00
var children_size := Vector2(0, 0)
2024-04-23 23:11:18 +03:00
var child_count = 0
for child in get_children():
if child is Container3D == false:
continue
if vertical:
2024-04-25 14:19:12 +03:00
children_size.x = max(child.size.x, children_size.x)
children_size.y += child.size.y + gap
2024-04-23 23:11:18 +03:00
else:
2024-04-25 14:19:12 +03:00
children_size.x += child.size.x + gap
children_size.y = max(child.size.y, children_size.y)
2024-04-23 23:11:18 +03:00
child_count += 1
if child_count == 0:
return
2024-04-25 14:19:12 +03:00
var children_scale = Vector2(size.x, size.y) / children_size
children_size.clamp(Vector2(0, 0), Vector2(size.x, size.y))
2024-04-23 23:11:18 +03:00
2024-04-25 14:19:12 +03:00
children_scale = children_scale.clamp(Vector2(0.001, 0.001), Vector2(1, 1))
2024-04-23 23:11:18 +03:00
var offset = 0.0
2024-04-25 14:19:12 +03:00
var children_width = children_size.y if vertical else children_size.x
2024-04-23 23:11:18 +03:00
match justification:
Justification.START:
offset = 0.0
Justification.CENTER:
2024-04-25 14:19:12 +03:00
offset = (width - children_width) / 2.0
2024-04-23 23:11:18 +03:00
Justification.END:
2024-04-25 14:19:12 +03:00
offset = width - children_width
2024-04-23 23:11:18 +03:00
Justification.SPACE_BETWEEN:
offset = 0.0
Justification.SPACE_AROUND:
2024-04-25 14:19:12 +03:00
offset = (width - children_width) / child_count / 2.0
2024-04-23 23:11:18 +03:00
Justification.SPACE_EVENLY:
2024-04-25 14:19:12 +03:00
offset = (width - children_width) / (child_count + 1)
2024-04-23 23:11:18 +03:00
for child in get_children():
if child is Container3D == false:
continue
2024-04-25 14:19:12 +03:00
child.scale = Vector3(children_scale.x, children_scale.y, 1)
2024-04-23 23:11:18 +03:00
if vertical:
2024-04-25 14:19:12 +03:00
var child_width = child.size.y * children_scale.y
child.position = Vector3(0, -offset - child_width / 2.0, 0)
offset += child.size.y * children_scale.y
2024-04-23 23:11:18 +03:00
else:
2024-04-25 14:19:12 +03:00
var child_width = child.size.x * children_scale.x
child.position = Vector3(offset + child_width / 2.0, 0, 0)
offset += child.size.x * children_scale.x
2024-04-23 23:11:18 +03:00
match justification:
Justification.START, Justification.CENTER, Justification.END:
offset += gap
Justification.SPACE_BETWEEN:
2024-04-25 14:19:12 +03:00
offset += (width - children_width) / (child_count - 1)
2024-04-23 23:11:18 +03:00
Justification.SPACE_AROUND:
2024-04-25 14:19:12 +03:00
offset += (width - children_width) / child_count
2024-04-23 23:11:18 +03:00
Justification.SPACE_EVENLY:
2024-04-25 14:19:12 +03:00
offset += (width - children_width) / (child_count + 1)
2024-04-23 23:11:18 +03:00