Memory fixes, progress towards anchors support in the UI auto-layout

Also support for margins
This commit is contained in:
Edward R. Gonzalez 2024-03-12 20:55:29 -04:00
parent d2daa686d4
commit 159aedb592
16 changed files with 229 additions and 93 deletions

View File

@ -59,23 +59,48 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
alignment := uint(mem.DEFAULT_ALIGNMENT)
policy_ptr := & default_slab_policy
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 4 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 32 * Megabyte, 16 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 32 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 64 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 128 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 256 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 512 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 1 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 2 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 4 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 8 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 16 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 32 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 256 * Megabyte, 64 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 256 * Megabyte, 128 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 512 * Megabyte, 256 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment })
if false
{
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 4 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 32 * Megabyte, 16 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 32 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 64 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 128 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 256 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 512 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 1 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 2 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 4 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 8 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 16 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 32 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 256 * Megabyte, 64 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 256 * Megabyte, 128 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 512 * Megabyte, 256 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment })
}
else
{
push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 1 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 256 * Kilobyte, 2 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 512 * Kilobyte, 4 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 1 * Megabyte, 16 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 1 * Megabyte, 32 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 1 * Megabyte, 64 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 128 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 256 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 512 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 1 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 2 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 4 * Megabyte, 4 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 8 * Megabyte, 8 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 16 * Megabyte, 16 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 32 * Megabyte, 32 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 64 * Megabyte, 64 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 128 * Megabyte, 128 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 256 * Megabyte, 256 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment })
}
alloc_error : AllocatorError
persistent_slab, alloc_error = slab_init( policy_ptr, allocator = persistent_allocator() )

View File

