Mostly cleanup

Text is athe biggest bottleneck right now. Raylib as a renderer fails for this prototype in that front.

I'll eventually need to look into other solutions such as SDL2 + something that renders UI boxes & text very fast...
This commit is contained in:
2024-05-13 21:53:08 -04:00
parent adc75f6977
commit 12c99bee26
16 changed files with 940 additions and 183 deletions

View File

@ -64,48 +64,25 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
alignment := uint(mem.DEFAULT_ALIGNMENT)
policy_ptr := & default_slab_policy
if false
{
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 4 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 32 * Megabyte, 16 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 32 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 64 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 128 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 256 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 512 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 1 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 2 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 4 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 8 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 16 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 32 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 256 * Megabyte, 64 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 256 * Megabyte, 128 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 512 * Megabyte, 256 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment })
}
else
{
push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 1 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 256 * Kilobyte, 2 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 512 * Kilobyte, 4 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 1 * Megabyte, 16 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 1 * Megabyte, 32 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 1 * Megabyte, 64 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 128 * Kilobyte, alignment })
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 { 8 * Megabyte, 8 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 16 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 32 * Megabyte, 32 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 64 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 128 * Megabyte, 128 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 256 * Megabyte, 256 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment })
}
push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 1 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 256 * Kilobyte, 2 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 512 * Kilobyte, 4 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 1 * Megabyte, 16 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 1 * Megabyte, 32 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 1 * Megabyte, 64 * Kilobyte, alignment })
push( policy_ptr, SlabSizeClass { 2 * Megabyte, 128 * Kilobyte, alignment })
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 { 8 * Megabyte, 8 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 16 * Megabyte, 16 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 32 * Megabyte, 32 * Megabyte, alignment })
push( policy_ptr, SlabSizeClass { 64 * Megabyte, 64 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 128 * Megabyte, 128 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 256 * Megabyte, 256 * Megabyte, alignment })
// push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment })
alloc_error : AllocatorError
persistent_slab, alloc_error = slab_init( policy_ptr, allocator = persistent_allocator(), dbg_name = Persistent_Slab_DBG_Name )
@ -238,7 +215,9 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
verify( alloc_error == .None, "Faield to parse due to allocation failure" )
// Render texture test
debug.viewport_rt = rl.LoadRenderTexture( 1280, 720 )
// debug.viewport_rt = rl.LoadRenderTexture( 1280, 720 )
// debug.proto_text_shader = rl.LoadShader( "C:/projects/SectrPrototype/code/shaders/text_shader.vs", "C:/projects/SectrPrototype/code/shaders/text_shader.fs" )
}
startup_ms := duration_ms( time.tick_lap_time( & startup_tick))
@ -340,9 +319,9 @@ tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32
rl.PollInputEvents()
debug.draw_ui_box_bounds_points = true
debug.draw_UI_padding_bounds = true
debug.draw_ui_content_bounds = true
debug.draw_ui_box_bounds_points = false
debug.draw_UI_padding_bounds = false
debug.draw_ui_content_bounds = false
should_close = update( host_delta_time )
render()
@ -353,8 +332,8 @@ tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32
// Timing
{
// profile("Client tick timing processing")
config.engine_refresh_hz = uint(monitor_refresh_hz)
// config.engine_refresh_hz = 1
// config.engine_refresh_hz = uint(monitor_refresh_hz)
config.engine_refresh_hz = 120
frametime_target_ms = 1.0 / f64(config.engine_refresh_hz) * S_To_MS
sub_ms_granularity_required := frametime_target_ms <= Frametime_High_Perf_Threshold_MS

View File

@ -36,4 +36,6 @@ DebugData :: struct {
// Test 3d Viewport
cam_vp : rl.Camera3D,
viewport_rt : rl.RenderTexture,
}
proto_text_shader : rl.Shader
}

View File

@ -63,7 +63,7 @@ str_cache_init :: proc( /*allocator : Allocator*/ ) -> ( cache : StringCache ) {
cache.slab, alloc_error = slab_init( & policy, allocator = persistent_allocator(), dbg_name = dbg_name )
verify(alloc_error == .None, "Failed to initialize the string cache" )
cache.table, alloc_error = zpl_hmap_init_reserve( StrRunesPair, persistent_allocator(), 1 * Megabyte, dbg_name )
cache.table, alloc_error = zpl_hmap_init_reserve( StrRunesPair, persistent_allocator(), 4 * Megabyte, dbg_name )
return
}

View File

