diff --git a/build_file.c b/build_file.c index b930669..337f265 100644 --- a/build_file.c +++ b/build_file.c @@ -75,7 +75,6 @@ int main(int argc, char **argv) { " /WX /W3 /wd4200 /diagnostics:column" " /link /incremental:no /DEBUG:FULL" ); - if (ok != 0) return ok; } if (core_test_target && cache_code_modified(s8_lit("../src/core/core_test_entry.c"), s8_lit("core_test.exe"))) { diff --git a/src/core/core_math.gen.c b/src/core/core_math.gen.c index d697889..193fa87 100644 --- a/src/core/core_math.gen.c +++ b/src/core/core_math.gen.c @@ -367,6 +367,7 @@ fn r2f32_t r2f32_get_bottom(const r2f32_t *r, f32 value) { /* Y is down */ } +fn_inline r2f32_t r2f32_expand(r2f32_t rect, v2f32_t value) { return (r2f32_t){ v2f32_sub(rect.min, value), v2f32_add(rect.max, value) }; } fn_inline r2f32_t r2f32_shrink(r2f32_t rect, v2f32_t value) { return (r2f32_t){ v2f32_add(rect.min, value), v2f32_sub(rect.max, value) }; } fn_inline r2f32_t r2f32_shrinks(r2f32_t rect, f32 value) { return (r2f32_t){ v2f32_adds(rect.min, value), v2f32_subs(rect.max, value) }; } fn_inline v2f32_t r2f32_get_size(r2f32_t r) { return (v2f32_t){r.max.x - r.min.x, r.max.y - r.min.y}; } @@ -390,6 +391,14 @@ fn v2f32_t v2f32_clamp(v2f32_t v, v2f32_t min, v2f32_t max) { v2f32_t result = { CLAMP(v.x, min.x, max.x), CLAMP(v.y, min.y, max.y) }; return result; } + +fn r2f32_t r2f32_fix(r2f32_t n) { + r2f32_t result = { + .min = {MIN(n.min.x, n.max.x), MIN(n.min.y, n.max.y)}, + .max = {MAX(n.min.x, n.max.x), MAX(n.min.y, n.max.y)}, + }; + return result; +} fn r2f64_t r2f64_cut_left(r2f64_t *r, f64 value) { @@ -503,6 +512,7 @@ fn r2f64_t r2f64_get_bottom(const r2f64_t *r, f64 value) { /* Y is down */ } +fn_inline r2f64_t r2f64_expand(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_sub(rect.min, value), v2f64_add(rect.max, value) }; } fn_inline r2f64_t r2f64_shrink(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_add(rect.min, value), v2f64_sub(rect.max, value) }; } fn_inline r2f64_t r2f64_shrinks(r2f64_t rect, f64 value) { return (r2f64_t){ v2f64_adds(rect.min, value), v2f64_subs(rect.max, value) }; } fn_inline v2f64_t r2f64_get_size(r2f64_t r) { return (v2f64_t){r.max.x - r.min.x, r.max.y - r.min.y}; } @@ -526,6 +536,14 @@ fn v2f64_t v2f64_clamp(v2f64_t v, v2f64_t min, v2f64_t max) { v2f64_t result = { CLAMP(v.x, min.x, max.x), CLAMP(v.y, min.y, max.y) }; return result; } + +fn r2f64_t r2f64_fix(r2f64_t n) { + r2f64_t result = { + .min = {MIN(n.min.x, n.max.x), MIN(n.min.y, n.max.y)}, + .max = {MAX(n.min.x, n.max.x), MAX(n.min.y, n.max.y)}, + }; + return result; +} fn r2i32_t r2i32_cut_left(r2i32_t *r, i32 value) { @@ -639,6 +657,7 @@ fn r2i32_t r2i32_get_bottom(const r2i32_t *r, i32 value) { /* Y is down */ } +fn_inline r2i32_t r2i32_expand(r2i32_t rect, v2i32_t value) { return (r2i32_t){ v2i32_sub(rect.min, value), v2i32_add(rect.max, value) }; } fn_inline r2i32_t r2i32_shrink(r2i32_t rect, v2i32_t value) { return (r2i32_t){ v2i32_add(rect.min, value), v2i32_sub(rect.max, value) }; } fn_inline r2i32_t r2i32_shrinks(r2i32_t rect, i32 value) { return (r2i32_t){ v2i32_adds(rect.min, value), v2i32_subs(rect.max, value) }; } fn_inline v2i32_t r2i32_get_size(r2i32_t r) { return (v2i32_t){r.max.x - r.min.x, r.max.y - r.min.y}; } @@ -662,6 +681,14 @@ fn v2i32_t v2i32_clamp(v2i32_t v, v2i32_t min, v2i32_t max) { v2i32_t result = { CLAMP(v.x, min.x, max.x), CLAMP(v.y, min.y, max.y) }; return result; } + +fn r2i32_t r2i32_fix(r2i32_t n) { + r2i32_t result = { + .min = {MIN(n.min.x, n.max.x), MIN(n.min.y, n.max.y)}, + .max = {MAX(n.min.x, n.max.x), MAX(n.min.y, n.max.y)}, + }; + return result; +} fn r2i64_t r2i64_cut_left(r2i64_t *r, i64 value) { @@ -775,6 +802,7 @@ fn r2i64_t r2i64_get_bottom(const r2i64_t *r, i64 value) { /* Y is down */ } +fn_inline r2i64_t r2i64_expand(r2i64_t rect, v2i64_t value) { return (r2i64_t){ v2i64_sub(rect.min, value), v2i64_add(rect.max, value) }; } fn_inline r2i64_t r2i64_shrink(r2i64_t rect, v2i64_t value) { return (r2i64_t){ v2i64_add(rect.min, value), v2i64_sub(rect.max, value) }; } fn_inline r2i64_t r2i64_shrinks(r2i64_t rect, i64 value) { return (r2i64_t){ v2i64_adds(rect.min, value), v2i64_subs(rect.max, value) }; } fn_inline v2i64_t r2i64_get_size(r2i64_t r) { return (v2i64_t){r.max.x - r.min.x, r.max.y - r.min.y}; } @@ -798,6 +826,14 @@ fn v2i64_t v2i64_clamp(v2i64_t v, v2i64_t min, v2i64_t max) { v2i64_t result = { CLAMP(v.x, min.x, max.x), CLAMP(v.y, min.y, max.y) }; return result; } + +fn r2i64_t r2i64_fix(r2i64_t n) { + r2i64_t result = { + .min = {MIN(n.min.x, n.max.x), MIN(n.min.y, n.max.y)}, + .max = {MAX(n.min.x, n.max.x), MAX(n.min.y, n.max.y)}, + }; + return result; +} fn_inline v2f64_t v2f32_to_v2f64(v2f32_t v) { return (v2f64_t){ (f64)v.x, (f64)v.y }; } fn_inline v3f64_t v3f32_to_v3f64(v3f32_t v) { return (v3f64_t){ (f64)v.x, (f64)v.y, (f64)v.z }; } diff --git a/src/core/core_math_gen.py b/src/core/core_math_gen.py index 98b810a..38a6448 100644 --- a/src/core/core_math_gen.py +++ b/src/core/core_math_gen.py @@ -315,6 +315,7 @@ fn r2f64_t r2f64_get_bottom(const r2f64_t *r, f64 value) { /* Y is down */ } +fn_inline r2f64_t r2f64_expand(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_sub(rect.min, value), v2f64_add(rect.max, value) }; } fn_inline r2f64_t r2f64_shrink(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_add(rect.min, value), v2f64_sub(rect.max, value) }; } fn_inline r2f64_t r2f64_shrinks(r2f64_t rect, f64 value) { return (r2f64_t){ v2f64_adds(rect.min, value), v2f64_subs(rect.max, value) }; } fn_inline v2f64_t r2f64_get_size(r2f64_t r) { return (v2f64_t){r.max.x - r.min.x, r.max.y - r.min.y}; } @@ -338,6 +339,14 @@ fn v2f64_t v2f64_clamp(v2f64_t v, v2f64_t min, v2f64_t max) { v2f64_t result = { CLAMP(v.x, min.x, max.x), CLAMP(v.y, min.y, max.y) }; return result; } + +fn r2f64_t r2f64_fix(r2f64_t n) { + r2f64_t result = { + .min = {MIN(n.min.x, n.max.x), MIN(n.min.y, n.max.y)}, + .max = {MAX(n.min.x, n.max.x), MAX(n.min.y, n.max.y)}, + }; + return result; +} """ s = s.replace("f64", basic_type) print(s) diff --git a/src/core/core_string.c b/src/core/core_string.c index a633795..547a926 100644 --- a/src/core/core_string.c +++ b/src/core/core_string.c @@ -486,4 +486,48 @@ fn f64 f64_from_s8(s8_t string) { f64 result = os_parse_float(num_string.str); ma_end_scratch(scratch); return result; +} + +gb_read_only i64 fuzzy_closer_word_begin = 5; +gb_read_only i64 fuzzy_consecutive_multiplier = 3; +fn i64 fuzzy_rate_string(s8_t string, s8_t with) { + if (with.len == 0) return 0; + + i64 points = 0; + i64 consecutive = 0; + i64 with_i = 0; + for (i64 i = 0; i < string.len; i++) { + if (string.str[i] == with.str[with_i]) { + i64 closer_begin = CLAMP_BOT((i64)0, fuzzy_closer_word_begin - i); + points += closer_begin; + consecutive++; + with_i += 1; + } else { + points += consecutive * fuzzy_consecutive_multiplier; + consecutive = 0; + with_i = 0; + } + + if (with_i >= with.len) with_i = 0; + } + points += consecutive * fuzzy_consecutive_multiplier; + return points; +} + +fn fuzzy_pair_t *fuzzy_rate_array(ma_arena_t *arena, s8_t needle, s8_t *array, i32 len) { + fuzzy_pair_t *pairs = ma_push_array(arena, fuzzy_pair_t, len); + for (i32 i = 0; i < len; i += 1) { + pairs[i].rating = fuzzy_rate_string(array[i], needle); + pairs[i].index = i; + } + + for (i32 i = 0; i < len - 1; i++) { + for (i32 j = 0; j < len - 1; j++) { + if (pairs[j].rating < pairs[j + 1].rating) { + SWAP(fuzzy_pair_t, pairs[j], pairs[j + 1]); + } + } + } + + return pairs; } \ No newline at end of file diff --git a/src/core/core_string.h b/src/core/core_string.h index 78f6f86..323b14c 100644 --- a/src/core/core_string.h +++ b/src/core/core_string.h @@ -175,3 +175,9 @@ void *sbin_read_data(stream_t *stream, i64 size); va_start(args1, str); \ i32 len = stbsp_vsnprintf(buff, sizeof(buff), str, args1); \ va_end(args1) + +typedef struct fuzzy_pair_t fuzzy_pair_t; +struct fuzzy_pair_t { + i64 index; + i64 rating; +}; diff --git a/src/ui/ui.c b/src/ui/ui.c index ce15051..ec54032 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -265,18 +265,6 @@ fn ui_box_t *ui_build_box_from_id(ui_code_loc_t loc, ui_box_flags_t flags, ui_id box->border_thickness = ui_top_border_thickness(); box->string_pos_offset = ui_top_string_pos_offset(); - // :ui_box_flags_t - ui_box_flags_t top_flags = ui_top_flags(); - { - if(top_flags.draw_rect) box->flags.draw_rect = true; - if(top_flags.draw_border) box->flags.draw_border = true; - if(top_flags.draw_text) box->flags.draw_text = true; - if(top_flags.clip_rect) box->flags.clip_rect = true; - if(top_flags.children_sum_x) box->flags.children_sum_x = true; - if(top_flags.children_sum_y) box->flags.children_sum_y = true; - if(top_flags.keyboard_nav) box->flags.keyboard_nav = true; - } - ui_box_fill_with_colors(box); ui_push_box(ui->top, box); return box; @@ -335,7 +323,6 @@ fn ui_signal_t ui_signal_from_box(ui_box_t *box) { b32 inside = r2f32_contains(box->final_rect, ev->mouse_pos); if (ui_is_active_box(box)) { - result.press = true; result.dragging = true; result.drag = ui->event->mouse_delta; if (ev_left_up(ev)) { @@ -357,17 +344,14 @@ fn ui_signal_t ui_signal_from_box(ui_box_t *box) { result.drag.x -= 1; result.dragging = true; result.clicked = true; - result.press = true; } else if (ev->kind == app_event_kind_key_down && ev->key == app_key_right) { result.drag.x += 1; result.dragging = true; result.clicked = true; - result.press = true; } if (ev->kind == app_event_kind_key_down && ev->key == app_key_enter) { result.clicked = true; - result.press = true; } } @@ -430,7 +414,7 @@ fn ui_draw_compute_t ui_draw_compute(ui_box_t *box) { } if (ui_is_focused_box(box)) { - co.background_color = v4f32_lerp(co.background_color, ui_color_table[ui_color_focused_rect], 0.4f); + co.background_color = v4f32_lerp(co.background_color, ui_color_table[ui_color_focused_rect], 0.7f); // co.text_color = v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.6f, 0.7f, 1.0f}); box->flags.draw_rect = true; @@ -527,15 +511,16 @@ fn_test void ui_test_text_replace(void) { assert(s8_are_equal(ti.string, s8_lit("qaer"))); } -#define ui_text_input(ti) ui__text_input(UILOC, ti) -fn ui_signal_t ui__text_input(ui_code_loc_t loc, ui_text_input_t *ti) { +#define ui_text_input(...) ui__text_input(UILOC, __VA_ARGS__) +fn ui_signal_t ui__text_input(ui_code_loc_t loc, ui_text_input_t *ti, b32 sim_even_if_no_focus) { ui_box_t *box = ui_box(.loc = loc, .string = s8_lit("text_input"), .flags = { .draw_border = true, .draw_rect = true, .draw_text = true, .keyboard_nav = true }); box->text_input = ti; box->custom_draw = ui_text_input_draw; - ui_signal_t signal = ui_signal_from_box(box); - if (ui_is_focused_box(box)) { + + b32 sim = sim_even_if_no_focus || ui_is_focused_box(box); + if (sim) { app_event_t *ev = ui->event; i32 sel_size = r1i32_size(ti->caret.range); if (ev->kind == app_event_kind_text) { @@ -636,7 +621,7 @@ fn ui_box_t *ui__label(ui_code_loc_t loc, char *str, ...) { } fn void ui_tree_table_begin(ui_code_loc_t loc) { - ui_box_t *box = ui_box(.loc = loc, .rect = ui_next_rect(ui_top_lop(), ui_top_rectp(), v2f32_null), .flags = { .draw_border = true, .children_sum_y = true }); + ui_box_t *box = ui_box(.loc = loc, .rect = ui_next_rect(ui_top_lop(), ui_top_rectp(), v2f32_null), .flags = { .draw_border = true, .children_sum_y = true, .clip_rect = true, }); ui_push_top(box); } @@ -649,6 +634,8 @@ fn void ui_tree_table_end(void) { #define ui_tree_table_expandable(...) defer_if (ui_tree_table_push_expandable(UILOC, __VA_ARGS__).clicked, ui_tree_table_pop_expandable()) fn void ui_tree_table_pop_expandable(void) { r2f32_add_left(ui_top_rectp(), ui_dm(1)); + // r2f32_cut_right(ui_top_rectp(), ui_dm(0.1f)); + // ui_top_rectp()[0] = r2f32_expand(ui_top_rect(), v2f32(ui_dm(1), 0)); ui_tree_table_end(); ui_pop_id(); } @@ -664,7 +651,10 @@ fn ui_signal_t ui_tree_table_push_expandable(ui_code_loc_t loc, char *str, ...) if (button.clicked) button.box->expanded = !button.box->expanded; button.clicked = button.box->expanded; + + // ui_top_rectp()[0] = r2f32_shrink(ui_top_rect(), v2f32(ui_dm(1), 0)); r2f32_cut_left(ui_top_rectp(), ui_dm(1)); + // r2f32_cut_right(ui_top_rectp(), ui_dm(0.1f)); if (button.clicked == false) { ui_tree_table_pop_expandable(); @@ -731,111 +721,40 @@ fn b32 ui_match_keynav(ui_box_t *box) { return result; } -fn void ui_begin_build(ui_code_loc_t loc, app_event_t *ev, r2f32_t window_rect) { - ui->event = ev; - - for (ui_box_t *box = ui->hash_first, *next = NULL; box; box = next) { - next = box->hash_next; - if (box->id.value == 0) { - DLLQ_REMOVE_EX(ui->hash_first, ui->hash_last, box, hash_next, hash_prev); - zero_struct(box); - SLLS_PUSH(ui->free_first, box); - } - } - - ui_push_init_values(); - - zero_struct(&ui->root); - ui->top = &ui->root; - ui->root.loc = loc; +#define ui_reverse_node_order() defer_block(ui_begin_reversal(), ui_end_reversal()) +fn void ui_begin_reversal(void) { + ui->reverse_order_ref = ui->top->last; } -fn void ui_end_build(void) { - ui_set_children_sums(&ui->root); +fn void ui_end_reversal(void) { + assert(ui->reverse_order_ref); + assert(ui->reverse_order_ref->next); + ui_box_t *first = ui->reverse_order_ref->next; + ui_box_t *last = ui->top->last; + ui->reverse_order_ref = NULL; - { - app_event_t *ev = ui->event; - ui_box_t *focus_box = ui_find_box(ui->focus); - if (focus_box == NULL) { - ui->focus = ui_get_next_box(&ui->root, ui_match_keynav)->id; - } - - if (ev->kind == app_event_kind_key_down && ev->key == app_key_up) { - ui->focus = ui_get_prev_box(focus_box, ui_match_keynav)->id; - } else if (ev->kind == app_event_kind_key_down && ev->key == app_key_down) { - ui->focus = ui_get_next_box(focus_box, ui_match_keynav)->id; + b32 connected = false; + for (ui_box_t *it = first; it; it = it->next) { + if (it == last) { + connected = true; + break; } } - assert(ui->top == &ui->root); - ui_pop_init_values(); - ui_assert_stacks_are_null(); + assert(connected); - for (ui_box_t *box = ui->hash_first, *next = NULL; box; box = next) { - next = box->hash_next; - b32 touched_box_during_update = ui->event->id <= box->last_touched_event_id; - if (!touched_box_during_update) { - DLLQ_REMOVE_EX(ui->hash_first, ui->hash_last, box, hash_next, hash_prev); - zero_struct(box); - SLLS_PUSH(ui->free_first, box); - } - } -} - -fn void ui__draw_box(app_frame_t *frame, ui_box_t *box) { - box->final_rect = r2f32_intersect(box->rect, ui->clip_rect); - if (box->custom_draw) { - box->custom_draw(box); - } else { - ui_default_draw_box(box); + ui_box_t *first2 = NULL; + ui_box_t *last2 = NULL; + for (ui_box_t *it = first, *next = it->next; next; it = next) { + next = it->next; + DLLQ_REMOVE(it->parent->first, it->parent->last, it); + DLLQ_APPEND(first2, last2, it); } - r2f32_t prev_clip_rect = ui->clip_rect; - if (box->flags.clip_rect) { - ui->clip_rect = box->rect; - rn_set_clip(ui->clip_rect); - } - for (ui_box_t *it = box->first; it; it = it->next) { - ui__draw_box(frame, it); - } - if (box->flags.clip_rect) { - ui->clip_rect = prev_clip_rect; - rn_set_clip(ui->clip_rect); - } - -} - -fn void ui_draw(void) { - ui->clip_rect = window_rect_from_frame(ui->frame); - rn_set_clip(ui->clip_rect); - ui__draw_box(ui->frame, &ui->root); -} - -fn void ui_begin_frame(app_frame_t *frame) { - ui = tcx->data[tcx_slot_ui]; - ui->frame = frame; -} - -fn void ui_end_frame(void) { - for (ui_box_t *box = ui->hash_first, *next = NULL; box; box = next) { - next = box->hash_next; - box->appear_t += (f32)ui->frame->delta; - if (ui_is_hot_box(box)) { - box->hot_t += (f32)ui->frame->delta; - } else { - box->hot_t = 0; - } - if (ui_is_active_box(box)) { - box->active_t += (f32)ui->frame->delta; - } else { - box->active_t = 0; - } - } - - for (app_event_t *ev = ui->frame->first_event; ev; ev = ev->next) { - if (ev_left_up(ev)) { - ui->active = ui_null_id; - } + for (ui_box_t *it = last2, *prev = it->prev; prev; it = prev) { + prev = it->prev; + DLLQ_REMOVE(first2, last2, it); + DLLQ_APPEND(it->parent->first, it->parent->last, it); } } @@ -1036,6 +955,248 @@ fn void ui_serial_type(ui_code_loc_t loc, void *p, type_t *type) { ui_set_id(ui_id_from_loc(loc)) ui_serial_subtype(p, type, type->name); } +typedef struct ui_scroller_params_t ui_scroller_params_t; +struct ui_scroller_params_t { + ui_box_t *parent; + struct { + b8 enabled; + f32 *value; + f32 max_size; + } hori; + struct { + b8 enabled; + f32 *value; + f32 item_pixels; + i32 item_count; + } verti; +}; + +typedef struct ui_scroller_t ui_scroller_t; +struct ui_scroller_t { + struct { + ui_box_t *box; + i32 istart; + i32 iend; + f32 item_box_pixels; + } verti; + struct { + ui_box_t *box; + } hori; + ui_scroller_params_t p; +}; + +fn ui_scroller_t ui_begin_scroller(ui_scroller_params_t p) { + ui_scroller_t r = {.p = p}; + + if (p.verti.enabled) { + r.verti.box = ui_box(.rect = r2f32_cut_right(&p.parent->rect, ui_dm(0.5f)), .flags = {.draw_rect = true}); + r2f32_cut_bottom(&r.verti.box->rect, ui_dm(0.5f)); + + r.verti.item_box_pixels = r2f32_get_size(p.parent->rect).y; + f32 visible_item_count = f32_ceil(r.verti.item_box_pixels / p.verti.item_pixels); + f32 render_start_count = f32_floor(p.verti.value[0] / p.verti.item_pixels); + + i32 istart = (i32)render_start_count; + i32 iend = (i32)render_start_count + (i32)visible_item_count; + r.verti.istart = CLAMP(istart, 0, (i32)p.verti.item_count); + r.verti.iend = CLAMP(iend, 0, (i32)p.verti.item_count); + } + + if (p.hori.enabled) { + r.hori.box = ui_box(.rect = r2f32_cut_bottom(&p.parent->rect, ui_dm(0.5f)), .flags = {.draw_rect = true}); + } + + return r; +} + +fn void ui_cut_top_scroller_offset(ui_scroller_t s) { + r2f32_cut_top_no_squash(ui_top_rectp(), (f32)s.verti.istart * s.p.verti.item_pixels); +} + +fn void ui_end_scroller(ui_scroller_t s) { + if (s.p.verti.enabled) ui_set_top(s.verti.box) { + f32 scroller_rect_pixels = r2f32_get_size(s.verti.box->rect).y; + f32 all_items_size = s.p.verti.item_pixels * s.p.verti.item_count; + f32 scroller_size = f32_clamp01(s.verti.item_box_pixels / (all_items_size + s.verti.item_box_pixels)); + f32 scrollable_space = (1 - scroller_size); + f32 scroller_value_norm = s.p.verti.value[0] / (all_items_size); + f32 scroller_value_n = scroller_value_norm * scrollable_space; + + ui_box_t *upper_box = ui_box(r2f32_cut_top(ui_top_rectp(), scroller_value_n * scroller_rect_pixels), {.draw_rect = true}); + ui_box_t *slider_box = ui_box(r2f32_cut_top(ui_top_rectp(), scroller_size * scroller_rect_pixels), {.draw_rect = true}); + ui_box_t *down_box = ui_box(r2f32_cut_top(ui_top_rectp(), ui_max), {.draw_rect = true}); + slider_box->background_color = ui_color_table[ui_color_scroller]; + slider_box->bg_hot_color = ui_color_table[ui_color_scroller_hot]; + slider_box->bg_active_color = ui_color_table[ui_color_scroller_active]; + ui_signal_t signal = ui_signal_from_box(slider_box); + ui_signal_t upper_box_signal = ui_signal_from_box(upper_box); + ui_signal_t down_box_signal = ui_signal_from_box(down_box); + + app_event_t *ev = ui->event; + f32 drag = ev->mouse_delta.y; + f32 coef = f32_safe_ratio0((all_items_size / s.verti.item_box_pixels), scrollable_space); + if (signal.dragging) { + s.p.verti.value[0] += drag * coef; + } + if (upper_box_signal.dragging || down_box_signal.dragging) { + s.p.verti.value[0] = (ev->mouse_pos.y - upper_box->rect.min.y) * coef; + s.p.verti.value[0] -= (r2f32_get_size(slider_box->rect).y / 2) * coef; + } + if (ev->kind == app_event_kind_mouse_wheel) { + s.p.verti.value[0] -= ev->mouse_wheel_delta.y; + } + s.p.verti.value[0] = CLAMP(s.p.verti.value[0], 0, all_items_size); + } + + if (s.p.hori.enabled) ui_set_top(s.hori.box) { + f32 scroller_rect_pixels = r2f32_get_size(s.hori.box->rect).x; + f32 scroller_button_size_norm = f32_clamp01(scroller_rect_pixels / s.p.hori.max_size); + f32 scrollable_space = (1.f - scroller_button_size_norm); + + f32 scroller_value_norm = s.p.hori.value[0] / s.p.hori.max_size; + f32 scroller_value_n = scroller_value_norm * scrollable_space; + ui_box_t *left_box = ui_box(r2f32_cut_left(ui_top_rectp(), scroller_value_n * scroller_rect_pixels), {.draw_rect = true}); + ui_box_t *slider_box = ui_box(r2f32_cut_left(ui_top_rectp(), scroller_button_size_norm * scroller_rect_pixels), {.draw_rect = true}); + ui_box_t *down_box = ui_box(r2f32_cut_left(ui_top_rectp(), ui_max), {.draw_rect = true}); + slider_box->background_color = ui_color_table[ui_color_scroller]; + slider_box->bg_hot_color = ui_color_table[ui_color_scroller_hot]; + slider_box->bg_active_color = ui_color_table[ui_color_scroller_active]; + ui_signal_t left_box_sig = ui_signal_from_box(left_box); + ui_signal_t signal = ui_signal_from_box(slider_box); + ui_signal_t right_box_sig = ui_signal_from_box(down_box); + + app_event_t *ev = ui->event; + f32 coef = f32_safe_ratio0((s.p.hori.max_size / scroller_rect_pixels), scrollable_space); + + if (signal.dragging) { + s.p.hori.value[0] += ev->mouse_delta.x * coef; + } + if (left_box_sig.dragging || right_box_sig.dragging) { + s.p.hori.value[0] = (ev->mouse_pos.x - left_box->rect.min.x) * coef; + s.p.hori.value[0] -= (r2f32_get_size(slider_box->rect).x / 2) * coef; + } + if (ev->kind == app_event_kind_mouse_wheel) { + s.p.hori.value[0] -= ev->mouse_wheel_delta.x; + } + + s.p.hori.value[0] = CLAMP(s.p.hori.value[0], 0, s.p.hori.max_size); + + } + + ui_offset_children(s.p.parent, v2f32(s.p.hori.value ? s.p.hori.value[0] : 0, s.p.verti.value ? s.p.verti.value[0] : 0)); +} + +/////////////////////////////// +// main ui control points + +fn void ui_begin_build(ui_code_loc_t loc, app_event_t *ev, r2f32_t window_rect) { + ui->event = ev; + + for (ui_box_t *box = ui->hash_first, *next = NULL; box; box = next) { + next = box->hash_next; + if (box->id.value == 0) { + DLLQ_REMOVE_EX(ui->hash_first, ui->hash_last, box, hash_next, hash_prev); + zero_struct(box); + SLLS_PUSH(ui->free_first, box); + } + } + + ui_push_init_values(); + + zero_struct(&ui->root); + ui->top = &ui->root; + ui->root.loc = loc; +} + +fn void ui_end_build(void) { + ui_set_children_sums(&ui->root); + + { + app_event_t *ev = ui->event; + ui_box_t *focus_box = ui_find_box(ui->focus); + if (focus_box == NULL) { + ui->focus = ui_get_next_box(&ui->root, ui_match_keynav)->id; + } + + if (ev->kind == app_event_kind_key_down && ev->key == app_key_up) { + ui->focus = ui_get_prev_box(focus_box, ui_match_keynav)->id; + } else if (ev->kind == app_event_kind_key_down && ev->key == app_key_down) { + ui->focus = ui_get_next_box(focus_box, ui_match_keynav)->id; + } + } + + assert(ui->top == &ui->root); + ui_pop_init_values(); + ui_assert_stacks_are_null(); + + for (ui_box_t *box = ui->hash_first, *next = NULL; box; box = next) { + next = box->hash_next; + b32 touched_box_during_update = ui->event->id <= box->last_touched_event_id; + if (!touched_box_during_update) { + DLLQ_REMOVE_EX(ui->hash_first, ui->hash_last, box, hash_next, hash_prev); + zero_struct(box); + SLLS_PUSH(ui->free_first, box); + } + } +} + +fn void ui__draw_box(app_frame_t *frame, ui_box_t *box) { + box->final_rect = r2f32_intersect(box->rect, ui->clip_rect); + if (box->custom_draw) { + box->custom_draw(box); + } else { + ui_default_draw_box(box); + } + + r2f32_t prev_clip_rect = ui->clip_rect; + if (box->flags.clip_rect) { + ui->clip_rect = r2f32_intersect(ui->clip_rect, box->rect); + rn_set_clip(ui->clip_rect); + } + for (ui_box_t *it = box->first; it; it = it->next) { + ui__draw_box(frame, it); + } + if (box->flags.clip_rect) { + ui->clip_rect = prev_clip_rect; + rn_set_clip(ui->clip_rect); + } + +} + +fn void ui_draw(void) { + ui->clip_rect = window_rect_from_frame(ui->frame); + rn_set_clip(ui->clip_rect); + ui__draw_box(ui->frame, &ui->root); +} + +fn void ui_begin_frame(app_frame_t *frame) { + ui = tcx->data[tcx_slot_ui]; + ui->frame = frame; +} + +fn void ui_end_frame(void) { + for (ui_box_t *box = ui->hash_first, *next = NULL; box; box = next) { + next = box->hash_next; + box->appear_t += (f32)ui->frame->delta; + if (ui_is_hot_box(box)) { + box->hot_t += (f32)ui->frame->delta; + } else { + box->hot_t = 0; + } + if (ui_is_active_box(box)) { + box->active_t += (f32)ui->frame->delta; + } else { + box->active_t = 0; + } + } + + for (app_event_t *ev = ui->frame->first_event; ev; ev = ev->next) { + if (ev_left_up(ev)) { + ui->active = ui_null_id; + } + } +} + fn void ui_reload(void) { ui_init_colors(); } @@ -1047,95 +1208,8 @@ fn void ui_init(ma_arena_t *arena) { ui_reload(); } -#define ui_reverse_node_order() defer_block(ui_begin_reversal(), ui_end_reversal()) -fn void ui_begin_reversal(void) { - ui->reverse_order_ref = ui->top->last; -} - -fn void ui_end_reversal(void) { - assert(ui->reverse_order_ref); - assert(ui->reverse_order_ref->next); - ui_box_t *first = ui->reverse_order_ref->next; - ui_box_t *last = ui->top->last; - ui->reverse_order_ref = NULL; - - b32 connected = false; - for (ui_box_t *it = first; it; it = it->next) { - if (it == last) { - connected = true; - break; - } - } - - assert(connected); - - ui_box_t *first2 = NULL; - ui_box_t *last2 = NULL; - for (ui_box_t *it = first, *next = it->next; next; it = next) { - next = it->next; - DLLQ_REMOVE(it->parent->first, it->parent->last, it); - DLLQ_APPEND(first2, last2, it); - } - - for (ui_box_t *it = last2, *prev = it->prev; prev; it = prev) { - prev = it->prev; - DLLQ_REMOVE(first2, last2, it); - DLLQ_APPEND(it->parent->first, it->parent->last, it); - } -} - -gb_read_only i64 fuzzy_closer_word_begin = 5; -gb_read_only i64 fuzzy_consecutive_multiplier = 3; -fn i64 fuzzy_rate_string(s8_t string, s8_t with) { - if (with.len == 0) return 0; - - i64 points = 0; - i64 consecutive = 0; - i64 with_i = 0; - for (i64 i = 0; i < string.len; i++) { - if (string.str[i] == with.str[with_i]) { - i64 closer_begin = CLAMP_BOT((i64)0, fuzzy_closer_word_begin - i); - points += closer_begin; - consecutive++; - with_i += 1; - } else { - points += consecutive * fuzzy_consecutive_multiplier; - consecutive = 0; - with_i = 0; - } - - if (with_i >= with.len) with_i = 0; - } - points += consecutive * fuzzy_consecutive_multiplier; - return points; -} - -typedef struct fuzzy_pair_t fuzzy_pair_t; -struct fuzzy_pair_t { - i64 index; - i64 rating; -}; - -fn fuzzy_pair_t *fuzzy_rate_array(ma_arena_t *arena, s8_t needle, s8_t *array, i32 len) { - fuzzy_pair_t *pairs = ma_push_array(arena, fuzzy_pair_t, len); - for (i32 i = 0; i < len; i += 1) { - pairs[i].rating = fuzzy_rate_string(array[i], needle); - pairs[i].index = i; - } - - for (i32 i = 0; i < len - 1; i++) { - for (i32 j = 0; j < len - 1; j++) { - if (pairs[j].rating < pairs[j + 1].rating) { - SWAP(fuzzy_pair_t, pairs[j], pairs[j + 1]); - } - } - } - - return pairs; -} - gb app_event_t ui_test_event; -gb i32 ui_g_panel = 2; +gb i32 ui_g_panel = 1; fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_count) { ui_begin_frame(frame); rn_begin_frame(frame); @@ -1169,18 +1243,10 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co ui_box_t *bottom_scroller = ui_box(r2f32_cut_bottom(ui_top_rectp(), 10 * frame->dpr), {.draw_rect = true}); ui_box_t *item_box = ui_box(r2f32_cut_left(ui_top_rectp(), ui_max), {.draw_rect = true, .clip_rect = true}); - + r2f32_t scroll_rect = {0}; ui_set_text_align(ui_text_align_left) ui_set_top(item_box) { ui_top_rectp()[0] = r2f32_shrinks(ui_top_rect(), ui_em(1)); - locl char buff[128]; - locl ui_text_input_t text_input; - if (text_input.str == NULL) { - text_input.str = buff; - text_input.cap = lengthof(buff); - } - ui_text_input(&text_input); - for (i32 i = 0; i < tweak_count; i += 1) { mt_tweak_t *tweak = tweak_table + i; if (s8_starts_with(tweak->name, s8_lit("_"), false)) { @@ -1205,13 +1271,13 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co ui_label("allocated boxes: %d", ui->allocated_boxes); ui_serial_type(UILOC, &ui_test_event, type(app_event_t)); ui_serial_type(UILOC, &ui_test_event, type(app_event_t)); + + scroll_rect = r2f32_fix(ui_top_rect()); } locl f32 scroller_value; ui_set_top(scroller_box) { - f32 item_count = (f32)item_box->node_count; - f32 one_item_y_size = ui_em(1); - f32 all_items_size = item_count * one_item_y_size; + f32 all_items_size = r2f32_get_size(scroll_rect).y; f32 item_box_size = r2f32_get_size(item_box->rect).y; f32 scroller_box_size = r2f32_get_size(scroller_box->rect).y; f32 scroller_size = CLAMP(item_box_size / (all_items_size + frame->window_size.y), 0, 1.0f); @@ -1233,59 +1299,21 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co f32 coef = f32_safe_ratio0(all_items_size / item_box_size, scrollable_space); if (signal.dragging) { scroller_value += drag * coef; + scroller_value = CLAMP(scroller_value, 0, all_items_size); } if (upper_box_signal.dragging || down_box_signal.dragging) { scroller_value = (ev->mouse_pos.y - upper_box->final_rect.min.y) * coef; scroller_value -= (slider_box_size / 2) * coef; + scroller_value = CLAMP(scroller_value, 0, all_items_size); } if (ev->kind == app_event_kind_mouse_wheel) { scroller_value -= ev->mouse_wheel_delta.y; + scroller_value = CLAMP(scroller_value, 0, all_items_size); } - scroller_value = CLAMP(scroller_value, 0, all_items_size); } - - locl f32 bottom_scroller_value; - ui_set_top(bottom_scroller) { - f32 max_size = 0; - for (ui_box_t *it = item_box->first; it; it = it->next) { - max_size = MAX(max_size, it->string_size.x); - } - - f32 scroller_rect_pixels = r2f32_get_size(bottom_scroller->rect).x; - f32 scroller_button_size_norm = f32_clamp01(scroller_rect_pixels / max_size); - f32 scrollable_space = (1.f - scroller_button_size_norm); - - f32 scroller_value_norm = bottom_scroller_value / max_size; - f32 scroller_value_n = scroller_value_norm * scrollable_space; - ui_box_t *left_box = ui_box(r2f32_cut_left(ui_top_rectp(), scroller_value_n * scroller_rect_pixels), {.draw_rect = true}); - ui_box_t *slider_box = ui_box(r2f32_cut_left(ui_top_rectp(), scroller_button_size_norm * scroller_rect_pixels), {.draw_rect = true}); - ui_box_t *down_box = ui_box(r2f32_cut_left(ui_top_rectp(), ui_max), {.draw_rect = true}); - slider_box->background_color = ui_color_table[ui_color_scroller]; - slider_box->bg_hot_color = ui_color_table[ui_color_scroller_hot]; - slider_box->bg_active_color = ui_color_table[ui_color_scroller_active]; - ui_signal_t left_box_sig = ui_signal_from_box(left_box); - ui_signal_t signal = ui_signal_from_box(slider_box); - ui_signal_t right_box_sig = ui_signal_from_box(down_box); - - f32 coef = f32_safe_ratio0(max_size / scroller_rect_pixels, scrollable_space); - - if (signal.dragging) { - bottom_scroller_value += ev->mouse_delta.x * coef; - } - if (left_box_sig.dragging || right_box_sig.dragging) { - bottom_scroller_value = (ev->mouse_pos.x - left_box->rect.min.x) * coef; - bottom_scroller_value -= (r2f32_get_size(slider_box->rect).x / 2) * coef; - } - if (ev->kind == app_event_kind_mouse_wheel) { - bottom_scroller_value -= ev->mouse_wheel_delta.x; - } - - bottom_scroller_value = CLAMP(bottom_scroller_value, 0, max_size); - } - - ui_offset_children(item_box, v2f32(bottom_scroller_value, scroller_value)); + ui_offset_children(item_box, v2f32(0, scroller_value)); } /////////////////////////////// @@ -1424,103 +1452,31 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co } } - ui_box_t *right_scroller = ui_box(.rect = r2f32_cut_right(ui_top_rectp(), 10 * frame->dpr), .flags = {.draw_rect = true}); - ui_box_t *bottom_scroller = ui_box(.rect = r2f32_cut_bottom(ui_top_rectp(), 10 * frame->dpr), .flags = {.draw_rect = true}); ui_box_t *item_box = ui_box(.rect = r2f32_cut_left(ui_top_rectp(), ui_max), .flags = {.draw_rect = true, .clip_rect = true}); locl f32 right_scroller_value; + locl f32 bottom_scroller_value; + ui_scroller_t scroller = ui_begin_scroller((ui_scroller_params_t){ + .parent = item_box, + .verti = { + .enabled = true, + .value = &right_scroller_value, + .item_pixels = ui_em(1), + .item_count = (i32)item_count + }, + .hori = { .enabled = true, .value = &bottom_scroller_value, .max_size = 2000 }, + }); - f32 one_item_y_size = ui_em(1); - f32 all_items_size = item_count * one_item_y_size; - f32 item_box_pixels = r2f32_get_size(item_box->rect).y; - f32 visible_item_count = f32_ceil(item_box_pixels / one_item_y_size); - f32 render_start_count = f32_floor(right_scroller_value / one_item_y_size); - - i32 istart = (i32)render_start_count; - i32 iend = (i32)render_start_count + (i32)visible_item_count; - istart = CLAMP(istart, 0, (i32)item_count); - iend = CLAMP(iend, 0, (i32)item_count); ui_set_top(item_box) { - r2f32_cut_top_no_squash(ui_top_rectp(), render_start_count * one_item_y_size); - for (i32 i = istart; i rect).y; - f32 scroller_size = f32_clamp01(item_box_pixels / (all_items_size + frame->window_size.y)); - f32 scrollable_space = (1 - scroller_size); - f32 scroller_value_norm = right_scroller_value / (all_items_size); - f32 scroller_value_n = scroller_value_norm * scrollable_space; - - ui_box_t *upper_box = ui_box(r2f32_cut_top(ui_top_rectp(), scroller_value_n * scroller_rect_pixels), {.draw_rect = true}); - ui_box_t *slider_box = ui_box(r2f32_cut_top(ui_top_rectp(), scroller_size * scroller_rect_pixels), {.draw_rect = true}); - ui_box_t *down_box = ui_box(r2f32_cut_top(ui_top_rectp(), ui_max), {.draw_rect = true}); - slider_box->background_color = ui_color_table[ui_color_scroller]; - slider_box->bg_hot_color = ui_color_table[ui_color_scroller_hot]; - slider_box->bg_active_color = ui_color_table[ui_color_scroller_active]; - ui_signal_t signal = ui_signal_from_box(slider_box); - ui_signal_t upper_box_signal = ui_signal_from_box(upper_box); - ui_signal_t down_box_signal = ui_signal_from_box(down_box); - f32 drag = ev->mouse_delta.y; - f32 coef = f32_safe_ratio0((all_items_size / item_box_pixels), scrollable_space); - if (signal.dragging) { - right_scroller_value += drag * coef; - } - if (upper_box_signal.dragging || down_box_signal.dragging) { - right_scroller_value = (ev->mouse_pos.y - upper_box->rect.min.y) * coef; - right_scroller_value -= (r2f32_get_size(slider_box->rect).y / 2) * coef; - } - if (ev->kind == app_event_kind_mouse_wheel) { - right_scroller_value -= ev->mouse_wheel_delta.y; - } - right_scroller_value = CLAMP(right_scroller_value, 0, all_items_size); - } - - locl f32 bottom_scroller_value; - ui_set_top(bottom_scroller) { - f32 max_size = 0; - for (ui_box_t *it = item_box->first; it; it = it->next) { - max_size = MAX(max_size, it->string_size.x); - } - - f32 scroller_rect_pixels = r2f32_get_size(bottom_scroller->rect).x; - f32 scroller_button_size_norm = f32_clamp01(scroller_rect_pixels / max_size); - f32 scrollable_space = (1.f - scroller_button_size_norm); - - f32 scroller_value_norm = bottom_scroller_value / max_size; - f32 scroller_value_n = scroller_value_norm * scrollable_space; - ui_box_t *left_box = ui_box(r2f32_cut_left(ui_top_rectp(), scroller_value_n * scroller_rect_pixels), {.draw_rect = true}); - ui_box_t *slider_box = ui_box(r2f32_cut_left(ui_top_rectp(), scroller_button_size_norm * scroller_rect_pixels), {.draw_rect = true}); - ui_box_t *down_box = ui_box(r2f32_cut_left(ui_top_rectp(), ui_max), {.draw_rect = true}); - slider_box->background_color = ui_color_table[ui_color_scroller]; - slider_box->bg_hot_color = ui_color_table[ui_color_scroller_hot]; - slider_box->bg_active_color = ui_color_table[ui_color_scroller_active]; - ui_signal_t left_box_sig = ui_signal_from_box(left_box); - ui_signal_t signal = ui_signal_from_box(slider_box); - ui_signal_t right_box_sig = ui_signal_from_box(down_box); - - f32 coef = f32_safe_ratio0((max_size / scroller_rect_pixels), scrollable_space); - - if (signal.dragging) { - bottom_scroller_value += ev->mouse_delta.x * coef; - } - if (left_box_sig.dragging || right_box_sig.dragging) { - bottom_scroller_value = (ev->mouse_pos.x - left_box->rect.min.x) * coef; - bottom_scroller_value -= (r2f32_get_size(slider_box->rect).x / 2) * coef; - } - if (ev->kind == app_event_kind_mouse_wheel) { - bottom_scroller_value -= ev->mouse_wheel_delta.x; - } - - bottom_scroller_value = CLAMP(bottom_scroller_value, 0, max_size); - - } - - ui_offset_children(item_box, v2f32(bottom_scroller_value, right_scroller_value)); + ui_end_scroller(scroller); } /////////////////////////////// @@ -1580,13 +1536,58 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co if (lister_open) lister_just_opened = true; } + s8_t cmds[] = { + s8_lit("show data tab"), + s8_lit("show log tab"), + s8_lit("show menus tab"), + s8_lit("x"), + s8_lit("x1"), + s8_lit("x2"), + s8_lit("x3"), + s8_lit("x4"), + s8_lit("x5"), + s8_lit("x6"), + s8_lit("x7"), + s8_lit("x8"), + s8_lit("x9"), + s8_lit("x0"), + s8_lit("x22"), + s8_lit("x33"), + s8_lit("x44"), + s8_lit("x55"), + s8_lit("x66"), + s8_lit("x77"), + s8_lit("x88"), + s8_lit("x99"), + s8_lit("x123"), + s8_lit("x12"), + s8_lit("x32"), + s8_lit("x42"), + s8_lit("x52"), + s8_lit("x64"), + s8_lit("x75"), + }; + if (lister_open) { v2f32_t max_size = v2f32_sub(frame->window_size, v2f32(ui_em(2), ui_em(2))); - v2f32_t _lister_size = v2f32(ui_em(50), ui_em(40)); + v2f32_t _lister_size = v2f32(ui_dm(50), ui_em(25)); v2f32_t lister_size = v2f32_clamp(_lister_size, v2f32_null, max_size); v2f32_t pos = v2f32_divs(v2f32_sub(frame->window_size, lister_size), 2.0); + pos.y *= 0.05f; r2f32_t rect = r2f32_min_dim(pos, lister_size); ui_box_t *lister = ui_box(.id = lister_id, .rect = rect, .flags = {.draw_rect = true, .draw_border = true, .clip_rect = true}); + + locl f32 verti_scroller_value; + ui_scroller_t scroller = ui_begin_scroller((ui_scroller_params_t){ + .parent = lister, + .verti = { + .enabled = true, + .value = &verti_scroller_value, + .item_pixels = ui_em(1), + .item_count = (i32)lengthof(cmds), + }, + }); + ui_set_top(lister) ui_set_lop(ui_lop_cut_top) { locl char buff[128]; @@ -1595,24 +1596,27 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co text_input.str = buff; text_input.cap = lengthof(buff); } - ui_signal_t ti_sig = ui_text_input(&text_input); - ui->focus = ti_sig.box->id; - - s8_t cmds[] = { - s8_lit("show data tab"), - s8_lit("show log tab"), - s8_lit("show menus tab"), - }; + ui_signal_t ti_sig = ui_text_input(&text_input, true); ma_temp_t scratch = ma_begin_scratch(); s8_t needle = s8(text_input.str, text_input.len); fuzzy_pair_t *pairs = fuzzy_rate_array(scratch.arena, needle, cmds, lengthof(cmds)); - ui_set_string_pos_offset(ui_dm(1)) - for (i32 i = 0; i < lengthof(cmds); i += 1) { - ui_button(cmds[pairs[i].index].str); + b32 set_focus = lister_just_opened || ti_sig.text_changed; + + ui_set_string_pos_offset(ui_dm(1)) { + ui_cut_top_scroller_offset(scroller); + for (i32 i = scroller.verti.istart; i < scroller.verti.iend; i += 1) { + ui_signal_t sig = ui_button(cmds[pairs[i].index].str); + + if (set_focus) { + ui->focus = sig.box->id; + set_focus = false; + } + } } + if (ti_sig.text_commit) { fuzzy_pair_t *pair = &pairs[0]; ui_g_panel = (i32)pair->index + 1; @@ -1622,6 +1626,9 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co ma_end_scratch(scratch); } + + ui_end_scroller(scroller); + } ui_end_build(); diff --git a/src/ui/ui.gen.c b/src/ui/ui.gen.c index 17cdf47..3210f0b 100644 --- a/src/ui/ui.gen.c +++ b/src/ui/ui.gen.c @@ -36,12 +36,12 @@ fn void ui_init_colors(void) { ui_color_table[ui_color_rect] = v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.2f, 0.95f, 1.0f}); ui_color_table[ui_color_rect_hot] = v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.5f, 0.95f, 1.0f}); ui_color_table[ui_color_rect_active] = v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.5f, 0.95f, 1.0f}); -ui_color_table[ui_color_rect_turned_on] = v4f32_hsla_to_rgba((v4f32_t){0.4f, 0.5f, 0.95f, 1.0f}); +ui_color_table[ui_color_rect_turned_on] = v4f32_hsla_to_rgba((v4f32_t){0.55f, 0.5f, 0.95f, 1.0f}); ui_color_table[ui_color_border] = v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.2f, 0.70f, 1.0f}); ui_color_table[ui_color_text] = v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.2f, 0.70f, 1.0f}); ui_color_table[ui_color_text_hot] = v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.4f, 0.70f, 1.0f}); ui_color_table[ui_color_text_active] = v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.5f, 0.70f, 1.0f}); -ui_color_table[ui_color_focused_rect] = (v4f32_t){1,1,1,1}; +ui_color_table[ui_color_focused_rect] = v4f32_hsla_to_rgba((v4f32_t){0.4f, 0.5f, 0.95f, 1.0f}); ui_color_table[ui_color_scroller] = ui_color_table[ui_color_text]; ui_color_table[ui_color_scroller_hot] = v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.2f, 0.7f, 1.0f}); ui_color_table[ui_color_scroller_active] = v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.2f, 0.5f, 1.0f}); @@ -78,10 +78,6 @@ fn void ui_push_rect(r2f32_t v) { ui_r2f32_node_t *n = ma_push_type(tcx->temp, u fn void ui_pop_rect(void) { SLLS_POP(ui->rect_stack); } fn r2f32_t ui_top_rect(void) { return ui->rect_stack->value; } #define ui_set_rect(x) defer_block(ui_push_rect(x), ui_pop_rect()) -fn void ui_push_flags(ui_box_flags_t v) { ui_box_flags_node_t *n = ma_push_type(tcx->temp, ui_box_flags_node_t); n->value = v; SLLS_PUSH(ui->flags_stack, n); } -fn void ui_pop_flags(void) { SLLS_POP(ui->flags_stack); } -fn ui_box_flags_t ui_top_flags(void) { return ui->flags_stack->value; } -#define ui_set_flags(x) defer_block(ui_push_flags(x), ui_pop_flags()) fn void ui_push_background_color(v4f32_t v) { ui_v4f32_node_t *n = ma_push_type(tcx->temp, ui_v4f32_node_t); n->value = v; SLLS_PUSH(ui->background_color_stack, n); } fn void ui_pop_background_color(void) { SLLS_POP(ui->background_color_stack); } fn v4f32_t ui_top_background_color(void) { return ui->background_color_stack->value; } @@ -120,7 +116,6 @@ assert(ui->required_size_stack == NULL); assert(ui->padding_stack == NULL); assert(ui->string_pos_offset_stack == NULL); assert(ui->rect_stack == NULL); -assert(ui->flags_stack == NULL); assert(ui->background_color_stack == NULL); assert(ui->bg_hot_color_stack == NULL); assert(ui->bg_active_color_stack == NULL); @@ -136,7 +131,6 @@ ui_push_border_thickness(1.0f); ui_push_text_align(ui_text_align_left); ui_push_string_pos_offset(0); ui_push_rect(window_rect_from_frame(ui->frame)); -ui_push_flags((ui_box_flags_t){0}); ui_push_background_color(ui_color_table[ui_color_rect]); ui_push_bg_hot_color(ui_color_table[ui_color_rect_hot]); ui_push_bg_active_color(ui_color_table[ui_color_rect_active]); @@ -152,7 +146,6 @@ ui_pop_border_thickness(); ui_pop_text_align(); ui_pop_string_pos_offset(); ui_pop_rect(); -ui_pop_flags(); ui_pop_background_color(); ui_pop_bg_hot_color(); ui_pop_bg_active_color(); diff --git a/src/ui/ui.gen.h b/src/ui/ui.gen.h index c15e588..5ccbc6d 100644 --- a/src/ui/ui.gen.h +++ b/src/ui/ui.gen.h @@ -20,7 +20,6 @@ typedef struct ui_lop_node_t ui_lop_node_t; struct ui_lop_node_t { ui_lop_t valu typedef struct ui_f32_node_t ui_f32_node_t; struct ui_f32_node_t { f32 value; ui_f32_node_t *next; }; typedef struct ui_text_align_node_t ui_text_align_node_t; struct ui_text_align_node_t { ui_text_align_t value; ui_text_align_node_t *next; }; typedef struct ui_r2f32_node_t ui_r2f32_node_t; struct ui_r2f32_node_t { r2f32_t value; ui_r2f32_node_t *next; }; -typedef struct ui_box_flags_node_t ui_box_flags_node_t; struct ui_box_flags_node_t { ui_box_flags_t value; ui_box_flags_node_t *next; }; typedef struct ui_v4f32_node_t ui_v4f32_node_t; struct ui_v4f32_node_t { v4f32_t value; ui_v4f32_node_t *next; }; #define UI_DECL_BOX_MEMBERS \ f32 border_thickness;\ @@ -29,7 +28,6 @@ f32 required_size;\ f32 padding;\ f32 string_pos_offset;\ r2f32_t rect;\ -ui_box_flags_t flags;\ v4f32_t background_color;\ v4f32_t bg_hot_color;\ v4f32_t bg_active_color;\ @@ -47,7 +45,6 @@ ui_f32_node_t *required_size_stack;\ ui_f32_node_t *padding_stack;\ ui_f32_node_t *string_pos_offset_stack;\ ui_r2f32_node_t *rect_stack;\ -ui_box_flags_node_t *flags_stack;\ ui_v4f32_node_t *background_color_stack;\ ui_v4f32_node_t *bg_hot_color_stack;\ ui_v4f32_node_t *bg_active_color_stack;\ diff --git a/src/ui/ui.h b/src/ui/ui.h index cd72aa7..766a97b 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -12,7 +12,6 @@ struct ui_id_t { typedef struct ui_box_flags_t ui_box_flags_t; struct ui_box_flags_t { - // :ui_box_flags_t - change those places when modifying this b8 draw_rect: 1; b8 draw_border: 1; b8 draw_text: 1; @@ -80,6 +79,7 @@ struct ui_box_t { s8_t string; v2f32_t string_size; + ui_box_flags_t flags; b8 created_new; ui_custom_draw_t *custom_draw; ui_lop_t lop; @@ -107,7 +107,6 @@ struct ui_signal_t { v2f32_t drag; struct { b8 clicked: 1; - b8 press: 1; b8 dragging: 1; b8 text_changed: 1; diff --git a/src/ui/ui.meta.c b/src/ui/ui.meta.c index 0592602..b2fc560 100644 --- a/src/ui/ui.meta.c +++ b/src/ui/ui.meta.c @@ -4,12 +4,12 @@ fn void mt_ui_colors(ma_arena_t *arena, sb8_t *c, sb8_t *h) { { rect `v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.2f, 0.95f, 1.0f})` } { rect_hot `v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.5f, 0.95f, 1.0f})` } { rect_active `v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.5f, 0.95f, 1.0f})` } - { rect_turned_on `v4f32_hsla_to_rgba((v4f32_t){0.4f, 0.5f, 0.95f, 1.0f})` } + { rect_turned_on `v4f32_hsla_to_rgba((v4f32_t){0.55f, 0.5f, 0.95f, 1.0f})` } { border `v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.2f, 0.70f, 1.0f})` } { text `v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.2f, 0.70f, 1.0f})` } { text_hot `v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.4f, 0.70f, 1.0f})` } { text_active `v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.5f, 0.70f, 1.0f})` } - { focused_rect `(v4f32_t){1,1,1,1}` } + { focused_rect `v4f32_hsla_to_rgba((v4f32_t){0.4f, 0.5f, 0.95f, 1.0f})` } { scroller `ui_color_table[ui_color_text]` } { scroller_hot `v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.2f, 0.7f, 1.0f})` } { scroller_active `v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.2f, 0.5f, 1.0f})` } @@ -42,7 +42,6 @@ fn void mt_ui_stacks(ma_arena_t *arena, sb8_t *c, sb8_t *h) { { f32 padding 0 x } { f32 string_pos_offset 0 0 } { r2f32_t rect 0 `window_rect_from_frame(ui->frame)` } - { ui_box_flags_t flags 0 `(ui_box_flags_t){0}` } { v4f32_t background_color 0 `ui_color_table[ui_color_rect]` } { v4f32_t bg_hot_color 0 `ui_color_table[ui_color_rect_hot]` } { v4f32_t bg_active_color 0 `ui_color_table[ui_color_rect_active]` } diff --git a/todo.txt b/todo.txt index 084b491..b02d02c 100644 --- a/todo.txt +++ b/todo.txt @@ -10,7 +10,7 @@ [ ] drag and drop [ ] open file dialog [ ] os - [ ] DELETE ALL PDBS\DLLS ON START + [x] delete all pdbs\dlls on start [?] wasm (explore) [ ] win32 [ ] linux @@ -23,15 +23,20 @@ [ ] maybe copy package stuff to build? [ ] ui - [ ] jumping between nodes (get_prev, get_next) needs a fix - [ ] bring back also the old expander? + [ ] concept of active panel + [ ] separate root so can't focus off with keyboard + [ ] clicking away from panel, closes it or changes focus + [ ] hot to move between panels? [ ] table - [ ] vertical scroll - [x] working - [ ] we depend on ui_boxes existing to calculate max_size which doesn't play well with efficient horiscroll, canm this be fixed? - [x] horizontal scroll - [x] efficient, on fixed size - [x] non-efficient + [ ] scroll + [x] basic abstraction + [ ] allow for horizontal non-efficient + [ ] keyboard handling + [x] vertical scroll + [x] working + [x] horizontal scroll + [x] efficient, on fixed size + [x] non-efficient [ ] context menu [x] working [ ] maybe a separate root for context menu? @@ -42,7 +47,7 @@ [x] fix elements getting offset when font large and they are on the edge [ ] text input [x] basic working - [ ] enter signal + [x] enter signal [ ] ctrl backspace, ctrl delete [ ] set mouse cursor on hover [ ] everything lister (with edits etc.) @@ -58,6 +63,7 @@ [ ] slider [ ] draw image in box ui [x] rect stack + [x] jumping between nodes (get_prev, get_next) needs a fix [ ] core [ ] ast