From e5769bf5fc6100127d6d0a905e67ae08dd1921ec Mon Sep 17 00:00:00 2001 From: Synthasmagoria Date: Wed, 29 Jul 2026 23:08:28 +0200 Subject: [PATCH] Auto dimensions --- example/main.odin | 11 ++++----- ui.odin | 61 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/example/main.odin b/example/main.odin index 5e78b11..83eca18 100644 --- a/example/main.odin +++ b/example/main.odin @@ -29,11 +29,11 @@ main :: proc() { ui.start(&ctx, origin = {0, 0}, size = {WINDOW_WIDTH, WINDOW_HEIGHT}) for i in 0..<9 { - ui.container_begin(dimensions = {ui.Size_Percentage(1.0), ui.Size_Percentage(0.1)}, config = inner_container_config) + ui.container_begin(dimensions = {ui.SIZE_AUTO, ui.Size_Percentage(0.1)}, config = inner_container_config) for j in 0..<10 { config := button_config config.label = fmt.ctprintf("%d", i * 10 + j) - ui.button(dimensions = {ui.Size_Percentage(0.1), ui.Size_Percentage(1.0)}, config = config) + ui.button(dimensions = {ui.Size_Pixels(64.0), ui.Size_Percentage(1.0)}, config = config) ui.same_line() } ui.container_end() @@ -87,16 +87,13 @@ render_ui_elements :: proc(elements: []ui.Element) { switch element.type { case .Container: rl.DrawRectangleRounded(area, 0.1, 4.0, {0, 0, 0, 192}) - if len(element.label) == 0 { - rl.DrawRectangleRoundedLinesEx(area, 0.1, 4.0, 1.0, rl.Color(element.color)) - } else { - rl.GuiGroupBox(area, element.label) - } + rl.GuiGroupBox(area, element.label) case .Button: rl.GuiButton(area, element.label) case .Slider: data := element.data.float_input_data rl.GuiSlider(area, "", "", data.value, data.min, data.max) + case .InputFloat: } } } diff --git a/ui.odin b/ui.odin index 7c8ecf0..9edab17 100644 --- a/ui.odin +++ b/ui.odin @@ -4,11 +4,13 @@ v2 :: [2]f32 rect2 :: struct {x, y, width, height: f32} col :: [4]u8 +SIZE_AUTO :: Size_Auto {} + rect_get_tl :: #force_inline proc(rect: rect2) -> v2 {return {rect.x, rect.y}} rect_get_tr :: #force_inline proc(rect: rect2) -> v2 {return {rect.x + rect.width, rect.y}} rect_get_br :: #force_inline proc(rect: rect2) -> v2 {return {rect.x + rect.width, rect.y + rect.height}} rect_get_bl :: #force_inline proc(rect: rect2) -> v2 {return {rect.x, rect.y + rect.height}} - +rect_get_size :: #force_inline proc(rect: rect2) -> v2 {return {rect.width, rect.height}} rect_grow :: proc(rect: rect2, amount: v2) -> rect2 { return {rect.x - amount.x / 2.0, rect.y - amount.y / 2.0, rect.width + amount.x, rect.height + amount.y} } @@ -30,6 +32,7 @@ Element :: struct { using config: ElementConfiguration, data: ElementData, type: ElementType, + dimensions: Dimensions, } ElementConfiguration :: struct { @@ -51,18 +54,19 @@ ElementType :: enum { Container, Button, Slider, + InputFloat, } Size_Pixels :: distinct f32 Size_Percentage :: distinct f32 Size_PercentageRemainder :: distinct f32 -Size_Flex :: distinct bool +Size_Auto :: distinct bool -Size :: union { +Size :: union #no_nil { Size_Pixels, Size_Percentage, Size_PercentageRemainder, - Size_Flex, + Size_Auto, } Dimensions :: struct { @@ -108,7 +112,7 @@ same_line :: proc() { container_begin :: proc(dimensions: Dimensions, config: ElementConfiguration) -> ^Element { area := _resolve_element_area(dimensions, config.margin) - element := _append_element({area = area, config = config, type = .Container}) + element := _append_element({area = area, config = config, type = .Container, dimensions = dimensions}) container_index := len(ctx.elements) - 1 append(&ctx.containers, container_index) append(&ctx.container_last_element, -1) @@ -116,21 +120,56 @@ container_begin :: proc(dimensions: Dimensions, config: ElementConfiguration) -> } container_end :: proc() { - container := ctx.elements[pop(&ctx.containers)] + container_index := pop(&ctx.containers) + container := &ctx.elements[container_index] pop(&ctx.container_last_element) - // TODO: Set flex + + _, width_is_auto := container.dimensions.width.(Size_Auto) + _, height_is_auto := container.dimensions.height.(Size_Auto) + if width_is_auto || height_is_auto { + content_size: v2 + #reverse for element in ctx.elements[container_index + 1:] { + content_size += rect_get_size(get_element_outer_area(element)) + } + if width_is_auto { + container.area.width = content_size.x + } + if height_is_auto { + container.area.height = content_size.y + } + } + ctx.same_line = false - outer := get_element_outer_area(container) +} + +assert_no_dimensions_percentage_in_auto_container :: proc(dimensions: Dimensions) { + container := _container_current() + if _, is_auto := container.dimensions.width.(Size_Auto); is_auto { + _, is_pixels := dimensions.width.(Size_Pixels) + assert(is_pixels, "Any width that is not Size_Pixels is disallowed in a container using Size_Auto for width") + } + if _, is_auto := container.dimensions.height.(Size_Auto); is_auto { + _, is_pixels := dimensions.height.(Size_Pixels) + assert(is_pixels, "Any height that is not Size_Pixels is disallowed in a container using Size_Auto for height") + } } button :: proc(dimensions: Dimensions, config: ElementConfiguration) -> ^Element { + assert_no_dimensions_percentage_in_auto_container(dimensions) area := _resolve_element_area(dimensions, config.margin) - return _append_element({area = area, config = config, type = .Button}) + return _append_element({area = area, config = config, type = .Button, dimensions = dimensions}) } slider :: proc(dimensions: Dimensions, config: ElementConfiguration, data: ElementData_FloatInput) -> ^Element { + assert_no_dimensions_percentage_in_auto_container(dimensions) area := _resolve_element_area(dimensions, config.margin) - return _append_element({area = area, config = config, type = .Slider, data = {float_input_data = data}}) + return _append_element({area = area, config = config, type = .Slider, data = {float_input_data = data}, dimensions = dimensions}) +} + +input_float :: proc(dimensions: Dimensions, config: ElementConfiguration, data: ElementData_FloatInput) -> ^Element { + assert_no_dimensions_percentage_in_auto_container(dimensions) + area := _resolve_element_area(dimensions, config.margin) + return _append_element({area = area, config = config, type = .InputFloat, data = {float_input_data = data}, dimensions = dimensions}) } _append_element :: proc(element: Element) -> ^Element { @@ -194,7 +233,7 @@ _resolve_elemment_outer_size_axis :: proc(size: Size, axis: Axis) -> f32 { container_size := inner.width if axis == .X else inner.height return container_size * f32(value) } - case Size_Flex: + case Size_Auto: return 0.0 } unreachable()