Fixed issue with ui_signal_from_box

Biggest win was getting the intial fixes for overlapping boxes.
Eventually I'll need to add support for sorting actives of top-most ancestors
(pretty much just remove from linked list and add to last position (adjust indices of adjacent and new top most, etc)
This commit is contained in:
2024-05-10 04:16:04 -04:00
parent 1afe74b4b5
commit 5b24e591eb
6 changed files with 74 additions and 21 deletions

View File

@ -207,6 +207,7 @@ update :: proc( delta_time : f64 ) -> b32
*/
if true
{
profile("App Menu Bar")
fmt :: str_fmt_alloc
@static bar_pos := Vec2{0, 100}
@ -234,7 +235,7 @@ update :: proc( delta_time : f64 ) -> b32
}
ui_theme_via_style(theme)
menu_bar = ui_widget("App Menu Bar", {} )
menu_bar = ui_widget("App Menu Bar", { .Mouse_Clickable} )
menu_bar.text = to_str_runes_pair( fmt("%v", bar_pos))
if (menu_bar.first_frame) {
@ -277,6 +278,15 @@ update :: proc( delta_time : f64 ) -> b32
if move_box.active {
bar_pos += input.mouse.delta
}
using move_box
hot := ui_box_from_key(ui.curr_cache, ui.hot)
if hot != nil {
text = to_str_runes_pair(str_fmt_tmp("Hot box: %v %v", hot.label.str, hot.hot_delta))
style.font = default_font
style.font_size = 12
style.text_color = Color_White
style.text_alignment = {0, 1}
}
}
move_settings_spacer := ui_widget("Move-Settings Spacer", {})
@ -315,6 +325,7 @@ update :: proc( delta_time : f64 ) -> b32
@static settings_open := true
if settings_btn.pressed || settings_open
{
profile("Settings Menu")
settings_open = true
resize_border_width : f32 = 20
@ -336,6 +347,10 @@ update :: proc( delta_time : f64 ) -> b32
style.alignment = { 1.0, 0.5 }
style.bg_color = Color_BG_Panel_Translucent
style.size = range2( size, {})
text = to_str_runes_pair(str_fmt_tmp("Hot Delta: %v", hot_delta))
style.font = default_font
style.font_size = 12
style.text_color = Color_White
}
ui_parent(settings_menu)

View File

@ -138,6 +138,8 @@ UI_Box :: struct {
disabled_delta : f32,
style_delta : f32,
parent_index : i32,
// prev_computed : UI_Computed,
// prev_style : UI_Style,v
// mouse : UI_InteractState,
@ -276,6 +278,7 @@ ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
if parent != nil
{
dll_full_push_back( null_box, parent, curr_box )
curr_box.parent_index = parent.num_children
parent.num_children += 1
curr_box.parent = parent
}
@ -398,3 +401,11 @@ ui_parent_pop :: proc() {
@(deferred_none = ui_parent_pop)
ui_parent :: #force_inline proc( ui : ^UI_Box) { ui_parent_push( ui ) }
// Topmost ancestor that is not the root
ui_top_ancestor :: #force_inline proc "contextless" ( box : ^UI_Box ) -> (^UI_Box) {
using ui := get_state().ui_context
ancestor := box
for ; ancestor.parent != root; ancestor = ancestor.parent {}
return ancestor
}

View File

@ -1,5 +1,7 @@
package sectr
import "base:runtime"
UI_Signal :: struct {
cursor_pos : Vec2,
drag_delta : Vec2,
@ -33,6 +35,25 @@ ui_signal_from_box :: proc ( box : ^ UI_Box ) -> UI_Signal
// profile_begin( "Cursor collision")
signal.cursor_pos = ui_cursor_pos()
signal.cursor_over = cast(b8) pos_within_range2( signal.cursor_pos, box.computed.bounds )
// TODO(Ed): We eventually need to setup a sorted root based on last active history
UnderCheck:
{
if ! signal.cursor_over do break UnderCheck
last_root := ui_box_from_key( ui.prev_cache, ui.root.key )
if last_root == nil do break UnderCheck
top_ancestor := ui_top_ancestor(box)
if top_ancestor.parent_index != last_root.num_children - 1
{
for curr := last_root.last; curr != nil && curr.key != box.key; curr = curr.prev {
if pos_within_range2( signal.cursor_pos, curr.computed.bounds ) && curr.parent_index > top_ancestor.parent_index {
signal.cursor_over = false
}
}
}
}
// profile_end()
// profile_begin("misc")
@ -42,13 +63,17 @@ ui_signal_from_box :: proc ( box : ^ UI_Box ) -> UI_Signal
mouse_clickable := UI_BoxFlag.Mouse_Clickable in box.flags
keyboard_clickable := UI_BoxFlag.Keyboard_Clickable in box.flags
was_hot := ui.hot == box.key && box.hot_delta > 0
was_active := ui.active == box.key && box.active_delta > 0
was_hot := (box.hot_delta > 0)
was_active := (ui.active == box.key) && (box.active_delta > 0)
was_disabled := box.disabled_delta > 0
if was_hot {
// runtime.debug_trap()
}
if mouse_clickable && signal.cursor_over && left_pressed
if mouse_clickable && signal.cursor_over && left_pressed && was_hot
{
ui.hot = box.key
// runtime.debug_trap()
// ui.hot = box.key
ui.active = box.key
ui.active_mouse[MouseBtn.Left] = box.key
@ -61,7 +86,7 @@ ui_signal_from_box :: proc ( box : ^ UI_Box ) -> UI_Signal
if mouse_clickable && ! signal.cursor_over && left_released
{
box.hot_delta = 0
box.active_delta = 0
ui.active = UI_Key(0)
ui.active_mouse[MouseBtn.Left] = UI_Key(0)
@ -94,15 +119,18 @@ ui_signal_from_box :: proc ( box : ^ UI_Box ) -> UI_Signal
is_disabled := UI_BoxFlag.Disabled in box.flags
is_hot := ui.hot == box.key
is_active := ui.active == box.key
is_rooted := ui.root == box.parent
if signal.cursor_over && ! is_disabled
if mouse_clickable && signal.cursor_over && ! is_disabled
{
hot_vacant := ui.hot == UI_Key(0)
active_vacant := ui.active == UI_Key(0)
// (active_vacant is_active)
if (hot_vacant && signal.cursor_over || is_hot)
if signal.cursor_over
{
if ! hot_vacant {
prev := ui_box_from_key( ui.curr_cache, ui.hot )
prev.hot_delta = 0
}
// prev_hot := zpl_hmap_get( ui.prev_cache, u64(ui.hot) )
// prev_hot_label := prev_hot != nil ? prev_hot.label.str : ""
// log( str_fmt_tmp("Detected HOT via CURSOR OVER: %v is_hot: %v is_active: %v prev_hot: %v", box.label.str, is_hot, is_active, prev_hot_label ))
@ -112,16 +140,17 @@ ui_signal_from_box :: proc ( box : ^ UI_Box ) -> UI_Signal
ui.hot_start_style = box.style
}
}
else
else if ! signal.cursor_over && was_hot
{
is_hot = false
if ui.hot == box.key {
ui.hot = UI_Key(0)
}
ui.hot = UI_Key(0)
is_hot = false
box.hot_delta = 0
}
if mouse_clickable && signal.cursor_over && left_released
{
box.active_delta = 0
ui.active = UI_Key(0)
ui.active_mouse[MouseBtn.Left] = UI_Key(0)
@ -143,9 +172,6 @@ ui_signal_from_box :: proc ( box : ^ UI_Box ) -> UI_Signal
box.style_delta += frame_delta
}
}
else {
box.hot_delta = 0
}
if is_active
{
box.active_delta += frame_delta

View File

@ -107,6 +107,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget,
corner_br := true,
corner_bl := true, )
{
profile(#procedure)
handle_left : UI_Widget
handle_right : UI_Widget
handle_top : UI_Widget