diff --git a/Readme.md b/Readme.md index c13e8b6..28c2ef0 100644 --- a/Readme.md +++ b/Readme.md @@ -1,5 +1,7 @@ # Sectr Prototype +![img](docs/assets/sectr_host_2024-03-09_04-30-27.png) + This prototype aims to flesh out ideas I've wanted to explore futher when it came to code editing and tools for code in general. The things to explore: diff --git a/code/api.odin b/code/api.odin index 966ef90..caf159b 100644 --- a/code/api.odin +++ b/code/api.odin @@ -112,7 +112,7 @@ startup :: proc( persistent_mem, frame_mem, transient_mem, files_buffer_mem : ^V rl.SetConfigFlags( { rl.ConfigFlag.WINDOW_RESIZABLE, - // rl.ConfigFlag.WINDOW_TOPMOST, + rl.ConfigFlag.WINDOW_TOPMOST, }) // Rough setup of window with rl stuff diff --git a/code/colors.odin b/code/colors.odin index 940c2a3..26768f6 100644 --- a/code/colors.odin +++ b/code/colors.odin @@ -17,3 +17,6 @@ Color_Frame_Hover :: Color { 122, 122, 125, 200 } Color_Frame_Select :: Color { 188, 188, 188, 220 } Color_GreyRed :: Color { 220, 100, 100, 125 } Color_White_A125 :: Color { 255, 255, 255, 125 } + +Color_Debug_UI_Padding_Bounds :: Color { 40, 195, 170, 125 } +Color_Debug_UI_Content_Bounds :: Color { 195, 40, 170, 125 } diff --git a/code/font_provider.odin b/code/font_provider.odin index 7dee121..09e4c45 100644 --- a/code/font_provider.odin +++ b/code/font_provider.odin @@ -114,7 +114,7 @@ font_load :: proc( path_file : string, default_size = Font_Default_Point_Size } - key := cast(u64) crc32( transmute([]byte) desired_id ) + key := cast(u64) xxh32( transmute([]byte) desired_id ) def, set_error := zpl_hmap_set( & font_cache, key,FontDef {} ) verify( set_error == AllocatorError.None, "Failed to add new font entry to cache" ) diff --git a/code/grime.odin b/code/grime.odin index 9f67e94..9bb8b2c 100644 --- a/code/grime.odin +++ b/code/grime.odin @@ -18,7 +18,9 @@ import "base:runtime" import c "core:c/libc" import "core:dynlib" import "core:hash" - crc32 :: hash.crc32 + // crc32 :: hash.crc32 +import "core:hash/xxhash" + xxh32 :: xxhash.XXH32 import fmt_io "core:fmt" str_fmt :: fmt_io.printf str_fmt_tmp :: fmt_io.tprintf diff --git a/code/grime_string_interning.odin b/code/grime_string_interning.odin index 77d3d93..6f9daaa 100644 --- a/code/grime_string_interning.odin +++ b/code/grime_string_interning.odin @@ -64,7 +64,7 @@ str_intern :: proc( { cache := get_state().string_cache - key := u64( crc32( transmute([]byte) content )) + key := u64( xxh32( transmute([]byte) content )) result := zpl_hmap_get( & cache.table, key ) if result != nil { return (result ^) diff --git a/code/text.odin b/code/text.odin index 4885808..40534c7 100644 --- a/code/text.odin +++ b/code/text.odin @@ -70,17 +70,15 @@ draw_text_string_cached :: proc( content : StringCached, pos : Vec2, size : f32, } font := font if font.key == Font_Default.key { - // if len(font) == 0 { font = default_font } pos := world_to_screen_pos(pos) px_size := size zoom_adjust := px_size * project.workspace.cam.zoom + rl_font := to_rl_Font(font, zoom_adjust ) + runes := content.runes - runes := content.runes - - rl_font := to_rl_Font(font, zoom_adjust ) rl.DrawTextCodepoints( rl_font, raw_data(runes), cast(i32) len(runes), position = transmute(rl.Vector2) pos, diff --git a/code/tick_render.odin b/code/tick_render.odin index 1b04112..a04d6de 100644 --- a/code/tick_render.odin +++ b/code/tick_render.odin @@ -114,16 +114,44 @@ render_mode_2d :: proc() world_to_screen_pos(computed.bounds.max), }} - rect := rl.Rectangle { + render_padding := range2( + world_to_screen_pos(computed.padding.min), + world_to_screen_pos(computed.padding.max), + ) + render_content := range2( + world_to_screen_pos(computed.content.min), + world_to_screen_pos(computed.content.max), + ) + + rect_bounds := rl.Rectangle { render_bounds.min.x, render_bounds.min.y, render_bounds.max.x - render_bounds.min.x, render_bounds.max.y - render_bounds.min.y, } - rl.DrawRectangleRec( rect, style.bg_color ) + rect_padding := rl.Rectangle { + render_padding.min.x, + render_padding.min.y, + render_padding.max.x - render_padding.min.x, + render_padding.max.y - render_padding.min.y, + } + rect_content := rl.Rectangle { + render_content.min.x, + render_content.min.y, + render_content.max.x - render_content.min.x, + render_content.max.y - render_content.min.y, + } + + rl.DrawRectangleRounded( rect_bounds, style.layout.corner_radii[0], 9, style.bg_color ) + rl.DrawRectangleRoundedLines( rect_padding, style.layout.corner_radii[0], 9, 2, Color_Debug_UI_Padding_Bounds ) + rl.DrawRectangleRoundedLines( rect_content, style.layout.corner_radii[0], 9, 2, Color_Debug_UI_Content_Bounds ) rl.DrawCircleV( render_bounds.p0, 5, Color_Red ) rl.DrawCircleV( render_bounds.p1, 5, Color_Blue ) + if len(current.text.str) > 0 { + draw_text_string_cached( current.text, world_to_screen_pos(computed.text_pos), style.font_size, style.text_color ) + } + current = ui_box_tranverse_next( current ) } } diff --git a/code/tick_update.odin b/code/tick_update.odin index 3eefc7b..24017a8 100644 --- a/code/tick_update.odin +++ b/code/tick_update.odin @@ -200,18 +200,30 @@ update :: proc( delta_time : f64 ) -> b32 frame_style_default := UI_Style { flags = frame_style_flags, bg_color = Color_BG_TextBox, + font = default_font, + font_size = 30, + text_color = Color_White, } frame_style_disabled := UI_Style { flags = frame_style_flags, bg_color = Color_Frame_Disabled, + font = default_font, + font_size = 30, + text_color = Color_White, } frame_style_hovered := UI_Style { flags = frame_style_flags, bg_color = Color_Frame_Hover, + font = default_font, + font_size = 30, + text_color = Color_White, } frame_style_select := UI_Style { flags = frame_style_flags, bg_color = Color_Frame_Select, + font = default_font, + font_size = 30, + text_color = Color_White, } frame_theme := UI_StyleTheme { styles = { frame_style_default, @@ -223,9 +235,11 @@ update :: proc( delta_time : f64 ) -> b32 default_layout := UI_Layout { anchor = {}, - // alignment = { 0.0, 0.0 }, + // alignment = { 0.0, 0.5 }, alignment = { 0.5, 0.5 }, + text_alignment = { 1.0, 1.0 }, // alignment = { 1.0, 1.0 }, + corner_radii = { 0.3, 0.3, 0.3, 0.3 }, pos = { 0, 0 }, size = { 200, 200 }, } @@ -234,7 +248,44 @@ update :: proc( delta_time : f64 ) -> b32 // test_hover_n_click() // test_draggable() + config.ui_resize_border_width = 2 + // First box with text!!!! + { + @static pos : Vec2 + text := str_intern( "Lorem ipsum dolor sit amet") + + text_size := measure_text_size( text.str, default_font, 30, 0 ) + + ui_style_theme( { styles = { + frame_style_default, + frame_style_default, + frame_style_default, + frame_style_default, + }}) + + layout := default_layout + layout.size = cast(Vec2) text_size + layout.size.y *= 4 + layout.size.x *= 1.5 + // layout.size.y *= 3.248 + // layout.size.x *= 1.348 + // layout.size.x *= 1.348 + layout.padding = ui_layout_padding( 30 ) + ui_set_layout( layout ) + + text_box := ui_widget( "TEXT BOX!", UI_BoxFlags { .Mouse_Clickable, .Focusable, .Click_To_Focus } ) + if text_box.first_frame { + pos = text_box.style.layout.pos + text_box.text = text + } + + if text_box.dragging { + pos += mouse_world_delta() + } + + text_box.style.layout.pos = pos + } } //endregion Imgui Tick diff --git a/code/ui.odin b/code/ui.odin index 15f5d15..b1f048e 100644 --- a/code/ui.odin +++ b/code/ui.odin @@ -74,16 +74,18 @@ UI_BoxFlag_Scroll :: UI_BoxFlags { .Scroll_X, .Scroll_Y } // The UI_Box's actual positioning and sizing // There is an excess of rectangles here for debug puproses. UI_Computed :: struct { - bounds : Range2, - padding : Range2, - content : Range2, + bounds : Range2, + padding : Range2, + content : Range2, + text_pos : Vec2, + text_size : Vec2, } -UI_LayoutSide :: struct #raw_union { - using _ : struct { +UI_LayoutSide :: struct { + // using _ : struct { top, bottom : UI_Scalar, left, right : UI_Scalar, - } + // } } UI_Cursor :: struct { @@ -124,8 +126,9 @@ UI_Layout :: struct { // flags : UI_LayoutFlags // TODO(Ed) : Make sure this is all we need to represent an anchor. - anchor : Range2, - alignment : Vec2, + anchor : Range2, + alignment : Vec2, + text_alignment : Vec2, border_width : UI_Scalar, @@ -197,7 +200,6 @@ UI_Style :: struct { font : FontID, font_size : f32, text_color : Color, - text_alignment : UI_TextAlign, cursor : UI_Cursor, @@ -333,11 +335,6 @@ ui_box_equal :: proc( a, b : ^ UI_Box ) -> b32 { return result } -UI_Widget :: struct { - using box : ^UI_Box, - using signal : UI_Signal, -} - ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box) { using ui := get_state().ui_context @@ -451,10 +448,14 @@ ui_graph_build :: proc( ui : ^ UI_State ) { } ui_key_from_string :: proc( value : string ) -> UI_Key { - key := cast(UI_Key) crc32( transmute([]byte) value ) + key := cast(UI_Key) xxh32( transmute([]byte) value ) return key } +ui_layout_padding :: proc( pixels : f32 ) -> UI_LayoutSide { + return { pixels, pixels, pixels, pixels } +} + ui_parent_push :: proc( ui : ^ UI_Box ) { stack := & get_state().ui_context.parent_stack stack_push( & get_state().ui_context.parent_stack, ui ) diff --git a/code/ui.layout.odin b/code/ui_layout.odin similarity index 67% rename from code/ui.layout.odin rename to code/ui_layout.odin index 0c79e4b..cd8a0a7 100644 --- a/code/ui.layout.odin +++ b/code/ui_layout.odin @@ -28,10 +28,10 @@ ui_compute_layout :: proc() style := current.style layout := & style.layout - margins := Range2 { pts = { + margins := range2( parent_content.p0 + { layout.margins.left, layout.margins.top }, parent_content.p1 - { layout.margins.right, layout.margins.bottom }, - }} + ) anchor := & layout.anchor pos : Vec2 @@ -61,35 +61,53 @@ ui_compute_layout :: proc() } half_size := size * 0.5 - size_bounds := Range2 { pts = { + size_bounds := range2( Vec2 {}, { size.x, -size.y }, - }} + ) - aligned_bounds := Range2 { pts = { + aligned_bounds := range2( size_bounds.p0 + size * { -layout.alignment.x, layout.alignment.y }, size_bounds.p1 - size * { layout.alignment.x, -layout.alignment.y }, - }} + ) bounds := & computed.bounds (bounds^) = aligned_bounds - (bounds^) = { pts = { + (bounds^) = range2( pos + aligned_bounds.p0, pos + aligned_bounds.p1, - }} + ) border_offset := Vec2 { layout.border_width, layout.border_width } padding := & computed.padding - (padding^) = { pts = { + (padding^) = range2( bounds.p0 + border_offset, - bounds.p1 - border_offset, - }} + bounds.p1 + border_offset, + ) content := & computed.content - (content^) = { pts = { - bounds.p0 + { layout.padding.left, layout.padding.top }, - bounds.p1 - { layout.padding.right, layout.padding.bottom }, - }} + (content^) = range2( + bounds.p0 + { layout.padding.left, -layout.padding.top }, + bounds.p1 + { -layout.padding.right, layout.padding.bottom }, + ) + + // Text + if len(current.text.str) > 0 + { + top_left := content.p0 + bottom_right := content.p1 + + content_size := Vec2 { top_left.x - bottom_right.x, top_left.y - bottom_right.y } + text_size := cast(Vec2) measure_text_size( current.text.str, style.font, style.font_size, 0 ) + + text_pos : Vec2 + text_pos = top_left + 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 + + computed.text_size = text_size + computed.text_pos = { text_pos.x, -text_pos.y } + } current = ui_box_tranverse_next( current ) } diff --git a/code/ui_widgets.odin b/code/ui_widgets.odin index e30ce78..87d664b 100644 --- a/code/ui_widgets.odin +++ b/code/ui_widgets.odin @@ -1,5 +1,10 @@ package sectr +UI_Widget :: struct { + using box : ^UI_Box, + using signal : UI_Signal, +} + ui_widget :: proc( label : string, flags : UI_BoxFlags ) -> (widget : UI_Widget) { widget.box = ui_box_make( flags, label ) diff --git a/docs/assets/sectr_host_2024-03-09_04-30-27.png b/docs/assets/sectr_host_2024-03-09_04-30-27.png new file mode 100644 index 0000000..7db5622 Binary files /dev/null and b/docs/assets/sectr_host_2024-03-09_04-30-27.png differ