From fd2552a82f420dac317f7705db5f8ee10b6aec31 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Tue, 14 May 2024 21:54:12 -0400 Subject: [PATCH] improve layout visibile lag to none for vbox & hbox on the settings menu --- code/app_screen.odin | 115 ++++++++++++++++++----- code/engine_api.odin | 9 +- code/grime_hashmap_chained.odin | 1 + code/tick_update.odin | 6 +- code/ui_floating.odin | 39 ++++---- code/ui_layout.odin | 162 ++++---------------------------- code/ui_layout_compute.odin | 8 +- code/ui_layout_widget.odin | 142 ++++++++++++++++++++++++++++ code/ui_tests.odin | 14 +-- code/ui_widgets.odin | 24 ++--- 10 files changed, 302 insertions(+), 218 deletions(-) diff --git a/code/app_screen.odin b/code/app_screen.odin index 5ca4d76..34f2fc8 100644 --- a/code/app_screen.odin +++ b/code/app_screen.odin @@ -21,7 +21,7 @@ UI_ScreenState :: struct settings_menu : struct { pos, size, min_size : Vec2, - container : UI_VBox, + vb_container : UI_VBox, is_open : b32, is_maximized : b32, }, @@ -49,7 +49,6 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 ) using state := get_state() using screen_ui - // ui_floating("Menu Bar", No_Captures, proc( captures : rawptr = nil ) { using state := get_state(); using screen_ui.menu_bar @@ -74,6 +73,7 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 ) ui_layout( UI_Layout { flags = {}, anchor = {}, + alignment = { 0.0, 0.0 }, text_alignment = {0.5, 0.5}, border_width = 1.0, font_size = 12, @@ -129,23 +129,35 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b if size.x < min_size.x do size.x = min_size.x if size.y < min_size.y do size.y = min_size.y - container = ui_vbox_begin( .Top_To_Bottom, "Settings Menu", {.Mouse_Clickable}) + resize_box_base := ui_widget("Settings Menu Wrapper", {}) + { + using resize_box_base + layout.flags = { .Fixed_Width, .Fixed_Height, .Origin_At_Anchor_Center, .Fixed_Position_X, .Fixed_Position_Y } + layout.pos = pos + layout.alignment = { 0.5, 0.5 } + layout.size = range2( size, {}) + style.bg_color = Color_3D_BG + } + ui_parent(resize_box_base) + if settings_menu.is_maximized { + using resize_box_base + layout.flags = {.Origin_At_Anchor_Center } + layout.pos = {} + } + ui_resizable_handles( & resize_box_base, & pos, & size) + + vb_container = ui_vbox_begin( .Top_To_Bottom, "Settings Menu", {.Mouse_Clickable}, compute_layout = true) { { - using container - // flags = {} - layout.flags = { .Fixed_Width, .Fixed_Height, .Origin_At_Anchor_Center } - layout.pos = pos - layout.alignment = { 0.5, 0.5 } - // layout.alignment = {} - layout.size = range2( size, {}) - style.bg_color = Color_BG_Panel_Translucent + using vb_container + flags = {} + style.bg_color = Color_BG_Panel_Translucent } - ui_parent(container) + ui_parent(vb_container) ui_layout( UI_Layout { font_size = 16, - alignment = {0, 1} + alignment = {0, 0}, }) ui_style( UI_Style { bg_color = Color_Transparent, @@ -153,13 +165,20 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b text_color = Color_White, }) ui_style_ref().hot.bg_color = Color_Blue - frame_bar := ui_hbox_begin(.Left_To_Right, "Settings Menu: Frame Bar", { .Mouse_Clickable, .Focusable, .Click_To_Focus }) + frame_bar : UI_HBox + frame_bar = ui_hbox_begin(.Left_To_Right, "Settings Menu: Frame Bar", { .Mouse_Clickable, .Focusable, .Click_To_Focus }) { frame_bar.style.bg_color = Color_BG_Panel frame_bar.layout.flags = {.Fixed_Height} frame_bar.layout.size.min.y = 50 + frame_bar.layout.anchor.ratio.y = 0.25 ui_parent(frame_bar) + ui_layout( UI_Layout { + font_size = 16, + // alignment = {1, 0}, + // anchor = range2({}, {}) + }) title := ui_text("Settings Menu: Title", str_intern("Settings Menu"), {.Disabled}) { using title @@ -176,7 +195,7 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b { using maximize_btn layout.flags = {.Fixed_Width} - layout.size.min = {50, 0} + layout.size.min = {50, 50} layout.text_alignment = {0.5, 0.5} layout.anchor.ratio.x = 1.0 if maximize_btn.pressed { @@ -202,24 +221,72 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b } } - ui_hbox_end(frame_bar) + ui_hbox_end(frame_bar, compute_layout = true) } if frame_bar.active { pos += input.mouse.delta should_raise = true } + ui_style( UI_Style { + bg_color = Color_Red, + font = default_font, + text_color = Color_White, + }) + + // Populate settings with values from config (hardcoded for now) + { + ui_layout(UI_Layout { + flags = { + // .Origin_At_Anchor_Center, + // .Fixed_Height, + }, + // pos = {0, 50}, + // size = range2({100, 100},{}), + // alignment = {0,0}, + }) + ui_style( UI_Style { + bg_color = Color_GreyRed + }) + { + drop_down_bar := ui_hbox_begin(.Left_To_Right, "settings_menu.vbox: config drop_down_bar", {.Mouse_Clickable}) + drop_down_bar.layout.anchor.ratio.y = 1.0 + // drop_down_bar.style.bg_color = Color_Red + + ui_parent(drop_down_bar) + btn := ui_button("pls") + btn.text = str_intern("Config") + btn.style.font = default_font + btn.layout.font_size = 32 + btn.layout.size.min.y = 50 + btn.layout.text_alignment = { 0.5, 0.5 } + btn.layout.flags = {.Fixed_Width, .Size_To_Text} + // btn.layout.size.min = {50, 0} + btn.style.bg_color = Color_Green + ui_hbox_end(drop_down_bar, compute_layout = false) + } + + // ui_layout(UI_Layout { + + // }) + // ui_style( UI_Style { + + // }) + // res_width_hbox := ui_hbox_begin(.Left_To_Right, "settings_menu.vbox: config.resolution_width: hbox", {}) + // ui_parent(res_width_hbox) + } + + // ui_layout_ref().default.flags = {.Fixed_Width, .Fixed_Height, .Fixed_Position_Y} + // ui_layout_ref().default.size.min = {50, 50} spacer := ui_spacer("Settings Menu: Spacer") + // spacer.style.bg_color = Color_Red spacer.layout.anchor.ratio.y = 1.0 + // spacer.layout.flags = {.Origin_At_Anchor_Center} + // spacer.layout.alignment = {0.5, 0.5} - ui_vbox_end(container, compute_layout = false ) + // ui_box_compute_layout(spacer) + ui_vbox_end(vb_container, compute_layout = false ) + // ui_box_compute_layout(spacer) } - if settings_menu.is_maximized { - using settings_menu.container - layout.flags = {.Origin_At_Anchor_Center } - layout.pos = {} - } - - ui_resizable_handles( & container, & pos, & size) return } diff --git a/code/engine_api.odin b/code/engine_api.odin index 1701bf2..f812dfb 100644 --- a/code/engine_api.odin +++ b/code/engine_api.odin @@ -318,9 +318,9 @@ tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32 rl.PollInputEvents() - debug.draw_ui_box_bounds_points = false - debug.draw_UI_padding_bounds = false - debug.draw_ui_content_bounds = false + debug.draw_ui_box_bounds_points = true + debug.draw_UI_padding_bounds = true + debug.draw_ui_content_bounds = true should_close = update( host_delta_time ) render() @@ -332,7 +332,7 @@ tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32 { // profile("Client tick timing processing") // config.engine_refresh_hz = uint(monitor_refresh_hz) - config.engine_refresh_hz = 120 + config.engine_refresh_hz = 6 frametime_target_ms = 1.0 / f64(config.engine_refresh_hz) * S_To_MS sub_ms_granularity_required := frametime_target_ms <= Frametime_High_Perf_Threshold_MS @@ -398,3 +398,4 @@ clean_frame :: proc() verify( alloc_error == .None, "Failed to allocate transient slab" ) } } + diff --git a/code/grime_hashmap_chained.odin b/code/grime_hashmap_chained.odin index 36c5436..7920416 100644 --- a/code/grime_hashmap_chained.odin +++ b/code/grime_hashmap_chained.odin @@ -163,6 +163,7 @@ hmap_chained_remove :: proc( self : HMapChainedPtr($Type), key : u64 ) -> b32 // Will preemptively allocate the next slot in the hashtable if its null for the slot. hmap_chained_set :: proc( using self : HMapChainedPtr($Type), key : u64, value : Type ) -> (^ Type, AllocatorError) { + // profile(#procedure) hash_index := hmap_chained_lookup_id(self, key) surface_slot := lookup[hash_index] set_slot :: #force_inline proc( using self : HMapChainedPtr(Type), diff --git a/code/tick_update.odin b/code/tick_update.odin index ad3986a..b818637 100644 --- a/code/tick_update.odin +++ b/code/tick_update.odin @@ -210,17 +210,17 @@ update :: proc( delta_time : f64 ) -> b32 frame_style_flags : UI_LayoutFlags = { .Fixed_Position_X, .Fixed_Position_Y, .Fixed_Width, .Fixed_Height, - .Origin_At_Anchor_Center, + // .Origin_At_Anchor_Center, } default_layout := UI_Layout { flags = frame_style_flags, anchor = {}, - alignment = { 0.5, 0.5 }, + // alignment = { 0.5, 0.5 }, font_size = 30, text_alignment = { 0.0, 0.0 }, // corner_radii = { 0.2, 0.2, 0.2, 0.2 }, pos = { 0, 0 }, - size = range2( { 1000, 1000 }, {}), + // size = range2( { 1000, 1000 }, {}), // padding = { 20, 20, 20, 20 } } ui_layout( default_layout ) diff --git a/code/ui_floating.odin b/code/ui_floating.odin index 8f3d322..7060401 100644 --- a/code/ui_floating.odin +++ b/code/ui_floating.odin @@ -14,7 +14,8 @@ UI_FloatingBuilder :: #type proc( captures : rawptr ) -> (became_active : b32) UI_FloatingManager :: struct { using links : DLL_NodeFL(UI_Floating), build_queue : Array(UI_Floating), - tracked : HMapZPL(UI_Floating), + tracked : HMapChainedPtr(UI_Floating), + // tracked : HMapZPL(UI_Floating), } ui_floating_startup :: proc( self : ^UI_FloatingManager, allocator : Allocator, build_queue_cap, tracked_cap : u64, dbg_name : string = "" ) -> AllocatorError @@ -30,7 +31,8 @@ ui_floating_startup :: proc( self : ^UI_FloatingManager, allocator : Allocator, } tracked_dbg_name := str_intern(str_fmt_tmp("%s: tracked", dbg_name)) - self.tracked, error = zpl_hmap_init_reserve( UI_Floating, allocator, tracked_cap, dbg_name = tracked_dbg_name.str ) + // self.tracked, error = zpl_hmap_init_reserve( UI_Floating, allocator, tracked_cap, dbg_name = tracked_dbg_name.str ) + self.tracked, error = hmap_chained_init(UI_Floating, uint(tracked_cap), allocator, dbg_name = tracked_dbg_name.str ) if error != AllocatorError.None { ensure(false, "Failed to allocate tracking table") @@ -43,8 +45,7 @@ ui_floating_reload :: proc( self : ^UI_FloatingManager, allocator : Allocator ) { using self build_queue.backing = allocator - tracked.entries.backing = allocator - tracked.table.backing = allocator + hmap_chained_reload(tracked, allocator) } ui_floating_just_builder :: #force_inline proc( label : string, builder : UI_FloatingBuilder ) -> ^UI_Floating @@ -95,7 +96,8 @@ ui_floating_build :: proc() for to_enqueue in array_to_slice( build_queue) { key := ui_key_from_string(to_enqueue.label) - lookup := zpl_hmap_get( & tracked, transmute(u64) key ) + // lookup := zpl_hmap_get( & tracked, transmute(u64) key ) + lookup := hmap_chained_get( tracked, transmute(u64) key ) // Check if entry is already present if lookup != nil && lookup.prev != nil && lookup.next != nil { @@ -107,28 +109,13 @@ ui_floating_build :: proc() if lookup == nil { error : AllocatorError - lookup, error = zpl_hmap_set( & tracked, transmute(u64) key, to_enqueue ) + // lookup, error = zpl_hmap_set( & tracked, transmute(u64) key, to_enqueue ) + lookup, error = hmap_chained_set( tracked, transmute(u64) key, to_enqueue ) if error != AllocatorError.None { ensure(false, "Failed to allocate entry to hashtable") continue } lookup.queued = true - - if first == nil { - first = lookup - continue - } - else if last == nil { - first.next = lookup - last = lookup - last.prev = first - continue - } - else { - last.next = lookup - last = lookup - continue - } } else { lookup.captures = to_enqueue.captures @@ -136,6 +123,14 @@ ui_floating_build :: proc() lookup.queued = true continue } + + if first == nil { + first = lookup + last = lookup + continue + } + last.next = lookup + last = lookup } array_clear(build_queue) diff --git a/code/ui_layout.odin b/code/ui_layout.odin index 2d20f07..79d50a0 100644 --- a/code/ui_layout.odin +++ b/code/ui_layout.odin @@ -3,6 +3,23 @@ package sectr import "core:math" import "core:math/linalg" + +// Anchor_ + +// Alignment presets + +LayoutAlign_OriginTL_TopLeft :: Vec2{ 0, 1} +LayoutAlign_OriginTL_TopRight :: Vec2{-1, 1} +LayoutAlign_OriginTL_Centered :: Vec2{ 0, 1} +LayoutAlign_OriginTL_BottomLeft :: Vec2{ 0, 1} + +Layout_OriginCenter_Centered :: Vec2{0.5, 0.5} + + + + + + // The UI_Box's actual positioning and sizing // There is an excess of rectangles here for debug puproses. UI_Computed :: struct { @@ -138,148 +155,3 @@ ui_layout_pop :: #force_inline proc() { pop( & @(deferred_none = ui_layout_pop) ui_layout_via_combo :: #force_inline proc( combo : UI_LayoutCombo ) { ui_layout_push( combo) } ui_set_layout :: #force_inline proc( layout : UI_Layout, preset : UI_StylePreset ) { stack_peek_ref( & get_state().ui_context.layout_combo_stack).array[preset] = layout } - -/* -Widget Layout Ops -*/ - -ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_LayoutDirectionX, width_ref : ^f32 ) -{ - container_width : f32 - if width_ref != nil { - container_width = width_ref ^ - } - else { - container_width = container.computed.content.max.x - container.computed.content.min.x - } - - // do layout calculations for the children - total_stretch_ratio : f32 = 0.0 - size_req_children : f32 = 0 - for child := container.first; child != nil; child = child.next - { - using child.layout - scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in flags) - if .Fixed_Width in flags - { - if scaled_width_by_height { - height := size.max.y != 0 ? size.max.y : container_width - width := height * size.min.x - - size_req_children += width - continue - } - - size_req_children += size.min.x - continue - } - - total_stretch_ratio += anchor.ratio.x - } - - avail_flex_space := container_width - size_req_children - - allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 ) - { - using child.layout - if ! (.Fixed_Width in flags) { - size.min.x = anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space - } - flags |= {.Fixed_Width} - } - - space_used : f32 = 0.0 - switch direction{ - case .Right_To_Left: - for child := container.last; child != nil; child = child.prev { - allocate_space(child, total_stretch_ratio, avail_flex_space) - using child.layout - anchor = range2({0, 0}, {0, 0}) - alignment = { 0, 1 }// - hbox.layout.alignment - pos.x = space_used - space_used += size.min.x - size.min.y = container.computed.content.max.y - container.computed.content.min.y - } - case .Left_To_Right: - for child := container.first; child != nil; child = child.next { - allocate_space(child, total_stretch_ratio, avail_flex_space) - using child.layout - anchor = range2({0, 0}, {0, 0}) - alignment = { 0, 1 } - pos.x = space_used - space_used += size.min.x - size.min.y = container.computed.content.max.y - container.computed.content.min.y - } - } -} - -ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_LayoutDirectionY, height_ref : ^f32 ) -{ - container_height : f32 - if height_ref != nil { - container_height = height_ref ^ - } - else { - container_height = container.computed.content.max.y - container.computed.content.min.y - } - - // do layout calculations for the children - total_stretch_ratio : f32 = 0.0 - size_req_children : f32 = 0 - for child := container.first; child != nil; child = child.next - { - using child.layout - scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in flags) - if .Fixed_Height in flags - { - if scaled_width_by_height { - width := size.max.x != 0 ? size.max.x : container_height - height := width * size.min.y - - size_req_children += height - continue - } - - size_req_children += size.min.y - continue - } - - total_stretch_ratio += anchor.ratio.y - } - - avail_flex_space := container_height - size_req_children - - allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 ) - { - using child.layout - if ! (.Fixed_Height in flags) { - size.min.y = anchor.ratio.y * (1 / total_stretch_ratio) * avail_flex_space - } - flags |= {.Fixed_Height} - alignment = {0, 0} - } - - space_used : f32 = 0.0 - switch direction { - case .Top_To_Bottom: - for child := container.last; child != nil; child = child.prev { - allocate_space(child, total_stretch_ratio, avail_flex_space) - using child.layout - anchor = range2({0, 0}, {0, 1}) - // alignment = {0, 1} - pos.y = space_used - space_used += size.min.y - size.min.x = container.computed.content.max.x - container.computed.content.min.x - } - case .Bottom_To_Top: - for child := container.first; child != nil; child = child.next { - allocate_space(child, total_stretch_ratio, avail_flex_space) - using child.layout - anchor = range2({0, 0}, {0, 1}) - // alignment = {0, 1} - pos.y = space_used - space_used += size.min.y - size.min.x = container.computed.content.max.x - container.computed.content.min.x - } - } -} diff --git a/code/ui_layout_compute.odin b/code/ui_layout_compute.odin index c61eee9..903b8e2 100644 --- a/code/ui_layout_compute.odin +++ b/code/ui_layout_compute.odin @@ -129,6 +129,10 @@ ui_box_compute_layout :: proc( box : ^UI_Box, rel_pos - adjusted_size * alignment, rel_pos + adjusted_size * (vec2_one - alignment), ) + if ! (.Origin_At_Anchor_Center in layout.flags) { + bounds.min -= { 0, adjusted_size.y } + bounds.max -= { 0, adjusted_size.y } + } // Determine Padding's outer bounds border_offset := Vec2 { layout.border_width, layout.border_width } @@ -166,8 +170,8 @@ ui_box_compute_layout_children :: proc( box : ^UI_Box ) { for current := box.first; current != nil; current = ui_box_tranverse_next( current ) { - if current == box do return - if current.computed.fresh do continue + // if current == box do return + // if current.computed.fresh do continue ui_box_compute_layout( current ) } } diff --git a/code/ui_layout_widget.odin b/code/ui_layout_widget.odin index 7ba6dc6..540e438 100644 --- a/code/ui_layout_widget.odin +++ b/code/ui_layout_widget.odin @@ -1,3 +1,145 @@ package sectr +/* +Widget Layout Ops +*/ +ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_LayoutDirectionX, width_ref : ^f32 ) +{ + container_width : f32 + if width_ref != nil { + container_width = width_ref ^ + } + else { + container_width = container.computed.content.max.x - container.computed.content.min.x + } + + // do layout calculations for the children + total_stretch_ratio : f32 = 0.0 + size_req_children : f32 = 0 + for child := container.first; child != nil; child = child.next + { + using child.layout + scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in flags) + if .Fixed_Width in flags + { + if scaled_width_by_height { + height := size.max.y != 0 ? size.max.y : container_width + width := height * size.min.x + + size_req_children += width + continue + } + + size_req_children += size.min.x + continue + } + + total_stretch_ratio += anchor.ratio.x + } + + avail_flex_space := container_width - size_req_children + + allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 ) + { + using child.layout + if ! (.Fixed_Width in flags) { + size.min.x = anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space + } + flags |= {.Fixed_Width} + } + + space_used : f32 = 0.0 + switch direction{ + case .Right_To_Left: + for child := container.last; child != nil; child = child.prev { + allocate_space(child, total_stretch_ratio, avail_flex_space) + using child.layout + anchor = range2({0, 0}, {0, 0}) + // alignment = { 0, 0 }// - hbox.layout.alignment + pos.x = space_used + space_used += size.min.x + // size.min.y = container.computed.content.max.y - container.computed.content.min.y + } + case .Left_To_Right: + for child := container.first; child != nil; child = child.next { + allocate_space(child, total_stretch_ratio, avail_flex_space) + using child.layout + anchor = range2({0, 0}, {0, 0}) + // alignment = { 0, 0 } + pos.x = space_used + space_used += size.min.x + // size.min.y = container.computed.content.max.y - container.computed.content.min.y + } + } +} + +ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_LayoutDirectionY, height_ref : ^f32 ) +{ + container_height : f32 + if height_ref != nil { + container_height = height_ref ^ + } + else { + container_height = container.computed.content.max.y - container.computed.content.min.y + } + + // do layout calculations for the children + total_stretch_ratio : f32 = 0.0 + size_req_children : f32 = 0 + for child := container.first; child != nil; child = child.next + { + using child.layout + scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in flags) + if .Fixed_Height in flags + { + if scaled_width_by_height { + width := size.max.x != 0 ? size.max.x : container_height + height := width * size.min.y + + size_req_children += height + continue + } + + size_req_children += size.min.y + continue + } + + total_stretch_ratio += anchor.ratio.y + } + + avail_flex_space := container_height - size_req_children + + allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 ) + { + using child.layout + if ! (.Fixed_Height in flags) { + size.min.y = anchor.ratio.y * (1 / total_stretch_ratio) * avail_flex_space + } + flags |= {.Fixed_Height} + } + + space_used : f32 = 0.0 + switch direction { + case .Bottom_To_Top: + for child := container.last; child != nil; child = child.prev { + allocate_space(child, total_stretch_ratio, avail_flex_space) + using child.layout + anchor = range2({0, 0}, {0, 0}) + // alignment = {0, 0} + pos.y = -space_used + space_used += size.min.y + size.min.x = container.computed.content.max.x + container.computed.content.min.x + } + case .Top_To_Bottom: + for child := container.first; child != nil; child = child.next { + allocate_space(child, total_stretch_ratio, avail_flex_space) + using child.layout + anchor = range2({0, 0}, {0, 0}) + // alignment = {0, 0} + pos.y = -space_used + space_used += size.min.y + size.min.x = container.computed.content.max.x - container.computed.content.min.x + } + } +} diff --git a/code/ui_tests.odin b/code/ui_tests.odin index 0385ddd..56a2fb5 100644 --- a/code/ui_tests.odin +++ b/code/ui_tests.odin @@ -74,7 +74,7 @@ test_parenting :: proc( default_layout : ^UI_Layout, frame_style_default : ^UI_S parent_layout := default_layout ^ parent_layout.size = range2( { 300, 300 }, {} ) parent_layout.alignment = { 0.5, 0.5 } - parent_layout.margins = { 100, 100, 100, 100 } + // parent_layout.margins = { 100, 100, 100, 100 } parent_layout.padding = { 5, 10, 5, 5 } parent_layout.pos = { 0, 0 } parent_layout.flags = { @@ -105,15 +105,15 @@ test_parenting :: proc( default_layout : ^UI_Layout, frame_style_default : ^UI_S } child_layout := default_layout ^ - child_layout.size = range2({ 0, 0 }, { 0, 0 }) - child_layout.alignment = { 0.5, 0.5 } - child_layout.margins = { 20, 20, 20, 20 } + child_layout.size = range2({ 100, 100 }, { 0, 0 }) + child_layout.alignment = { 0.0, 0.0 } + // child_layout.margins = { 20, 20, 20, 20 } child_layout.padding = { 5, 5, 5, 5 } - child_layout.anchor = range2({ 0.2, 0.1 }, { 0.1, 0.15 }) + // child_layout.anchor = range2({ 0.2, 0.1 }, { 0.1, 0.15 }) child_layout.pos = { 0, 0 } child_layout.flags = { - // .Fixed_Width, .Fixed_Height, - .Origin_At_Anchor_Center + .Fixed_Width, .Fixed_Height, + // .Origin_At_Anchor_Center } child_style := frame_style_default ^ diff --git a/code/ui_widgets.odin b/code/ui_widgets.odin index 81e0e06..8068d81 100644 --- a/code/ui_widgets.odin +++ b/code/ui_widgets.odin @@ -50,6 +50,7 @@ ui_hbox_begin :: proc( direction : UI_LayoutDirectionX, label : string, flags : hbox.direction = direction hbox.box = ui_box_make( flags, label ) hbox.signal = ui_signal_from_box(hbox.box) + // ui_box_compute_layout(hbox) return } @@ -181,7 +182,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, layout_bar_width := UI_Layout { flags = { .Fixed_Width }, - alignment = {1, 1}, + alignment = {1, 0}, margins = { handle_width, handle_width, 0, 0 }, size = range2({handle_width, 0}, {}), } @@ -198,7 +199,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, layout_bar_height.flags = {.Fixed_Height} layout_bar_height.size.min = {0, handle_width} layout_bar_height.margins = { 0, 0, handle_width, handle_width } - layout_bar_height.alignment = {0, 0} + layout_bar_height.alignment = {0, -1} context.user_ptr = & parent.label name :: proc( ) -> StrRunesPair { @@ -210,7 +211,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, if right { handle_right = ui_widget("Settings Menu: Resize Right Handle", flags) handle_right.layout.anchor.left = 1 - handle_right.layout.alignment = { 0, 1 } + handle_right.layout.alignment = { 0, 0 } } ui_layout(layout_bar_height) @@ -220,12 +221,12 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, handle_bottom = ui_widget("Settings Menu: Resize Bottom Border", flags) using handle_bottom.layout anchor.top = 1 - alignment = { 0, 1 } + alignment = { 0, 0 } } layout_corner := UI_Layout { flags = { .Fixed_Width, .Fixed_Height }, - alignment = {1, 0}, + alignment = {1, -1}, size = range2({handle_width, handle_width}, {}), } style_corner := UI_Style { @@ -238,18 +239,18 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, if corner_tr { handle_corner_tr = ui_widget("Settings Menu: Corner TR", flags) handle_corner_tr.layout.anchor = range2({1, 0}, {}) - handle_corner_tr.layout.alignment = {0, 0} + handle_corner_tr.layout.alignment = {0, -1} } if corner_bl { handle_corner_bl = ui_widget("Settings Menu: Corner BL", flags) handle_corner_bl.layout.anchor = range2({}, {0, 1}) - handle_corner_bl.layout.alignment = { 1, 1 } + handle_corner_bl.layout.alignment = { 1, 0 } } if corner_br { handle_corner_br = ui_widget("Settings Menu: Corner BR", flags) handle_corner_br.layout.anchor = range2({1, 0}, {0, 1}) - handle_corner_br.layout.alignment = {0, 1} + handle_corner_br.layout.alignment = {0, 0} } process_handle_drag :: #force_inline proc ( handle : ^UI_Widget, @@ -291,8 +292,6 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, delta := get_state().input.mouse.delta alignment := & parent.layout.alignment - if compute_layout do ui_box_compute_layout_children(parent) - if right do process_handle_drag( & handle_right, { 1, 0 }, delta, {0, 0}, pos, size, alignment ) if left do process_handle_drag( & handle_left, { -1, 0 }, delta, {1, 0}, pos, size, alignment ) if top do process_handle_drag( & handle_top, { 0, 1 }, delta, {0, 0}, pos, size, alignment ) @@ -301,6 +300,8 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, if corner_tl do process_handle_drag( & handle_corner_tl, { -1, 1 }, delta, {1, 0}, pos, size, alignment ) if corner_br do process_handle_drag( & handle_corner_br, { 1, -1 }, delta, {0, 1}, pos, size, alignment ) if corner_bl do process_handle_drag( & handle_corner_bl, { -1, -1 }, delta, {1, 1}, pos, size, alignment ) + + ui_box_compute_layout(parent) } #endregion("Resizable") @@ -379,11 +380,12 @@ UI_VBox :: struct { } // Boilerplate creation -ui_vbox_begin :: proc( direction : UI_LayoutDirectionY, label : string, flags : UI_BoxFlags = {} ) -> (vbox : UI_VBox) { +ui_vbox_begin :: proc( direction : UI_LayoutDirectionY, label : string, flags : UI_BoxFlags = {}, compute_layout := false ) -> (vbox : UI_VBox) { // profile(#procedure) vbox.direction = direction vbox.box = ui_box_make( flags, label ) vbox.signal = ui_signal_from_box( vbox.box ) + if compute_layout do ui_box_compute_layout(vbox) return }