diff options
author | San Jacobs | 2025-09-04 01:59:45 +0200 |
---|---|---|
committer | San Jacobs | 2025-09-04 01:59:45 +0200 |
commit | 2c3bf1f92aec1407b85666b62089c979fa5361a0 (patch) | |
tree | 18c39edfd741062224613c41ca2a0798b841b8fa | |
parent | 2c5b14dfd7ed3affda7ce47ff466767343b94285 (diff) | |
download | tafl-2c3bf1f92aec1407b85666b62089c979fa5361a0.tar.gz tafl-2c3bf1f92aec1407b85666b62089c979fa5361a0.tar.bz2 tafl-2c3bf1f92aec1407b85666b62089c979fa5361a0.zip |
Big progress. Growing, positioning and rendering now.
-rw-r--r-- | src/main.odin | 74 | ||||
-rw-r--r-- | src/tafl.odin | 262 | ||||
-rw-r--r-- | src/tafl/tafl.odin | 355 |
3 files changed, 429 insertions, 262 deletions
diff --git a/src/main.odin b/src/main.odin new file mode 100644 index 0000000..0cc699f --- /dev/null +++ b/src/main.odin @@ -0,0 +1,74 @@ +package main + +import t "tafl" + + +main :: proc() { + + width, height : i32 = 1920, 1080 + + t.start_window(width, height, "tafl test") + + for !t.window_should_close() { + + if t.resized(){ + width, height = t.get_window_size() + } + + { + t.tafl( + sizing_width=t.FIXED(int(width)), + sizing_height=t.FIXED(int(height)), + layout=.LEFT_TO_RIGHT, + color={.0,.0,.0, 1}, + padding={16,16,16,16}, + child_gap=16, + ) + { + t.tafl(color={.3,.6,.9, 1}, + sizing_height=t.GROW, + sizing_width=t.FIXED(500)) + + { + t.tafl(color={.1,.1,.1, 1}) + + { + t.tafl(color={.1,.1,.1, 1}) + } + { + t.tafl(color={.1,.1,.1, 1}) + } + { + t.tafl(color={.1,.1,.1, 1}) + } + } + + { + t.tafl(color={.1,.1,.1, 1}) + } + } + + { + t.tafl(color={.2,.2,.2, 1}, + sizing_width=t.GROW, + sizing_height=t.GROW) + } + { + t.tafl(color={.1,.8,.2, 1}, + sizing_width=t.FIXED(300), + sizing_height=t.GROW,) + /*{ + t.tafl(color={.1,.1,.1, 1}) + } + { + t.tafl(color={.1,.1,.1, 1}) + }*/ + } + /*{ + t.tafl(color={.1,.1,.1, 1}) + }*/ + } + + t.render() + } +} diff --git a/src/tafl.odin b/src/tafl.odin deleted file mode 100644 index a582858..0000000 --- a/src/tafl.odin +++ /dev/null @@ -1,262 +0,0 @@ -package tafl - -import "core:fmt" -//import "core:math" -import rl "vendor:raylib" - -tafl_elements : [4096]Tafl -tafl_elements_count : int - -tafl_stack : [4096]int -tafl_stack_depth : int - -child_buffer : [4096]int -child_buffer_len : int - -temp_child_buffer : [4096]int -temp_child_buffer_len : int // May be inferred by child count, and not be needed - -main :: proc() { - - { - tafl(color={.1,.1,.1,1}) - - { - tafl(color={.1,.1,.1,1}) - - { - tafl(color={.1,.1,.1,1}) - - { - tafl(color={.1,.1,.1,1}) - } - { - tafl(color={.1,.1,.1,1}) - } - { - tafl(color={.1,.1,.1,1}) - } - } - - { - tafl(color={.1,.1,.1,1}) - } - } - - { - tafl(color={.1,.1,.1,1}) - } - { - tafl(color={.1,.1,.1,1}) - { - tafl(color={.1,.1,.1,1}) - } - { - tafl(color={.1,.1,.1,1}) - } - } - { - tafl(color={.1,.1,.1,1}) - } - } -} - - - -@(deferred_out=__tafl_close) -tafl :: proc( - /*width : int = 0, - height : int = 0, - x : int = 0, - y : int = 0,*/ - sizing_width : Sizing_Dimension = {.FIT, 0, 0}, - sizing_height : Sizing_Dimension = {.FIT, 0, 0}, - layout : Layout = .LEFT_TO_RIGHT, - padding : Sides = {0,0,0,0}, - child_gap : int = 0, - color : Color = {1,1,0,1}, - ) -> ^Tafl{ - - parent_ptr : ^Tafl = nil - if tafl_stack_depth > 0 { - parent_ptr = &tafl_elements[tafl_stack[tafl_stack_depth-1]] - } - - tafl_elements[tafl_elements_count] = { - /*width = width, - height = height, - x = x, - y = y,*/ - sizing = {sizing_width, sizing_height}, - layout = layout, - padding = padding, - child_gap = child_gap, - - parent = parent_ptr, - } - this_tafl : ^Tafl = &tafl_elements[tafl_elements_count] - - tafl_stack[tafl_stack_depth] = tafl_elements_count - this_tafl.own_index = tafl_elements_count - this_tafl.own_depth = tafl_stack_depth - this_tafl.children.index = temp_child_buffer_len - - indent(this_tafl.own_depth) - fmt.printfln("+ Opened tafl {}", this_tafl.own_index) - - tafl_elements_count += 1 - tafl_stack_depth += 1 - - return this_tafl -} - - -__tafl_close :: proc(tafl : ^Tafl) { - - parent := tafl.parent - if parent != nil { - - tafl.width += tafl.padding.left + tafl.padding.right - tafl.height += tafl.padding.top + tafl.padding.bottom - - // Not entirely sure yet, because Nic's video doesn't say you need this - // max(), but I have a feeling that childless tafls will cause negative - // total_child_gaps, which would be bad. - // - // ALSO: Wtf? Why are we basing this off of the tafls number of siblings? - // I do not understand this. - total_child_gap := max(parent.children.len - 1, 0) * parent.child_gap - - switch parent.layout { - case .LEFT_TO_RIGHT: - tafl.width += total_child_gap - parent.width += tafl.width - parent.height = max(tafl.height, parent.height) - case .TOP_TO_BOTTOM: - tafl.height += total_child_gap - parent.height += tafl.height - parent.width = max(tafl.width, parent.width) - } - - } - - for i in 0..<tafl.children.len { - child_buffer[child_buffer_len+i] = temp_child_buffer[tafl.children.index+i] - temp_child_buffer_len -= 1 - } - tafl.children.index = child_buffer_len - child_buffer_len += tafl.children.len - - temp_child_buffer[temp_child_buffer_len] = tafl.own_index - temp_child_buffer_len += 1 - - if parent != nil { - parent.children.len += 1 - } else { - child_buffer[child_buffer_len] = 0 - child_buffer_len += 1 - } - - tafl_stack_depth -= 1 - - indent(tafl.own_depth) - fmt.printfln("+ Closed tafl {}\t\tchild_buffer:{}\t\ttemp_child_buffer:{}\tchild_index:{} {}", tafl.own_index, child_buffer[0:child_buffer_len], temp_child_buffer[0:temp_child_buffer_len], tafl.children.index, tafl.children.len) -} - - - -grow_children :: proc(parent : ^Tafl) { - remainingWidth := parent.width - remainingHeight := parent.height - remainingWidth -= parent.padding.left + parent.padding.right - remainingHeight -= parent.padding.top + parent.padding.bottom - - for i in 0..<parent.children.len { - child : ^Tafl = &tafl_elements[child_buffer[parent.children.index+i]] - remainingWidth -= child.width - } - // Do we need to make sure this isn't negative??? - remainingWidth -= (parent.children.len - 1) * parent.child_gap - - for i in 0..<parent.children.len { - child : ^Tafl = &tafl_elements[child_buffer[parent.children.index+i]] - if child.sizing.width.type == .GROW { - child.width += remainingWidth - } else if (child.sizing.height.type == .GROW) { - child.height += remainingHeight - } - } -} - - - - - -Sizing_Dimension :: struct { - type : enum{ - FIT, - GROW, - FIXED - }, - min, max : int -} - -Layout :: enum { - LEFT_TO_RIGHT, - TOP_TO_BOTTOM, -} - -Sides :: struct { - top, bottom, left, right : int -} - -Color :: struct { - r,g,b,a : f32 -} - -Tafl :: struct { - width, height : int, - x, y : int, - - own_index : int, // Delete me - own_depth : int, // Delete me - - parent : ^Tafl, - - - - // style - - children : struct { - index, len : int - }, - sizing : struct { - width : Sizing_Dimension, - height : Sizing_Dimension, - }, - layout : Layout, - padding : Sides, - child_gap : int, - color : Color, -} - -Tafl_Style :: struct { - sizing : struct { - width : Sizing_Dimension, - height : Sizing_Dimension, - }, - layout : Layout, - padding : Sides, - child_gap : int, - color : Color, -} - -indent :: proc(x : int) { - for _ in 0..<x { - fmt.print("| ") - } -} - -GROW : Sizing_Dimension : {.GROW, 0, max(type_of(Sizing_Dimension{}.max))} - -FIT : Sizing_Dimension : {.FIT, 0, max(type_of(Sizing_Dimension{}.max))}
\ No newline at end of file diff --git a/src/tafl/tafl.odin b/src/tafl/tafl.odin new file mode 100644 index 0000000..c816493 --- /dev/null +++ b/src/tafl/tafl.odin @@ -0,0 +1,355 @@ +package tafl + +import "core:fmt" +import rl "vendor:raylib" + +tafl_elements : [4096]Tafl +tafl_elements_count : int + +tafl_stack : [4096]int +tafl_stack_depth : int + +child_index_buffer : [4096]int +child_index_buffer_len : int + +temp_child_buffer : [4096]int +temp_child_buffer_len : int // May be inferred by child count, and not be needed + +clear_layout :: proc() { + tafl_stack_depth = 0 + tafl_elements_count = 0 + child_index_buffer_len = 0 + temp_child_buffer_len = 0 +} + +@(deferred_out=__tafl_close) +tafl :: proc( + /*width : int = 0, + height : int = 0, + x : int = 0, + y : int = 0,*/ + sizing_width : Sizing_Dimension = {.FIT, 0, 0}, + sizing_height : Sizing_Dimension = {.FIT, 0, 0}, + layout : Layout = .LEFT_TO_RIGHT, + padding : Sides = {0,0,0,0}, + child_gap : int = 0, + color : Color = {1,1,0,1}, + ) -> ^Tafl{ + + parent_ptr : ^Tafl = nil + if tafl_stack_depth > 0 { + parent_ptr = &tafl_elements[tafl_stack[tafl_stack_depth-1]] + } + + tafl_elements[tafl_elements_count] = { + /*width = width, + height = height, + x = x, + y = y,*/ + sizing = {sizing_width, sizing_height}, + layout = layout, + padding = padding, + child_gap = child_gap, + + color = color, + + parent = parent_ptr, + } + this_tafl : ^Tafl = &tafl_elements[tafl_elements_count] + + if this_tafl.sizing.width.type == .FIXED { + this_tafl.width = this_tafl.sizing.width.max + } + if this_tafl.sizing.height.type == .FIXED { + this_tafl.height = this_tafl.sizing.height.max + } + + tafl_stack[tafl_stack_depth] = tafl_elements_count + this_tafl.own_index = tafl_elements_count + this_tafl.own_depth = tafl_stack_depth + this_tafl.children.index = temp_child_buffer_len + + indent(this_tafl.own_depth) + fmt.printfln("┌ Opened tafl {}", this_tafl.own_index) + + tafl_elements_count += 1 + tafl_stack_depth += 1 + + return this_tafl +} + + +__tafl_close :: proc(tafl : ^Tafl) { + + parent := tafl.parent + if parent != nil { + + tafl.width += tafl.padding.left + tafl.padding.right + tafl.height += tafl.padding.top + tafl.padding.bottom + + // Not entirely sure yet, because Nic's video doesn't say you need this + // max(), but I have a feeling that childless tafls will cause negative + // total_child_gaps, which would be bad. + // + // ALSO: Wtf? Why are we basing this off of the tafls number of siblings? + // I do not understand this. + total_child_gap := max(tafl.children.len - 1, 0) * tafl.child_gap + + switch parent.layout { + case .LEFT_TO_RIGHT: + tafl.width += total_child_gap + parent.width = min(parent.width+tafl.width, parent.sizing.width.max) + parent.height = min(max(tafl.height, parent.height), parent.sizing.height.max) + case .TOP_TO_BOTTOM: + tafl.height += total_child_gap + parent.height = min(parent.height+tafl.height, parent.sizing.height.max) + parent.width = min(max(tafl.width, parent.width), parent.sizing.width.max) + } + + } + + for i in 0..<tafl.children.len { + child_index_buffer[child_index_buffer_len+i] = temp_child_buffer[tafl.children.index+i] + temp_child_buffer_len -= 1 + } + tafl.children.index = child_index_buffer_len + child_index_buffer_len += tafl.children.len + + temp_child_buffer[temp_child_buffer_len] = tafl.own_index + temp_child_buffer_len += 1 + + if parent != nil { + parent.children.len += 1 + } else { + child_index_buffer[child_index_buffer_len] = 0 + child_index_buffer_len += 1 + } + + tafl_stack_depth -= 1 + + indent(tafl.own_depth) + fmt.printfln("└ Closed tafl {}\t\tchild_buffer:{}\t\ttemp_child_buffer:{}\tchild_index:{} {}", tafl.own_index, child_index_buffer[0:child_index_buffer_len], temp_child_buffer[0:temp_child_buffer_len], tafl.children.index, tafl.children.len) +} + + +// TODO: Support multiple growing tǫfl +grow_children :: proc(parent : ^Tafl) { + + // X is the layout direction, Y is across the layout direction. + // So that LEFT_TO_RIGHT means X = width, + // and TOP_TO_BOTTOM means X = height + + parent_x : ^int + parent_y : ^int + padding_x : int + padding_y : int + switch parent.layout { + case .LEFT_TO_RIGHT: + parent_x = &parent.width + parent_y = &parent.height + padding_x = parent.padding.left + parent.padding.right + padding_y = parent.padding.top + parent.padding.bottom + case .TOP_TO_BOTTOM: + parent_x = &parent.height + parent_y = &parent.width + padding_x = parent.padding.top + parent.padding.bottom + padding_y = parent.padding.left + parent.padding.right + } + remaining_x : int = parent_x^ + remaining_y : int = parent_y^ + remaining_x -= padding_x + remaining_y -= padding_y + + for child in children_of(parent) { + switch parent.layout { + case .LEFT_TO_RIGHT: + remaining_x -= child.width + case .TOP_TO_BOTTOM: + remaining_x -= child.height + } + } + // Do we need to make sure this isn't negative??? + remaining_x -= (parent.children.len - 1) * parent.child_gap + + switch parent.layout { + case .LEFT_TO_RIGHT: + for child in children_of(parent) { + if child.sizing.width.type == .GROW { + child.width += remaining_x + } + if child.sizing.height.type == .GROW { + child.height += remaining_y - child.height + } + } + case .TOP_TO_BOTTOM: + for child in children_of(parent) { + if child.sizing.width.type == .GROW { + child.width += remaining_y - child.width + } + if child.sizing.height.type == .GROW { + child.height += remaining_x + } + } + } +} + +position_children :: proc(parent: ^Tafl) { + switch parent.layout { + case .LEFT_TO_RIGHT: + left_offset : int = parent.padding.left + for child in children_of(parent) { + child.x = left_offset + child.y = parent.padding.top + left_offset += child.width + parent.child_gap + } + case .TOP_TO_BOTTOM: + top_offset : int = parent.padding.top + for child in children_of(parent) { + child.x = top_offset + child.y = parent.padding.left + top_offset += child.width + parent.child_gap + } + + } +} + +render :: proc() { + + grow_pass() + position_pass() + + rl.BeginDrawing() + rl.ClearBackground({255,0,0,255}) + + #reverse for tafl_index in child_index_buffer[:child_index_buffer_len] { + tafl := tafl_elements[tafl_index] + color : rl.Color = {u8(tafl.color.r*255.0), + u8(tafl.color.g*255.0), + u8(tafl.color.b*255.0), + u8(tafl.color.a*255.0),} + //fmt.printf("%#v\n\n", tafl) + rl.DrawRectangleRec({f32(tafl.x), f32(tafl.y), f32(tafl.width), f32(tafl.height),}, color) + } + + rl.DrawFPS(5, 5) + + rl.EndDrawing() + clear_layout() +} + +grow_pass :: proc() { + #reverse for tafl_index in child_index_buffer[:child_index_buffer_len] { + tafl := &tafl_elements[tafl_index] + grow_children(tafl) + } +} + +position_pass :: proc() { + #reverse for tafl_index in child_index_buffer[:child_index_buffer_len] { + tafl := &tafl_elements[tafl_index] + position_children(tafl) + } +} + +start_window :: proc(width, height : i32, title : cstring, fps_target : int = 60) { + rl.SetWindowMinSize(800,600) + rl.SetTargetFPS(60) + rl.SetConfigFlags({.WINDOW_RESIZABLE}) + rl.InitWindow(width, height, title) +} + +window_should_close :: proc() -> bool { + return rl.WindowShouldClose() +} + +resized :: proc() -> (resized: bool) { + return rl.IsWindowResized() +} + +get_window_size :: proc() -> (i32, i32) { + return rl.GetScreenWidth(), rl.GetScreenHeight() +} + +Sizing_Dimension :: struct { + type : enum{ + FIT, + GROW, + FIXED + }, + min, max : int +} + +Layout :: enum { + LEFT_TO_RIGHT, + TOP_TO_BOTTOM, +} + +Sides :: struct { + top, bottom, left, right : int +} + +Color :: struct { + r,g,b,a : f32 +} + +Tafl :: struct { + width, height : int, + x, y : int, + + own_index : int, // Delete me + own_depth : int, // Delete me + + parent : ^Tafl, + children : struct { + index, len : int + }, + + using style : Tafl_Style, +} + +__child_iterator_index : int = 0 +children_of :: proc(tafl: ^Tafl) -> (child: ^Tafl, ok: bool) { + if __child_iterator_index >= tafl.children.len { + __child_iterator_index = 0 + return nil, false + } + + // Assuming you have some way to get the actual child at index + // This depends on how your children are actually stored + child = &tafl_elements[child_index_buffer[(tafl.children.index+__child_iterator_index)]] + __child_iterator_index += 1 + return child, true +} + +Tafl_Style :: struct { + sizing : struct { + width : Sizing_Dimension, + height : Sizing_Dimension, + }, + layout : Layout, + padding : Sides, + child_gap : int, + color : Color, +} + +indent :: proc(x : int) { + for _ in 0..<x { + fmt.print("│ ") + } +} + +GROW : Sizing_Dimension : {.GROW, 0, max(type_of(Sizing_Dimension{}.max))} + +FIT : Sizing_Dimension : {.FIT, 0, max(type_of(Sizing_Dimension{}.max))} + +FIXED :: proc(x: int) -> Sizing_Dimension { + return {.FIXED, x, x} +} + +u8_clamp :: proc(input: f32) -> u8 { + mult := input*255 + output := u8(mult) + if mult<0 do output = 0 + if mult>255 do output = 255 + return output +}
\ No newline at end of file |