First text box!!!
This commit is contained in:
parent
f1edf1c43e
commit
635ce91a9d
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -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" )
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ^)
|
||||
|
@ -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,
|
||||
|
@ -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 )
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
31
code/ui.odin
31
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 )
|
||||
|
@ -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 )
|
||||
}
|
@ -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 )
|
||||
|
BIN
docs/assets/sectr_host_2024-03-09_04-30-27.png
Normal file
BIN
docs/assets/sectr_host_2024-03-09_04-30-27.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
Loading…
Reference in New Issue
Block a user