Got "Line LODs" working for the whitespace AST test, first step toward hboxes

Yet another issue with memory persists (seems to be related to slab free)
This commit is contained in:
Edward R. Gonzalez 2024-03-15 00:02:28 -04:00
parent ee8b68ac3e
commit 49a4e117a2
16 changed files with 463 additions and 146 deletions

View File

@ -91,8 +91,8 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 256 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 512 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 1 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 2 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 4 * Megabyte, 4 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 2 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 4 * Megabyte, 4 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 8 * Megabyte, 8 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 16 * Megabyte, 16 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 32 * Megabyte, 32 * Megabyte, alignment })
@ -135,6 +135,8 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
engine_refresh_hz = 30
timing_fps_moving_avg_alpha = 0.9
ui_resize_border_width = 5
}
@ -359,6 +361,10 @@ tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32
}
}
config.timing_fps_moving_avg_alpha = 0.99
frametime_avg_ms = mov_avg_exp( f64(config.timing_fps_moving_avg_alpha), frametime_elapsed_ms, frametime_avg_ms )
fps_avg = 1 / (frametime_avg_ms * MS_To_S)
if frametime_elapsed_ms > 60.0 {
log( str_fmt_tmp("Big tick! %v ms", frametime_elapsed_ms), LogLevel.Warning )
}

View File

@ -2,14 +2,23 @@ package sectr
import "core:math/linalg"
pos_within_range2 :: proc( pos : Vec2, range : Range2 ) -> b32 {
within_x := pos.x > range.min.x && pos.x < range.max.x
within_y := pos.y > range.min.y && pos.y < range.max.y
return b32(within_x && within_y)
// AABB: Separating Axis Theorem
intersects_range2 :: #force_inline proc "contextless" ( a, b: Range2 ) -> bool
{
// Check if there's no overlap on the x-axis
if a.max.x < b.min.x || b.max.x < a.min.x {
return false; // No overlap on x-axis means no intersection
}
// Check if there's no overlap on the y-axis
if a.max.y < b.min.y || b.max.y < a.min.y {
return false; // No overlap on y-axis means no intersection
}
// If neither of the above conditions are true, there's at least a partial overlap
return true;
}
// TODO(Ed): Do we need this? Also does it even work (looks unfinished)?
is_within_screenspace :: proc( pos : Vec2 ) -> b32 {
is_within_screenspace :: #force_inline proc "contextless" ( pos : Vec2 ) -> b32 {
state := get_state(); using state
screen_extent := state.app_window.extent
cam := & project.workspace.cam
@ -18,13 +27,14 @@ is_within_screenspace :: proc( pos : Vec2 ) -> b32 {
return within_x_bounds && within_y_bounds
}
within_range2 :: #force_inline proc ( a, b : Range2 ) -> bool {
a_half_size := size_range2( a ) * 0.5
b_half_size := size_range2( b ) * 0.5
a_center := a.p0 + { a_half_size.x, -a_half_size.y }
b_center := b.p0 + { b_half_size.x, -b_half_size.y }
within_x := abs(a_center.x - b_center.x) <= (a_half_size.x + b_half_size.y)
within_y := abs(a_center.y - b_center.y) <= (a_half_size.y + b_half_size.y)
within_range2 :: #force_inline proc "contextless" ( a, b : Range2 ) -> bool {
within_x := b.min.x >= a.min.x && b.max.x <= a.max.x
within_y := b.min.y >= a.min.y && b.max.y <= a.max.y
return within_x && within_y
}
pos_within_range2 :: #force_inline proc "contextless" ( pos : Vec2, range : Range2 ) -> b32 {
within_x := pos.x > range.min.x && pos.x < range.max.x
within_y := pos.y > range.min.y && pos.y < range.max.y
return b32(within_x && within_y)
}

View File

@ -137,6 +137,8 @@ AppConfig :: struct {
engine_refresh_hz : uint,
timing_fps_moving_avg_alpha : f32,
ui_resize_border_width : f32,
}
@ -169,12 +171,13 @@ State :: struct {
sleep_is_granular : b32,
frametime_delta_seconds : f64,
frametime_delta_ms : f64,
frametime_delta_ns : Duration,
frametime_target_ms : f64,
frametime_elapsed_ms : f64,
frametime_delta_seconds : f64,
frametime_delta_ms : f64,
frametime_delta_ns : Duration,
frametime_target_ms : f64,
frametime_elapsed_ms : f64,
frametime_avg_ms : f64,
fps_avg : f64,
font_firacode : FontID,
font_squidgy_slimes : FontID,

View File

@ -104,6 +104,11 @@ draw_text :: proc {
draw_text_string_cached,
}
mov_avg_exp :: proc {
mov_avg_exp_f32,
mov_avg_exp_f64,
}
get_bounds :: proc {
view_get_bounds,
}

View File

@ -82,7 +82,7 @@ zpl_hmap_destroy :: proc( using self : ^ HMapZPL( $ Type ) ) {
}
}
zpl_hmap_get :: proc( using self : ^ HMapZPL( $ Type ), key : u64 ) -> ^ Type
zpl_hmap_get :: proc ( using self : ^ HMapZPL( $ Type ), key : u64 ) -> ^ Type
{
// profile(#procedure)
id := zpl_hmap_find( self, key ).entry_index

View File

@ -7,11 +7,23 @@ Axis2 :: enum i32 {
Count,
}
is_power_of_two_u32 :: proc( value : u32 ) -> b32
is_power_of_two_u32 :: #force_inline proc "contextless" ( value : u32 ) -> b32
{
return value != 0 && ( value & ( value - 1 )) == 0
}
mov_avg_exp_f32 := #force_inline proc "contextless" ( alpha, delta_interval, last_value : f32 ) -> f32
{
result := (delta_interval * alpha) + (delta_interval * (1.0 - alpha))
return result
}
mov_avg_exp_f64 := #force_inline proc "contextless" ( alpha, delta_interval, last_value : f64 ) -> f64
{
result := (delta_interval * alpha) + (delta_interval * (1.0 - alpha))
return result
}
import "core:math/linalg"
Vec2 :: linalg.Vector2f32

17
code/render.odin Normal file
View File

@ -0,0 +1,17 @@
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
}

