Memory fixes, progress towards anchors support in the UI auto-layout
Also support for margins
This commit is contained in:
parent
d2daa686d4
commit
159aedb592
@ -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() )
|
||||
|
@ -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
|
||||
|
@ -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 )
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 )
|
||||
|
@ -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 })
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
25
code/ui.odin
25
code/ui.odin
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user