@ -8,6 +8,7 @@ pos_within_range2 :: proc( pos : Vec2, range : Range2 ) -> b32 {
return b32(within_x && within_y)
}
// TODO(Ed): Do we need this? Also does it even work (looks unfinished)?
is_within_screenspace :: proc( pos : Vec2 ) -> b32 {
state := get_state(); using state
screen_extent := state.app_window.extent

View File

@ -98,6 +98,7 @@ font_load :: proc( path_file : string,
) -> FontID
{
profile(#procedure)
log( str_fmt_tmp("Loading font: %v", path_file))
font_provider_data := & get_state().font_provider_data; using font_provider_data
font_data, read_succeded : = os.read_entire_file( path_file, context.temp_allocator )

View File

@ -4,6 +4,7 @@ package sectr
import "base:builtin"
copy :: builtin.copy
import "base:intrinsics"
mem_zero :: intrinsics.mem_zero
ptr_sub :: intrinsics.ptr_sub
type_has_field :: intrinsics.type_has_field
type_elem_type :: intrinsics.type_elem_type

View File

@ -14,6 +14,7 @@ The pool doesn't allocate any buckets on initialization unless the user specifes
package sectr
import "core:mem"
import "core:slice"
Pool :: struct {
using header : ^PoolHeader,
@ -32,9 +33,9 @@ PoolHeader :: struct {
}
PoolBucket :: struct {
blocks : [^]byte,
next_block : uint,
using nodes : DLL_NodePN( PoolBucket),
next_block : uint,
blocks : [^]byte
}
Pool_FreeBlock :: struct {
@ -86,6 +87,7 @@ pool_destroy :: proc ( using self : Pool )
pool_allocate_buckets :: proc( using self : Pool, num_buckets : uint ) -> AllocatorError
{
profile(#procedure)
pool := self
if num_buckets == 0 {
return .Invalid_Argument
}
@ -103,6 +105,8 @@ pool_allocate_buckets :: proc( using self : Pool, num_buckets : uint ) -> Alloca
bucket := cast( ^PoolBucket) next_bucket_ptr
bucket.blocks = memory_after_header(bucket)
bucket.next_block = 0
log( str_fmt_tmp("Pool allocated block: %p capacity: %d", raw_data(bucket_memory), bucket_capacity))
if self.bucket_list.first == nil {
self.bucket_list.first = bucket
@ -111,20 +115,22 @@ pool_allocate_buckets :: proc( using self : Pool, num_buckets : uint ) -> Alloca
else {
dll_push_back( & self.bucket_list.last, bucket )
}
log( str_fmt_tmp("Bucket List First: %p", self.bucket_list.first))
next_bucket_ptr = next_bucket_ptr[ bucket_capacity: ]
}
return alloc_error
}
pool_grab :: proc( using pool : Pool ) -> ( block : []byte, alloc_error : AllocatorError )
pool_grab :: proc( using pool : Pool, zero_memory := false ) -> ( block : []byte, alloc_error : AllocatorError )
{
pool := pool
// profile(#procedure)
alloc_error = .None
// Check the free-list first for a block
if free_list_head != nil {
if free_list_head != nil
{
head := & pool.free_list_head
// Compiler Bug? Fails to compile
@ -135,7 +141,8 @@ pool_grab :: proc( using pool : Pool ) -> ( block : []byte, alloc_error : Alloca
pool.free_list_head = pool.free_list_head.next // ll_pop
block = slice_ptr( cast([^]byte) last_free, int(pool.block_size) )
block = byte_slice( cast([^]byte) last_free, int(pool.block_size) )
log( str_fmt_tmp("Returning free block: %p %d", raw_data(block), pool.block_size))
return
}
@ -164,10 +171,12 @@ pool_grab :: proc( using pool : Pool ) -> ( block : []byte, alloc_error : Alloca
// if current_bucket.next != nil {
if pool.current_bucket.next != nil {
// current_bucket = current_bucket.next
log( str_fmt_tmp("Bucket %p exhausted using %p", pool.current_bucket, pool.current_bucket.next))
pool.current_bucket = pool.current_bucket.next
}
else
{
log( "All previous buckets exhausted, allocating new bucket")
alloc_error := pool_allocate_buckets( pool, 1 )
if alloc_error != .None {
ensure(false, "Failed to allocate bucket")
@ -180,8 +189,12 @@ pool_grab :: proc( using pool : Pool ) -> ( block : []byte, alloc_error : Alloca
// Compiler Bug
// block = slice_ptr( current_bucket.blocks[ current_bucket.next_block:], int(block_size) )
// self.current_bucket.next_block += block_size
block = slice_ptr( pool.current_bucket.blocks[ pool.current_bucket.next_block:], int(block_size) )
block = byte_slice( pool.current_bucket.blocks[ pool.current_bucket.next_block:], int(block_size) )
pool.current_bucket.next_block += block_size
if zero_memory {
slice.zero(block)
}
return
}

View File

@ -106,27 +106,34 @@ slab_alloc :: proc( using self : Slab,
{
// profile(#procedure)
pool : Pool
for id in 0 ..< pools.idx {
id : u32 = 0
for ; id < pools.idx; id += 1 {
pool = pools.items[id]
if pool.block_size >= size && pool.alignment >= alignment {
break
}
}
verify( id < pools.idx, "There is not a size class in the slab's policy to satisfy the requested allocation" )
verify( pool.header != nil, "Requested alloc not supported by the slab allocator", location = loc )
block : []byte
block, alloc_error = pool_grab(pool)
if alloc_error != .None {
ensure(false, "Bad block from pool")
return nil, alloc_error
}
log( str_fmt_tmp("Retrieved block: %p %d", raw_data(block), len(block) ))
if zero_memory {
slice.zero(block)
}
// if zero_memory {
// slice.zero(block)
// }
data = byte_slice(raw_data(block), size)
if zero_memory {
slice.zero(data)
}
return
}
@ -177,11 +184,14 @@ slab_resize :: proc( using self : Slab,
// Resize will keep block in the same size_class, just give it more of its already allocated block
if pool_old == pool_resize
{
new_data = byte_slice( raw_data(data), new_size )
new_data_ptr := memory_after(data)
new_data = byte_slice( raw_data(data), new_size )
log( str_fmt_tmp("Resize via expanding block space allocation %p %d", new_data_ptr, int(new_size - old_size)))
if zero_memory && new_size > old_size {
to_zero := slice_ptr( memory_after(data), int(new_size - old_size) )
to_zero := byte_slice( memory_after(data), int(new_size - old_size) )
slice.zero( to_zero )
log( str_fmt_tmp("Zeroed memory - Range(%p to %p)", new_data_ptr, int(new_size - old_size)))
}
return
}
@ -189,11 +199,18 @@ slab_resize :: proc( using self : Slab,
// We'll need to provide an entirely new block, so the data will need to be copied over.
new_block : []byte
new_block, alloc_error = pool_grab( pool_resize )
if alloc_error != .None do return
if zero_memory {
slice.zero( new_block )
if new_block == nil {
ensure(false, "Retreived a null block")
return
}
if alloc_error != .None do return
// if zero_memory {
// slice.zero( new_block )
// }
log( str_fmt_tmp("Resize via new block: %p %d (old : %p $d )", raw_data(new_block), len(new_block), raw_data(data), old_size ))
if raw_data(data) != raw_data(new_block) {
copy_non_overlapping( raw_data(new_block), raw_data(data), int(old_size) )
pool_release( pool_old, data )

View File

@ -30,16 +30,16 @@ str_cache_init :: proc( /*allocator : Allocator*/ ) -> ( cache : StringCache ) {
policy : SlabPolicy
policy_ptr := & policy
push( policy_ptr, SlabSizeClass { 8 * Megabyte, 16, alignment })
push( policy_ptr, SlabSizeClass { 8 * Megabyte, 32, alignment })
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 64, alignment })
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 128, alignment })
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 256, alignment })
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 512, alignment })
push( policy_ptr, SlabSizeClass { 32 * Megabyte, 1 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 32 * Megabyte, 4 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 16 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 32 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 16, alignment })
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 32, alignment })
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 64, alignment })
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 128, alignment })
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 256, alignment })
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 512, alignment })
push( policy_ptr, SlabSizeClass { 1 * Megabyte, 1 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 4 * Megabyte, 4 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 16 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 32 * Megabyte, 32 * Kilobyte, alignment })
// push( policy_ptr, SlabSizeClass { 64 * Megabyte, 64 * Kilobyte, alignment })
// push( policy_ptr, SlabSizeClass { 64 * Megabyte, 128 * Kilobyte, alignment })
// push( policy_ptr, SlabSizeClass { 64 * Megabyte, 256 * Kilobyte, alignment })

View File

@ -23,11 +23,11 @@ import "core:sync"
VArena_GrowthPolicyProc :: #type proc( commit_used, committed, reserved, requested_size : uint ) -> uint
VArena :: struct {
using vmem : VirtualMemoryRegion,
commit_used : uint,
growth_policy : VArena_GrowthPolicyProc,
allow_any_reize : b32,
mutex : sync.Mutex,
using vmem : VirtualMemoryRegion,
commit_used : uint,
growth_policy : VArena_GrowthPolicyProc,
allow_any_reize : b32,
mutex : sync.Mutex,
}
varena_default_growth_policy :: proc( commit_used, committed, reserved, requested_size : uint ) -> uint
@ -74,8 +74,8 @@ varena_init :: proc( base_address : uintptr, to_reserve, to_commit : uint,
return
}
arena.vmem = vmem
arena.commit_used = 0
arena.vmem = vmem
arena.commit_used = 0
if growth_policy == nil {
arena.growth_policy = varena_default_growth_policy
@ -145,12 +145,21 @@ varena_alloc :: proc( using self : ^VArena,
data_ptr := rawptr(current_offset + uintptr(alignment_offset))
data = byte_slice( data_ptr, int(requested_size) )
self.commit_used += size_to_allocate
self.commit_used += size_to_allocate
alloc_error = .None
if zero_memory {
slice.zero( data )
log_backing : [Kilobyte * 16]byte
backing_slice := byte_slice( & log_backing[0], len(log_backing))
// log( str_fmt_buffer( backing_slice, "varena alloc - BASE: %p PTR: %X, SIZE: %d", cast(rawptr) self.base_address, & data[0], requested_size) )
if zero_memory
{
// log( str_fmt_buffer( backing_slice, "Zeroring data (Range: %p to %p)", raw_data(data), cast(rawptr) (uintptr(raw_data(data)) + uintptr(requested_size))))
// slice.zero( data )
mem_zero( data_ptr, int(requested_size) )
}
return
}
@ -229,6 +238,9 @@ varena_allocator_proc :: proc(
verify( old_memory_offset == current_offset || arena.allow_any_reize,
"Cannot resize existing allocation in vitual arena to a larger size unless it was the last allocated" )
log_backing : [Kilobyte * 16]byte
backing_slice := byte_slice( & log_backing[0], len(log_backing))
if old_memory_offset != current_offset && arena.allow_any_reize
{
// Give it new memory and copy the old over. Old memory is unrecoverable until clear.
@ -242,6 +254,7 @@ varena_allocator_proc :: proc(
copy_non_overlapping( raw_data(new_region), old_memory, int(old_size) )
data = new_region
// log( str_fmt_tmp("varena resize (new): old: %p %v new: %p %v", old_memory, old_size, (& data[0]), size))
return
}
@ -254,6 +267,7 @@ varena_allocator_proc :: proc(
}
data = byte_slice( old_memory, size )
// log( str_fmt_tmp("varena resize (expanded): old: %p %v new: %p %v", old_memory, old_size, (& data[0]), size))
return
case .Query_Features:

View File

@ -97,6 +97,7 @@ when ODIN_OS == runtime.Odin_OS_Type.Windows
Path_Sectr_Debug_Symbols :: "sectr.pdb"
}
// TODO(Ed): Disable the default allocators for the host, we'll be handling it instead.
RuntimeState :: struct {
running : b32,
client_memory : ClientMemory,

View File

@ -8,7 +8,7 @@ import str "core:strings"
import "core:time"
import core_log "core:log"
Max_Logger_Message_Width :: 300
Max_Logger_Message_Width :: 180
LogLevel :: core_log.Level

View File

@ -118,6 +118,9 @@ PWS_LexerData :: struct {
pws_parser_lex :: proc ( text : string, allocator : Allocator ) -> ( PWS_LexResult, AllocatorError )
{
bytes := transmute([]byte) text
log( str_fmt_tmp( "lexing: %v ...", (len(text) > 30 ? transmute(string) bytes[ :30] : text) ))
profile(#procedure)
using lexer : PWS_LexerData
context.user_ptr = & lexer
@ -235,6 +238,9 @@ PWS_ParseData :: struct {
pws_parser_parse :: proc( text : string, allocator : Allocator ) -> ( PWS_ParseResult, AllocatorError )
{
bytes := transmute([]byte) text
log( str_fmt_tmp( "parsing: %v ...", (len(text) > 30 ? transmute(string) bytes[ :30] : text) ))
profile(#procedure)
using parser : PWS_ParseData
context.user_ptr = & result

View File

@ -204,22 +204,22 @@ update :: proc( delta_time : f64 ) -> b32
.Fixed_Width, .Fixed_Height,
}
default_layout := UI_Layout {
anchor = {},
// alignment = { 0.0, 0.5 },
alignment = { 0.0, 0.0 },
anchor = {},
alignment = { 0.0, 0.0 },
text_alignment = { 0.0, 0.0 },
// alignment = { 1.0, 1.0 },
// corner_radii = { 0.3, 0.3, 0.3, 0.3 },
pos = { 0, 0 },
size = { 200, 200 },
corner_radii = { 0.2, 0.2, 0.2, 0.2 },
pos = { 0, 0 },
size = { 200, 200 },
}
frame_style_default := UI_Style {
flags = frame_style_flags,
bg_color = Color_BG_TextBox,
font = default_font,
font_size = 30,
font = default_font,
font_size = 30,
text_color = Color_White,
layout = default_layout,
}
@ -230,19 +230,53 @@ update :: proc( delta_time : f64 ) -> b32
frame_style_default,
}}
frame_theme.disabled.bg_color = Color_Frame_Disabled
frame_theme.hovered.bg_color = Color_Frame_Hover
frame_theme.focused.bg_color = Color_Frame_Select
frame_theme.hot.bg_color = Color_Frame_Hover
frame_theme.active.bg_color = Color_Frame_Select
ui_style_theme( frame_theme )
config.ui_resize_border_width = 2.5
test_draggable()
// test_draggable()
// test_text_box()
// Test Parenting
// test_parenting()
if true
{
parent_layout := default_layout
parent_layout.size = { 300, 300 }
parent_layout.alignment = { 0.0, 0.0 }
ui_style_theme_set_layout( parent_layout )
parent := ui_widget( "Parent", { .Mouse_Clickable })
ui_parent(parent)
{
if parent.first_frame {
debug.draggable_box_pos = parent.style.layout.pos + { 0, -100 }
debug.draggable_box_size = parent.style.layout.size
}
if parent.dragging {
debug.draggable_box_pos += mouse_world_delta()
}
parent.style.layout.pos = debug.draggable_box_pos
}
child_layout := default_layout
child_layout.size = { 100, 100 }
child_layout.alignment = { 0.5, 0.5 }
child_layout.margins = { 20, 20, 20, 20 }
child_layout.anchor = range2( { 0.5, 0.5 }, { 0.5, 0.5 })
child_theme := frame_style_default
// child_theme.flags = {}
child_theme.layout = child_layout
ui_theme_via_style(child_theme)
child := ui_widget( "Child", { .Mouse_Clickable })
}
// Whitespace AST test
when false
if true
{
profile("Whitespace AST test")
@ -260,8 +294,8 @@ update :: proc( delta_time : f64 ) -> b32
}}
text_theme.default.bg_color = Color_Transparent
text_theme.disabled.bg_color = Color_Frame_Disabled
text_theme.hovered.bg_color = Color_Frame_Hover
text_theme.focused.bg_color = Color_Frame_Select
text_theme.hot.bg_color = Color_Frame_Hover
text_theme.active.bg_color = Color_Frame_Select
layout_text := default_layout

View File

@ -144,13 +144,15 @@ UI_Layout :: struct {
pos : Vec2,
// TODO(Ed) : Should everything no matter what its parent is use a WS_Pos instead of a raw vector pos?
// TODO(Ed): Support a min/max range for the size of a box
size : Vec2,
// size : Range2
// If the box is a child of the root parent, its automatically in world space and thus will use the tile_pos.
tile_pos : WS_Pos,
// TODO(Ed) : Add support for size_to_content?
size_to_text : b8,
// TODO(Ed) : Add support for size_to_content?
// size_to_content : b8,
}
@ -187,8 +189,8 @@ UI_StyleFlags :: bit_set[UI_StyleFlag; u32]
UI_StylePreset :: enum u32 {
Default,
Disabled,
Hovered,
Focused,
Hot,
Active,
Count,
}
@ -214,7 +216,7 @@ UI_Style :: struct {
UI_StyleTheme :: struct #raw_union {
array : [UI_StylePreset.Count] UI_Style,
using styles : struct {
default, disabled, hovered, focused : UI_Style,
default, disabled, hot, active : UI_Style,
}
}
@ -258,8 +260,8 @@ UI_Box :: struct {
// UI_BoxFlags_Stack_Size :: 512
UI_Layout_Stack_Size :: 512
UI_Style_Stack_Size :: 512
UI_Parent_Stack_Size :: 1024 * 10
UI_Built_Boxes_Array_Size :: 1024 * 10
UI_Parent_Stack_Size :: 512
UI_Built_Boxes_Array_Size :: Kilobyte * 5
UI_State :: struct {
// TODO(Ed) : Use these
@ -313,6 +315,7 @@ ui_startup :: proc( ui : ^ UI_State, cache_allocator : Allocator )
ui.curr_cache = & ui.caches[1]
ui.prev_cache = & ui.caches[0]
log("ui_startup completed")
}
ui_reload :: proc( ui : ^ UI_State, cache_allocator : Allocator )
@ -374,7 +377,6 @@ ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
}
curr_box.flags = flags
curr_box.parent = stack_peek( & parent_stack )
// Clear old links
curr_box.parent = nil
@ -394,7 +396,7 @@ ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
return curr_box
}
ui_box_tranverse_next :: #force_inline proc "contextless" ( box : ^ UI_Box ) -> (^ UI_Box)
ui_box_tranverse_next :: proc "contextless" ( box : ^ UI_Box ) -> (^ UI_Box)
{
// If current has children, do them first
if box.first != nil {
@ -509,7 +511,7 @@ ui_parent_pop :: proc() {
}
@(deferred_none = ui_parent_pop)
ui_parent :: proc( ui : ^ UI_Box) {
ui_parent :: proc( ui : ^UI_Box) {
ui_parent_push( ui )
}
@ -542,6 +544,11 @@ ui_style_theme :: proc( preset : UI_StyleTheme ) {
ui_style_theme_push( preset )
}
@(deferred_none = ui_style_theme_pop)
ui_theme_via_style :: proc ( style : UI_Style ) {
ui_style_theme_push( UI_StyleTheme { styles = { style, style, style, style } })
}
ui_style_theme_set_layout :: proc ( layout : UI_Layout ) {
for & preset in stack_peek_ref( & get_state().ui_context.theme_stack ).array {
preset.layout = layout

View File

@ -31,21 +31,36 @@ ui_compute_layout :: proc()
layout := & style.layout
margins := range2(
parent_content.p0 + { layout.margins.left, layout.margins.top },
parent_content.p1 - { layout.margins.right, layout.margins.bottom },
{ layout.margins.left, -layout.margins.top },
{ -layout.margins.right, layout.margins.bottom },
)
margined_bounds := range2(
parent_content.p0 + margins.p0,
parent_content.p1 + margins.p1,
)
margined_size := margined_bounds.p1 - margined_bounds.p0
anchored_bounds := range2(
margined_bounds.p0 + margined_size * layout.anchor.p0,
margined_bounds.p0 + margined_size * layout.anchor.p1,
)
anchored_size := Vec2 {
anchored_bounds.max.x - anchored_bounds.min.x,
anchored_bounds.max.y - anchored_bounds.min.y,
}
anchor := & layout.anchor
pos : Vec2
if UI_StyleFlag.Fixed_Position_X in style.flags {
pos.x = layout.pos.x
pos.x -= margins.p0.x * anchor.x0
pos.x += margins.p0.x * anchor.x1
pos.x += anchored_bounds.p0.x
}
if UI_StyleFlag.Fixed_Position_Y in style.flags {
pos.y = layout.pos.y
pos.y -= margins.p1.y * anchor.y0
pos.y += margins.p1.y * anchor.y1
pos.y += anchored_bounds.p0.y
}
text_size : Vec2
@ -53,7 +68,8 @@ ui_compute_layout :: proc()
// if computed.text_size.y == style.font_size {
if current.first_frame || ! style.size_to_text || computed.text_size.y != size_range2(computed.bounds).y {
text_size = cast(Vec2) measure_text_size( current.text.str, style.font, style.font_size, 0 )
} else {
}
else {
text_size = computed.text_size
}
@ -62,14 +78,14 @@ ui_compute_layout :: proc()
size.x = layout.size.x
}
else {
// TODO(Ed) : Not sure what todo here...
size.x = anchored_size.x
}
if UI_StyleFlag.Fixed_Height in style.flags {
size.y = layout.size.y
}
else {
// TODO(Ed) : Not sure what todo here...
size.y = anchored_size.y
}
if style.size_to_text {

View File

@ -173,7 +173,7 @@ ui_signal_from_box :: proc ( box : ^ UI_Box ) -> UI_Signal
box.prev_style = box.style
box.style_delta = 0
}
box.style = stack_peek( & ui.theme_stack ).hovered
box.style = stack_peek( & ui.theme_stack ).hot
}
if is_active
{
@ -182,7 +182,7 @@ ui_signal_from_box :: proc ( box : ^ UI_Box ) -> UI_Signal
box.style_delta = 0
log( str_fmt_tmp("NEW ACTIVE: %v", box.label.str))
}
box.style = stack_peek( & ui.theme_stack ).focused
box.style = stack_peek( & ui.theme_stack ).active
}
if is_disabled
{

View File

@ -160,8 +160,8 @@ push-location $path_root
$build_args += $flag_build_mode_dll
$build_args += $flag_output_path + $module_dll
# $build_args += ($flag_collection + $pkg_collection_thirdparty)
$build_args += $flag_micro_architecture_native
$build_args += $flag_use_separate_modules
# $build_args += $flag_micro_architecture_native
# $build_args += $flag_use_separate_modules
$build_args += $flag_thread_count + $CoreCount_Physical
$build_args += $flag_optimize_none
# $build_args += $flag_optimize_minimal