pushing what I have rn, decided not to go this route
Instead going with ![img](https://i.imgur.com/S3tjZUu.png)
This commit is contained in:
parent
e8c3312b69
commit
0744069b0d
@ -5,6 +5,9 @@
|
||||
},
|
||||
{
|
||||
"path": "scripts"
|
||||
},
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
|
@ -352,8 +352,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 = 10
|
||||
config.engine_refresh_hz = uint(monitor_refresh_hz)
|
||||
// config.engine_refresh_hz = 10
|
||||
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
|
||||
|
||||
|
@ -344,14 +344,17 @@ render_screen_ui :: proc()
|
||||
// Sort roots children by top-level order
|
||||
|
||||
current := root.first
|
||||
for ; current != nil; current = ui_box_tranverse_next( current, is_destructive = true )
|
||||
for ; current != nil; current = ui_box_tranverse_next( current, is_destructive = false )
|
||||
{
|
||||
// profile("Box")
|
||||
parent := current.parent
|
||||
if parent == ui.root && current.ancestors == -1 {
|
||||
// current.parent = nil
|
||||
// current.first = nil
|
||||
// current.last = nil
|
||||
// This is a deceased rooted box
|
||||
// Ignore it as its not constructed this frame
|
||||
// continue
|
||||
continue
|
||||
}
|
||||
|
||||
style := current.style
|
||||
@ -408,28 +411,6 @@ render_screen_ui :: proc()
|
||||
}
|
||||
// profile_end()
|
||||
|
||||
// if .Mouse_Resizable in current.flags
|
||||
// {
|
||||
// // profile("Resize Bounds")
|
||||
// resize_border_width := cast(f32) get_state().config.ui_resize_border_width
|
||||
// resize_percent_width := computed_size * (resize_border_width * 1.0/ 200.0)
|
||||
// resize_border_non_range := add(current.computed.bounds, range2(
|
||||
// { resize_percent_width.x, -resize_percent_width.x },
|
||||
// { -resize_percent_width.x, resize_percent_width.x }))
|
||||
|
||||
// render_resize := range2(
|
||||
// resize_border_non_range.min,
|
||||
// resize_border_non_range.max,
|
||||
// )
|
||||
// rect_resize := rl.Rectangle {
|
||||
// render_resize.min.x,
|
||||
// render_resize.min.y,
|
||||
// render_resize.max.x - render_resize.min.x,
|
||||
// render_resize.max.y - render_resize.min.y,
|
||||
// }
|
||||
// draw_rectangle_lines( rect_padding, current, Color_Red, line_thickness )
|
||||
// }
|
||||
|
||||
point_radius : f32 = 3
|
||||
|
||||
// profile_begin("circles")
|
||||
|
@ -6,14 +6,15 @@ import "core:math/linalg"
|
||||
// The UI_Box's actual positioning and sizing
|
||||
// There is an excess of rectangles here for debug puproses.
|
||||
UI_Computed :: struct {
|
||||
fresh : b32, // If the auto-layout has been computed for the current frame
|
||||
// anchors : Range2, // Bounds for anchors within parent
|
||||
// margins : Range2, // Bounds for margins within parent
|
||||
padding : Range2, // Bounds for padding's starting bounds (will be offset by border if there is one), only here for debug vis
|
||||
|
||||
bounds : Range2, // Bounds for box itself
|
||||
padding : Range2, // Bounds for padding's starting bounds (will be offset by border if there is one)
|
||||
content : Range2, // Bounds for content (text or children)
|
||||
text_pos : Vec2, // Position of text within content
|
||||
text_size : Vec2, // Size of text within content
|
||||
fresh : b32, // If the auto-layout has been computed for the current frame
|
||||
}
|
||||
|
||||
UI_LayoutDirectionX :: enum(i32) {
|
||||
@ -73,6 +74,7 @@ UI_LayoutFlag :: enum u32 {
|
||||
Size_To_Text,
|
||||
|
||||
// TODO(Ed): Implement this!
|
||||
// Wrap text around the box, text_alignment specifies the justification for its compostion when wrapping.
|
||||
Text_Wrap,
|
||||
|
||||
Count,
|
||||
|
@ -1,14 +1,15 @@
|
||||
package sectr
|
||||
|
||||
// Note(Ed): This is naturally pretty expensive
|
||||
|
||||
ui_box_compute_layout :: proc( box : ^UI_Box )
|
||||
ui_box_compute_layout :: proc( box : ^UI_Box,
|
||||
ancestors_layout_required : b32 = false,
|
||||
root_layout_required : b32 = false )
|
||||
{
|
||||
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 )
|
||||
// }
|
||||
@ -45,6 +46,9 @@ ui_box_compute_layout :: proc( box : ^UI_Box )
|
||||
If fixed size (X or Y):
|
||||
* Ignore Parent constraints (can only be clipped)
|
||||
|
||||
If an axis is auto-sized by a ratio of the other axis
|
||||
*
|
||||
|
||||
If auto-sized:
|
||||
* Enforce parent size constraint of bounds relative to
|
||||
where the adjusted content bounds are after applying margins & anchors.
|
||||
|
@ -69,10 +69,11 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
|
||||
// runtime.debug_trap()
|
||||
}
|
||||
|
||||
// Check to see if this box is active
|
||||
if mouse_clickable && signal.cursor_over && left_pressed && was_hot
|
||||
{
|
||||
top_ancestor := ui_top_ancestor(box)
|
||||
if ui.root.last != top_ancestor && false
|
||||
if ui.root.last != top_ancestor
|
||||
{
|
||||
// dll_full_pop(top_ancestor, top_ancestor.parent)
|
||||
// dll_full_push_back( top_ancestor.parent, top_ancestor, nil )
|
||||
@ -81,7 +82,7 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
|
||||
right := top_ancestor.next
|
||||
|
||||
if left != nil {
|
||||
left.next = top_ancestor.prev
|
||||
left.next = top_ancestor.next
|
||||
}
|
||||
else {
|
||||
// We are the first box on root,
|
||||
@ -92,10 +93,17 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
|
||||
|
||||
if ui.root.last != nil
|
||||
{
|
||||
// ui.root.last - > top_ancestor
|
||||
ui.root.last.next = top_ancestor
|
||||
top_ancestor.prev = ui.root.last
|
||||
prev_last := ui.root.last
|
||||
ui.root.last = top_ancestor
|
||||
|
||||
prev_last.next = top_ancestor
|
||||
top_ancestor.prev = prev_last
|
||||
top_ancestor.next = nil
|
||||
if left == nil && right == prev_last
|
||||
{
|
||||
right.prev = nil
|
||||
right.next = top_ancestor
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -105,8 +113,8 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
|
||||
ui.root.first.next = top_ancestor
|
||||
top_ancestor.prev = ui.root.first
|
||||
top_ancestor.next = nil
|
||||
ui.root.last = top_ancestor
|
||||
}
|
||||
ui.root.last = top_ancestor
|
||||
|
||||
for curr := right; curr != nil; curr = curr.next {
|
||||
curr.parent_index -= 1
|
||||
@ -147,26 +155,26 @@ ui_signal_from_box :: proc ( box : ^ UI_Box, update_style := true, update_deltas
|
||||
// TODO(Ed) : Add keyboard interaction support
|
||||
}
|
||||
|
||||
// TODO(Ed): Should panning and scrolling get supported here? (problably not...)
|
||||
// TODO(Ed) : Add scrolling support
|
||||
if UI_BoxFlag.Scroll_X in box.flags {
|
||||
// if UI_BoxFlag.Scroll_X in box.flags {
|
||||
|
||||
}
|
||||
if UI_BoxFlag.Scroll_Y in box.flags {
|
||||
|
||||
}
|
||||
// }
|
||||
// if UI_BoxFlag.Scroll_Y in box.flags {
|
||||
|
||||
// }
|
||||
// TODO(Ed) : Add panning support
|
||||
if UI_BoxFlag.Pan_X in box.flags {
|
||||
// if UI_BoxFlag.Pan_X in box.flags {
|
||||
|
||||
}
|
||||
if UI_BoxFlag.Pan_Y in box.flags {
|
||||
|
||||
}
|
||||
// }
|
||||
// if UI_BoxFlag.Pan_Y in box.flags {
|
||||
// }
|
||||
|
||||
is_disabled := UI_BoxFlag.Disabled in box.flags
|
||||
is_hot := ui.hot == box.key
|
||||
is_active := ui.active == box.key
|
||||
|
||||
// TODO(Ed): It should be able to enter hot without mouse_clickable
|
||||
if mouse_clickable && signal.cursor_over && ! is_disabled
|
||||
{
|
||||
hot_vacant := ui.hot == UI_Key(0)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package sectr
|
||||
|
||||
// TODO(Ed): We problably can embedd this info into the UI_Layout with the regular text_alignment
|
||||
UI_TextAlign :: enum u32 {
|
||||
Left,
|
||||
Center,
|
||||
@ -20,7 +21,7 @@ UI_Style :: struct {
|
||||
border_color : Color,
|
||||
|
||||
// TODO(Ed): We cannot support individual corners unless we add it to raylib (or finally change the rendering backend)
|
||||
corner_radii : [Corner.Count]f32,
|
||||
corner_radii : [Corner.Count]f32,
|
||||
|
||||
// TODO(Ed) : Add support for this eventually
|
||||
blur_size : f32,
|
||||
@ -31,9 +32,8 @@ UI_Style :: struct {
|
||||
// TODO(Ed): Add support for custom shader
|
||||
// shader : UI_Shader,
|
||||
|
||||
font : FontID,
|
||||
// TODO(Ed): Should this get moved to the layout struct? Techncially font-size is mainly
|
||||
text_color : Color,
|
||||
font : FontID,
|
||||
text_color : Color,
|
||||
|
||||
// TODO(Ed) : Support setting the cursor state
|
||||
cursor : UI_Cursor,
|
||||
|
@ -42,7 +42,7 @@ test_draggable :: proc()
|
||||
corner_radii = { 0.3, 0.3, 0.3, 0.3 },
|
||||
})
|
||||
|
||||
draggable := ui_widget( "Draggable Box!", UI_BoxFlags { .Mouse_Clickable, .Mouse_Resizable } )
|
||||
draggable := ui_widget( "Draggable Box!", UI_BoxFlags { .Mouse_Clickable } )
|
||||
if draggable.first_frame {
|
||||
debug.draggable_box_pos = draggable.layout.pos + { 0, -100 }
|
||||
debug.draggable_box_size = draggable.layout.size.min
|
||||
@ -87,7 +87,7 @@ test_parenting :: proc( default_layout : ^UI_Layout, frame_style_default : ^UI_S
|
||||
parent_style := frame_style_default ^
|
||||
ui_style(parent_style)
|
||||
|
||||
parent := ui_widget( "Parent", { .Mouse_Clickable, .Mouse_Resizable })
|
||||
parent := ui_widget( "Parent", { .Mouse_Clickable })
|
||||
ui_parent_push(parent)
|
||||
{
|
||||
if parent.first_frame {
|
||||
|
@ -59,22 +59,19 @@ UI_BoxFlag :: enum u64 {
|
||||
Click_To_Focus,
|
||||
|
||||
Mouse_Clickable,
|
||||
Mouse_Resizable,
|
||||
|
||||
Keyboard_Clickable,
|
||||
|
||||
Scroll_X,
|
||||
Scroll_Y,
|
||||
// Pan_X,
|
||||
// Pan_Y,
|
||||
|
||||
Pan_X,
|
||||
Pan_Y,
|
||||
|
||||
Screenspace,
|
||||
// Scroll_X,
|
||||
// Scroll_Y,
|
||||
|
||||
// Screenspace,
|
||||
Count,
|
||||
}
|
||||
UI_BoxFlags :: bit_set[UI_BoxFlag; u64]
|
||||
UI_BoxFlag_Scroll :: UI_BoxFlags { .Scroll_X, .Scroll_Y }
|
||||
// UI_BoxFlag_Scroll :: UI_BoxFlags { .Scroll_X, .Scroll_Y }
|
||||
|
||||
UI_Cursor :: struct {
|
||||
placeholder : int,
|
||||
@ -110,7 +107,10 @@ UI_Box :: struct {
|
||||
text : StrRunesPair,
|
||||
|
||||
// Regenerated per frame.
|
||||
using links : DLL_NodeFull( UI_Box ), // first, last, prev, next
|
||||
|
||||
// first, last : The first and last child of this box
|
||||
// prev, next : The adjacent neighboring boxes who are children of to the same parent
|
||||
using links : DLL_NodeFull( UI_Box ),
|
||||
parent : ^UI_Box,
|
||||
num_children : i32,
|
||||
ancestors : i32, // This value for rooted widgets gets set to -1 after rendering see ui_box_make() for the reason.
|
||||
@ -126,7 +126,7 @@ UI_Box :: struct {
|
||||
style : UI_Style,
|
||||
|
||||
// Persistent Data
|
||||
first_frame : b8,
|
||||
first_frame : b8, // TODO(Ed): Move to end if keeping as b8
|
||||
hot_delta : f32,
|
||||
active_delta : f32,
|
||||
disabled_delta : f32,
|
||||
@ -148,8 +148,8 @@ UI_Built_Boxes_Array_Size :: 16 * Kilobyte
|
||||
|
||||
UI_State :: struct {
|
||||
// TODO(Ed) : Use these
|
||||
build_arenas : [2]Arena,
|
||||
build_arena : ^ Arena,
|
||||
// build_arenas : [2]Arena,
|
||||
// build_arena : ^ Arena,
|
||||
|
||||
built_box_count : i32,
|
||||
|
||||
@ -165,7 +165,7 @@ UI_State :: struct {
|
||||
// So long as their parent-index is non-negative they'll be rendered
|
||||
|
||||
// Do we need to recompute the layout?
|
||||
layout_dirty : b32,
|
||||
// layout_dirty : b32,
|
||||
|
||||
// TODO(Ed) : Look into using a build arena like Ryan does for these possibly (and thus have a linked-list stack)
|
||||
layout_combo_stack : StackFixed( UI_LayoutCombo, UI_Style_Stack_Size ),
|
||||
@ -300,7 +300,10 @@ ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
|
||||
}
|
||||
if parent != nil
|
||||
{
|
||||
if parent != ui.root || curr_box.first_frame
|
||||
// There are three possible reasons to just add as usual:
|
||||
// 1. Its not rooted, which means we don't track order
|
||||
// 2.
|
||||
if parent != ui.root || curr_box.first_frame //|| (prev_box.prev == nil && prev_box.next == nil)
|
||||
{
|
||||
// Only occurs when this is no prior history for rooted boxes
|
||||
// Otherwise regular children always complete this
|
||||
@ -335,11 +338,11 @@ ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
|
||||
{
|
||||
// Make only todo if links are properly wiped on current
|
||||
set_error : AllocatorError
|
||||
if curr_box.prev == nil && prev_box.prev != nil {
|
||||
if curr_box.prev == nil && prev_box.prev != nil && prev_box.ancestors == 1 {
|
||||
curr_box.prev, set_error = zpl_hmap_set( curr_cache, cast(u64) prev_box.prev.key, prev_box.prev ^ )
|
||||
verify( set_error == AllocatorError.None, "Failed to set zpl_hmap due to allocator error" )
|
||||
}
|
||||
if curr_box.next == nil && prev_box.next != nil {
|
||||
if curr_box.next == nil && prev_box.next != nil && prev_box.ancestors == 1 {
|
||||
curr_box.next, set_error = zpl_hmap_set( curr_cache, cast(u64) prev_box.next.key, prev_box.next ^ )
|
||||
verify( set_error == AllocatorError.None, "Failed to set zpl_hmap due to allocator error" )
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user