From cf0f52ca736d340d7353df86928f2c86e4a1b77c Mon Sep 17 00:00:00 2001 From: Synthasmagoria Date: Fri, 31 Jul 2026 12:48:33 +0200 Subject: [PATCH] container index baked into id --- example/main.odin | 4 ++-- ui.odin | 52 +++++++++++++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/example/main.odin b/example/main.odin index d39f9ba..f2dea33 100644 --- a/example/main.odin +++ b/example/main.odin @@ -15,8 +15,8 @@ v2 :: [2]f32 V2_ONE :: v2{1.0, 1.0} V2_LEFT :: v2{-1.0, 0.0} V2_RIGHT :: v2{1.0, 0.0} -V2_UP :: v2{-1.0, 0.0} -V2_DOWN :: v2{1.0, 0.0} +V2_UP :: v2{0.0, -1.0} +V2_DOWN :: v2{0.0, 1.0} UiContainerType :: enum { Normal, diff --git a/ui.odin b/ui.odin index 66557fe..eebde26 100644 --- a/ui.odin +++ b/ui.odin @@ -11,16 +11,15 @@ rect_get_tr :: #force_inline proc(rect: rect2) -> v2 {return {rect.x + rect.widt 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_get_corners :: #force_inline proc(rect: rect2) -> (tl, tr, br, bl: v2) { - return rect_get_tl(rect), rect_get_tr(rect), rect_get_br(rect), rect_get_bl(rect) -} -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}} +rect_get_corners :: #force_inline proc(rect: rect2) -> (tl, tr, br, bl: v2) {return rect_get_tl(rect), rect_get_tr(rect), rect_get_br(rect), rect_get_bl(rect)} +rect_grow :: #force_inline 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}} ctx: ^Context Context :: struct { origin: v2, - element_focus_id: int, + element_focus_id: ElementId, + container_count: u16, containers: [dynamic]int, container_last_element: [dynamic]int, elements: [dynamic]Element, @@ -29,15 +28,24 @@ Context :: struct { CONTAINER_STACK_SIZE :: 16 +ElementId :: bit_field(int) { + container_index: u16 | 16, + element_index: u16 | 16, +} + Element :: struct { area: rect2, - id: int, + id: ElementId, using config: ElementConfiguration, data: rawptr, type: ElementType, dimensions: Dimensions, } +element_id_invalid :: proc() -> ElementId { + return {container_index = max(u16), element_index = max(u16)} +} + ElementConfiguration :: struct { label: cstring, color: col, @@ -80,6 +88,7 @@ init :: proc(state: ^Context, element_capacity: int, allocator := context.alloca start :: proc(ui_context: ^Context, origin: v2, size: v2) { ctx = ui_context ctx.origin = origin + ctx.container_count = 0 clear(&ctx.elements) clear(&ctx.containers) clear(&ctx.container_last_element) @@ -105,7 +114,7 @@ focus_element :: proc(ctx: ^Context, element: Element) { } unfocus_element :: proc(ctx: ^Context) { - ctx.element_focus_id = -1 + ctx.element_focus_id = element_id_invalid() } is_element_focused :: proc(ctx: ^Context, element: Element) -> bool { @@ -113,25 +122,28 @@ is_element_focused :: proc(ctx: ^Context, element: Element) -> bool { } focus_next_element :: proc(ctx: ^Context, allowed_focus := element_type_input) { - if ctx.element_focus_id == -1 { + if ctx.element_focus_id == element_id_invalid() { return } - if ctx.element_focus_id + 1 >= len(ctx.elements) { - ctx.element_focus_id = -1 + element_index := int(ctx.element_focus_id.element_index) + if element_index + 1 >= len(ctx.elements) { + ctx.element_focus_id = element_id_invalid() return } - ctx.element_focus_id += 1 - for ctx.element_focus_id < len(ctx.elements) { - if ctx.elements[ctx.element_focus_id].type in allowed_focus { + element_index += 1 + for element_index < len(ctx.elements) { + if ctx.elements[element_index].type in allowed_focus { + ctx.element_focus_id = ctx.elements[element_index].id return } - ctx.element_focus_id += 1 + element_index += 1 } - ctx.element_focus_id = -1 + ctx.element_focus_id = element_id_invalid() } container_begin :: proc(dimensions: Dimensions, config: ElementConfiguration, data: rawptr = nil) -> ^Element { area := _resolve_element_area(dimensions, config.margin) + ctx.container_count += 1 element := _append_element({area = area, config = config, type = .Container, dimensions = dimensions, data = data}) container_index := len(ctx.elements) - 1 append(&ctx.containers, container_index) @@ -202,11 +214,11 @@ get_element_inner_area :: proc(element: Element) -> rect2 { _append_element :: proc(element: Element) -> ^Element { append(&ctx.elements, element) - last_element_index := len(ctx.elements) - 1 - last_element := &ctx.elements[last_element_index] - last_element.id = last_element_index - ctx.container_last_element[len(ctx.containers) - 1] = last_element_index - return last_element + element_index := len(ctx.elements) - 1 + element := &ctx.elements[element_index] + element.id = ElementId {container_index = ctx.container_count, element_index = u16(element_index)} + ctx.container_last_element[len(ctx.containers) - 1] = element_index + return element } _resolve_element_area :: proc(dimensions: Dimensions, margin: v2) -> rect2 {