diff --git a/code/env_scratch.odin b/code/app_scratch.odin similarity index 100% rename from code/env_scratch.odin rename to code/app_scratch.odin diff --git a/code/tick_new_render.odin b/code/app_serialize.odin similarity index 100% rename from code/tick_new_render.odin rename to code/app_serialize.odin diff --git a/code/env_env.odin b/code/app_state.odin similarity index 100% rename from code/env_env.odin rename to code/app_state.odin diff --git a/code/app_ui_theme_default.odin b/code/app_ui_theme_default.odin new file mode 100644 index 0000000..17d1aa1 --- /dev/null +++ b/code/app_ui_theme_default.odin @@ -0,0 +1,114 @@ +package sectr + +/* +UI Themes: Comprise of UI_Box's layout & style + +Provides presets for themes and their interface for manipulating the combo stacks in UI_State in pairs +*/ +// TODO(Ed): Eventually this will have a configuration wizard, and we'll save the presets + +@(deferred_none = ui_theme_pop) +ui_theme_btn_default :: proc() +{ + @static theme : UI_Theme + @static loaded : b32 = false + if ! loaded + { + layout := UI_Layout { + flags = {}, + anchor = range2({},{}), + alignment = {0, 0}, + text_alignment = {0.5, 0.5}, + font_size = 16, + margins = {0, 0, 0, 0}, + padding = {0, 0, 0, 0}, + border_width = 1, + pos = {0, 0}, + size = range2({},{}) + } + style := UI_Style { + bg_color = Color_ThmDark_Btn_BG_Default, + border_color = Color_ThmDark_Border_Default, + corner_radii = {}, + blur_size = 0, + font = get_state().default_font, + text_color = Color_ThmDark_Text_Default, + cursor = {}, + } + layout_combo := to_ui_layout_combo(layout) + style_combo := to_ui_style_combo(style) + { + using layout_combo.hot + using style_combo.hot + bg_color = Color_ThmDark_Btn_BG_Hot + text_color = Color_ThmDark_Text_Hot + margins = {2, 2, 2, 2} + } + { + using layout_combo.active + using style_combo.active + bg_color = Color_ThmDark_Btn_BG_Active + text_color = Color_ThmDark_Text_Active + margins = {2, 2, 2, 2} + } + theme = UI_Theme { + layout_combo, style_combo + } + loaded = true + } + ui_layout_push(theme.layout) + ui_style_push(theme.style) +} + +@(deferred_none = ui_theme_pop) +ui_theme_transparent :: proc() +{ + @static theme : UI_Theme + @static loaded : b32 = false + if ! loaded || true + { + layout := UI_Layout { + flags = {}, + anchor = range2({},{}), + alignment = {0, 0}, + text_alignment = {0.0, 0.0}, + font_size = 16, + margins = {0, 0, 0, 0}, + padding = {0, 0, 0, 0}, + border_width = 0, + pos = {0, 0}, + size = range2({},{}) + } + style := UI_Style { + bg_color = Color_Transparent, + border_color = Color_Transparent, + corner_radii = {}, + blur_size = 0, + font = get_state().default_font, + text_color = Color_ThmDark_Text_Default, + cursor = {}, + } + + layout_combo := to_ui_layout_combo(layout) + style_combo := to_ui_style_combo(style) + { + using layout_combo.disabled + using style_combo.disabled + } + { + using layout_combo.hot + using style_combo.hot + } + { + using layout_combo.active + using style_combo.active + } + + theme = UI_Theme { + layout_combo, style_combo + } + loaded = true + } + ui_layout_push(theme.layout) + ui_style_push(theme.style) +} diff --git a/code/engine_api.odin b/code/engine_client_api.odin similarity index 100% rename from code/engine_api.odin rename to code/engine_client_api.odin diff --git a/code/engine_render.odin b/code/engine_render.odin deleted file mode 100644 index 55d9eb3..0000000 --- a/code/engine_render.odin +++ /dev/null @@ -1,17 +0,0 @@ -package sectr - -import rl "vendor:raylib" - - -range2_to_rl_rect :: #force_inline proc "contextless"( range : Range2 ) -> rl.Rectangle -{ - rect := rl.Rectangle { - range.min.x, - range.max.y, - abs(range.max.x - range.min.x), - abs(range.max.y - range.min.y), - } - return rect -} - - diff --git a/code/engine_render_gl.odin b/code/engine_render_gl.odin new file mode 100644 index 0000000..98633f0 --- /dev/null +++ b/code/engine_render_gl.odin @@ -0,0 +1,2 @@ +package sectr + diff --git a/code/tick_render.odin b/code/engine_render_raylib.odin similarity index 94% rename from code/tick_render.odin rename to code/engine_render_raylib.odin index 3090dc5..8807d46 100644 --- a/code/tick_render.odin +++ b/code/engine_render_raylib.odin @@ -4,6 +4,17 @@ import "core:fmt" import rl "vendor:raylib" +range2_to_rl_rect :: #force_inline proc "contextless"( range : Range2 ) -> rl.Rectangle +{ + rect := rl.Rectangle { + range.min.x, + range.max.y, + abs(range.max.x - range.min.x), + abs(range.max.y - range.min.y), + } + return rect +} + draw_rectangle :: #force_inline proc "contextless" ( rect : rl.Rectangle, box : ^UI_RenderBoxInfo ) { using box if style.corner_radii[0] > 0 { @@ -211,9 +222,9 @@ render_mode_screenspace :: proc () render_screen_ui() fps_msg := str_fmt_tmp( "FPS: %f", fps_avg) - fps_msg_width := measure_text_size( fps_msg, default_font, 16.0, 0.0 ).x + fps_msg_width := measure_text_size( fps_msg, default_font, 12.0, 0.0 ).x fps_msg_pos := screen_get_corners().top_right - { fps_msg_width, 0 } - { 5, 5 } - debug_draw_text( fps_msg, fps_msg_pos, 16.0, color = rl.GREEN ) + debug_draw_text( fps_msg, fps_msg_pos, 12.0, color = rl.GREEN ) debug_text :: proc( format : string, args : ..any ) { @@ -232,7 +243,7 @@ render_mode_screenspace :: proc () position.y -= debug.draw_debug_text_y content := str_fmt_buffer( draw_text_scratch[:], format, ..args ) - debug_draw_text( content, position, 14.0 ) + debug_draw_text( content, position, 12.0 ) debug.draw_debug_text_y += 14 } @@ -293,7 +304,6 @@ render_mode_screenspace :: proc () } view := view_get_bounds() - // debug_text("View Bounds (World): %v", view.pts ) debug.draw_debug_text_y = 14 @@ -304,10 +314,6 @@ render_mode_screenspace :: proc () 0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, // Vertex 2: Green 0.0, 0.5, 0.0, 0.0, 0.0, 1.0, 1.0 // Vertex 3: Blue } - - // Begin using the shader to draw - // rl.BeginShaderMode(debug.proto_text_shader) - // rl.EndShaderMode() } // A non-zoomable static-view for ui @@ -366,7 +372,6 @@ render_screen_ui :: proc() line_thickness : f32 = 1 - // profile_begin("rl.DrawRectangleRoundedLines: padding & content") if debug.draw_UI_padding_bounds && equal_range2(computed.content, computed.padding) { draw_rectangle_lines( rect_padding, & current, Color_Debug_UI_Padding_Bounds, line_thickness ) } @@ -376,16 +381,17 @@ render_screen_ui :: proc() point_radius : f32 = 3 - // profile_begin("circles") if debug.draw_ui_box_bounds_points { computed_size := computed.bounds.p1 - computed.bounds.p0 - // center := Vec2 { - // render_bounds.p0.x + computed_size.x * 0.5, - // render_bounds.p0.y - computed_size.y * 0.5, - // } - // rl.DrawCircleV( center, point_radius, Color_White ) - + if false + { + center := Vec2 { + render_bounds.p0.x + computed_size.x * 0.5, + render_bounds.p0.y - computed_size.y * 0.5, + } + rl.DrawCircleV( center, point_radius, Color_White ) + } rl.DrawCircleV( render_bounds.p0, point_radius, Color_Red ) rl.DrawCircleV( render_bounds.p1, point_radius, Color_Blue ) } diff --git a/code/text.odin b/code/engine_render_text_raylib.odin similarity index 97% rename from code/text.odin rename to code/engine_render_text_raylib.odin index 7a6f7b8..c69e899 100644 --- a/code/text.odin +++ b/code/engine_render_text_raylib.odin @@ -150,7 +150,7 @@ else // Raylib's equivalent doesn't take a length for the string (making it a pain in the ass) // So this is a 1:1 copy except it takes Odin strings -measure_text_size :: proc( text : string, font : FontID, font_size := Font_Use_Default_Size, spacing : f32 ) -> Vec2 +measure_text_size_raylib :: proc( text : string, font : FontID, font_size := Font_Use_Default_Size, spacing : f32 ) -> Vec2 { // profile(#procedure) px_size := math.round( points_to_pixels( font_size ) ) diff --git a/code/tick_update.odin b/code/engine_update.odin similarity index 100% rename from code/tick_update.odin rename to code/engine_update.odin diff --git a/code/gen/genodin.odin b/code/gen/genodin.odin index e69de29..f5674ad 100644 --- a/code/gen/genodin.odin +++ b/code/gen/genodin.odin @@ -0,0 +1 @@ +package genodin \ No newline at end of file diff --git a/code/grime_context.odin b/code/grime_context.odin index 233bfb3..60c121c 100644 --- a/code/grime_context.odin +++ b/code/grime_context.odin @@ -1,11 +1,5 @@ package sectr -// GrimeContextExt :: struct { -// dbg_name : string -// } - -// Global_Transient_Context : GrimeContextExt - context_ext :: proc( $ Type : typeid ) -> (^Type) { return cast(^Type) context.user_ptr } diff --git a/code/grime_grime.odin b/code/grime_grime.odin index 860a582..e9b9cdd 100644 --- a/code/grime_grime.odin +++ b/code/grime_grime.odin @@ -99,13 +99,6 @@ import "thirdparty:backtrace" #endregion("Import Aliases") -OS_Type :: type_of(ODIN_OS) - - -swap :: proc( a, b : ^ $Type ) -> ( ^ Type, ^ Type ) { - return b, a -} - #region("Proc overload mappings") // This has to be done on a per-module basis. @@ -163,6 +156,10 @@ is_power_of_two :: proc { is_power_of_two_uintptr, } +measure_text_size :: proc { + measure_text_size_raylib, +} + mov_avg_exp :: proc { mov_avg_exp_f32, mov_avg_exp_f64, @@ -279,6 +276,11 @@ to_ui_layout_side :: proc { to_ui_layout_side_vec2, } +ui_compute_layout :: proc { + ui_core_compute_layout, + ui_box_compute_layout, +} + ui_floating :: proc { ui_floating_just_builder, ui_floating_with_capture, @@ -316,3 +318,7 @@ wedge :: proc { } #endregion("Proc overload mappings") + +OS_Type :: type_of(ODIN_OS) + +swap :: #force_inline proc( a, b : ^ $Type ) -> ( ^ Type, ^ Type ) { return b, a } diff --git a/code/project_serialize_manual_unmarshal.odin b/code/project_manual_serialization.odin similarity index 100% rename from code/project_serialize_manual_unmarshal.odin rename to code/project_manual_serialization.odin diff --git a/code/ui_ui.odin b/code/ui_core.odin similarity index 82% rename from code/ui_ui.odin rename to code/ui_core.odin index 0c941b9..910fe48 100644 --- a/code/ui_ui.odin +++ b/code/ui_core.odin @@ -32,25 +32,25 @@ Side :: enum i32 { // Count, // } -UI_AnchorPresets :: enum u32 { - Top_Left, - Top_Right, - Bottom_Right, - Bottom_Left, - Center_Left, - Center_Top, - Center_Right, - Center_Bottom, - Center, - Left_Wide, - Top_Wide, - Right_Wide, - Bottom_Wide, - VCenter_Wide, - HCenter_Wide, - Full, - Count, -} +// UI_AnchorPresets :: enum u32 { +// Top_Left, +// Top_Right, +// Bottom_Right, +// Bottom_Left, +// Center_Left, +// Center_Top, +// Center_Right, +// Center_Bottom, +// Center, +// Left_Wide, +// Top_Wide, +// Right_Wide, +// Bottom_Wide, +// VCenter_Wide, +// HCenter_Wide, +// Full, +// Count, +// } UI_Cursor :: struct { placeholder : int, @@ -136,8 +136,7 @@ ui_startup :: proc( ui : ^ UI_State, cache_allocator : Allocator /* , cache_rese ui := ui ui^ = {} - // cache.ref in ui.caches.ref - for & cache in (& ui.caches) { + 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 @@ -155,7 +154,7 @@ ui_startup :: proc( ui : ^ UI_State, cache_allocator : Allocator /* , cache_rese ui_reload :: proc( ui : ^ UI_State, cache_allocator : Allocator ) { // We need to repopulate Allocator references - for & cache in & ui.caches { + for & cache in ui.caches { zpl_hmap_reload( & cache, cache_allocator) } ui.render_queue.backing = cache_allocator @@ -180,11 +179,6 @@ ui_drag_delta :: #force_inline proc "contextless" () -> Vec2 { return ui_cursor_pos() - state.ui_context.active_start_signal.cursor_pos } -ui_ws_drag_delta :: #force_inline proc "contextless" () -> Vec2 { - using state := get_state() - return screen_to_ws_view_pos(input.mouse.pos) - state.ui_context.active_start_signal.cursor_pos -} - ui_graph_build_begin :: proc( ui : ^ UI_State, bounds : Vec2 = {} ) { profile(#procedure) @@ -197,10 +191,7 @@ ui_graph_build_begin :: proc( ui : ^ UI_State, bounds : Vec2 = {} ) stack_clear( & style_combo_stack ) array_clear( render_queue ) - temp := prev_cache - prev_cache = curr_cache - curr_cache = temp - // curr_cache, prev_cache = swap( curr_cache, prev_cache ) + curr_cache, prev_cache = swap( curr_cache, prev_cache ) if ui.active == UI_Key(0) { //ui.hot = UI_Key(0) @@ -228,9 +219,7 @@ ui_graph_build_end :: proc( ui : ^UI_State ) } @(deferred_in = ui_graph_build_end) -ui_graph_build :: proc( ui : ^ UI_State ) { - ui_graph_build_begin( ui ) -} +ui_graph_build :: #force_inline proc( ui : ^ UI_State ) { ui_graph_build_begin( ui ) } ui_key_from_string :: #force_inline proc "contextless" ( value : string ) -> UI_Key { @@ -254,26 +243,13 @@ ui_key_from_string :: #force_inline proc "contextless" ( value : string ) -> UI_ return key } -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 ) -} +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 ) } @(deferred_none = ui_parent_pop) ui_parent :: #force_inline proc( ui : ^UI_Box) { ui_parent_push( ui ) } -ui_prev_cached_box :: #force_inline proc( box : ^UI_Box ) -> ^UI_Box { - return zpl_hmap_get( ui_context().prev_cache, cast(u64) box.key ) -} +ui_prev_cached_box :: #force_inline proc( box : ^UI_Box ) -> ^UI_Box { return zpl_hmap_get( ui_context().prev_cache, cast(u64) box.key ) } // Topmost ancestor that is not the root ui_top_ancestor :: #force_inline proc "contextless" ( box : ^UI_Box ) -> (^UI_Box) { diff --git a/code/ui_box.odin b/code/ui_core_box.odin similarity index 68% rename from code/ui_box.odin rename to code/ui_core_box.odin index 76ed0ad..b631ed5 100644 --- a/code/ui_box.odin +++ b/code/ui_core_box.odin @@ -1,6 +1,7 @@ package sectr -UI_BoxFlag :: enum u64 { +UI_BoxFlag :: enum u64 +{ Disabled, Focusable, @@ -9,13 +10,6 @@ UI_BoxFlag :: enum u64 { Mouse_Clickable, Keyboard_Clickable, - // Pan_X, - // Pan_Y, - - // Scroll_X, - // Scroll_Y, - - // Screenspace, Count, } UI_BoxFlags :: bit_set[UI_BoxFlag; u64] @@ -24,9 +18,9 @@ UI_BoxFlags :: bit_set[UI_BoxFlag; u64] UI_RenderBoxInfo :: struct { using computed : UI_Computed, using style : UI_Style, - text : StrRunesPair, - font_size : UI_Scalar, - border_width : UI_Scalar, + text : StrRunesPair, + font_size : UI_Scalar, + border_width : UI_Scalar, } UI_Box :: struct { @@ -60,8 +54,6 @@ UI_Box :: struct { first_frame : b8, // root_order_id : i16, - // prev_computed : UI_Computed, - // prev_style : UI_Style,v // mouse : UI_InteractState, // keyboard : UI_InteractState, } @@ -82,16 +74,13 @@ ui_box_from_key :: #force_inline proc ( cache : ^HMapZPL(UI_Box), key : UI_Key ) ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box) { // profile(#procedure) - using ui := get_state().ui_context - key := ui_key_from_string( label ) curr_box : (^ UI_Box) prev_box := zpl_hmap_get( prev_cache, cast(u64) key ) { // profile("Assigning current box") - set_result : ^ UI_Box set_error : AllocatorError if prev_box != nil @@ -103,18 +92,15 @@ ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box) box : UI_Box box.key = key box.label = str_intern( label ) - // set_result, set_error = zpl_hmap_set( prev_cache, cast(u64) key, box ) 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 - + curr_box = set_result curr_box.first_frame = prev_box == nil + curr_box.flags = flags } - curr_box.flags = flags - // Clear non-persistent data curr_box.computed.fresh = false curr_box.links = {} @@ -124,30 +110,7 @@ ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box) parent := stack_peek( & parent_stack ) if parent != nil { - when true { - dll_full_push_back( parent, curr_box, nil ) - } - else - { - // | - // v - // parent.first - if parent.first == nil { - parent.first = curr_box - parent.last = curr_box - curr_box.next = nil - curr_box.prev = nil - } - else { - // Positin is set to last, insert at end - // curr_box - parent.last.next = curr_box - curr_box.prev = parent.last - parent.last = curr_box - curr_box.next = nil - } - } - + dll_full_push_back( parent, curr_box, nil ) curr_box.parent_index = parent.num_children parent.num_children += 1 curr_box.parent = parent @@ -160,37 +123,31 @@ ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box) ui_box_tranverse_next :: proc "contextless" ( box : ^ UI_Box ) -> (^ UI_Box) { - // Check to make sure parent is present on the screen, if its not don't bother. - // If current has children, do them first using state := get_state() + // If current has children, do them first if box.first != nil { + // Check to make sure parent is present on the screen, if its not don't bother. is_app_ui := ui_context == & screen_ui - if is_app_ui || intersects_range2( view_get_bounds(), box.computed.bounds) + if intersects_range2( view_get_bounds(), box.computed.bounds) { return box.first } } - if box.next == nil - { - // There is no more adjacent nodes - if box.parent != nil - { - parent := box.parent - // Attempt to find a parent with a next, otherwise we just return a parent with nil - for ; parent.parent != nil; - { - if parent.next != nil { - break - } - parent = parent.parent - } + if box.next != nil do return box.next + // There is no more adjacent nodes - // Lift back up to parent, and set it to its next. - return parent.next + parent := box.parent + // Attempt to find a parent with a next, otherwise we just return a parent with nil + for ; parent.parent != nil; + { + if parent.next != nil { + break } + parent = parent.parent } - return box.next + // Lift back up to parent, and set it to its next. + return parent.next } diff --git a/code/ui_layout.odin b/code/ui_core_layout.odin similarity index 95% rename from code/ui_layout.odin rename to code/ui_core_layout.odin index dbcbd8c..bf2b3ce 100644 --- a/code/ui_layout.odin +++ b/code/ui_core_layout.odin @@ -76,7 +76,6 @@ UI_LayoutFlag :: enum u32 { Fixed_Width, Fixed_Height, - // TODO(Ed): Implement this! // Enforces the widget will have a width specified as a ratio of its height (use the size.min/max.x to specify the scalar) // If you wish for the width to stay fixed couple with the Fixed_Width flag Scale_Width_By_Height_Ratio, @@ -96,6 +95,9 @@ UI_LayoutFlag :: enum u32 { Size_To_Text, // TODO(Ed): Implement this! + // ?Note(Ed): This can get pretty complicated... Maybe its better to leave this to composition of boxes. + // ?A text wrapping panel can organize text and wrap it via procedrually generated lines in a hbox/vbox. + // ?It would be a non-issue so long as the text rendering bottleneck is resolved. // Wrap text around the box, text_alignment specifies the justification for its compostion when wrapping. Text_Wrap, diff --git a/code/ui_layout_compute.odin b/code/ui_core_layout_compute.odin similarity index 86% rename from code/ui_layout_compute.odin rename to code/ui_core_layout_compute.odin index f7234fa..8f22de7 100644 --- a/code/ui_layout_compute.odin +++ b/code/ui_core_layout_compute.odin @@ -8,26 +8,10 @@ ui_box_compute_layout :: proc( box : ^UI_Box, // profile("Layout Box") state := get_state() ui := state.ui_context - - parent := box.parent - - style := box.style - layout := & box.layout - - // These are used to choose via multiplication weather to apply - // position & size constraints of the parent. - // The parent's unadjusted content bounds however are enforced for position, - // they cannot be ignored. The user may bypass them by doing the - // relative offset math vs world/screen space if they desire. - // fixed_pos_x : f32 = cast(f32) int(.Fixed_Position_X in layout.flags) - // fixed_pos_y : f32 = cast(f32) int(.Fixed_Position_Y in layout.flags) - // fixed_width : f32 = cast(f32) int(.Fixed_Width in layout.flags) - // fixed_height : f32 = cast(f32) int(.Fixed_Height in layout.flags) + using box size_to_text : bool = .Size_To_Text in layout.flags - computed := & box.computed - parent_content := parent.computed.content parent_content_size := parent_content.max - parent_content.min parent_center := parent_content.min + parent_content_size * 0.5 @@ -98,6 +82,13 @@ ui_box_compute_layout :: proc( box : ^UI_Box, adjusted_size = text_size } + if .Scale_Width_By_Height_Ratio in layout.flags { + adjusted_size.x = adjusted_size.y * layout.size.min.x + } + if .Scale_Height_By_Width_Ratio in layout.flags { + adjusted_size.y = adjusted_size.x * layout.size.min.y + } + if .Size_To_Content in layout.flags { // Preemtively traverse the children of this parent and have them compute their layout. // This parent will just set its size to the max bounding area of those children. @@ -135,8 +126,7 @@ ui_box_compute_layout :: proc( box : ^UI_Box, // 6. Determine the box bounds // Adjust Alignment of pivot position alignment := layout.alignment - bounds : Range2 - + bounds : Range2 if ! (.Origin_At_Anchor_Center in layout.flags) { // The convention offset adjust the box so that the top-left point is at the top left of the anchor's bounds tl_convention_offset := adjusted_size * {0, -1} @@ -153,6 +143,7 @@ ui_box_compute_layout :: proc( box : ^UI_Box, ) } + // 7. Padding & Content // Determine Padding's outer bounds border_offset := Vec2 { layout.border_width, layout.border_width } @@ -167,21 +158,20 @@ ui_box_compute_layout :: proc( box : ^UI_Box, bounds.max - { layout.padding.right, layout.padding.top } - border_offset, ) - computed.bounds = bounds + computed.bounds = bounds computed.padding = padding_bounds computed.content = content_bounds + // 8. Text position & size if len(box.text.str) > 0 { content_size := content_bounds.max - content_bounds.min text_pos : Vec2 text_pos = content_bounds.min + { 0, text_size.y } - // text_pos.x += ( content_size.x - text_size.x ) * layout.text_alignment.x - // text_pos.y += ( content_size.y - text_size.y ) * layout.text_alignment.y text_pos += (content_size - text_size) * layout.text_alignment computed.text_size = text_size - computed.text_pos = { text_pos.x, text_pos.y } + computed.text_pos = text_pos } computed.fresh = true && !dont_mark_fresh } @@ -196,7 +186,7 @@ ui_box_compute_layout_children :: proc( box : ^UI_Box ) } } -ui_compute_layout :: proc( ui : ^UI_State ) +ui_core_compute_layout :: proc( ui : ^UI_State ) { profile(#procedure) state := get_state() diff --git a/code/ui_signal.odin b/code/ui_core_signal.odin similarity index 100% rename from code/ui_signal.odin rename to code/ui_core_signal.odin diff --git a/code/ui_style.odin b/code/ui_core_style.odin similarity index 100% rename from code/ui_style.odin rename to code/ui_core_style.odin diff --git a/code/ui_floating.odin b/code/ui_floating.odin index 17ac2e7..21d9b5a 100644 --- a/code/ui_floating.odin +++ b/code/ui_floating.odin @@ -116,20 +116,21 @@ ui_floating_build :: proc() lookup.builder = to_enqueue.builder } lookup.queued = true - if first == nil { - first = lookup - last = lookup - continue - } - if first == last { - last = lookup - last.prev = first - first.next = last - continue - } - last.next = lookup - lookup.prev = last - last = lookup + dll_full_push_back(floating, lookup, nil ) + // if first == nil { + // first = lookup + // last = lookup + // continue + // } + // if first == last { + // last = lookup + // last.prev = first + // first.next = last + // continue + // } + // last.next = lookup + // lookup.prev = last + // last = lookup } array_clear(build_queue) diff --git a/code/ui_theme.odin b/code/ui_theme.odin index 74de9d6..0c5d92e 100644 --- a/code/ui_theme.odin +++ b/code/ui_theme.odin @@ -35,116 +35,3 @@ ui_theme_via_theme :: #force_inline proc( theme : UI_Theme ) { ui_layout_push( theme.layout ) ui_style_push( theme.style ) } - -/* -UI Themes: Comprise of UI_Box's layout & style - -Provides presets for themes and their interface for manipulating the combo stacks in UI_State in pairs -*/ -// TODO(Ed): Eventually this will have a configuration wizard, and we'll save the presets - -@(deferred_none = ui_theme_pop) -ui_theme_btn_default :: proc() -{ - @static theme : UI_Theme - @static loaded : b32 = false - if ! loaded - { - layout := UI_Layout { - flags = {}, - anchor = range2({},{}), - alignment = {0, 0}, - text_alignment = {0.5, 0.5}, - font_size = 16, - margins = {0, 0, 0, 0}, - padding = {0, 0, 0, 0}, - border_width = 1, - pos = {0, 0}, - size = range2({},{}) - } - style := UI_Style { - bg_color = Color_ThmDark_Btn_BG_Default, - border_color = Color_ThmDark_Border_Default, - corner_radii = {}, - blur_size = 0, - font = get_state().default_font, - text_color = Color_ThmDark_Text_Default, - cursor = {}, - } - layout_combo := to_ui_layout_combo(layout) - style_combo := to_ui_style_combo(style) - { - using layout_combo.hot - using style_combo.hot - bg_color = Color_ThmDark_Btn_BG_Hot - text_color = Color_ThmDark_Text_Hot - margins = {2, 2, 2, 2} - } - { - using layout_combo.active - using style_combo.active - bg_color = Color_ThmDark_Btn_BG_Active - text_color = Color_ThmDark_Text_Active - margins = {2, 2, 2, 2} - } - theme = UI_Theme { - layout_combo, style_combo - } - loaded = true - } - ui_layout_push(theme.layout) - ui_style_push(theme.style) -} - -@(deferred_none = ui_theme_pop) -ui_theme_transparent :: proc() -{ - @static theme : UI_Theme - @static loaded : b32 = false - if ! loaded || true - { - layout := UI_Layout { - flags = {}, - anchor = range2({},{}), - alignment = {0, 0}, - text_alignment = {0.0, 0.0}, - font_size = 16, - margins = {0, 0, 0, 0}, - padding = {0, 0, 0, 0}, - border_width = 0, - pos = {0, 0}, - size = range2({},{}) - } - style := UI_Style { - bg_color = Color_Transparent, - border_color = Color_Transparent, - corner_radii = {}, - blur_size = 0, - font = get_state().default_font, - text_color = Color_ThmDark_Text_Default, - cursor = {}, - } - - layout_combo := to_ui_layout_combo(layout) - style_combo := to_ui_style_combo(style) - { - using layout_combo.disabled - using style_combo.disabled - } - { - using layout_combo.hot - using style_combo.hot - } - { - using layout_combo.active - using style_combo.active - } - - theme = UI_Theme { - layout_combo, style_combo - } - loaded = true - } - ui_layout_push(theme.layout) - ui_style_push(theme.style) -} diff --git a/code/ui_widgets.odin b/code/ui_widgets.odin index 6c0eafc..c4057ba 100644 --- a/code/ui_widgets.odin +++ b/code/ui_widgets.odin @@ -425,6 +425,18 @@ ui_spacer :: proc( label : string ) -> (widget : UI_Widget) { return } +// UI_ScrollBox { +// using widget : UI_Widget, +// scroll_bar : UI_Widget, +// content : UI_Widget, +// } + +// ui_scroll_box :: proc( label : string ) -> (scroll_box : UI_ScrollBox) { + +// } + +// ui_scrollable_view( ) + #region("Text") ui_text :: proc( label : string, content : StrRunesPair, flags : UI_BoxFlags = {} ) -> UI_Widget @@ -468,6 +480,8 @@ ui_text_tabs :: proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget box.text = tab_str return { box, signal } } + +ui_text_wrap_panel :: proc( label : string, flags : UI_BoxFlags = {} ) #endregion("Text") #region("Vertical Box") diff --git a/scripts/setup_virtual_code_view.ps1 b/scripts/setup_virtual_code_view.ps1 index 17a5776..d69accf 100644 --- a/scripts/setup_virtual_code_view.ps1 +++ b/scripts/setup_virtual_code_view.ps1 @@ -38,12 +38,16 @@ foreach ($file in $files) } else { - # For files without a namespace, create a symbolic link in the root of the original code's path in virtual view - $linkPath = Join-Path $path_virtual_view $fileName - if (-not (Test-Path $linkPath)) { - New-Item -ItemType SymbolicLink -Path $linkPath -Value $file.FullName - } - } + # For files without a namespace, maintain the directory structure in the virtual view + $relativePath = $file.FullName.Substring($path_code.Length + 1) + $linkPath = Join-Path $path_virtual_view $relativePath + $linkDir = Split-Path -Parent $linkPath + + if (-not (Test-Path $linkDir)) { + New-Item -ItemType Directory -Path $linkDir -Force + } + New-Item -ItemType SymbolicLink -Path $linkPath -Value $file.FullName + } } Write-Host "Virtual view created successfully." diff --git a/toolchain/Odin b/toolchain/Odin index 0d4069d..67ae530 160000 --- a/toolchain/Odin +++ b/toolchain/Odin @@ -1 +1 @@ -Subproject commit 0d4069d2ea7aaf155b8c5d979fbbc590360314d0 +Subproject commit 67ae530d22c116f86d476743b5dfc978255391d4