Buttons debug

This commit is contained in:
Synthasmagoria 2026-07-29 15:45:49 +02:00
commit 6c8479f922
2 changed files with 95 additions and 38 deletions

View file

@ -9,8 +9,11 @@ WINDOW_HEIGHT :: 720
WINDOW_CAPTION :: "Immediate mode GUI" WINDOW_CAPTION :: "Immediate mode GUI"
WINDOW_FRAMERATE :: 60 WINDOW_FRAMERATE :: 60
v2 :: [2]f32
V2_ONE :: v2{1.0, 1.0}
main :: proc() { main :: proc() {
rl.SetTraceLogLevel(.WARNING) // rl.SetTraceLogLevel(.WARNING)
rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_CAPTION) rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_CAPTION)
defer rl.CloseWindow() defer rl.CloseWindow()
rl.SetTargetFPS(WINDOW_FRAMERATE) rl.SetTargetFPS(WINDOW_FRAMERATE)
@ -18,46 +21,74 @@ main :: proc() {
ctx: ui.Context ctx: ui.Context
ui.init(&ctx, 4000) ui.init(&ctx, 4000)
outer_container_config := ui.ElementConfiguration {margin = {4.0, 8.0}, padding = {12.0, 24.0}, color = ui.col(rl.RED), label = ""}
inner_container_config := ui.ElementConfiguration {color = cast(ui.col)rl.GREEN, label = "", margin = {4.0, 4.0}}
button_config := ui.ElementConfiguration {margin = {4.0, 4.0}}
for !rl.WindowShouldClose() { for !rl.WindowShouldClose() {
ui.start(&ctx, {0, 0}, {WINDOW_WIDTH, WINDOW_HEIGHT})
outer_container := ui.container_begin( ui.start(&ctx, origin = {0, 0}, size = {WINDOW_WIDTH, WINDOW_HEIGHT})
dimensions = {ui.Size_Pixels(WINDOW_WIDTH), ui.Size_Pixels(WINDOW_HEIGHT)}, for i in 0..<10 {
config = { ui.container_begin(dimensions = {ui.Size_Percentage(1.0), ui.Size_Percentage(0.1)}, config = inner_container_config)
margin = {4.0, 8.0}, for j in 0..<10 {
padding = {12.0, 24.0}, config := button_config
color = cast([4]u8)rl.RED, config.label = fmt.ctprintf("%d", i * 10 + j)
label = "", ui.button(dimensions = {ui.Size_Percentage(0.1), ui.Size_Percentage(1.0)}, config = config)
}, ui.same_line()
) }
inner_container_config := ui.ElementConfiguration {color = cast([4]u8)rl.GREEN, label = "", margin = {16.0, 8.0}} ui.container_end()
inner_container_dimensions := ui.Dimensions {ui.Size_Percentage(1.0), ui.Size_Percentage(0.1)} }
for i in 0..<10 {
ui.container_begin(dimensions = inner_container_dimensions, config = inner_container_config)
ui.container_end()
}
// inner_container_dimensions := ui.Dimensions {ui.Size_Percentage(1.0), ui.Size_Percentage(1.0)}
// ui.container_begin(dimensions = inner_container_dimensions, config = inner_container_config)
// ui.container_end()
ui.container_end()
elements := ui.end() elements := ui.end()
rl.BeginDrawing() rl.BeginDrawing()
defer rl.EndDrawing() defer rl.EndDrawing()
rl.ClearBackground(rl.BLACK) rl.ClearBackground(rl.BLACK)
rl.DrawRectangleRec(rl.Rectangle(ui.get_element_inner_area(outer_container^)), rl.GRAY) render_ui_elements(elements)
for element in elements { ui.start(&ctx, {0, 0}, {WINDOW_WIDTH, WINDOW_HEIGHT})
switch element.type { config := ui.ElementConfiguration{margin = V2_ONE * 4, padding = V2_ONE * 4, color = ui.col(rl.MAGENTA)}
case .Container: ui.container_begin({ui.Size_Percentage(0.3), ui.Size_Percentage(0.3)}, config)
area := rl.Rectangle(element.area) slider_config := config
if len(element.label) == 0 { slider_config.label = "Outer container margin"
rl.DrawRectangleRoundedLinesEx(area, 0.1, 4.0, 1.0, rl.Color(element.color)) ui_slider_2d(1.0, 0.2, slider_config, &outer_container_config.margin, 0.0, 32.0)
} else { slider_config.label = "Inner container margin"
rl.GuiLabel(area, element.label) ui_slider_2d(1.0, 0.2, slider_config, &inner_container_config.margin, 0.0, 32.0)
} slider_config.label = "Button margin"
case .Button: ui_slider_2d(1.0, 0.2, slider_config, &button_config.margin, 0.0, 32.0)
ui.container_end()
debug_elements := ui.end()
render_ui_elements(debug_elements)
}
}
ui_slider_2d :: proc(width, height: ui.Size_Percentage, config: ui.ElementConfiguration, value: ^v2, min: f32, max: f32) -> ^ui.Element {
container := ui.container_begin(dimensions = {width, height}, config = config)
dimensions := ui.Dimensions {ui.Size_Percentage(0.5), ui.Size_Percentage(1.0)}
ui.slider(dimensions, {margin = config.margin}, {value = &value.x, min = min, max = max})
ui.same_line()
ui.slider(dimensions, {margin = config.margin}, {value = &value.y, min = min, max = max})
ui.container_end()
return container
}
render_ui_elements :: proc(elements: []ui.Element) {
for element in elements {
area := rl.Rectangle(element.area)
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)
} }
case .Button:
rl.GuiButton(area, element.label)
case .Slider:
data := element.data.float_input_data
rl.GuiSlider(area, "", "", data.value, data.min, data.max)
} }
} }
} }