@ -89,9 +89,9 @@ PWS_ParseError :: struct {
}
PWS_ParseError_Max :: 32
PWS_TokenArray_ReserveSize :: 8
PWS_NodeArray_ReserveSize :: 8
PWS_LineArray_ReserveSize :: 8
PWS_TokenArray_ReserveSize :: 64 * Kilobyte
PWS_NodeArray_ReserveSize :: 64 * Kilobyte
PWS_LineArray_ReserveSize :: 64 * Kilobyte
// TODO(Ed) : The ast arrays should be handled by a slab allocator dedicated to PWS_ASTs
// This can grow in undeterministic ways, persistent will get very polluted otherwise.

View File

@ -1,6 +1,7 @@
package sectr
import "core:math"
import "core:strings"
import "core:unicode/utf8"
import rl "vendor:raylib"
@ -85,7 +86,7 @@ ws_view_draw_text_string :: proc( content : string, pos : Vec2, size : f32, colo
zoom_adjust := px_size * project.workspace.cam.zoom
rl_font := to_rl_Font(font, zoom_adjust )
rl.SetTextureFilter(rl_font.texture, rl.TextureFilter.ANISOTROPIC_4X)
rl.SetTextureFilter(rl_font.texture, rl.TextureFilter.POINT)
rl.DrawTextCodepoints( rl_font,
raw_data(runes), cast(i32) len(runes),
position = transmute(rl.Vector2) pos,
@ -95,33 +96,56 @@ ws_view_draw_text_string :: proc( content : string, pos : Vec2, size : f32, colo
rl.SetTextureFilter(rl_font.texture, rl.TextureFilter.POINT)
}
ws_view_draw_text_StrRunesPair :: proc( content : StrRunesPair, pos : Vec2, size : f32, color : rl.Color = rl.WHITE, font : FontID = Font_Default )
when true
{
// profile(#procedure)
state := get_state(); using state
ws_view_draw_text_StrRunesPair :: proc( content : StrRunesPair, pos : Vec2, size : f32, color : rl.Color = rl.WHITE, font : FontID = Font_Default )
{
profile(#procedure)
state := get_state(); using state
if len( content.str ) == 0 {
return
if len( content.str ) == 0 {
return
}
font := font
if font.key == Font_Default.key {
font = default_font
}
pos := ws_view_to_render_pos(pos)
px_size := size
zoom_adjust := px_size * project.workspace.cam.zoom
rl_font := to_rl_Font(font, zoom_adjust )
runes := content.runes
profile_begin("raylib draw codepoints related")
// rl.DrawTextCodepoints( rl_font,
// raw_data(runes), cast(i32) len(runes),
// position = transmute(rl.Vector2) pos,
// fontSize = px_size,
// spacing = 0.0,
// tint = color );
rl.DrawTextEx(rl_font,
strings.clone_to_cstring(content.str),
position = transmute(rl.Vector2) pos,
fontSize = px_size,
spacing = 0.0,
tint = color
)
profile_end()
}
font := font
if font.key == Font_Default.key {
font = default_font
}
else
{
ws_view_draw_text_StrRunesPair :: proc( content : StrRunesPair, pos : Vec2, size : f32, color : rl.Color = rl.WHITE, font : FontID = Font_Default )
{
profile(#procedure)
state := get_state(); using state
// We need an alternative way to draw text to the screen (the above is way to expensive)
// Possibly need to watch handmade hero...
}
pos := ws_view_to_render_pos(pos)
px_size := size
zoom_adjust := px_size * project.workspace.cam.zoom
rl_font := to_rl_Font(font, zoom_adjust )
runes := content.runes
rl.SetTextureFilter(rl_font.texture, rl.TextureFilter.ANISOTROPIC_4X)
rl.DrawTextCodepoints( rl_font,
raw_data(runes), cast(i32) len(runes),
position = transmute(rl.Vector2) pos,
fontSize = px_size,
spacing = 0.0,
tint = color );
rl.SetTextureFilter(rl_font.texture, rl.TextureFilter.POINT)
}
// Raylib's equivalent doesn't take a length for the string (making it a pain in the ass)

View File

@ -0,0 +1,2 @@
package sectr

View File

@ -4,7 +4,7 @@ import "core:fmt"
import rl "vendor:raylib"
draw_rectangle :: #force_inline proc "contextless" ( rect : rl.Rectangle, box : ^UI_Box ) {
draw_rectangle :: #force_inline proc "contextless" ( rect : rl.Rectangle, box : ^UI_RenderBoxInfo ) {
using box
if style.corner_radii[0] > 0 {
rl.DrawRectangleRounded( rect, style.corner_radii[0], 9, style.bg_color )
@ -14,7 +14,7 @@ draw_rectangle :: #force_inline proc "contextless" ( rect : rl.Rectangle, box :
}
}
draw_rectangle_lines :: #force_inline proc "contextless" ( rect : rl.Rectangle, box : ^UI_Box, color : Color, thickness : f32 ) {
draw_rectangle_lines :: #force_inline proc "contextless" ( rect : rl.Rectangle, box : ^UI_RenderBoxInfo, color : Color, thickness : f32 ) {
using box
if style.corner_radii[0] > 0 {
rl.DrawRectangleRoundedLines( rect, style.corner_radii[0], 9, thickness, color )
@ -78,8 +78,8 @@ render_mode_2d_workspace :: proc()
vp_half_size := viewport_size * 0.5
viewport_box := range2( -vp_half_size, vp_half_size )
viewport_render := range2(
world_to_screen_pos( viewport_box.min),
world_to_screen_pos( viewport_box.max),
ws_view_to_render_pos( viewport_box.min),
ws_view_to_render_pos( viewport_box.max),
)
viewport_rect := range2_to_rl_rect( viewport_render )
rl.DrawTextureRec( debug.viewport_rt.texture, viewport_rect, -vp_half_size, Color_White )
@ -93,8 +93,8 @@ render_mode_2d_workspace :: proc()
when false
{
render_view := Range2 { pts = {
world_to_screen_pos( view_bounds.min),
world_to_screen_pos( view_bounds.max),
ws_view_to_render_pos( view_bounds.min),
ws_view_to_render_pos( view_bounds.max),
}}
view_rect := rl.Rectangle {
render_view.min.x,
@ -116,32 +116,17 @@ render_mode_2d_workspace :: proc()
state.ui_context = ui
current := root.first
for ; current != nil; current = ui_box_tranverse_next( current )
for & current in array_to_slice_num(ui.render_queue)
{
// profile("Box")
parent := current.parent
layout := current.layout
profile("Box")
style := current.style
computed := & current.computed
computed_size := computed.bounds.p1 - computed.bounds.p0
computed := current.computed
if ! intersects_range2( view_bounds, computed.bounds ) {
continue
}
// TODO(Ed) : Render Borders
// profile_begin("Calculating Raylib rectangles")
// render_anchors := range2(
// ws_view_to_render_pos(computed.anchors.min),
// ws_view_to_render_pos(computed.anchors.max),
// )
// render_margins := range2(
// ws_view_to_render_pos(computed.margins.min),
// ws_view_to_render_pos(computed.margins.max),
// )
profile_begin("render space calc")
render_bounds := range2(
ws_view_to_render_pos(computed.bounds.min),
ws_view_to_render_pos(computed.bounds.max),
@ -160,34 +145,31 @@ render_mode_2d_workspace :: proc()
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()
profile_end()
// profile_begin("rl.DrawRectangleRounded( rect_bounds, style.layout.corner_radii[0], 9, style.bg_color )")
profile_begin("raylib drawing")
if style.bg_color.a != 0
{
draw_rectangle( rect_bounds, current )
draw_rectangle( rect_bounds, & current )
}
if layout.border_width > 0 {
draw_rectangle_lines( rect_bounds, current, style.border_color, layout.border_width )
if current.border_width > 0 {
draw_rectangle_lines( rect_bounds, & current, style.border_color, current.border_width )
}
// profile_end()
line_thickness := 1 * cam_zoom_ratio
// 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 )
draw_rectangle_lines( rect_padding, & current, Color_Debug_UI_Padding_Bounds, line_thickness )
}
else if debug.draw_ui_content_bounds {
draw_rectangle_lines( rect_content, current, Color_Debug_UI_Content_Bounds, line_thickness )
draw_rectangle_lines( rect_content, & current, Color_Debug_UI_Content_Bounds, line_thickness )
}
// profile_end()
point_radius := 3 * cam_zoom_ratio
// 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,
@ -199,8 +181,10 @@ render_mode_2d_workspace :: proc()
}
// profile_end()
profile_end()
if len(current.text.str) > 0 {
ws_view_draw_text( current.text, ws_view_to_render_pos(computed.text_pos * {1, -1}), layout.font_size, style.text_color )
ws_view_draw_text( current.text, ws_view_to_render_pos(computed.text_pos * {1, -1}), current.font_size, style.text_color )
}
}
}
@ -314,6 +298,18 @@ render_mode_screenspace :: proc ()
// debug_text("View Bounds (World): %v", view.pts )
debug.draw_debug_text_y = 14
// Define the triangle vertices and colors
vertices := []f32{
// Positions // Colors (RGBA)
-0.5, -0.5, 0.0, 1.0, 0.0, 0.0, 1.0, // Vertex 1: Red
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
@ -336,28 +332,14 @@ render_screen_ui :: proc()
break Render_App_UI
}
// Sort roots children by top-level order
current := root.first
for ; current != nil; current = ui_box_tranverse_next( current )
for & current in array_to_slice_num(ui.render_queue)
{
// profile("Box")
parent := current.parent
style := current.style
layout := current.layout
computed := & current.computed
computed_size := computed.bounds.p1 - computed.bounds.p0
// render_anchors := range2(
// screen_to_render_pos(computed.anchors.min),
// screen_to_render_pos(computed.anchors.max),
// )
// render_margins := range2(
// screen_to_render_pos(computed.margins.min),
// screen_to_render_pos(computed.margins.max),
// )
render_bounds := range2(
screen_to_render_pos(computed.bounds.min),
screen_to_render_pos(computed.bounds.max),
@ -370,8 +352,6 @@ render_screen_ui :: proc()
screen_to_render_pos(computed.content.min),
screen_to_render_pos(computed.content.max),
)
// 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 )
@ -380,10 +360,10 @@ render_screen_ui :: proc()
// profile_begin("rl.DrawRectangleRounded( rect_bounds, style.layout.corner_radii[0], 9, style.bg_color )")
if style.bg_color.a != 0
{
draw_rectangle( rect_bounds, current )
draw_rectangle( rect_bounds, & current )
}
if layout.border_width > 0 {
draw_rectangle_lines( rect_bounds, current, style.border_color, layout.border_width )
if current.border_width > 0 {
draw_rectangle_lines( rect_bounds, & current, style.border_color, current.border_width )
}
// profile_end()
@ -391,10 +371,10 @@ render_screen_ui :: proc()
// 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 )
draw_rectangle_lines( rect_padding, & current, Color_Debug_UI_Padding_Bounds, line_thickness )
}
else if debug.draw_ui_content_bounds {
draw_rectangle_lines( rect_content, current, Color_Debug_UI_Content_Bounds, line_thickness )
draw_rectangle_lines( rect_content, & current, Color_Debug_UI_Content_Bounds, line_thickness )
}
// profile_end()
@ -415,7 +395,7 @@ render_screen_ui :: proc()
// profile_end()
if len(current.text.str) > 0 && style.font.key != 0 {
draw_text_screenspace( current.text, screen_to_render_pos(computed.text_pos), layout.font_size, style.text_color )
draw_text_screenspace( current.text, screen_to_render_pos(computed.text_pos), current.font_size, style.text_color )
}
}
}

View File

@ -200,7 +200,6 @@ update :: proc( delta_time : f64 ) -> b32
ui_screen_tick()
//region WorkspaceImgui Tick
if false
{
profile("Workspace Imgui")
@ -241,7 +240,7 @@ update :: proc( delta_time : f64 ) -> b32
// test_draggable()
// test_text_box()
// test_parenting( & default_layout, & frame_style_default )
// test_whitespace_ast( & default_layout, & frame_style_default )
test_whitespace_ast( & default_layout, & frame_style_default )
}
//endregion Workspace Imgui Tick

View File

@ -88,7 +88,7 @@ UI_Layout :: struct {
alignment : Vec2,
text_alignment : Vec2,
font_size : f32,
font_size : UI_Scalar,
margins : UI_LayoutSide,
padding : UI_LayoutSide,
@ -104,8 +104,6 @@ UI_Layout :: struct {
// (We can union either varient and just know based on checking if its the screenspace UI)
// If the box is a child of the root parent, its automatically in world space and thus will use the tile_pos.
// tile_pos : WS_Pos,
transition_time : f32,
}
UI_LayoutCombo :: struct #raw_union {

View File

@ -4,15 +4,11 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
ancestors_layout_required : b32 = false,
root_layout_required : b32 = false )
{
profile("Layout Box")
// profile("Layout Box")
state := get_state()
ui := state.ui_context
parent := box.parent
// TODO(Ed): Add support to premmtively compute ancestor's layouts
// if parent != ui.root && ! parent.computed.fresh {
// ui_box_compute_layout( parent )
// }
style := box.style
layout := & box.layout
@ -22,14 +18,14 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
// 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)
// 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)
size_to_text : bool = .Size_To_Text in layout.flags
computed := & box.computed
computed := & box.computed
parent_content := parent.computed.content
parent_content_size := parent_content.max - parent_content.min
@ -148,9 +144,7 @@ ui_box_compute_layout :: proc( box : ^UI_Box,
bounds.max - { layout.padding.right, layout.padding.top } - border_offset,
)
// computed.anchors = anchored_bounds
// computed.margins = margined_bounds
computed.bounds = bounds
computed.bounds = bounds
computed.padding = padding_bounds
computed.content = content_bounds
@ -197,7 +191,15 @@ ui_compute_layout :: proc( ui : ^UI_State )
for current := root.first; current != nil; current = ui_box_tranverse_next( current )
{
if current.computed.fresh do continue
ui_box_compute_layout( current )
if ! current.computed.fresh {
ui_box_compute_layout( current )
}
array_append( & ui.render_queue, UI_RenderBoxInfo {
current.computed,
current.style,
current.text,
current.layout.font_size,
current.layout.border_width,
})
}
}

View File

@ -13,7 +13,12 @@ UI_Signal :: struct {
keyboard_clicked : b8,
active : b8,
was_active : b8,
hot : b8,
disabled : b8,
was_active : b8,
was_hot : b8,
was_disabled : b8,
pressed : b8,
released : b8,
@ -205,7 +210,6 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
if is_hot
{
if ! was_hot {
box.prev_style = box.style
box.style_delta = 0
}
box.layout = ui_layout_peek().hot
@ -214,7 +218,6 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
if is_active
{
if ! was_active {
box.prev_style = box.style
box.style_delta = 0
}
box.layout = ui_layout_peek().active
@ -223,7 +226,6 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
if is_disabled
{
if ! was_disabled {
box.prev_style = box.style
box.style_delta = 0
}
box.layout = ui_layout_peek().disabled
@ -232,7 +234,6 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
if ! is_disabled && ! is_active && ! is_hot {
if was_disabled || was_active || was_hot {
box.prev_style = box.style
box.style_delta = 0
}
else {

View File

@ -37,10 +37,6 @@ UI_Style :: struct {
// TODO(Ed) : Support setting the cursor state
cursor : UI_Cursor,
// Used with style, prev_style, and style_delta to produce a simple interpolated animation
// Applied in the layout pass & the rendering pass for their associated fields.
transition_time : f32,
}
UI_StyleCombo :: struct #raw_union {

View File

@ -91,6 +91,14 @@ UI_InteractState :: struct {
UI_Key :: distinct u64
UI_RenderBoxInfo :: struct {
using computed : UI_Computed,
using style : UI_Style,
text : StrRunesPair,
font_size : UI_Scalar,
border_width : UI_Scalar,
}
UI_Scalar :: f32
UI_ScalarConstraint :: struct {
@ -119,20 +127,15 @@ UI_Box :: struct {
flags : UI_BoxFlags,
computed : UI_Computed,
// TODO(Ed): Move prev_layout out, this is no longer managed by the core UI, its managed by w/e is constructing the graph
prev_layout : UI_Layout,
layout : UI_Layout,
// TODO(Ed): Move prev_style out, this is no longer managed by the core UI, its managed by w/e is constructing the graph
prev_style : UI_Style,
style : UI_Style,
layout : UI_Layout,
style : UI_Style,
// Persistent Data
first_frame : b8, // TODO(Ed): Move to end if keeping as b8
hot_delta : f32,
active_delta : f32,
disabled_delta : f32,
style_delta : f32,
first_frame : b8,
// root_order_id : i16,
// prev_computed : UI_Computed,
@ -146,7 +149,7 @@ UI_Layout_Stack_Size :: 512
UI_Style_Stack_Size :: 512
UI_Parent_Stack_Size :: 512
// UI_Built_Boxes_Array_Size :: 8
UI_Built_Boxes_Array_Size :: 16 * Kilobyte
UI_Built_Boxes_Array_Size :: 128 * Kilobyte
UI_State :: struct {
// TODO(Ed) : Use these
@ -159,6 +162,8 @@ UI_State :: struct {
prev_cache : ^HMapZPL( UI_Box ),
curr_cache : ^HMapZPL( UI_Box ),
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,
@ -205,6 +210,10 @@ ui_startup :: proc( ui : ^ UI_State, cache_allocator : Allocator /* , cache_rese
ui.curr_cache = (& ui.caches[1])
ui.prev_cache = (& ui.caches[0])
allocation_error : AllocatorError
ui.render_queue, allocation_error = array_init_reserve( UI_RenderBoxInfo, cache_allocator, UI_Built_Boxes_Array_Size, fixed_cap = true )
verify( allocation_error == AllocatorError.None, "Failed to allocate render queue" )
log("ui_startup completed")
}
@ -365,6 +374,8 @@ ui_graph_build_begin :: proc( ui : ^ UI_State, bounds : Vec2 = {} )
get_state().ui_context = ui
using get_state().ui_context
array_clear( render_queue )
temp := prev_cache
prev_cache = curr_cache
curr_cache = temp