improve layout visibile lag to none for vbox & hbox on the settings menu
This commit is contained in:
parent
a29632daea
commit
fd2552a82f
@ -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
|
||||
}
|
||||
|
@ -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" )
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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 )
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 )
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 ^
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user