General codebase refactor & cleanup

Renamed HashTable to HMapZPL, with procs having the zpl_ namespace prefix.
(I want to eventually get away from using it)

Started to use the grime pattern for library aliasing better.
This commit is contained in:
2024-02-27 07:50:57 -05:00
parent c9dc5fe54a
commit 4deee942a8
28 changed files with 752 additions and 613 deletions

View File

@ -138,30 +138,34 @@ UI_Layout :: struct {
corner_radii : [Corner.Count]f32,
// TODO(Ed) I problably won't use this as I can determine
// the size of content manually when needed and make helper procs...
// size_to_content : b32,
// TODO(Ed) : Add support for this
size_to_content : b32,
size : Vec2,
}
size : Vec2,
UI_BoxState :: enum {
Disabled,
Default,
Hovered,
Focused,
}
UI_Style :: struct {
bg_color : Color,
overlay_color : Color,
border_color : Color,
bg_color : Color,
border_color : Color,
// blur_size : f32,
blur_size : f32,
font : FontID,
font_size : f32,
text_color : Color,
text_alignment : UI_TextAlign,
// text_wrap_width_pixels : f32,
// text_wrap_width_percent : f32,
font : FontID,
font_size : f32,
text_color : Color,
text_alignment : UI_TextAlign,
// cursors : [CursorKind.Count]UI_Cursor,
// active_cursor : ^UI_Cursor,
// hover_cursor : ^ UI_Cursor,
cursor : UI_Cursor,
layout : UI_Layout,
transition_time : f32,
}
UI_TextAlign :: enum u32 {
@ -171,124 +175,239 @@ UI_TextAlign :: enum u32 {
Count
}
UI_Box :: struct {
first, last, prev, next : ^ UI_Box,
num_children : i32,
flags : UI_BoxFlags,
key : UI_Key,
label : string,
computed : UI_Computed,
layout : UI_Layout,
style : UI_Style,
// Persistent Data
UI_InteractState :: struct {
hot_time : f32,
active_time : f32,
disabled_time : f32,
}
Layout_Stack_Size :: 512
Style_Stack_Size :: 512
UI_Box :: struct {
// Cache ID
key : UI_Key,
label : string,
// Regenerated per frame.
first, last, prev, next, parent : ^ UI_Box,
num_children : i32,
flags : UI_BoxFlags,
computed : UI_Computed,
style : UI_Style,
// Persistent Data
// prev_computed : UI_Computed,
// prev_style : UI_Style,
mouse : UI_InteractState,
keyboard : UI_InteractState,
}
UI_Layout_Stack_Size :: 512
UI_Style_Stack_Size :: 512
UI_Parent_Stack_Size :: 1024
UI_Built_Boxes_Array_Size :: Kilobyte * 8
UI_FramePassKind :: enum {
Generate,
Compute,
Logical,
}
UI_State :: struct {
box_cache : HashTable( UI_Box ),
// TODO(Ed) : Use these
build_arenas : [2]Arena,
build_arena : ^ Arena,
built_box_count : i32,
caches : [2] HMapZPL( UI_Box ),
prev_cache : ^ HMapZPL( UI_Box ),
curr_cache : ^ HMapZPL( UI_Box ),
root : ^ UI_Box,
// Do we need to recompute the layout?
layout_dirty : b32,
layout_stack : Stack( UI_Layout, Layout_Stack_Size ),
style_stack : Stack( UI_Style, Style_Stack_Size ),
hot : UI_Key,
active : UI_Key,
clipboard_copy_key : UI_Key,
// TODO(Ed) : Look into using a build arena like Ryan does for these possibly (and thus have a linked-list stack)
style_stack : Stack( UI_Style, UI_Style_Stack_Size ),
parent_stack : Stack( ^ UI_Box, UI_Parent_Stack_Size ),
hot : UI_Key,
active : UI_Key,
clipboard_copy : UI_Key,
last_clicked : UI_Key,
drag_start_mouse : Vec2,
// drag_state_arena : ^ Arena,
// drag_state data : string,
}
ui_key_from_string :: proc ( value : string ) -> UI_Key {
ui_key_from_string :: proc( value : string ) -> UI_Key {
key := cast(UI_Key) crc32( transmute([]byte) value )
return key
}
ui_box_equal :: proc ( a, b : ^ UI_Box ) -> b32 {
ui_box_equal :: proc( a, b : ^ UI_Box ) -> b32 {
BoxSize :: size_of(UI_Box)
hash_a := crc32( transmute([]u8) slice_ptr( a, BoxSize ) )
hash_b := crc32( transmute([]u8) slice_ptr( b, BoxSize ) )
result : b32 = hash_a == hash_b
result : b32 = true
result &= a.key == b.key // We assume for now the label is the same as the key, if not something is terribly wrong.
result &= a.flags == b.flags
return result
}
ui_startup :: proc ( ui : ^ UI_State, cache_allocator : Allocator ) {
ui_startup :: proc( ui : ^ UI_State, cache_allocator : Allocator )
{
ui := ui
ui^ = {}
box_cache, allocation_error := hashtable_init_reserve( UI_Box, cache_allocator, Kilobyte * 8 )
verify( allocation_error != AllocatorError.None, "Failed to allocate box cache" )
ui.box_cache = box_cache
for cache in (& ui.caches) {
box_cache, allocation_error := zpl_hmap_init_reserve( UI_Box, cache_allocator, UI_Built_Boxes_Array_Size )
verify( allocation_error == AllocatorError.None, "Failed to allocate box cache" )
cache = box_cache
}
ui.curr_cache = & ui.caches[1]
ui.prev_cache = & ui.caches[0]
}
ui_reload :: proc ( ui : ^ UI_State, cache_allocator : Allocator ) {
ui_reload :: proc( ui : ^ UI_State, cache_allocator : Allocator )
{
// We need to repopulate Allocator references
ui.box_cache.entries.allocator = cache_allocator
ui.box_cache.hashes.allocator = cache_allocator
for cache in & ui.caches {
cache.entries.allocator = cache_allocator
cache.hashes.allocator = cache_allocator
}
}
// TODO(Ed) : Is this even needed?
ui_shutdown :: proc () {
ui_shutdown :: proc() {
}
ui_graph_build_begin :: proc ( ui : ^ UI_State )
ui_graph_build_begin :: proc( ui : ^ UI_State, bounds : Vec2 = {} )
{
ui_context := & get_state().ui_context
ui_context = ui
using ui_context
get_state().ui_context = ui
using get_state().ui_context
box : UI_Box = {}
box.label = "root#001"
box.key = ui_key_from_string( box.label )
box.layout = stack_peek( & layout_stack ) ^
box.style = stack_peek( & style_stack ) ^
swap( & curr_cache, & prev_cache )
cached_box := hashtable_get( & box_cache, cast(u64) box.key )
root = ui_box_make( {}, "root#001" )
ui_parent_push(root)
if cached_box != nil {
layout_dirty &= ! ui_box_equal( & box, cached_box )
log("BUILD GRAPH BEGIN")
}
// TODO(Ed) :: Is this even needed?
ui_graph_build_end :: proc()
{
ui_parent_pop()
// Regenerate the computed layout if dirty
// ui_compute_layout()
get_state().ui_context = nil
log("BUILD GRAPH END")
}
@(deferred_none = ui_graph_build_end)
ui_graph_build :: proc( ui : ^ UI_State ) {
ui_graph_build_begin( ui )
}
ui_parent_push :: proc( ui : ^ UI_Box ) {
stack := & get_state().ui_context.parent_stack
stack_push( & get_state().ui_context.parent_stack, ui )
}
ui_parent_pop :: proc() {
// If size_to_content is set, we need to compute the layout now.
// Check to make sure that the parent's children are the same for this frame,
// if its not we need to mark the layout as dirty.
stack_pop( & get_state().ui_context.parent_stack )
}
@(deferred_none = ui_parent_pop)
ui_parent :: proc( ui : ^ UI_Box) {
ui_parent_push( ui )
}
ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
{
using get_state().ui_context
key := ui_key_from_string( label )
curr_box : (^ UI_Box)
prev_box := zpl_hmap_get( prev_cache, cast(u64) key )
{
set_result : ^ UI_Box
set_error : AllocatorError
if prev_box != nil {
// Previous history was found, copy over previous state.
set_result, set_error = zpl_hmap_set( curr_cache, cast(u64) key, (prev_box ^) )
}
else {
box : UI_Box
box.key = key
box.label = label
set_result, set_error = zpl_hmap_set( curr_cache, cast(u64) key, box )
}
verify( set_error == AllocatorError.None, "Failed to set zpl_hmap due to allocator error" )
curr_box = set_result
}
if prev_box != nil {
layout_dirty &= ! ui_box_equal( curr_box, prev_box )
}
else {
layout_dirty = true
}
set_result, set_error: = hashtable_set( & box_cache, cast(u64) box.key, box )
verify( set_error != AllocatorError.None, "Failed to set hashtable due to allocator error" )
root = set_result
curr_box.flags = flags
curr_box.style = ( stack_peek( & style_stack ) ^ )
curr_box.parent = ( stack_peek( & parent_stack ) ^ )
// If there is a parent, setup the relevant references
if curr_box.parent != nil
{
// dbl_linked_list_push_back( box.parent, nil, box )
curr_box.parent.last = curr_box
if curr_box.parent.first == nil {
curr_box.parent.first = curr_box
}
}
return curr_box
}
ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
{
return nil
ui_set_layout :: proc ( layout : UI_Layout ) {
log("LAYOUT SET")
}
ui_layout_push :: proc ( preset : UI_Layout ) {
ui_compute_layout :: proc() {
// TODO(Ed) : This generates the bounds for each box.
}
ui_layout_pop :: proc () {
ui_layout_set_size :: proc( size : Vec2 ) {
}
ui_layout_push_size :: proc( size : Vec2 ) {
ui_style_push :: proc( preset : UI_Style ) {
log("STYLE PUSH")
stack_push( & get_state().ui_context.style_stack, preset )
}
ui_style_push :: proc ( preset : UI_Style ) {
ui_style_pop :: proc() {
log("STYLE POP")
stack_pop( & get_state().ui_context.style_stack )
}
@(deferred_none = ui_style_pop)
ui_style :: proc( preset : UI_Style ) {
ui_style_push( preset )
}