Got render_list proper setup for UI_State rendering...

Still need a spacial indexing method to prevent redundant enqueues to the drawlist (esp for text)

I'm in the process of trying to see if I can keep getting vefontcache even more performant... Making it multi-threaded can help but there might be some single-thread per still possible..
This commit is contained in:
2025-01-01 14:13:30 -05:00
parent c7d465d06e
commit 5559d62826
20 changed files with 659 additions and 564 deletions

View File

@ -310,7 +310,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
{
profile("screen ui")
ui_startup( & screen_ui.base, cache_allocator = persistent_slab_allocator() )
ui_startup( & screen_ui.base, cache_table_size = 2 * Kilo, cache_allocator = persistent_slab_allocator() )
ui_floating_startup( & screen_ui.floating, 1 * Kilobyte, 1 * Kilobyte, persistent_slab_allocator(), "screen ui floating manager" )
using screen_ui
@ -348,7 +348,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
// }
// Setup workspace UI state
ui_startup( & workspace.ui, cache_allocator = persistent_slab_allocator() )
ui_startup( & workspace.ui, cache_table_size = 8 * Kilo, cache_allocator = persistent_slab_allocator() )
}
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/Lorem Ipsum (197).txt", allocator = persistent_slab_allocator())

View File

@ -106,8 +106,9 @@ render_mode_2d_workspace :: proc( screen_extent : Vec2, cam : Camera, input : In
cam := cam
when UI_Render_Method == .Layers {
render_list := array_to_slice( ui.render_list )
render_ui_via_box_list( render_list, screen_extent, ve_ctx, ve_render, & cam )
render_list_box := array_to_slice( ui.render_list_box )
render_list_text := array_to_slice( ui.render_list_text )
render_ui_via_box_list( render_list_box, render_list_text, screen_extent, ve_ctx, ve_render, & cam )
}
when UI_Render_Method == .Depth_First
{
@ -281,8 +282,10 @@ render_screen_ui :: proc( screen_extent : Extents2, ui : ^UI_State, ve_ctx : ^ve
render_set_view_space(screen_extent)
when UI_Render_Method == .Layers {
render_list := array_to_slice( ui.render_list )
render_ui_via_box_list( render_list, screen_extent, ve_ctx, ve_render )
render_list_box := array_to_slice( ui.render_list_box )
render_list_text := array_to_slice( ui.render_list_text )
render_ui_via_box_list( render_list_box, render_list_text, screen_extent, ve_ctx, ve_render )
// render_ui_via_box_list( render_list, screen_extent, ve_ctx, ve_render )
}
when UI_Render_Method == .Depth_First
{
@ -468,7 +471,8 @@ render_ui_via_box_tree :: proc( ui : ^UI_State, screen_extent : Vec2, ve_ctx : ^
}
previous_layer : i32 = 0
for box := ui.root.first; box != nil; box = ui_box_tranverse_next_depth_first( box, bypass_intersection_test = false, ctx = ui )
for box := ui_box_tranverse_next_depth_first( ui.root, bypass_intersection_test = true, ctx = ui ); box != nil;
box = ui_box_tranverse_next_depth_first( box, bypass_intersection_test = true, ctx = ui )
{
if box.ancestors != previous_layer {
if shape_enqueued do render_flush_gp()
@ -555,68 +559,102 @@ render_ui_via_box_tree :: proc( ui : ^UI_State, screen_extent : Vec2, ve_ctx : ^
if text_enqueued do render_text_layer( screen_extent, ve_ctx, ve_render )
}
render_ui_via_box_list :: proc( render_list : []UI_RenderBoxInfo, screen_extent : Vec2, ve_ctx : ^ve.Context, ve_render : VE_RenderData, cam : ^Camera = nil )
render_ui_via_box_list :: proc( box_list : []UI_RenderBoxInfo, text_list : []UI_RenderTextInfo, screen_extent : Vec2, ve_ctx : ^ve.Context, ve_render : VE_RenderData, cam : ^Camera = nil )
{
profile(#procedure)
debug := get_state().debug
default_font := get_state().default_font
text_enqueued : b32 = false
shape_enqueued : b32 = false
cam_zoom_ratio := cam != nil ? 1.0 / cam.zoom : 1.0
circle_radius := cam != nil ? cam_zoom_ratio * 3 : 3
for entry, id in render_list
box_id : i32 = 0
text_id : i32 = 0
layer_left : b32 = true
for layer_left
{
already_passed_signal := id > 0 && render_list[ id - 1 ].layer_signal
if !already_passed_signal && entry.layer_signal
profile("layer")
shape_enqueued : b32 = false
box_layer_done : b32 = false
for box_id < cast(i32) len(box_list) && ! box_layer_done
{
// profile("render ui layer")
render_flush_gp()
if text_enqueued do render_text_layer( screen_extent, ve_ctx, ve_render )
continue
}
using entry
profile("GP_Render")
box_layer_done = b32(box_id > 0) && box_list[ box_id - 1 ].layer_signal
// profile("enqueue box")
entry := box_list[box_id]
GP_Render:
{
// profile("draw_shapes")
if style.bg_color.a != 0
corner_radii_total : f32 = 0
for radius in entry.corner_radii do corner_radii_total += radius
if entry.bg_color.a != 0
{
render_set_color( style.bg_color )
draw_rect( bounds )
render_set_color( entry.bg_color )
if corner_radii_total > 0 do draw_rect_rounded( entry.bounds, entry.corner_radii, 16 )
else do draw_rect( entry.bounds)
shape_enqueued = true
}
if style.border_color.a != 0 && border_width > 0 {
render_set_color( style.border_color )
draw_rect_border( bounds, border_width )
if entry.border_color.a != 0 && entry.border_width > 0
{
render_set_color( entry.border_color )
if corner_radii_total > 0 do draw_rect_rounded_border( entry.bounds, entry.corner_radii, entry.border_width, 16 )
else do draw_rect_border( entry.bounds, entry.border_width )
shape_enqueued = true
}
if debug.draw_ui_box_bounds_points
{
render_set_color(Color_Red)
draw_filled_circle(bounds.min.x, bounds.min.y, 3, 24)
draw_filled_circle(entry.bounds.min.x, entry.bounds.min.y, circle_radius, 24)
render_set_color(Color_Blue)
draw_filled_circle(bounds.max.x, bounds.max.y, 3, 24)
draw_filled_circle(entry.bounds.max.x, entry.bounds.max.y, circle_radius, 24)
shape_enqueued = true
}
box_id += 1
}
if len(text.str) > 0 && style.font.key != 0 {
if cam != nil {
draw_text_string_pos_extent_zoomed( text.str, default_font, font_size, computed.text_pos, cam^, style.text_color )
}
else {
draw_text_string_pos_extent( text.str, default_font, font_size, computed.text_pos, style.text_color )
}
text_enqueued = true
if shape_enqueued {
profile("render ui box_layer")
render_flush_gp()
shape_enqueued = false
}
text_enqueued : b32 = false
text_layer_done : b32 = false
for text_id < cast(i32) len(text_list) && ! text_layer_done
{
profile("Text_Render")
text_layer_done = b32(text_id > 0) && text_list[ text_id - 1 ].layer_signal
entry := text_list[text_id]
font := entry.font.key != 0 ? entry.font : default_font
if len(entry.text) > 0
{
if cam != nil {
draw_text_string_pos_extent_zoomed( entry.text, font, entry.font_size, entry.position, cam^, entry.color )
}
else {
draw_text_string_pos_extent( entry.text, font, entry.font_size, entry.position, entry.color )
}
text_enqueued = true
}
text_id += 1
}
if text_enqueued {
profile("render ui text layer")
if text_enqueued do render_text_layer( screen_extent, ve_ctx, ve_render )
text_enqueued = false
}
layer_left = box_id < cast(i32) len(box_list) && text_id < cast(i32) len(text_list)
}
if shape_enqueued do render_flush_gp()
if text_enqueued do render_text_layer( screen_extent, ve_ctx, ve_render )
}
#region("Helpers")

View File

@ -46,8 +46,6 @@ font_provider_startup :: proc( ctx : ^FontProviderContext )
ve.startup( & ve_ctx, .STB_TrueType, allocator = persistent_slab_allocator() )
ve_ctx.glyph_buffer.over_sample = { 4,4 }
log("VEFontCached initialized")
// provider_data.ve_ctx.debug_print = true
// provider_data.ve_ctx.debug_print_verbose = true
font_provider_setup_sokol_gfx_objects( & render, ve_ctx )
}

View File

@ -64,7 +64,7 @@ UI_Style_Stack_Size :: 512
UI_Parent_Stack_Size :: 512
// UI_Built_Boxes_Array_Size :: 8
UI_Built_Boxes_Array_Size :: 56 * Kilobyte
UI_BoxCache_TableSize :: 8 * Kilobyte
UI_BoxCache_TableSize :: 8 * Kilobyte
UI_RenderEntry :: struct {
info : UI_RenderBoxInfo,
@ -75,14 +75,32 @@ UI_RenderEntry :: struct {
UI_RenderLayer :: DLL_NodeFL(UI_RenderEntry)
// UI_RenderBoxInfo :: struct {
// using computed : UI_Computed,
// using style : UI_Style,
// text : StrRunesPair,
// font_size : UI_Scalar,
// border_width : UI_Scalar,
// label : StrRunesPair,
// layer_signal : b32,
// }
UI_RenderBoxInfo :: struct {
using computed : UI_Computed,
using style : UI_Style,
text : StrRunesPair,
font_size : UI_Scalar,
border_width : UI_Scalar,
label : StrRunesPair,
layer_signal : b32,
bounds : Range2,
corner_radii : [Corner.Count]f32,
bg_color : RGBA8,
border_color : RGBA8,
border_width : UI_Scalar,
layer_signal : b8,
}
UI_RenderTextInfo :: struct {
text : string,
position : Vec2,
color : RGBA8,
font : FontID,
font_size : f32,
layer_signal : b8
}
UI_RenderMethod :: enum u32 {
@ -90,7 +108,7 @@ UI_RenderMethod :: enum u32 {
Layers,
}
UI_Render_Method :: UI_RenderMethod.Depth_First
UI_Render_Method :: UI_RenderMethod.Layers
// TODO(Ed): Rename to UI_Context
UI_State :: struct {
@ -104,10 +122,15 @@ UI_State :: struct {
prev_cache : ^HMapChained( UI_Box ),
curr_cache : ^HMapChained( UI_Box ),
// TODO(Ed): DO WE ACTUALLY NEED THIS?
spacial_indexing_method : UI_SpacialIndexingMethod,
// For rendering via a set of layers organized into a single command list
// render_queue_builder : SubArena,
render_queue : Array(UI_RenderLayer),
render_list : Array(UI_RenderBoxInfo),
// render_queue : Array(UI_RenderLayer),
// render_list : Array(UI_RenderBoxInfo),
render_list_box : Array(UI_RenderBoxInfo),
render_list_text : Array(UI_RenderTextInfo),
null_box : ^UI_Box, // This was used with the Linked list interface...
root : ^UI_Box,
@ -138,13 +161,13 @@ UI_State :: struct {
#region("Lifetime")
ui_startup :: proc( ui : ^ UI_State, cache_allocator : Allocator /* , cache_reserve_size : u64 */ )
ui_startup :: proc( ui : ^ UI_State, spacial_indexing_method : UI_SpacialIndexingMethod = .QuadTree, cache_allocator : Allocator, cache_table_size : uint )
{
ui := ui
ui^ = {}
for & cache in ui.caches {
box_cache, allocation_error := make( HMapChained(UI_Box), UI_BoxCache_TableSize, cache_allocator )
box_cache, allocation_error := make( HMapChained(UI_Box), cache_table_size, cache_allocator )
verify( allocation_error == AllocatorError.None, "Failed to allocate box cache" )
cache = box_cache
}
@ -153,11 +176,17 @@ ui_startup :: proc( ui : ^ UI_State, cache_allocator : Allocator /* , cache_rese
allocation_error : AllocatorError
ui.render_queue, allocation_error = make( Array(UI_RenderLayer), 32, cache_allocator )
verify( allocation_error == AllocatorError.None, "Failed to allcate render_queue")
// ui.render_queue, allocation_error = make( Array(UI_RenderLayer), 32, cache_allocator )
// verify( allocation_error == AllocatorError.None, "Failed to allcate render_queue")
ui.render_list, allocation_error = make( Array(UI_RenderBoxInfo), UI_Built_Boxes_Array_Size, cache_allocator, fixed_cap = true )
verify( allocation_error == AllocatorError.None, "Failed to allocate rener_list" )
// ui.render_list, allocation_error = make( Array(UI_RenderBoxInfo), UI_Built_Boxes_Array_Size, cache_allocator, fixed_cap = true )
// verify( allocation_error == AllocatorError.None, "Failed to allocate rener_list" )
ui.render_list_box, allocation_error = make( Array(UI_RenderBoxInfo), UI_Built_Boxes_Array_Size, cache_allocator, fixed_cap = true )
verify( allocation_error == AllocatorError.None, "Failed to allocate rener_list_box" )
ui.render_list_text, allocation_error = make( Array(UI_RenderTextInfo), UI_Built_Boxes_Array_Size, cache_allocator, fixed_cap = true )
verify( allocation_error == AllocatorError.None, "Failed to allocate rener_list_box" )
log("ui_startup completed")
}
@ -168,8 +197,10 @@ ui_reload :: proc( ui : ^ UI_State, cache_allocator : Allocator )
for & cache in ui.caches {
hmap_chained_reload( cache, cache_allocator)
}
ui.render_queue.backing = cache_allocator
ui.render_list.backing = cache_allocator
// ui.render_queue.backing = cache_allocator
// ui.render_list.backing = cache_allocator
ui.render_list_box.backing = cache_allocator
ui.render_list_text.backing = cache_allocator
}
// TODO(Ed) : Is this even needed?
@ -186,8 +217,10 @@ ui_graph_build_begin :: proc( ui : ^ UI_State, bounds : Vec2 = {} )
stack_clear( & layout_combo_stack )
stack_clear( & style_combo_stack )
array_clear( render_queue )
array_clear( render_list )
// array_clear( render_queue )
// array_clear( render_list )
array_clear( render_list_box )
array_clear( render_list_text )
curr_cache, prev_cache = swap( curr_cache, prev_cache )
@ -210,6 +243,7 @@ ui_graph_build_end :: proc( ui : ^UI_State )
state := get_state()
ui_parent_pop() // Should be ui_context.root
assert(stack_peek(& ui.parent_stack) == nil)
Post_Build_Graph_Traversal:
{
@ -225,196 +259,68 @@ ui_graph_build_end :: proc( ui : ^UI_State )
computed.content = computed.bounds
}
previous_layer : i32 = 1
// Auto-layout and initial render_queue generation
profile_begin("Auto-layout and render_queue generation")
render_queue := array_to_slice(ui.render_queue)
for current := root.first; current != nil; current = ui_box_traverse_next_breadth_first( current, bypass_intersection_test = true )
// render_queue := array_to_slice(ui.render_queue)
for current := ui.root.first; current != nil;
current = ui_box_tranverse_next_depth_first( current, bypass_intersection_test = true, ctx = ui )
{
if ! current.computed.fresh {
ui_box_compute_layout( current )
}
when UI_Render_Method == .Layers
{
if ! intersects_range2(ui_view_bounds(ui), current.computed.bounds) {
continue
}
// TODO(Ed): Eventually put this into a sub-arena
entry, error := new(UI_RenderEntry)
(entry^) = UI_RenderEntry {
info = {
current.computed,
current.style,
current.text,
current.layout.font_size,
current.layout.border_width,
current.label,
false,
},
layer_id = current.ancestors -1,
}
when true {
// entry : UI_RenderBoxInfo = {
// current.computed,
// current.style,
// current.text,
// current.layout.font_size,
// current.layout.border_width,
// current.label,
// false,
// }
entry_box := UI_RenderBoxInfo {
bounds = current.computed.bounds,
corner_radii = current.style.corner_radii,
bg_color = current.style.bg_color,
border_color = current.style.border_color,
border_width = current.layout.border_width,
}
entry_text := UI_RenderTextInfo {
text = current.text.str,
position = current.computed.text_pos,
color = current.style.text_color,
font = current.style.font,
font_size = current.layout.font_size,
}
if entry.layer_id >= i32(ui.render_queue.num) {
append( & ui.render_queue, UI_RenderLayer {})
render_queue = array_to_slice(ui.render_queue)
}
if current.ancestors != previous_layer {
entry_box .layer_signal = true
entry_text.layer_signal = true
}
// else if layer.last == nil {
// layer.first.next = entry
// entry.prev = layer.first
// layer.last = entry
// }
// push_back to next layer
layer := & render_queue[entry.layer_id]
if layer.first == nil {
layer.first = entry
layer.last = entry
}
else {
layer.last.next = entry
entry.prev = layer.last
layer.last = entry
}
// dll_full_push_back( layer, entry, nil )
// If there is a parent entry, give it a reference to the child entry
parent_entry : ^UI_RenderEntry
if entry.layer_id > 0 {
parent_layer := & render_queue[entry.layer_id - 1]
parent_entry = parent_layer.last
entry.parent = parent_entry
if parent_entry.first == nil {
parent_entry.first = entry
parent_entry.last = entry
}
else {
parent_entry.last = entry
}
// dll_fl_append( parent_entry, entry )
}
array_append(& ui.render_list_box, entry_box)
array_append(& ui.render_list_text, entry_text)
previous_layer = current.ancestors
}
}
profile_end()
profile("render_list generation")
when UI_Render_Method == .Layers
{
// render_queue overlap corrections & render_list generation
render_queue = array_to_slice(ui.render_queue)
for layer_id : i32 = 0; layer_id < i32(ui.render_queue.num); layer_id += 1
{
layer := & ui.render_queue.data[ layer_id ]
append( & ui.render_list, UI_RenderBoxInfo { layer_signal = true })
to_increment, error := make( Array(^UI_RenderEntry), 4 * Kilo )
verify( error == .None, "Faied to make to_increment array.")
to_inc_last_iterated : i32 = 0
for entry := layer.first; entry != nil; entry = entry.next
{
for neighbor := entry.next; neighbor != nil; neighbor = neighbor.next
{
if ! overlap_range2( entry.info.computed.bounds, neighbor.info.computed.bounds) do continue
append( & to_increment, neighbor )
} // for neighbor := entry.next; neighbor != nil; neighbor = neighbor.next
if entry == to_increment.data[ to_inc_last_iterated ] {
to_inc_last_iterated += 1
}
else {
// This entry stayed in this layer, we can append the value
array_append_value( & ui.render_list, entry.info )
}
} // for entry := layer.first; entry != nil; entry = entry.next
// Move overlaping entries & their children's by 1 layer
to_inc_slice := array_to_slice(to_increment)
for entry in to_inc_slice
{
pop_layer := render_queue[entry.layer_id]
entry.layer_id += 1
if entry.layer_id >= i32(ui.render_queue.num) {
append( & ui.render_queue, UI_RenderLayer {} )
render_queue = array_to_slice(ui.render_queue)
}
push_layer := render_queue[entry.layer_id]
// pop entry from layer
prev := entry.prev
prev.next = entry.next
if entry == pop_layer.last {
pop_layer.last = prev
}
// push entry to next layer
if push_layer.first == nil {
push_layer.first = entry
push_layer.last = entry
}
else {
push_layer.last.next = entry
entry.prev = push_layer.last
push_layer.last = entry
entry.next = nil
}
// else if push_layer.last == nil {
// push_layer.last = entry
// entry.prev = push_layer.first
// push_layer.first.next = entry
// entry.next = nil
// }
// increment children's layers
if entry.first != nil
{
for child := entry.first; child != nil; child = ui_render_entry_tranverse( child )
{
pop_layer := render_queue[child.layer_id]
child.layer_id += 1
if child.layer_id >= i32(ui.render_queue.num) {
append( & ui.render_queue, UI_RenderLayer {})
render_queue = array_to_slice(ui.render_queue)
}
push_layer := render_queue[child.layer_id]
// pop from current layer
if child == pop_layer.first {
pop_layer.first = nil
}
if child == pop_layer.last {
pop_layer.last = child.prev
}
// push_back to next layer
if push_layer.first == nil {
push_layer.first = child
push_layer.last = child
}
else {
push_layer.last.next = child
child.prev = push_layer.last
push_layer.last = child
}
// else if push_layer.last == nil {
// push_layer.first.next = child
// child.prev = push_layer.first
// push_layer.last = child
// }
} // for child := neighbor.first; child != nil; child = ui_render_entry_traverse_depth( child )
} // if entry.first != nil
} // for entry in to_inc_slice
} // for & layer in render_queue
}
render_list := array_to_slice(ui.render_list)
// render_list := array_to_slice(ui.render_list)
render_list_box := array_to_slice(ui.render_list_box)
render_list_text := array_to_slice(ui.render_list_text)
}
get_state().ui_context = nil
}
// TODO(Ed): Review usage if at all.
ui_render_entry_tranverse :: proc( entry : ^UI_RenderEntry ) -> ^UI_RenderEntry
{
// using state := get_state()

View File

@ -0,0 +1,29 @@
package sectr
UI_SpacialIndexingMethod :: enum(i32) {
QuadTree,
SpacialHash,
}
ui_collision_register :: proc( box : ^UI_Box )
{
}
ui_collision_query :: proc ( box : ^UI_Box ) -> DLL_NodePN(UI_Box) {
return {}
}
QuadTree_Tile :: struct {
}
QuadTree :: struct
{
boundary : Range2,
}
SpacialHashMap :: struct {
}

View File

@ -216,11 +216,17 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
else if .Order_Children_Bottom_To_Top in layout.flags {
ui_layout_children_vertically( box, .Bottom_To_Top )
}
if computed.fresh {
ui_collision_register( box )
}
}
ui_compute_children_overall_bounds :: proc ( box : ^UI_Box ) -> ( children_bounds : Range2 )
{
for current := box.first; current != nil && current.prev != box; current = ui_box_tranverse_next_depth_first( current, parent_limit = box )
// for current := box.first; current != nil && current.prev != box; current = ui_box_tranverse_next_depth_first( current, parent_limit = box )
for current := ui_box_tranverse_next_depth_first( box, parent_limit = box, bypass_intersection_test = false ); current != nil;
current = ui_box_tranverse_next_depth_first( current, parent_limit = box, bypass_intersection_test = false )
{
if current == box do return
if ! current.computed.fresh do ui_box_compute_layout( current )
@ -236,7 +242,9 @@ ui_compute_children_overall_bounds :: proc ( box : ^UI_Box ) -> ( children_bound
ui_box_compute_layout_children :: proc( box : ^UI_Box )
{
// for current := box.first; current != nil && current.prev != box; current = ui_box_tranverse_next_depth_first( current, parent_limit = box )
for current := box.first; current != nil && current.prev != box; current = ui_box_traverse_next_breadth_first( current )
// for current := box.first; current != nil && current.prev != box; current = ui_box_traverse_next_breadth_first( current )
for current := ui_box_tranverse_next_depth_first( box, parent_limit = box, bypass_intersection_test = false ); current != nil;
current = ui_box_tranverse_next_depth_first( current, parent_limit = box, bypass_intersection_test = false )
{
if current == box do return
if current.computed.fresh do continue

View File

@ -202,6 +202,7 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
line_id += 1
continue
}
profile("line")
ui_layout( text_layout )
line_hbox := ui_widget(str_fmt( "line %v", line_id ), {.Mouse_Clickable})

View File

@ -153,7 +153,7 @@ ui_hbox_begin :: proc( direction : UI_LayoutDirection_X, label : string, flags :
ui_hbox_end :: proc( hbox : UI_HBox, width_ref : ^f32 = nil, compute_layout := false )
{
// profile(#procedure)
if compute_layout do ui_box_compute_layout(hbox.box, dont_mark_fresh = true)
// if compute_layout do ui_box_compute_layout(hbox.box, dont_mark_fresh = true)
// ui_layout_children_horizontally( hbox.box, hbox.direction, width_ref )
}
@ -773,7 +773,7 @@ ui_vbox_begin :: proc( direction : UI_LayoutDirection_Y, label : string, flags :
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, dont_mark_fresh = true)
// if compute_layout do ui_box_compute_layout(vbox, dont_mark_fresh = true)
switch direction {
case .Top_To_Bottom:
vbox.layout.flags |= { .Order_Children_Top_To_Bottom }
@ -786,7 +786,7 @@ ui_vbox_begin :: proc( direction : UI_LayoutDirection_Y, label : string, flags :
// Auto-layout children
ui_vbox_end :: proc( vbox : UI_VBox, height_ref : ^f32 = nil, compute_layout := false ) {
// profile(#procedure)
if compute_layout do ui_box_compute_layout(vbox, dont_mark_fresh = true)
// if compute_layout do ui_box_compute_layout(vbox, dont_mark_fresh = true)
// ui_layout_children_vertically( vbox.box, vbox.direction, height_ref )
}