38
ui.odin
View file

@ -2,6 +2,7 @@ package synthas_ui
v2 :: [2]f32 v2 :: [2]f32
rect2 :: struct {x, y, width, height: f32} rect2 :: struct {x, y, width, height: f32}
col :: [4]u8
rect_get_tl :: #force_inline proc(rect: rect2) -> v2 {return {rect.x, rect.y}} 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_tr :: #force_inline proc(rect: rect2) -> v2 {return {rect.x + rect.width, rect.y}}
@ -27,18 +28,29 @@ CONTAINER_STACK_SIZE :: 16
Element :: struct { Element :: struct {
area: rect2, area: rect2,
using config: ElementConfiguration, using config: ElementConfiguration,
data: ElementData,
type: ElementType, type: ElementType,
} }
ElementConfiguration :: struct { ElementConfiguration :: struct {
label: cstring, label: cstring,
color: [4]u8, color: col,
margin, padding: v2, margin, padding: v2,
} }
ElementData :: struct {
using float_input_data: ElementData_FloatInput,
}
ElementData_FloatInput :: struct {
min, max: f32,
value: ^f32,
}
ElementType :: enum { ElementType :: enum {
Container, Container,
Button, Button,
Slider,
} }
Size_Pixels :: distinct f32 Size_Pixels :: distinct f32
@ -85,7 +97,7 @@ end :: proc() -> []Element {
assert(len(ctx.containers) > 0, "Closed base container before ending UI layout mode") assert(len(ctx.containers) > 0, "Closed base container before ending UI layout mode")
elements := ctx.elements[:] elements := ctx.elements[:]
ctx = nil ctx = nil
return elements return elements[1:]
} }
same_line :: proc() { same_line :: proc() {
@ -94,7 +106,7 @@ same_line :: proc() {
container_begin :: proc(dimensions: Dimensions, config: ElementConfiguration) -> ^Element { container_begin :: proc(dimensions: Dimensions, config: ElementConfiguration) -> ^Element {
area := _resolve_element_area(dimensions, config.margin) area := _resolve_element_area(dimensions, config.margin)
element := _append_element(Element{area = area, config = config, type = .Container}) element := _append_element({area = area, config = config, type = .Container})
container_index := len(ctx.elements) - 1 container_index := len(ctx.elements) - 1
append(&ctx.containers, container_index) append(&ctx.containers, container_index)
append(&ctx.container_last_element, -1) append(&ctx.container_last_element, -1)
@ -105,11 +117,18 @@ container_end :: proc() {
container := ctx.elements[pop(&ctx.containers)] container := ctx.elements[pop(&ctx.containers)]
pop(&ctx.container_last_element) pop(&ctx.container_last_element)
// TODO: Set flex // TODO: Set flex
ctx.same_line = false
outer := get_element_outer_area(container) outer := get_element_outer_area(container)
} }
button :: proc(dimensions: Dimensions) -> ^Element { button :: proc(dimensions: Dimensions, config: ElementConfiguration) -> ^Element {
return nil area := _resolve_element_area(dimensions, config.margin)
return _append_element({area = area, config = config, type = .Button})
}
slider :: proc(dimensions: Dimensions, config: ElementConfiguration, data: ElementData_FloatInput) -> ^Element {
area := _resolve_element_area(dimensions, config.margin)
return _append_element({area = area, config = config, type = .Slider, data = {float_input_data = data}})
} }
_append_element :: proc(element: Element) -> ^Element { _append_element :: proc(element: Element) -> ^Element {
@ -134,7 +153,14 @@ _resolve_element_area :: proc(dimensions: Dimensions, margin: v2) -> rect2 {
_resolve_element_outer_position :: proc() -> v2 { _resolve_element_outer_position :: proc() -> v2 {
if alignment_element := _element_container_previous(); alignment_element != nil { if alignment_element := _element_container_previous(); alignment_element != nil {
return rect_get_bl(get_element_outer_area(alignment_element^)) area: v2
if ctx.same_line {
area = rect_get_tr(get_element_outer_area(alignment_element^))
} else {
area = rect_get_bl(get_element_outer_area(alignment_element^))
}
ctx.same_line = false
return area
} }
return rect_get_tl(get_element_inner_area(_element_previous()^)) return rect_get_tl(get_element_inner_area(_element_previous()^))
} }