View File

@ -32,53 +32,53 @@ when ODIN_OS == OS_Type.Windows {
// return points *
// }
f32_cm_to_pixels :: proc(cm: f32) -> f32 {
f32_cm_to_pixels :: #force_inline proc "contextless"(cm: f32) -> f32 {
screen_ppcm := get_state().app_window.ppcm
return cm * screen_ppcm
}
f32_pixels_to_cm :: proc(pixels: f32) -> f32 {
f32_pixels_to_cm :: #force_inline proc "contextless"(pixels: f32) -> f32 {
screen_ppcm := get_state().app_window.ppcm
cm_per_pixel := 1.0 / screen_ppcm
return pixels * cm_per_pixel
}
f32_points_to_pixels :: proc(points: f32) -> f32 {
f32_points_to_pixels :: #force_inline proc "contextless"(points: f32) -> f32 {
screen_ppcm := get_state().app_window.ppcm
cm_per_pixel := 1.0 / screen_ppcm
return points * DPT_PPCM * cm_per_pixel
}
f32_pixels_to_points :: proc(pixels: f32) -> f32 {
f32_pixels_to_points :: #force_inline proc "contextless"(pixels: f32) -> f32 {
screen_ppcm := get_state().app_window.ppcm
cm_per_pixel := 1.0 / screen_ppcm
return pixels * cm_per_pixel * Points_Per_CM
}
vec2_cm_to_pixels :: proc(v: Vec2) -> Vec2 {
vec2_cm_to_pixels :: #force_inline proc "contextless"(v: Vec2) -> Vec2 {
screen_ppcm := get_state().app_window.ppcm
return v * screen_ppcm
}
vec2_pixels_to_cm :: proc(v: Vec2) -> Vec2 {
vec2_pixels_to_cm :: #force_inline proc "contextless"(v: Vec2) -> Vec2 {
screen_ppcm := get_state().app_window.ppcm
cm_per_pixel := 1.0 / screen_ppcm
return v * cm_per_pixel
}
vec2_points_to_pixels :: proc(vpoints: Vec2) -> Vec2 {
vec2_points_to_pixels :: #force_inline proc "contextless"(vpoints: Vec2) -> Vec2 {
screen_ppcm := get_state().app_window.ppcm
cm_per_pixel := 1.0 / screen_ppcm
return vpoints * DPT_PPCM * cm_per_pixel
}
range2_cm_to_pixels :: proc( range : Range2 ) -> Range2 {
range2_cm_to_pixels :: #force_inline proc "contextless"( range : Range2 ) -> Range2 {
screen_ppcm := get_state().app_window.ppcm
result := Range2 { pts = { range.min * screen_ppcm, range.max * screen_ppcm }}
return result
}
range2_pixels_to_cm :: proc( range : Range2 ) -> Range2 {
range2_pixels_to_cm :: #force_inline proc "contextless"( range : Range2 ) -> Range2 {
screen_ppcm := get_state().app_window.ppcm
cm_per_pixel := 1.0 / screen_ppcm
result := Range2 { pts = { range.min * cm_per_pixel, range.max * cm_per_pixel }}
@ -132,7 +132,7 @@ screen_size :: proc "contextless" () -> AreaSize {
return transmute(AreaSize) ( extent * 2.0 )
}
screen_get_corners :: proc() -> BoundsCorners2 {
screen_get_corners :: #force_inline proc "contextless"() -> BoundsCorners2 {
state := get_state(); using state
screen_extent := state.app_window.extent
top_left := Vec2 { -screen_extent.x, screen_extent.y }
@ -142,16 +142,17 @@ screen_get_corners :: proc() -> BoundsCorners2 {
return { top_left, top_right, bottom_left, bottom_right }
}
view_get_bounds :: proc() -> Range2 {
state := get_state(); using state
cam := & project.workspace.cam
screen_extent := state.app_window.extent
top_left := Vec2 { cam.target.x, -cam.target.y } + Vec2 { -screen_extent.x, screen_extent.y} * (1/cam.zoom)
bottom_right := Vec2 { cam.target.x, -cam.target.y } + Vec2 { screen_extent.x, -screen_extent.y} * (1/cam.zoom)
return range2(top_left, bottom_right)
view_get_bounds :: #force_inline proc "contextless"() -> Range2 {
state := get_state(); using state
cam := & project.workspace.cam
screen_extent := state.app_window.extent
cam_zoom_ratio := 1.0 / cam.zoom
bottom_left := Vec2 { cam.target.x, -cam.target.y } + Vec2 { -screen_extent.x, -screen_extent.y} * cam_zoom_ratio
top_right := Vec2 { cam.target.x, -cam.target.y } + Vec2 { screen_extent.x, screen_extent.y} * cam_zoom_ratio
return range2( bottom_left, top_right )
}
view_get_corners :: proc() -> BoundsCorners2 {
view_get_corners :: #force_inline proc "contextless"() -> BoundsCorners2 {
state := get_state(); using state
cam := & project.workspace.cam
cam_zoom_ratio := 1.0 / cam.zoom
@ -170,22 +171,22 @@ screen_to_world :: #force_inline proc "contextless" (pos: Vec2) -> Vec2 {
return result
}
screen_to_render :: proc(pos: Vec2) -> Vec2 {
screen_to_render :: #force_inline proc "contextless"(pos: Vec2) -> Vec2 {
screen_extent := transmute(Vec2) get_state().project.workspace.cam.offset
return pos + { screen_extent.x, -screen_extent.y }
}
world_screen_extent :: proc() -> Extents2 {
world_screen_extent :: #force_inline proc "contextless"() -> Extents2 {
state := get_state(); using state
cam_zoom_ratio := 1.0 / project.workspace.cam.zoom
return app_window.extent * cam_zoom_ratio
}
world_to_screen_pos :: proc(position: Vec2) -> Vec2 {
world_to_screen_pos :: #force_inline proc "contextless"(position: Vec2) -> Vec2 {
return { position.x, position.y * -1 }
}
world_to_screen_no_zoom :: proc(position: Vec2) -> Vec2 {
world_to_screen_no_zoom :: #force_inline proc "contextless"(position: Vec2) -> Vec2 {
state := get_state(); using state
cam_zoom_ratio := 1.0 / state.project.workspace.cam.zoom
return { position.x, position.y * -1 } * cam_zoom_ratio

View File

@ -4,6 +4,7 @@ import "core:fmt"
import rl "vendor:raylib"
//@(optimization_mode="speed")
render :: proc()
{
profile(#procedure)
@ -23,7 +24,7 @@ render :: proc()
//region Render Screenspace
{
profile("Render Screenspace")
fps_msg := str_fmt_tmp( "FPS: %f", 1 / (frametime_elapsed_ms * MS_To_S) )
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_pos := screen_get_corners().top_right - { fps_msg_width, 0 }
debug_draw_text( fps_msg, fps_msg_pos, 16.0, color = rl.GREEN )
@ -77,21 +78,21 @@ render :: proc()
ui := project.workspace.ui
debug_text("Box Count: %v", ui.built_box_count )
// debug_text("Box Count: %v", ui.built_box_count )
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
active_box := ui_box_from_key( ui.curr_cache, ui.active )
if hot_box != nil {
debug_text("Hot Box : %v", hot_box.label.str )
debug_text("Hot Range2: %v", hot_box.computed.bounds.pts)
// debug_text("Hot Range2: %v", hot_box.computed.bounds.pts)
}
if active_box != nil{
debug_text("Active Box: %v", active_box.label.str )
// debug_text("Active Box: %v", active_box.label.str )
}
// debug_text("Active Resizing: %v", ui.active_start_signal.resizing)
view := view_get_bounds()
debug_text("View Bounds (World): %v", view.pts )
// debug_text("View Bounds (World): %v", view.pts )
debug.draw_debug_text_y = 50
}
@ -122,9 +123,9 @@ render_mode_2d :: proc()
}}
view_rect := rl.Rectangle {
render_view.min.x,
render_view.min.y,
render_view.max.x - render_view.min.x,
render_view.max.y - render_view.min.y,
render_view.max.y,
abs(render_view.max.x - render_view.min.x),
abs(render_view.max.y - render_view.min.y),
}
rl.DrawRectangleRounded( view_rect, 0.3, 9, { 255, 0, 0, 20 } )
}
@ -141,7 +142,7 @@ render_mode_2d :: proc()
current := root.first
for ; current != nil; current = ui_box_tranverse_next( current )
{
profile("Box")
// profile("Box")
parent := current.parent
style := current.style
@ -149,18 +150,25 @@ render_mode_2d :: proc()
computed_size := computed.bounds.p1 - computed.bounds.p0
if ! within_range2( view_bounds, computed.bounds ) {
if ! intersects_range2( view_bounds, computed.bounds ) {
continue
}
// TODO(Ed) : Render Borders
// profile_begin("Calculating Raylib rectangles")
render_anchors := range2(
world_to_screen_pos(computed.anchors.min),
world_to_screen_pos(computed.anchors.max),
)
render_margins := range2(
world_to_screen_pos(computed.margins.min),
world_to_screen_pos(computed.margins.max),
)
render_bounds := range2(
world_to_screen_pos(computed.bounds.min),
world_to_screen_pos(computed.bounds.max),
)
render_padding := range2(
world_to_screen_pos(computed.padding.min),
world_to_screen_pos(computed.padding.max),
@ -170,24 +178,11 @@ render_mode_2d :: proc()
world_to_screen_pos(computed.content.max),
)
rect_bounds := rl.Rectangle {
render_bounds.min.x,
render_bounds.max.y,
abs(render_bounds.max.x - render_bounds.min.x),
abs(render_bounds.max.y - render_bounds.min.y),
}
rect_padding := rl.Rectangle {
render_padding.min.x,
render_padding.max.y,
abs(render_padding.max.x - render_padding.min.x),
abs(render_padding.max.y - render_padding.min.y),
}
rect_content := rl.Rectangle {
render_content.min.x,
render_content.max.y,
abs(render_content.max.x - render_content.min.x),
abs(render_content.max.y - render_content.min.y),
}
rect_anchors := range2_to_rl_rect( render_anchors )
rect_margins := range2_to_rl_rect( render_margins )
rect_bounds := range2_to_rl_rect( render_bounds )
rect_padding := range2_to_rl_rect( render_padding )
rect_content := range2_to_rl_rect( render_content )
// profile_end()
draw_rectangle :: #force_inline proc "contextless" ( rect : rl.Rectangle, style : UI_Style ) {

View File

@ -4,6 +4,7 @@ import "base:runtime"
import "core:math"
import "core:math/linalg"
import "core:os"
import str "core:strings"
import rl "vendor:raylib"
@ -63,6 +64,7 @@ frametime_delta32 :: #force_inline proc "contextless" () -> f32 {
return cast(f32) get_state().frametime_delta_seconds
}
//@(optimization_mode="speed")
update :: proc( delta_time : f64 ) -> b32
{
profile(#procedure)
@ -205,7 +207,7 @@ update :: proc( delta_time : f64 ) -> b32
}
default_layout := UI_Layout {
anchor = {},
alignment = { 0.0, 0.0 },
alignment = { 0., 0.0 },
text_alignment = { 0.0, 0.0 },
// corner_radii = { 0.2, 0.2, 0.2, 0.2 },
pos = { 0, 0 },
@ -240,7 +242,7 @@ update :: proc( delta_time : f64 ) -> b32
// test_text_box()
// test_parenting()
if true
if false
{
// frame := ui_widget( "Frame", {} )
// ui_parent(frame)
@ -292,11 +294,11 @@ update :: proc( delta_time : f64 ) -> b32
}
child_layout := default_layout
child_layout.size = range2({ 75, 75 }, { 0, 0 })
child_layout.alignment = { 0.5, 0.0 }
child_layout.size = range2({ 0, 0 }, { 0, 0 })
child_layout.alignment = { 0.5, 0.5 }
child_layout.margins = { 20, 20, 20, 20 }
child_layout.padding = {}
child_layout.anchor = range2({ 0.0, 0.0 }, { 0.0, 1.0 })
child_layout.anchor = range2({ 0.0, 0.0 }, { 0.0, 0.0 })
child_layout.pos = { 0, 0 }
child_theme := frame_style_default
@ -310,16 +312,19 @@ update :: proc( delta_time : f64 ) -> b32
}
// Whitespace AST test
if false
if true
{
profile("Whitespace AST test")
text_style := frame_style_default
text_style.flags = {
.Size_To_Text,
.Origin_At_Anchor_Center,
.Fixed_Position_X, .Fixed_Position_Y,
// .Fixed_Width, .Fixed_Height,
}
text_style.text_alignment = { 0.0, 0.5 }
text_style.alignment = { 0.0, 1.0 }
text_style.size.min = { 1600, 30 }
text_theme := UI_StyleTheme { styles = {
text_style,
@ -332,7 +337,7 @@ update :: proc( delta_time : f64 ) -> b32
text_theme.hot.bg_color = Color_Frame_Hover
text_theme.active.bg_color = Color_Frame_Select
layout_text := default_layout
layout_text := text_style.layout
ui_style_theme( text_theme )
@ -347,65 +352,114 @@ update :: proc( delta_time : f64 ) -> b32
// index := 0
widgets : Array(UI_Widget)
widgets, alloc_error = array_init( UI_Widget, frame_slab_allocator() )
widgets, alloc_error = array_init_reserve( UI_Widget, frame_slab_allocator(), Kilobyte * 4 )
widgets_ptr := & widgets
label_id := 0
line_id := 0
for line in array_to_slice_num( debug.lorem_parse.lines )
{
profile("WS AST Line")
head := line.first
for ; head != nil;
{
ui_style_theme_set_layout( layout_text )
widget : UI_Widget
// We're assumping PWS_Token for now...
// Eventually I'm going to flatten this, its not worth doing it the way I am...
#partial switch head.type
{
case .Visible:
label := str_intern( str_fmt_alloc( "%v %v", head.content.str, label_id ))
widget = ui_text( label.str, head.content )
label_id += 1
layout_text.pos.x += size_range2( widget.computed.bounds ).x
case .Spaces:
label := str_intern( str_fmt_alloc( "%v %v", "space", label_id ))
widget = ui_space( label.str )
label_id += 1
for idx in 1 ..< len( head.content.runes )
{
// TODO(Ed): VIRTUAL WHITESPACE
// widget.style.layout.size.x += range2_size( widget.computed.bounds )
}
layout_text.pos.x += size_range2( widget.computed.bounds ).x
case .Tabs:
label := str_intern( str_fmt_alloc( "%v %v", "tab", label_id ))
widget = ui_tab( label.str )
label_id += 1
for idx in 1 ..< len( head.content.runes )
{
// widget.style.layout.size.x += range2_size( widget.computed.bounds )
}
layout_text.pos.x += size_range2( widget.computed.bounds ).x
}
array_append( widgets_ptr, widget )
head = head.next
if line_id == 0 {
line_id += 1
continue
}
layout_text.pos.x = default_layout.pos.x
layout_text.pos.y -= 30
ui_style_theme_set_layout( layout_text )
line_hbox := ui_widget(str_fmt_alloc( "line %v", line_id ), {})
if line_hbox.key == ui.hot
{
line_hbox.text = StringCached {}
ui_parent(line_hbox)
chunk_layout := layout_text
chunk_layout.alignment = { 0.0, 1.0 }
chunk_layout.anchor = range2({ 0.0, 0 }, { 0.0, 0 })
chunk_layout.pos = {}
chunk_style := text_style
chunk_style.flags = { .Fixed_Position_X, .Size_To_Text }
chunk_style.layout = chunk_layout
chunk_theme := UI_StyleTheme { styles = {
chunk_style,
chunk_style,
chunk_style,
chunk_style,
}}
ui_style_theme( chunk_theme )
head := line.first
for ; head != nil;
{
ui_style_theme_set_layout( chunk_layout )
widget : UI_Widget
#partial switch head.type
{
case .Visible:
label := str_intern( str_fmt_alloc( "%v %v", head.content.str, label_id ))
widget = ui_text( label.str, head.content )
label_id += 1
chunk_layout.pos.x += size_range2( widget.computed.bounds ).x
case .Spaces:
label := str_intern( str_fmt_alloc( "%v %v", "space", label_id ))
widget = ui_text_spaces( label.str )
label_id += 1
for idx in 1 ..< len( head.content.runes )
{
// TODO(Ed): VIRTUAL WHITESPACE
// widget.style.layout.size.x += range2_size( widget.computed.bounds )
}
chunk_layout.pos.x += size_range2( widget.computed.bounds ).x
case .Tabs:
label := str_intern( str_fmt_alloc( "%v %v", "tab", label_id ))
widget = ui_text_tabs( label.str )
label_id += 1
for idx in 1 ..< len( head.content.runes )
{
// widget.style.layout.size.x += range2_size( widget.computed.bounds )
}
chunk_layout.pos.x += size_range2( widget.computed.bounds ).x
}
array_append( widgets_ptr, widget )
head = head.next
}
line_hbox.style.size.min.x = chunk_layout.pos.x
}
else
{
builder_backing : [16 * Kilobyte] byte
builder := str.builder_from_bytes( builder_backing[:] )
line_hbox.style.flags |= { .Size_To_Text }
head := line.first.next
for ; head != nil;
{
str.write_string( & builder, head.content.str )
head = head.next
}
line_hbox.text = str_intern( to_string( builder ) )
}
array_append( widgets_ptr, line_hbox )
layout_text.pos.x = text_style.layout.pos.x
layout_text.pos.y += size_range2(line_hbox.computed.bounds).y
line_id += 1
}
label_id += 1
label_id += 1 // Dummy action
}
}
//endregion Imgui Tick

View File

@ -183,6 +183,10 @@ UI_StyleFlag :: enum u32 {
Fixed_Width,
Fixed_Height,
// Sets the (0, 0) position of the child box to the parents anchor's center (post-margins bounds)
// By Default, the origin is at the top left of the anchor's bounds
Origin_At_Anchor_Center,
// Will size the box to its text. (Padding & Margins will thicken )
Size_To_Text,
Text_Wrap,
@ -340,7 +344,7 @@ ui_reload :: proc( ui : ^ UI_State, cache_allocator : Allocator )
ui_shutdown :: proc() {
}
ui_box_equal :: proc( a, b : ^ UI_Box ) -> b32 {
ui_box_equal :: #force_inline proc "contextless" ( a, b : ^ UI_Box ) -> b32 {
BoxSize :: size_of(UI_Box)
result : b32 = true
@ -349,10 +353,11 @@ ui_box_equal :: proc( a, b : ^ UI_Box ) -> b32 {
return result
}
ui_box_from_key :: proc( cache : ^HMapZPL(UI_Box), key : UI_Key ) -> (^UI_Box) {
ui_box_from_key :: #force_inline proc ( cache : ^HMapZPL(UI_Box), key : UI_Key ) -> (^UI_Box) {
return zpl_hmap_get( cache, cast(u64) key )
}
//@(optimization_mode="speed")
ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
{
// profile(#procedure)
@ -407,8 +412,10 @@ 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
if box.first != nil {
if intersects_range2( view_get_bounds(), box.computed.bounds) && box.first != nil
{
return box.first
}
@ -479,7 +486,8 @@ ui_graph_build :: proc( ui : ^ UI_State ) {
ui_graph_build_begin( ui )
}
ui_key_from_string :: proc( value : string ) -> UI_Key
//@(optimization_mode="speed")
ui_key_from_string :: #force_inline proc "contextless" ( value : string ) -> UI_Key
{
// profile(#procedure)
USE_RAD_DEBUGGERS_METHOD :: true

View File

@ -3,6 +3,8 @@ package sectr
import "core:math"
import "core:math/linalg"
// Note(Ed): This is naturally pretty expensive
//@(optimization_mode="speed")
ui_compute_layout :: proc()
{
profile(#procedure)
@ -21,7 +23,7 @@ ui_compute_layout :: proc()
current := root.first
for ; current != nil;
{
profile("Layout Box")
// profile("Layout Box")
style := current.style
// These are used to choose via multiplication weather to apply
@ -118,15 +120,18 @@ ui_compute_layout :: proc()
// 5. Determine relative position
// TODO(Ed): Let the user determine the coordinate space origin?
// rel_pos := margined_bounds_origin + alignment_offset + layout.pos
rel_pos := margined_bounds_origin + layout.pos
origin_center := margined_bounds_origin
origin_top_left := Vec2 { margined_bounds.min.x, margined_bounds.max.y }
origin := .Origin_At_Anchor_Center in style.flags ? origin_center : origin_top_left
rel_pos := origin + layout.pos
if .Fixed_Position_X in style.flags {
rel_pos.x = parent_center.x + layout.pos.x
rel_pos.x = origin.x + layout.pos.x
}
if .Fixed_Position_Y in style.flags {
rel_pos.y = parent_center.y + layout.pos.y
rel_pos.y = origin.y + layout.pos.y
}
vec2_one := Vec2 { 1, 1 }

View File

@ -1,5 +1,6 @@
package sectr
//@(optimization_mode="speed")
ui_signal_from_box :: proc ( box : ^ UI_Box ) -> UI_Signal
{
// profile(#procedure)
@ -182,7 +183,6 @@ ui_signal_from_box :: proc ( box : ^ UI_Box ) -> UI_Signal
if ! was_active {
box.prev_style = box.style
box.style_delta = 0
log( str_fmt_tmp("NEW ACTIVE: %v", box.label.str))
}
box.style = stack_peek( & ui.theme_stack ).active
}

View File

@ -5,6 +5,7 @@ UI_Widget :: struct {
using signal : UI_Signal,
}
//@(optimization_mode="speed")
ui_widget :: proc( label : string, flags : UI_BoxFlags ) -> (widget : UI_Widget)
{
// profile(#procedure)
@ -14,6 +15,7 @@ ui_widget :: proc( label : string, flags : UI_BoxFlags ) -> (widget : UI_Widget)
return
}
//@(optimization_mode="speed")
ui_button :: proc( label : string, flags : UI_BoxFlags = {} ) -> (btn : UI_Widget)
{
// profile(#procedure)
@ -24,6 +26,7 @@ ui_button :: proc( label : string, flags : UI_BoxFlags = {} ) -> (btn : UI_Widge
return
}
//@(optimization_mode="speed")
ui_text :: proc( label : string, content : StringCached, flags : UI_BoxFlags = {} ) -> UI_Widget
{
// profile(#procedure)
@ -36,7 +39,8 @@ ui_text :: proc( label : string, content : StringCached, flags : UI_BoxFlags = {
return { box, signal }
}
ui_space :: proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget
//@(optimization_mode="speed")
ui_text_spaces :: proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget
{
// profile(#procedure)
state := get_state(); using state
@ -51,7 +55,8 @@ ui_space :: proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget
return { box, signal }
}
ui_tab :: proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget
//@(optimization_mode="speed")
ui_text_tabs :: proc( label : string, flags : UI_BoxFlags = {} ) -> UI_Widget
{
// profile(#procedure)
state := get_state(); using state

View File

@ -60,3 +60,199 @@ Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi laoreet bibendum finibus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Aenean ut elementum leo, eu luctus lorem.
Sed sit amet dapibus odio, at porttitor magna.
Cras id justo et risus porta eleifend.
Donec fringilla porta faucibus. Maecenas metus dolor, ornare eu justo sed, mattis porta ante.
Maecenas faucibus odio nisl, non posuere felis laoreet et.
Nullam tincidunt varius lacus sit amet laoreet.
Proin sodales vestibulum dolor, non condimentum arcu sodales nec.
Sed a tortor pharetra ante vehicula porta.
Maecenas congue venenatis euismod.
Suspendisse dapibus id lorem efficitur faucibus.
Aliquam consectetur urna in turpis consectetur, eu vehicula diam egestas.
Cras a semper metus, et porttitor tortor.
Aenean ac nisi consectetur, fermentum leo et, elementum odio.
Etiam imperdiet quam tellus, non suscipit lectus mattis ut. Nulla egestas urna vitae ex consectetur aliquam.
Maecenas vel luctus nibh. Morbi eget nisl justo.
Donec condimentum dolor id quam lacinia, vel ullamcorper mauris gravida.
Aliquam erat volutpat. Aliquam vitae neque venenatis, ultrices dui non, ornare velit.
Vivamus mollis ligula a ligula commodo ultrices.
Pellentesque ante felis, ultrices in risus eu, faucibus tincidunt ante.
Suspendisse potenti. Sed eget ligula mauris. Donec lorem est, porttitor auctor varius sed, lobortis nec eros.
Integer urna ligula, auctor ac sapien et, volutpat elementum leo.
Ut commodo arcu a turpis tempor, id semper justo egestas.
Aliquam erat volutpat.
Sed placerat malesuada eros.
Suspendisse egestas auctor magna a aliquam.
Pellentesque interdum pretium hendrerit.
Sed eget libero massa.
Nam egestas viverra odio, et ultrices risus scelerisque vel.
Nunc sodales laoreet elementum.
Mauris et risus nec erat placerat lobortis.
Donec ultrices eleifend mi.
Nullam tempus, felis at sodales finibus, libero mauris luctus sem, vehicula dictum lectus quam et lectus.
Phasellus et ligula nisl.
Sed dui enim, efficitur quis viverra nec, facilisis sed est.
Proin eget lectus diam.
Nullam in purus elementum, pharetra eros sed, volutpat metus.
Vestibulum pellentesque efficitur mauris, ut iaculis purus vehicula imperdiet.
Aliquam sit amet dolor id justo aliquam cursus.
Etiam mollis, tellus ut iaculis molestie, nunc libero feugiat arcu, vitae mattis neque leo a erat.
Pellentesque non ex interdum nulla faucibus tincidunt in vel magna.
Nam nec condimentum lacus, at pellentesque sem.
Pellentesque tristique pulvinar aliquet.
Sed varius dolor in sapien varius, sed blandit ipsum viverra.
Duis consectetur lacus dolor, non pellentesque enim pulvinar a.
Proin id leo vel ligula hendrerit facilisis.
Sed fringilla tellus est, non pretium sem consectetur fermentum.
Nam a tellus augue.
Suspendisse quis odio nibh.
Cras pellentesque turpis a mauris euismod, vel posuere enim eleifend.
Phasellus purus ex, mollis at ante at, convallis interdum tellus.
Proin at porttitor mauris, ut egestas ligula.
Suspendisse ultricies commodo lorem, quis auctor turpis efficitur ut.
Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi laoreet bibendum finibus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Aenean ut elementum leo, eu luctus lorem.
Sed sit amet dapibus odio, at porttitor magna.
Cras id justo et risus porta eleifend.
Donec fringilla porta faucibus. Maecenas metus dolor, ornare eu justo sed, mattis porta ante.
Maecenas faucibus odio nisl, non posuere felis laoreet et.
Nullam tincidunt varius lacus sit amet laoreet.
Proin sodales vestibulum dolor, non condimentum arcu sodales nec.
Sed a tortor pharetra ante vehicula porta.
Maecenas congue venenatis euismod.
Suspendisse dapibus id lorem efficitur faucibus.
Aliquam consectetur urna in turpis consectetur, eu vehicula diam egestas.
Cras a semper metus, et porttitor tortor.
Aenean ac nisi consectetur, fermentum leo et, elementum odio.
Etiam imperdiet quam tellus, non suscipit lectus mattis ut. Nulla egestas urna vitae ex consectetur aliquam.
Maecenas vel luctus nibh. Morbi eget nisl justo.
Donec condimentum dolor id quam lacinia, vel ullamcorper mauris gravida.
Aliquam erat volutpat. Aliquam vitae neque venenatis, ultrices dui non, ornare velit.
Vivamus mollis ligula a ligula commodo ultrices.
Pellentesque ante felis, ultrices in risus eu, faucibus tincidunt ante.
Suspendisse potenti. Sed eget ligula mauris. Donec lorem est, porttitor auctor varius sed, lobortis nec eros.
Integer urna ligula, auctor ac sapien et, volutpat elementum leo.
Ut commodo arcu a turpis tempor, id semper justo egestas.
Aliquam erat volutpat.
Sed placerat malesuada eros.
Suspendisse egestas auctor magna a aliquam.
Pellentesque interdum pretium hendrerit.
Sed eget libero massa.
Nam egestas viverra odio, et ultrices risus scelerisque vel.
Nunc sodales laoreet elementum.
Mauris et risus nec erat placerat lobortis.
Donec ultrices eleifend mi.
Nullam tempus, felis at sodales finibus, libero mauris luctus sem, vehicula dictum lectus quam et lectus.
Phasellus et ligula nisl.
Sed dui enim, efficitur quis viverra nec, facilisis sed est.
Proin eget lectus diam.
Nullam in purus elementum, pharetra eros sed, volutpat metus.
Vestibulum pellentesque efficitur mauris, ut iaculis purus vehicula imperdiet.
Aliquam sit amet dolor id justo aliquam cursus.
Etiam mollis, tellus ut iaculis molestie, nunc libero feugiat arcu, vitae mattis neque leo a erat.
Pellentesque non ex interdum nulla faucibus tincidunt in vel magna.
Nam nec condimentum lacus, at pellentesque sem.
Pellentesque tristique pulvinar aliquet.
Sed varius dolor in sapien varius, sed blandit ipsum viverra.
Duis consectetur lacus dolor, non pellentesque enim pulvinar a.
Proin id leo vel ligula hendrerit facilisis.
Sed fringilla tellus est, non pretium sem consectetur fermentum.
Nam a tellus augue.
Suspendisse quis odio nibh.
Cras pellentesque turpis a mauris euismod, vel posuere enim eleifend.
Phasellus purus ex, mollis at ante at, convallis interdum tellus.
Proin at porttitor mauris, ut egestas ligula.
Suspendisse ultricies commodo lorem, quis auctor turpis efficitur ut.
Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi laoreet bibendum finibus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Aenean ut elementum leo, eu luctus lorem.
Sed sit amet dapibus odio, at porttitor magna.
Cras id justo et risus porta eleifend.
Donec fringilla porta faucibus. Maecenas metus dolor, ornare eu justo sed, mattis porta ante.
Maecenas faucibus odio nisl, non posuere felis laoreet et.
Nullam tincidunt varius lacus sit amet laoreet.
Proin sodales vestibulum dolor, non condimentum arcu sodales nec.
Sed a tortor pharetra ante vehicula porta.
Maecenas congue venenatis euismod.
Suspendisse dapibus id lorem efficitur faucibus.
Aliquam consectetur urna in turpis consectetur, eu vehicula diam egestas.
Cras a semper metus, et porttitor tortor.
Aenean ac nisi consectetur, fermentum leo et, elementum odio.
Etiam imperdiet quam tellus, non suscipit lectus mattis ut. Nulla egestas urna vitae ex consectetur aliquam.
Maecenas vel luctus nibh. Morbi eget nisl justo.
Donec condimentum dolor id quam lacinia, vel ullamcorper mauris gravida.
Aliquam erat volutpat. Aliquam vitae neque venenatis, ultrices dui non, ornare velit.
Vivamus mollis ligula a ligula commodo ultrices.
Pellentesque ante felis, ultrices in risus eu, faucibus tincidunt ante.
Suspendisse potenti. Sed eget ligula mauris. Donec lorem est, porttitor auctor varius sed, lobortis nec eros.
Integer urna ligula, auctor ac sapien et, volutpat elementum leo.
Ut commodo arcu a turpis tempor, id semper justo egestas.
Aliquam erat volutpat.
Sed placerat malesuada eros.
Suspendisse egestas auctor magna a aliquam.
Pellentesque interdum pretium hendrerit.
Sed eget libero massa.
Nam egestas viverra odio, et ultrices risus scelerisque vel.
Nunc sodales laoreet elementum.
Mauris et risus nec erat placerat lobortis.
Donec ultrices eleifend mi.
Nullam tempus, felis at sodales finibus, libero mauris luctus sem, vehicula dictum lectus quam et lectus.
Phasellus et ligula nisl.
Sed dui enim, efficitur quis viverra nec, facilisis sed est.
Proin eget lectus diam.
Nullam in purus elementum, pharetra eros sed, volutpat metus.
Vestibulum pellentesque efficitur mauris, ut iaculis purus vehicula imperdiet.
Aliquam sit amet dolor id justo aliquam cursus.
Etiam mollis, tellus ut iaculis molestie, nunc libero feugiat arcu, vitae mattis neque leo a erat.
Pellentesque non ex interdum nulla faucibus tincidunt in vel magna.
Nam nec condimentum lacus, at pellentesque sem.
Pellentesque tristique pulvinar aliquet.
Sed varius dolor in sapien varius, sed blandit ipsum viverra.
Duis consectetur lacus dolor, non pellentesque enim pulvinar a.
Proin id leo vel ligula hendrerit facilisis.
Sed fringilla tellus est, non pretium sem consectetur fermentum.
Nam a tellus augue.
Suspendisse quis odio nibh.
Cras pellentesque turpis a mauris euismod, vel posuere enim eleifend.
Phasellus purus ex, mollis at ante at, convallis interdum tellus.
Proin at porttitor mauris, ut egestas ligula.
Suspendisse ultricies commodo lorem, quis auctor turpis efficitur ut.
Curabitur egestas laoreet mauris sed cursus.
Duis nec purus vel nibh venenatis dignissim.
Nam eget aliquam eros, vitae pellentesque neque.
Praesent mollis augue risus, ut commodo arcu auctor vel.

View File

@ -243,10 +243,10 @@ push-location $path_root
# $build_args += $flag_micro_architecture_native
# $build_args += $flag_use_separate_modules
$build_args += $flag_thread_count + $CoreCount_Physical
$build_args += $flag_optimize_none
# $build_args += $flag_optimize_none
# $build_args += $flag_optimize_minimal
# $build_args += $flag_optimize_speed
# $build_args += $falg_optimize_aggressive
$build_args += $falg_optimize_aggressive
$build_args += $flag_debug
$build_args += $flag_pdb_name + $pdb
$build_args += $flag_subsystem + 'windows'