diff --git a/Readme.md b/Readme.md index 7a0e657..39216f1 100644 --- a/Readme.md +++ b/Readme.md @@ -59,3 +59,4 @@ They'll be elaborated in their own documentation ![img](docs/assets/Code_2024-05-04_12-55-53.png) ![img](docs/assets/sectr_host_2024-05-11_22-34-15.png) ![img](docs/assets/sectr_host_2024-05-15_03-32-36.png) +![img](docs/assets/Code_2024-05-21_23-15-16.gif) diff --git a/code/sectr/app/screen.odin b/code/sectr/app/screen.odin index 057399a..5848e7c 100644 --- a/code/sectr/app/screen.odin +++ b/code/sectr/app/screen.odin @@ -282,11 +282,6 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b } } - // scope(theme_transparent) - // spacer := ui_spacer("settings_menu.engine_refresh.end_spacer") - // spacer.layout.flags = {.Fixed_Height} - // spacer.layout.size.min.y = 10 - Min_Zoom: { scope( theme_table_row(is_even = true)) diff --git a/code/sectr/engine/client_api.odin b/code/sectr/engine/client_api.odin index 990bc21..408503f 100644 --- a/code/sectr/engine/client_api.odin +++ b/code/sectr/engine/client_api.odin @@ -142,7 +142,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem rl.SetConfigFlags( { rl.ConfigFlag.WINDOW_RESIZABLE, - // rl.ConfigFlag.WINDOW_TOPMOST, + rl.ConfigFlag.WINDOW_TOPMOST, }) window_width : i32 = cast(i32) config.resolution_width @@ -329,7 +329,7 @@ tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32 verify( alloc_error == .None, "Failed to allocate frame slab" ) } - context.allocator = frame_allocator() + context.allocator = frame_slab_allocator() context.temp_allocator = transient_allocator() rl.PollInputEvents() @@ -338,9 +338,10 @@ tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32 debug.draw_UI_padding_bounds = false debug.draw_ui_content_bounds = false - config.color_theme = App_Thm_Light + // config.color_theme = App_Thm_Light // config.color_theme = App_Thm_Dusk - // config.color_theme = App_Thm_Dark + config.color_theme = App_Thm_Dark + should_close = update( host_delta_time ) render() diff --git a/code/sectr/grime/arena.odin b/code/sectr/grime/arena.odin index 6ce5dc5..0384397 100644 --- a/code/sectr/grime/arena.odin +++ b/code/sectr/grime/arena.odin @@ -2,7 +2,7 @@ The default arena allocator Odin provides does fragmented resizes even for the last most allocated block getting resized. This is an alternative to alleviates that. -TODO(Ed): Implement? +TODO(Ed): Implement? Maybe we should trash this I' haven't seen a need to step away from using odin's */ package sectr @@ -19,8 +19,6 @@ sub_arena_init :: proc( address : ^byte, size : int ) -> ( ^ Arena) { return sub_arena } -// TODO(Ed) : Once this is done (ArenaFixed), rename to just Arena as we're not going to use the core implementation - ArenaFixedHeader :: struct { data : []byte, offset : uint, diff --git a/code/sectr/grime/array.odin b/code/sectr/grime/array.odin index 490f14e..d80ba35 100644 --- a/code/sectr/grime/array.odin +++ b/code/sectr/grime/array.odin @@ -7,13 +7,6 @@ import "core:c/libc" import "core:mem" import "core:slice" -// Array :: struct ( $ Type : typeid ) { -// bakcing : Allocator, -// capacity : u64, -// num : u64, -// data : [^]Type, -// } - ArrayHeader :: struct ( $ Type : typeid ) { backing : Allocator, dbg_name : string, @@ -105,6 +98,7 @@ array_append_array :: proc( using self: ^Array( $ Type), other : Array(Type)) -> // libc.memcpy( ptr_offset(data, num), raw_data(items), len(items) * size_of(Type) ) // TODO(Ed) : VERIFY VIA DEBUG THIS COPY IS FINE. + ensure(false, "time to check....") target := ptr_offset( data, num ) copy( slice_ptr(target, int(capacity - num)), array_to_slice(other) ) @@ -177,6 +171,7 @@ array_append_at_slice :: proc( using self : ^Array( $ Type ), items : []Type, id // libc.memcpy ( src, raw_data(items), len(items) * size_of(Type) ) // TODO(Ed) : VERIFY VIA DEBUG THIS COPY IS FINE + ensure(false, "time to check....") target := & data[id + len(items)] dst := slice_ptr( target, num - id - len(items) ) src := slice_ptr( & data[id], num - id ) @@ -189,15 +184,15 @@ array_append_at_slice :: proc( using self : ^Array( $ Type ), items : []Type, id // array_back :: proc( ) -array_push_back :: proc( using self : Array( $ Type)) -> b32 { - if num == capacity { - return false - } +// array_push_back :: proc( using self : Array( $ Type)) -> b32 { +// if num == capacity { +// return false +// } - data[ num ] = value - num += 1 - return true -} +// data[ num ] = value +// num += 1 +// return true +// } array_clear :: proc "contextless" ( using self : Array( $ Type ), zero_data : b32 = false ) { if zero_data { diff --git a/code/sectr/grime/filesystem.odin b/code/sectr/grime/filesystem.odin index ad35fdc..121f3d2 100644 --- a/code/sectr/grime/filesystem.odin +++ b/code/sectr/grime/filesystem.odin @@ -1,12 +1,11 @@ -// TODO(Ed) : Move this to a grime package package sectr +// TODO(Ed): Review these when os2 is done. + import "core:fmt" import "core:os" import "base:runtime" -// Test - file_copy_sync :: proc( path_src, path_dst: string, allocator := context.temp_allocator ) -> b32 { file_size : i64 diff --git a/code/sectr/grime/hashmap_zpl.odin b/code/sectr/grime/hashmap_zpl.odin index 88af50f..c36ef1e 100644 --- a/code/sectr/grime/hashmap_zpl.odin +++ b/code/sectr/grime/hashmap_zpl.odin @@ -2,6 +2,11 @@ This is an alternative to Odin's default map type. The only reason I may need this is due to issues with allocator callbacks or something else going on with hot-reloads... +--------------------------------------------------------------------------------------------------------- +5-21-2024 Update: Still haven't taken the time to see why but just to add the original case for the above +was I believe exclusively when I didn't set the base addresss of vmem +OR when I was attempting to use Casey's brute force replay feature with memory. +--------------------------------------------------------------------------------------------------------- This implementation uses two ZPL-Based Arrays to hold entires and the actual hash table. Instead of using separate chains, it maintains linked entries within the array. diff --git a/code/sectr/engine/logger.odin b/code/sectr/grime/logger.odin similarity index 97% rename from code/sectr/engine/logger.odin rename to code/sectr/grime/logger.odin index 150c2a9..0499a42 100644 --- a/code/sectr/engine/logger.odin +++ b/code/sectr/grime/logger.odin @@ -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 @@ -127,5 +127,5 @@ log :: proc( msg : string, level := LogLevel.Info, loc := #caller_location ) { logf :: proc( fmt : string, args : ..any, level := LogLevel.Info, loc := #caller_location ) { // context.allocator = transient_allocator() - core_log.logf( level, fmt, args, location = loc ) + core_log.logf( level, fmt, ..args, location = loc ) } diff --git a/code/sectr/grime/string_interning.odin b/code/sectr/grime/string_interning.odin index c99f737..efe1fcf 100644 --- a/code/sectr/grime/string_interning.odin +++ b/code/sectr/grime/string_interning.odin @@ -39,8 +39,8 @@ str_cache_init :: proc( /*allocator : Allocator*/ ) -> ( cache : StringCache ) { policy : SlabPolicy policy_ptr := & policy - // push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 8, alignment }) - // push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 16, alignment }) + push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 8, alignment }) + push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 16, alignment }) push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 32, alignment }) push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 64, alignment }) push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 128, alignment }) diff --git a/code/sectr/math/math.odin b/code/sectr/math/math.odin index b4b06e8..9cc0b57 100644 --- a/code/sectr/math/math.odin +++ b/code/sectr/math/math.odin @@ -77,10 +77,10 @@ vec3i_to_vec3 :: #force_inline proc "contextless" (v : Vec3i) -> Vec3 {return tr Range2 :: struct #raw_union { using min_max : struct { - min, max : Vec2 + min, max : Vec2, }, using pts : struct { - p0, p1 : Vec2 + p0, p1 : Vec2, }, using xy : struct { x0, y0 : f32, diff --git a/code/sectr/space.odin b/code/sectr/space.odin index cfab59c..4fca96a 100644 --- a/code/sectr/space.odin +++ b/code/sectr/space.odin @@ -106,8 +106,8 @@ CameraZoomMode :: enum u32 { // TODO(Ed) : I'm not sure making the size and extent types distinct has made things easier or more difficult in Odin.. // The lack of operator overloads is going to make any sort of nice typesystem -// for doing lots of math or phyiscs more error prone or filled with proc wrappers -AreaSize :: distinct Vec2 +// for doing lots of math or phyiscs more error prone or filled with proc overload mapppings +AreaSize :: Vec2 Bounds2 :: struct { top_left, bottom_right: Vec2, diff --git a/code/sectr/ui/core/Readme.md b/code/sectr/ui/core/Readme.md index 81f4dd0..b2e5013 100644 --- a/code/sectr/ui/core/Readme.md +++ b/code/sectr/ui/core/Readme.md @@ -3,8 +3,13 @@ Eventually want to generalize this core UI as its own library. This will keep track of here whats needed for it to work wihtout the rest of this codebase. -* Provide UI input state or "events" in its own data stucture at the beginning of `ui_build_graph`: -* +* Provide UI input "events" in its own data stucture at the beginning of `ui_build_graph`: + * Needed so that the UI can consume events in ui_signal_from_box. +* Make a global context state separate from UI_State for storing info persistent to all UI_States + * This is needed since UI_State can contextually exist for different viewports, etc. + * The ui state's major functions all assume a context +* ... +-- -TODO(Ed): I'm not sure what to make the default coordinate space for this widget \ No newline at end of file +It would eventually be nice to make this multi-threaded but its that isn't a major concern anytime soon. \ No newline at end of file diff --git a/code/sectr/ui/core/box.odin b/code/sectr/ui/core/box.odin index 8bfe367..ab806cf 100644 --- a/code/sectr/ui/core/box.odin +++ b/code/sectr/ui/core/box.odin @@ -34,11 +34,9 @@ UI_Box :: struct { text : StrRunesPair, // Regenerated per frame. - nav : UI_NavLinks, // signal_callback : #type proc(), - // first, last : The first and last child of this box // prev, next : The adjacent neighboring boxes who are children of to the same parent using links : DLL_NodeFull( UI_Box ), @@ -60,9 +58,6 @@ UI_Box :: struct { style_delta : f32, first_frame : b8, // root_order_id : i16, - - // mouse : UI_InteractState, - // keyboard : UI_InteractState, } ui_box_equal :: #force_inline proc "contextless" ( a, b : ^ UI_Box ) -> b32 { diff --git a/code/sectr/ui/core/layout_compute.odin b/code/sectr/ui/core/layout_compute.odin index d7daf9f..273d8bd 100644 --- a/code/sectr/ui/core/layout_compute.odin +++ b/code/sectr/ui/core/layout_compute.odin @@ -174,6 +174,11 @@ ui_box_compute_layout :: proc( box : ^UI_Box, computed.fresh = true && !dont_mark_fresh } +ui_compute_children_bounding_area :: proc ( box : ^UI_Box ) +{ + // TODO(Ed): Implement this so we can have the .Size_To_Content flag supported. +} + ui_box_compute_layout_children :: proc( box : ^UI_Box ) { for current := box.first; current != nil && current.prev != box; current = ui_box_tranverse_next( current ) diff --git a/code/sectr/ui/core/state.odin b/code/sectr/ui/core/state.odin index a8c50e4..0411115 100644 --- a/code/sectr/ui/core/state.odin +++ b/code/sectr/ui/core/state.odin @@ -100,14 +100,7 @@ UI_State :: struct { render_queue : Array(UI_RenderBoxInfo), null_box : ^UI_Box, // This was used with the Linked list interface... - // TODO(Ed): Should we change our convention for null boxes to use the above and nil as an invalid state? root : ^UI_Box, - // Children of the root node are unique in that they have their order preserved per frame - // This is to support overlapping frames - // So long as their parent-index is non-negative they'll be rendered - - // Do we need to recompute the layout? - // layout_dirty : b32, // TODO(Ed) : Look into using a build arena like Ryan does for these possibly (and thus have a linked-list stack) layout_combo_stack : StackFixed( UI_LayoutCombo, UI_Style_Stack_Size ), @@ -131,6 +124,8 @@ UI_State :: struct { last_pressed_key_us : [MouseBtn.count] f32, } +#region("Lifetime") + ui_startup :: proc( ui : ^ UI_State, cache_allocator : Allocator /* , cache_reserve_size : u64 */ ) { ui := ui @@ -164,20 +159,6 @@ ui_reload :: proc( ui : ^ UI_State, cache_allocator : Allocator ) ui_shutdown :: proc() { } -ui_cursor_pos :: #force_inline proc "contextless" () -> Vec2 { - using state := get_state() - if ui_context == & state.project.workspace.ui { - return screen_to_ws_view_pos( input.mouse.pos ) - } - else { - return input.mouse.pos - } -} - -ui_drag_delta :: #force_inline proc "contextless" () -> Vec2 { - using state := get_state() - return ui_cursor_pos() - state.ui_context.active_start_signal.cursor_pos -} ui_graph_build_begin :: proc( ui : ^ UI_State, bounds : Vec2 = {} ) { @@ -249,6 +230,22 @@ ui_graph_build_end :: proc( ui : ^UI_State ) @(deferred_in = ui_graph_build_end) ui_graph_build :: #force_inline proc( ui : ^ UI_State ) { ui_graph_build_begin( ui ) } +#endregion("Lifetime") + +#region("Caching") +// Mainly referenced from RAD Debugger + +// TODO(Ed): Need to setup the proper hashing convention for strings the other reference imguis use. +ui_hash_from_string :: proc ( value : string ) -> u64 { + fatal("NOT IMPLEMENTED") + return 0 +} + +ui_hash_part_from_key_string :: proc ( content : string ) -> string { + fatal("NOT IMPLEMENTED") + return "" +} + ui_key_from_string :: #force_inline proc "contextless" ( value : string ) -> UI_Key { // profile(#procedure) @@ -270,6 +267,22 @@ ui_key_from_string :: #force_inline proc "contextless" ( value : string ) -> UI_ return key } +#endregion("Caching") + +ui_cursor_pos :: #force_inline proc "contextless" () -> Vec2 { + using state := get_state() + if ui_context == & state.project.workspace.ui { + return screen_to_ws_view_pos( input.mouse.pos ) + } + else { + return input.mouse.pos + } +} + +ui_drag_delta :: #force_inline proc "contextless" () -> Vec2 { + using state := get_state() + return ui_cursor_pos() - state.ui_context.active_start_signal.cursor_pos +} ui_parent_push :: #force_inline proc( ui : ^ UI_Box ) { stack_push( & ui_context().parent_stack, ui ) } ui_parent_pop :: #force_inline proc() { stack_pop( & get_state().ui_context.parent_stack ) } diff --git a/code/sectr/ui/core/theme.odin b/code/sectr/ui/core/theme.odin index 601771d..f035cea 100644 --- a/code/sectr/ui/core/theme.odin +++ b/code/sectr/ui/core/theme.odin @@ -1,5 +1,12 @@ package sectr +/* +Themes: While technically in UI_State we only store the layout and style combo pairs in separate stacks, most of the time +widgets will want to push or pop a (layout_combo, style_combo) pair during construction. + +Themes provide that ease of use. +*/ + UI_ThemePtr :: struct { layout : ^UI_LayoutCombo, style : ^UI_StyleCombo, diff --git a/code/sectr/ui/layout_widget.odin b/code/sectr/ui/layout_widget.odin index abdb54a..530e3cf 100644 --- a/code/sectr/ui/layout_widget.odin +++ b/code/sectr/ui/layout_widget.odin @@ -65,22 +65,24 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay space_used : f32 = 0.0 switch direction{ - case .Right_To_Left: - for child := container.last; child != nil; child = child.prev { - using child.layout - child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height) - anchor = range2({0, 0}, {0, 0}) - pos.x = space_used - space_used += child_width + child.layout.margins.left + child.layout.margins.right - } case .Left_To_Right: for child := container.first; child != nil; child = child.next { using child.layout child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height) anchor = range2({0, 0}, {0, 0}) + alignment = {0, 0} pos.x = space_used space_used += child_width + child.layout.margins.left + child.layout.margins.right } + case .Right_To_Left: + for child := container.first; child != nil; child = child.next { + using child.layout + child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height) + anchor = range2({1, 0}, {0, 0}) + alignment = {1, 0} + pos.x = space_used + space_used -= child_width + child.layout.margins.left + child.layout.margins.right + } } } @@ -139,10 +141,10 @@ ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_Layou return } + space_used : f32 = 0 switch direction { case .Top_To_Bottom: - space_used : f32 = 0 for child := container.first; child != nil; child = child.next { using child.layout child_height := allocate_space(child, total_stretch_ratio, avail_flex_space, container_width) @@ -152,7 +154,6 @@ ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_Layou space_used -= child_height - child.layout.margins.top - child.layout.margins.bottom } case .Bottom_To_Top: - space_used : f32 = 0 for child := container.first; child != nil; child = child.next { using child.layout child_height := allocate_space(child, total_stretch_ratio, avail_flex_space, container_width) diff --git a/code/sectr/ui/widgets.odin b/code/sectr/ui/widgets.odin index 17f2fbe..979dd51 100644 --- a/code/sectr/ui/widgets.odin +++ b/code/sectr/ui/widgets.odin @@ -27,8 +27,6 @@ ui_button :: proc( label : string, flags : UI_BoxFlags = {} ) -> (btn : UI_Widge } #region("Drop Down") -/* TODO(Ed): Don't feel very good about the abstraction... -*/ UI_DropDown :: struct { btn : UI_Widget, title : UI_Widget, @@ -215,14 +213,6 @@ ui_resizable_end :: proc( resizable : ^UI_Resizable, pos, size : ^Vec2 ) { compute_layout) } -ui_resizable_begin_auto :: proc() { - -} - -ui_resizable_end_auto :: proc() { - -} - // Adds resizable handles to a widget ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, handle_width : f32 = 15, @@ -505,13 +495,12 @@ UI_ScrollBox :: struct { content : UI_Widget, } +// TODO(Ed): Implement ui_scroll_box :: proc( label : string, flags : UI_BoxFlags ) -> (scroll_box : UI_ScrollBox) { return } -// ui_scrollable_view( ) - #region("Text") ui_text :: proc( label : string, content : StrRunesPair, flags : UI_BoxFlags = {} ) -> UI_Widget { diff --git a/docs/assets/Code_2024-05-21_23-15-16.gif b/docs/assets/Code_2024-05-21_23-15-16.gif new file mode 100644 index 0000000..07bbfa3 Binary files /dev/null and b/docs/assets/Code_2024-05-21_23-15-16.gif differ