Files
leonwww/flumi/Scripts/Utils/FlexUtils.gd

136 lines
5.4 KiB
GDScript3
Raw Normal View History

class_name FlexUtils
extends RefCounted
static func apply_flex_container_properties(node, styles: Dictionary) -> void:
# Flex direction - default to row if not specified
if styles.has("flex-direction"):
match styles["flex-direction"]:
"row": node.flex_direction = FlexContainer.FlexDirection.Row
"row-reverse": node.flex_direction = FlexContainer.FlexDirection.RowReverse
"column": node.flex_direction = FlexContainer.FlexDirection.Column
"column-reverse": node.flex_direction = FlexContainer.FlexDirection.ColumnReverse
else:
node.flex_direction = FlexContainer.FlexDirection.Row
# Flex wrap
if styles.has("flex-wrap"):
match styles["flex-wrap"]:
"nowrap":
node.flex_wrap = FlexContainer.FlexWrap.NoWrap
"wrap":
node.flex_wrap = FlexContainer.FlexWrap.Wrap
# this is probably not needed but i dont feel like testing it
node.flex_property_changed("flex_wrap", FlexContainer.FlexWrap.Wrap)
"wrap-reverse":
node.flex_wrap = FlexContainer.FlexWrap.WrapReverse
# Justify content
if styles.has("justify-content"):
match styles["justify-content"]:
"flex-start": node.justify_content = FlexContainer.JustifyContent.FlexStart
"flex-end": node.justify_content = FlexContainer.JustifyContent.FlexEnd
"center": node.justify_content = FlexContainer.JustifyContent.Center
"space-between": node.justify_content = FlexContainer.JustifyContent.SpaceBetween
"space-around": node.justify_content = FlexContainer.JustifyContent.SpaceAround
"space-evenly": node.justify_content = FlexContainer.JustifyContent.SpaceEvenly
# Align items
if styles.has("align-items"):
match styles["align-items"]:
"flex-start": node.align_items = FlexContainer.AlignItems.FlexStart
"flex-end": node.align_items = FlexContainer.AlignItems.FlexEnd
"center": node.align_items = FlexContainer.AlignItems.Center
"stretch": node.align_items = FlexContainer.AlignItems.Stretch
"baseline": node.align_items = FlexContainer.AlignItems.Baseline
# Align content
if styles.has("align-content"):
match styles["align-content"]:
"flex-start": node.align_content = FlexContainer.AlignContent.FlexStart
"flex-end": node.align_content = FlexContainer.AlignContent.FlexEnd
"center": node.align_content = FlexContainer.AlignContent.Center
"stretch": node.align_content = FlexContainer.AlignContent.Stretch
"space-between": node.align_content = FlexContainer.AlignContent.SpaceBetween
"space-around": node.align_content = FlexContainer.AlignContent.SpaceAround
# Gap
if styles.has("gap"):
# YGGutterAll = 2
node._root.set_gap(2, parse_flex_value(styles["gap"]))
if styles.has("row-gap"):
# YGGutterRow = 1
node._root.set_gap(1, parse_flex_value(styles["row-gap"]))
if styles.has("column-gap"):
# YGGutterColumn = 0
node._root.set_gap(0, parse_flex_value(styles["column-gap"]))
if styles.has("width"):
var width_val = styles["width"]
if width_val == "full" or width_val == "100%":
# For flex containers, w-full should expand to fill parent
node.set_meta("should_fill_horizontal", true)
2025-08-27 20:23:05 +03:00
node.set_meta("size_flags_set_by_style_manager", true)
elif typeof(width_val) == TYPE_STRING and width_val.ends_with("%"):
node.set_meta("custom_css_width_percentage", width_val)
else:
node.set_meta("custom_css_width", SizingUtils.parse_size_value(width_val))
if styles.has("height"):
var height_val = styles["height"]
if height_val == "full":
# For flex containers, h-full should expand to fill parent
node.set_meta("should_fill_vertical", true)
2025-08-27 20:23:05 +03:00
node.set_meta("size_flags_set_by_style_manager", true)
elif typeof(height_val) == TYPE_STRING and height_val.ends_with("%"):
node.set_meta("custom_css_height_percentage", height_val)
else:
node.set_meta("custom_css_height", SizingUtils.parse_size_value(height_val))
if styles.has("background-color"):
node.set_meta("custom_css_background_color", styles["background-color"])
node.update_layout()
static func apply_flex_item_properties(node: Control, styles: Dictionary) -> void:
var properties: Dictionary = node.get_meta("flex_metas", {}).duplicate(true)
var changed = false
if styles.has("flex-grow"):
properties["grow"] = float(styles["flex-grow"])
changed = true
if styles.has("flex-shrink"):
properties["shrink"] = float(styles["flex-shrink"])
changed = true
if styles.has("flex-basis"):
properties["basis"] = parse_flex_value(styles["flex-basis"])
changed = true
if styles.has("align-self"):
var align_self_value = -1
match styles["align-self"]:
"auto": align_self_value = FlexContainer.AlignItems.Auto
"flex-start": align_self_value = FlexContainer.AlignItems.FlexStart
"flex-end": align_self_value = FlexContainer.AlignItems.FlexEnd
"center": align_self_value = FlexContainer.AlignItems.Center
"stretch": align_self_value = FlexContainer.AlignItems.Stretch
"baseline": align_self_value = FlexContainer.AlignItems.Baseline
if align_self_value != -1:
properties["align_self"] = align_self_value
changed = true
if changed:
node.set_meta("flex_metas", properties)
var parent = node.get_parent()
if parent is FlexContainer:
parent.update_layout()
static func parse_flex_value(val):
if val is float or val is int:
return float(val)
if val is String:
var s_val = val.strip_edges()
if s_val.is_valid_float():
return s_val.to_float()
if s_val.ends_with("%"):
return s_val.trim_suffix("%").to_float() / 100.0
if s_val.ends_with("px"):
return s_val.trim_suffix("px").to_float()
if s_val == "auto":
return "auto"
return null