Got this thing to compile and seem operable at runtime
There was quite a few errors with the hashtable (not suprised). I need to use it more to see if it fails to work properly. For now it should be fine enough for prototyping
This commit is contained in:
		| @@ -143,13 +143,8 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^ | ||||
| 			// 	projection = rl.CameraProjection.ORTHOGRAPHIC, | ||||
| 			// } | ||||
|  | ||||
| 			frame_1.color  = Color_BG_TextBox | ||||
| 			box_set_size( & frame_1, { 100, 50 } * CM_Per_Point ) | ||||
|  | ||||
| 			frame_2.color = Color_BG_TextBox_Green | ||||
| 			box_set_size( & frame_2, { 60, 100 } * CM_Per_Point ) | ||||
|  | ||||
|  | ||||
| 			// Setup workspace UI state | ||||
| 			ui_startup( & workspace.ui, persistent_allocator() ) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -208,6 +203,9 @@ reload :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^ L | ||||
| 	// font_provider_data := & get_state().font_provider_data | ||||
| 	// font_provider_data.font_cache.allocator = arena_allocator( & font_provider_data.font_arena ) | ||||
|  | ||||
| 	// Have to reload allocators for all dynamic allocating data-structures. | ||||
| 	ui_reload( & get_state().project.workspace.ui, persistent_allocator() ) | ||||
|  | ||||
| 	log("Module reloaded") | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -115,6 +115,11 @@ State :: struct { | ||||
| 	font_squidgy_slimes          : FontID, | ||||
| 	font_rec_mono_semicasual_reg : FontID, | ||||
| 	default_font                 : FontID, | ||||
|  | ||||
| 	// There are two potential UI contextes for this prototype so far, | ||||
| 	// the screen-space UI and the current workspace UI. | ||||
| 	// This is used so that the ui api doesn't need to have the user pass the context every single time. | ||||
| 	ui_context : UI_State, | ||||
| } | ||||
|  | ||||
| get_state :: proc "contextless" () -> ^ State { | ||||
|   | ||||
| @@ -4,12 +4,14 @@ package sectr | ||||
|  | ||||
| import "base:builtin" | ||||
| import "base:runtime" | ||||
| import c "core:c/libc" | ||||
| import "core:hash" | ||||
| import "core:mem" | ||||
| import "core:mem/virtual" | ||||
| import "core:os" | ||||
| import "core:path/filepath" | ||||
|  | ||||
| import c "core:c/libc" | ||||
|  | ||||
| Byte     :: 1 | ||||
| Kilobyte :: 1024 * Byte | ||||
| Megabyte :: 1024 * Kilobyte | ||||
| @@ -32,6 +34,7 @@ terabyte  :: proc ( tb : $ integer_type ) -> integer_type { | ||||
| } | ||||
|  | ||||
| copy                    :: builtin.copy | ||||
| crc32                   :: hash.crc32 | ||||
| Allocator               :: mem.Allocator | ||||
| AllocatorError          :: mem.Allocator_Error | ||||
| alloc                   :: mem.alloc | ||||
| @@ -53,6 +56,39 @@ get_bounds :: proc { | ||||
| 	view_get_bounds, | ||||
| } | ||||
|  | ||||
| //region Stack - Basic fixed-size stack container | ||||
| Stack :: struct ( $ Type : typeid, $ Size : i32 ) { | ||||
| 	idx   : i32, | ||||
| 	items : [ Size ] Type, | ||||
| } | ||||
|  | ||||
| stack_push :: proc( stack : ^ $ StackType / Stack( $ Type, $ Size ), value : Type ) { | ||||
| 	using stack | ||||
| 	verify( idx < len( items ), "Attempted to push on a full stack" ) | ||||
|  | ||||
| 	items[ idx ] = value | ||||
| 	idx += 1 | ||||
| } | ||||
|  | ||||
| stack_pop :: proc( stack : ^ $ StackType / Stack( $ Type, $ Size ) ) { | ||||
| 	using stack | ||||
| 	verify( idx > 0, "Attempted to pop an empty stack" ) | ||||
|  | ||||
| 	idx -= 1 | ||||
| } | ||||
|  | ||||
| stack_peek :: proc ( stack : ^ Stack( $ Type, $ Size ) ) -> ^ Type { | ||||
| 	using stack | ||||
| 	return & items[idx] | ||||
| } | ||||
| //endregion Stack | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| // TODO(Ed) : This is extremely jank, Raylib requires a 'heap' allocator with the way it works. | ||||
|   | ||||
| @@ -6,6 +6,7 @@ package sectr | ||||
|  | ||||
| import "core:c/libc" | ||||
| import "core:mem" | ||||
| import "core:slice" | ||||
|  | ||||
| Array :: struct ( $ Type : typeid ) { | ||||
| 	allocator : Allocator, | ||||
| @@ -28,7 +29,7 @@ array_init :: proc( $ Type : typeid, allocator : Allocator ) -> ( Array(Type), A | ||||
|  | ||||
| array_init_reserve :: proc( $ Type : typeid, allocator : Allocator, capacity : u64 ) -> ( Array(Type), AllocatorError ) | ||||
| { | ||||
| 	raw_data, result_code = alloc( capacity * size_of(Type), allocator = allocator ) | ||||
| 	raw_data, result_code := alloc( int(capacity) * size_of(Type), allocator = allocator ) | ||||
| 	result : Array( Type) | ||||
| 	result.data      = cast( [^] Type ) raw_data | ||||
| 	result.allocator = allocator | ||||
| @@ -157,6 +158,10 @@ array_fill :: proc ( array : ^ Array( $ Type ), begin, end : u64, value : Type ) | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	// TODO(Ed) : Bench this? | ||||
| 	// data_slice := slice_ptr( ptr_offset( data, begin ), end - begin ) | ||||
| 	// slice.fill( data_slice, cast(int) value ) | ||||
|  | ||||
| 	for id := begin; id < end; id += 1 { | ||||
| 		data[ id ] = value | ||||
| 	} | ||||
| @@ -172,7 +177,7 @@ array_free :: proc( array : ^ Array( $ Type ) ) { | ||||
| array_grow :: proc( array : ^ Array( $ Type ), min_capacity : u64 ) -> AllocatorError | ||||
| { | ||||
| 	using array | ||||
| 	new_capacity = grow_formula( capacity ) | ||||
| 	new_capacity := array_grow_formula( capacity ) | ||||
|  | ||||
| 	if new_capacity < min_capacity { | ||||
| 		new_capacity = min_capacity | ||||
| @@ -211,7 +216,7 @@ array_resize :: proc ( array : ^ Array( $ Type ), num : u64 ) -> AllocatorError | ||||
| { | ||||
| 	if array.capacity < num | ||||
| 	{ | ||||
| 		grow_result := array_grow( array, capacity ) | ||||
| 		grow_result := array_grow( array, array.capacity ) | ||||
| 		if grow_result != AllocatorError.None { | ||||
| 			return grow_result | ||||
| 		} | ||||
| @@ -225,14 +230,14 @@ array_set_capacity :: proc( array : ^ Array( $ Type ), new_capacity : u64 ) -> A | ||||
| { | ||||
| 	using array | ||||
| 	if new_capacity == capacity { | ||||
| 		return true | ||||
| 		return AllocatorError.None | ||||
| 	} | ||||
| 	if new_capacity < num { | ||||
| 		num = new_capacity | ||||
| 		return true | ||||
| 		return AllocatorError.None | ||||
| 	} | ||||
|  | ||||
| 	raw_data, result_code = alloc( new_capacity * size_of(Type), allocator = allocator ) | ||||
| 	raw_data, result_code := alloc( cast(int) new_capacity * size_of(Type), allocator = allocator ) | ||||
| 	data     = cast( [^] Type ) raw_data | ||||
| 	capacity = new_capacity | ||||
| 	return result_code | ||||
|   | ||||
| @@ -3,6 +3,9 @@ | ||||
| // with hot-reloads... | ||||
| package sectr | ||||
|  | ||||
| import "core:slice" | ||||
|  | ||||
|  | ||||
| // Note(Ed) : See core:hash for hasing procs. | ||||
|  | ||||
| // This might be problematic... | ||||
| @@ -17,11 +20,11 @@ HT_FindResult :: struct { | ||||
|  | ||||
| HashTable_Entry :: struct ( $ Type : typeid) { | ||||
| 	key   : u64, | ||||
| 	next  : u64, | ||||
| 	next  : i64, | ||||
| 	value : Type, | ||||
| } | ||||
|  | ||||
| HashTable :: struct ( $ Type : typeid) { | ||||
| HashTable :: struct ( $ Type : typeid ) { | ||||
| 	hashes  : Array( i64 ), | ||||
| 	entries : Array( HashTable_Entry(Type) ), | ||||
| } | ||||
| @@ -30,7 +33,7 @@ hashtable_init :: proc( $ Type : typeid, allocator : Allocator ) -> ( HashTable( | ||||
| 	return hashtable_init_reserve( Type, allocator ) | ||||
| } | ||||
|  | ||||
| hashtable_init_reserve :: proc ( $ Type : typeid, allcoator : Allocator, num : u64 ) -> ( HashTable( Type), AllocatorError ) | ||||
| hashtable_init_reserve :: proc ( $ Type : typeid, allocator : Allocator, num : u64 ) -> ( HashTable( Type), AllocatorError ) | ||||
| { | ||||
| 	result                        : HashTable(Type) | ||||
| 	hashes_result, entries_result : AllocatorError | ||||
| @@ -40,8 +43,11 @@ hashtable_init_reserve :: proc ( $ Type : typeid, allcoator : Allocator, num : u | ||||
| 		ensure( false, "Failed to allocate hashes array" ) | ||||
| 		return result, hashes_result | ||||
| 	} | ||||
| 	array_resize( & result.hashes, num ) | ||||
| 	slice.fill( slice_ptr( result.hashes.data, cast(int) result.hashes.num), -1 ) | ||||
| 	// array_fill( result.hashes, 0, num - 1, -1 ) | ||||
|  | ||||
| 	result.entries, entries_result = array_init_reserve( allocator, num ) | ||||
| 	result.entries, entries_result = array_init_reserve( HashTable_Entry(Type), allocator, num ) | ||||
| 	if entries_result != AllocatorError.None { | ||||
| 		ensure( false, "Failed to allocate entries array" ) | ||||
| 		return result, entries_result | ||||
| @@ -59,10 +65,10 @@ hashtable_clear :: proc( ht : ^ HashTable( $ Type ) ) { | ||||
| 	array_clear( entries ) | ||||
| } | ||||
|  | ||||
| hashtable_destroy :: proc( ht : ^ HashTable( $ Type ) ) { | ||||
| 	if hashes.data && hashes.capacity { | ||||
| 		array_free( hashes ) | ||||
| 		array_free( entries ) | ||||
| hashtable_destroy :: proc( using ht : ^ HashTable( $ Type ) ) { | ||||
| 	if hashes.data != nil && hashes.capacity > 0 { | ||||
| 		array_free( & hashes ) | ||||
| 		array_free( & entries ) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -70,9 +76,9 @@ hashtable_get :: proc( ht : ^ HashTable( $ Type ), key : u64 ) -> ^ Type | ||||
| { | ||||
| 	using ht | ||||
|  | ||||
| 	id := hashtable_find( key ).entry_index | ||||
| 	id := hashtable_find( ht, key ).entry_index | ||||
| 	if id >= 0 { | ||||
| 		return & entries[id].value | ||||
| 		return & entries.data[id].value | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| @@ -95,11 +101,12 @@ hashtable_map_mut :: proc( ht : ^ HashTable( $ Type), map_proc : HT_MapMutProc ) | ||||
| } | ||||
|  | ||||
| hashtable_grow :: proc( ht : ^ HashTable( $ Type ) ) -> AllocatorError { | ||||
| 	using ht | ||||
| 	new_num := array_grow_formula( entries.num ) | ||||
| 	return rehash( ht, new_num ) | ||||
| 	return hashtable_rehash( ht, new_num ) | ||||
| } | ||||
|  | ||||
| hashtable_rehash :: proc ( ht : ^ HashTable( $ Type ), new_num : i64 ) -> AllocatorError | ||||
| hashtable_rehash :: proc ( ht : ^ HashTable( $ Type ), new_num : u64 ) -> AllocatorError | ||||
| { | ||||
| 	last_added_index : i64 | ||||
|  | ||||
| @@ -109,30 +116,27 @@ hashtable_rehash :: proc ( ht : ^ HashTable( $ Type ), new_num : i64 ) -> Alloca | ||||
| 		return init_result | ||||
| 	} | ||||
|  | ||||
| 	for id := 0; id < new_ht.hashes.num; id += 1 { | ||||
| 		new_ht.hashes[id] = -1 | ||||
| 	} | ||||
| 	// for id : u64 = 0; id < new_ht.hashes.num; id += 1 { | ||||
| 	// 	new_ht.hashes.data[id] = -1 | ||||
| 	// } | ||||
| 	slice.fill( slice_ptr( new_ht.hashes.data, cast(int) new_ht.hashes.num ), -1 ) | ||||
|  | ||||
| 	for id := 0; id < ht.entries.num; id += 1 { | ||||
| 	for id : u64 = 0; id < ht.entries.num; id += 1 { | ||||
| 		find_result : HT_FindResult | ||||
|  | ||||
| 		if new_ht.hashes.num == 0 { | ||||
| 			hashtable_grow( new_ht ) | ||||
| 		} | ||||
|  | ||||
| 		entry            = & entries[id] | ||||
| 		entry           := & ht.entries.data[id] | ||||
| 		find_result      = hashtable_find( & new_ht, entry.key ) | ||||
| 		last_added_index = hashtable_add_entry( & new_ht, entry.key ) | ||||
|  | ||||
| 		if find_result.prev_index < 0 { | ||||
| 			new_ht.hashes[ find_result.hash_index ] = last_added_index | ||||
| 			new_ht.hashes.data[ find_result.hash_index ] = last_added_index | ||||
| 		} | ||||
| 		else { | ||||
| 			new_ht.hashes[ find_result.prev_index ].next = last_added_index | ||||
| 			new_ht.entries.data[ find_result.prev_index ].next = last_added_index | ||||
| 		} | ||||
|  | ||||
| 		new_ht.entries[ last_added_index ].next  = find_result.entry_index | ||||
| 		new_ht.entries[ last_added_index ].value = entry.value | ||||
| 		new_ht.entries.data[ last_added_index ].next  = find_result.entry_index | ||||
| 		new_ht.entries.data[ last_added_index ].value = entry.value | ||||
| 	} | ||||
|  | ||||
| 	hashtable_destroy( ht ) | ||||
| @@ -177,22 +181,22 @@ hashtable_remove_entry :: proc( ht : ^ HashTable( $ Type ), id : i64 ) { | ||||
| 	array_remove_at( & ht.entries, id ) | ||||
| } | ||||
|  | ||||
| hashtable_set :: proc( ht : ^ HashTable( $ Type), key : u64, value : Type ) -> AllocatorError | ||||
| hashtable_set :: proc( ht : ^ HashTable( $ Type), key : u64, value : Type ) -> (^ Type, AllocatorError) | ||||
| { | ||||
| 	using ht | ||||
|  | ||||
| 	id          := 0 | ||||
| 	id          : i64 = 0 | ||||
| 	find_result : HT_FindResult | ||||
|  | ||||
| 	if hashes.num == 0 | ||||
| 	if hashtable_full( ht ) | ||||
| 	{ | ||||
| 		grow_result := hashtable_grow( ht ) | ||||
| 		grow_result := hashtable_grow(ht) | ||||
| 		if grow_result != AllocatorError.None { | ||||
| 			return grow_result | ||||
| 				return nil, grow_result | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	find_result = hashtable_find( key ) | ||||
| 	find_result = hashtable_find( ht, key ) | ||||
| 	if find_result.entry_index >= 0 { | ||||
| 		id = find_result.entry_index | ||||
| 	} | ||||
| @@ -200,26 +204,26 @@ hashtable_set :: proc( ht : ^ HashTable( $ Type), key : u64, value : Type ) -> A | ||||
| 	{ | ||||
| 		id = hashtable_add_entry( ht, key ) | ||||
| 		if find_result.prev_index >= 0 { | ||||
| 			entries[ find_result.prev_index ].next = id | ||||
| 			entries.data[ find_result.prev_index ].next = id | ||||
| 		} | ||||
| 		else { | ||||
| 			hashes[ find_result.hash_index ] = id | ||||
| 			hashes.data[ find_result.hash_index ] = id | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	entries[id].value = value | ||||
| 	entries.data[id].value = value | ||||
|  | ||||
| 	if hashtable_full( ht ) { | ||||
| 		return hashtable_grow( ht ) | ||||
| 		return & entries.data[id].value, hashtable_grow( ht ) | ||||
| 	} | ||||
|  | ||||
| 	return AllocatorError.None | ||||
| 	return & entries.data[id].value, AllocatorError.None | ||||
| } | ||||
|  | ||||
| hashtable_slot :: proc( ht : ^ HashTable( $ Type), key : u64 ) -> i64 { | ||||
| 	using ht | ||||
| 	for id := 0; id < hashes.num; id += 1 { | ||||
| 		if hashes[id] == key                { | ||||
| 	for id : i64 = 0; id < hashes.num; id += 1 { | ||||
| 		if hashes.data[id] == key                { | ||||
| 			return id | ||||
| 		} | ||||
| 	} | ||||
| @@ -228,33 +232,34 @@ hashtable_slot :: proc( ht : ^ HashTable( $ Type), key : u64 ) -> i64 { | ||||
|  | ||||
| hashtable_add_entry :: proc( ht : ^ HashTable( $ Type), key : u64 ) -> i64 { | ||||
| 	using ht | ||||
| 	entry : HashTable_Entry = { key, -1 } | ||||
| 	id    := entries.num | ||||
| 	array_append( entries, entry ) | ||||
| 	entry : HashTable_Entry(Type) = { key, -1, {} } | ||||
| 	id    := cast(i64) entries.num | ||||
| 	array_append( & entries, entry ) | ||||
| 	return id | ||||
| } | ||||
|  | ||||
| hashtable_find :: proc( ht : ^ HashTable( $ Type), key : u64 ) -> HT_FindResult | ||||
| { | ||||
| 	using ht | ||||
| 	find_result : HT_FindResult = { -1, -1, -1 } | ||||
| 	result : HT_FindResult = { -1, -1, -1 } | ||||
|  | ||||
| 	if hashes.num > 0 { | ||||
| 		result.hash_index  = key % hash.num | ||||
| 		result.entry_index = hashes[ result.hash_index ] | ||||
| 		result.hash_index  = cast(i64)( key % hashes.num ) | ||||
| 		result.entry_index = hashes.data[ result.hash_index ] | ||||
|  | ||||
| 		for ; result.entry_index >= 0;                { | ||||
| 			if entries[ result.entry_index ].key == key { | ||||
| 		for ; result.entry_index >= 0;                     { | ||||
| 			if entries.data[ result.entry_index ].key == key { | ||||
| 				break | ||||
| 			} | ||||
|  | ||||
| 			result.prev_index  = result.entry_index | ||||
| 			result.entry_index = entries[ result.entry_index ].next | ||||
| 			result.entry_index = entries.data[ result.entry_index ].next | ||||
| 		} | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| hashtable_full :: proc( ht : ^ HashTable( $ Type) ) -> b32 { | ||||
| 	return 0.75 * hashes.num < entries.num | ||||
| hashtable_full :: proc( using ht : ^ HashTable( $ Type) ) -> b32 { | ||||
| 	result : b32 = entries.num > u64(0.75 * cast(f64) hashes.num) | ||||
| 	return result | ||||
| } | ||||
|   | ||||
| @@ -176,8 +176,14 @@ update :: proc( delta_time : f64 ) -> b32 | ||||
|  | ||||
| 	//region Imgui Tick | ||||
| 	{ | ||||
| 		// Layout  | ||||
| 		ui_context := & state.project.workspace.ui | ||||
|  | ||||
| 		// Build Graph (Determines if layout is dirty) | ||||
| 		ui_graph_build_begin( ui_context ) | ||||
|  | ||||
| 		 | ||||
|  | ||||
| 		// Regnerate compute if layout is dirty. | ||||
| 	} | ||||
| 	// endregion | ||||
|  | ||||
|   | ||||
							
								
								
									
										92
									
								
								code/ui.odin
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								code/ui.odin
									
									
									
									
									
								
							| @@ -138,7 +138,11 @@ UI_Layout :: struct { | ||||
|  | ||||
| 	corner_radii : [Corner.Count]f32, | ||||
|  | ||||
| 	size : UI_ScalarConstraint, | ||||
| 	// 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, | ||||
|  | ||||
| 	size : Vec2, | ||||
| } | ||||
|  | ||||
| UI_Style :: struct { | ||||
| @@ -187,11 +191,17 @@ UI_Box :: struct { | ||||
| 	disabled_time : f32, | ||||
| } | ||||
|  | ||||
| Layout_Stack_Size :: 512 | ||||
| Style_Stack_Size  :: 512 | ||||
|  | ||||
| UI_State :: struct { | ||||
| 	box_cache : HashTable( UI_Box ), | ||||
|  | ||||
| 	box_tree_dirty : b32, | ||||
| 	root           : ^ UI_Box, | ||||
| 	root : ^ UI_Box, | ||||
|  | ||||
| 	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, | ||||
| @@ -202,7 +212,83 @@ UI_State :: struct { | ||||
| 	// drag_state data  : string, | ||||
| } | ||||
|  | ||||
| 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 { | ||||
| 	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 | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| 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 | ||||
| } | ||||
|  | ||||
| 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 | ||||
| } | ||||
|  | ||||
| // TODO(Ed) : Is this even needed? | ||||
| ui_shutdown :: proc () { | ||||
| } | ||||
|  | ||||
| ui_graph_build_begin :: proc ( ui : ^ UI_State ) | ||||
| { | ||||
| 	ui_context := & get_state().ui_context | ||||
| 	ui_context = ui | ||||
| 	using 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 )  ^ | ||||
|  | ||||
| 	cached_box := hashtable_get( & box_cache, cast(u64) box.key ) | ||||
|  | ||||
| 	if cached_box != nil { | ||||
| 		layout_dirty &= ! ui_box_equal( & box, cached_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 | ||||
| } | ||||
|  | ||||
| ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box) | ||||
| { | ||||
|  | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| ui_layout_push :: proc ( preset : UI_Layout ) { | ||||
|  | ||||
| } | ||||
|  | ||||
| ui_layout_pop :: proc () { | ||||
|  | ||||
| } | ||||
|  | ||||
| ui_layout_push_size :: proc( size : Vec2 ) { | ||||
|  | ||||
| } | ||||
|  | ||||
| ui_style_push :: proc ( preset : UI_Style ) { | ||||
| 	 | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user