From 1b40ab9a8eaea0abf21c678217108bfc418c25d9 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Thu, 16 Jan 2025 11:44:23 +0100 Subject: [PATCH] new ui idea --- src/core/core.h | 2 +- src/wasm_app/main.c | 126 +--------------- src/wasm_app/ui.c | 331 ++++++++++------------------------------- src/wasm_app/ui.h | 132 ++++------------ src/wasm_app/ui_iter.c | 9 +- 5 files changed, 116 insertions(+), 484 deletions(-) diff --git a/src/core/core.h b/src/core/core.h index 0f3be62..0f755f7 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -67,7 +67,7 @@ typedef double f64; #define defer_if(begin, cond_end) for (b32 PASTE(_i_, __LINE__) = !!begin; PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) = (cond_end, 0)) #define defer_block(begin, end) for (i32 PASTE(_i_, __LINE__) = (begin, 0); !PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) += (end, 1)) -#define STACK(type, size) struct { type data[size]; i32 len; } +#define stack_t(type, size) struct { type data[size]; i32 len; } #define STACK_PUSH(stack, ...) (assert((stack).len < lengthof((stack).data)), (stack).data[(stack).len++] = __VA_ARGS__) #define STACK_POP(stack) (assert((stack).len > 0), (stack).data[--(stack).len]) #define STACK_TOP(stack) (assert((stack).len > 0), (stack).data[((stack).len-1)]) diff --git a/src/wasm_app/main.c b/src/wasm_app/main.c index dd143f7..e4b83b9 100644 --- a/src/wasm_app/main.c +++ b/src/wasm_app/main.c @@ -10,14 +10,12 @@ #include "render/backup_font.c" #include "render/font.c" #include "render/render_opengl.c" -// #include "gfx2d/gfx2d.c"dv #include "ui_iter.c" #include "ui.c" typedef struct globals_t globals_t; struct globals_t { - // gfx_t *gfx; app_event_t event; }; gb globals_t *globals; @@ -26,131 +24,11 @@ gb globals_t *globals; fn void app_init(f32 dpr) { ma_arena_t *perm = &tcx._perm; globals = ma_push_type(perm, globals_t); - ma_arena_t *ui_arena = ma_push_arena(perm, mib(1)); - ui_init(ui_arena); rn_init(perm, 50 * dpr); + ui_demo_init(perm); } fn b32 app_update(app_frame_t *frame) { - assert(frame != NULL); - ui_begin_frame(frame); - - assert(frame->first_event); - - for (app_event_t *ev = frame->first_event; ev; ev = ev->next) { - static f32 scroller_value; - defer_block(ui_begin_build(UI_CODE_LOC, ev), ui_end_build()) { - defer_block(ui_push_xcontainer(UI_CODE_LOC, ui_em(25), ui_em(30)), ui_pop_parent()) { - - - ui_box_t *item_box = ui_build_box_from_string(UI_CODE_LOC, (ui_box_flags_t){.scroll = true, .draw_rect = true}, s8_lit("scrolled item_box")); - ui_set_semantic_size(item_box, ui_percent(0.97f), ui_percent(1)); - item_box->grow_axis = ui_axis2_y; - defer_block(ui_push_parent(item_box), ui_pop_parent()) { - defer_if (ui_push_exp(UI_CODE_LOC, "app_event_t").clicked, ui_pop_exp()) { - defer_if (ui_push_exp(UI_CODE_LOC, "mouse_wheel_delta: v3f64_t").clicked, ui_pop_exp()) { - ui_label(UI_CODE_LOC, "x: f64 = value"); - ui_label(UI_CODE_LOC, "y: f64 = value"); - ui_label(UI_CODE_LOC, "z: f64 = value"); - } - ui_label(UI_CODE_LOC, "kind: app_event_kind_t = value"); - ui_label(UI_CODE_LOC, "ctrl: b8 = value"); - ui_label(UI_CODE_LOC, "shift: b8 = value"); - defer_if (ui_push_exp(UI_CODE_LOC, "pos: v2f64_t").clicked, ui_pop_exp()) { - defer_if (ui_push_exp(UI_CODE_LOC, "inner_pos: v2f64_t##asd").clicked, ui_pop_exp()) { - ui_label(UI_CODE_LOC, "x: f64 = value"); - ui_label(UI_CODE_LOC, "y: f64 = value"); - } - defer_if (ui_push_exp(UI_CODE_LOC, "inner_pos: v2f64_t##qwe").clicked, ui_pop_exp()) { - ui_label(UI_CODE_LOC, "x: f64 = value"); - ui_label(UI_CODE_LOC, "y: f64 = value"); - } - ui_label(UI_CODE_LOC, "y: f64 = value"); - } - ui_label(UI_CODE_LOC, "alt: b8 = value"); - ui_label(UI_CODE_LOC, "meta: b8 = value"); - } - defer_if (ui_push_exp(UI_CODE_LOC, "app_event_t").clicked, ui_pop_exp()) { - defer_if (ui_push_exp(UI_CODE_LOC, "mouse_wheel_delta: v3f64_t").clicked, ui_pop_exp()) { - ui_label(UI_CODE_LOC, "x: f64 = value"); - ui_label(UI_CODE_LOC, "y: f64 = value"); - ui_label(UI_CODE_LOC, "z: f64 = value"); - } - ui_label(UI_CODE_LOC, "kind: app_event_kind_t = value"); - ui_label(UI_CODE_LOC, "ctrl: b8 = value"); - ui_label(UI_CODE_LOC, "shift: b8 = value"); - defer_if (ui_push_exp(UI_CODE_LOC, "pos: v2f64_t").clicked, ui_pop_exp()) { - defer_if (ui_push_exp(UI_CODE_LOC, "inner_pos: v2f64_t##asd").clicked, ui_pop_exp()) { - ui_label(UI_CODE_LOC, "x: f64 = value"); - ui_label(UI_CODE_LOC, "y: f64 = value"); - } - defer_if (ui_push_exp(UI_CODE_LOC, "inner_pos: v2f64_t##qwe").clicked, ui_pop_exp()) { - ui_label(UI_CODE_LOC, "x: f64 = value"); - ui_label(UI_CODE_LOC, "y: f64 = value"); - } - ui_label(UI_CODE_LOC, "y: f64 = value"); - } - ui_label(UI_CODE_LOC, "alt: b8 = value"); - ui_label(UI_CODE_LOC, "meta: b8 = value"); - } - defer_if (ui_push_exp(UI_CODE_LOC, "app_event_t").clicked, ui_pop_exp()) { - defer_if (ui_push_exp(UI_CODE_LOC, "mouse_wheel_delta: v3f64_t").clicked, ui_pop_exp()) { - ui_label(UI_CODE_LOC, "x: f64 = value"); - ui_label(UI_CODE_LOC, "y: f64 = value"); - ui_label(UI_CODE_LOC, "z: f64 = value"); - } - ui_label(UI_CODE_LOC, "kind: app_event_kind_t = value"); - ui_label(UI_CODE_LOC, "ctrl: b8 = value"); - ui_label(UI_CODE_LOC, "shift: b8 = value"); - defer_if (ui_push_exp(UI_CODE_LOC, "pos: v2f64_t").clicked, ui_pop_exp()) { - defer_if (ui_push_exp(UI_CODE_LOC, "inner_pos: v2f64_t##asd").clicked, ui_pop_exp()) { - ui_label(UI_CODE_LOC, "x: f64 = value"); - ui_label(UI_CODE_LOC, "y: f64 = value"); - } - defer_if (ui_push_exp(UI_CODE_LOC, "inner_pos: v2f64_t##qwe").clicked, ui_pop_exp()) { - ui_label(UI_CODE_LOC, "x: f64 = value"); - ui_label(UI_CODE_LOC, "y: f64 = value"); - } - ui_label(UI_CODE_LOC, "y: f64 = value"); - } - ui_label(UI_CODE_LOC, "alt: b8 = value"); - ui_label(UI_CODE_LOC, "meta: b8 = value"); - } - } - - // scroller - { - f32 all_items_size = (f32)item_box->node_count * rn_state.main_font.size; - f32 item_box_size = r2f32_get_size(item_box->rect).y; - - f32 scroller_size = CLAMP(item_box_size / all_items_size, 0, 1.0f); - f32 scrollable_space = (1 - scroller_size); - f32 scroller_norm = scroller_value / (all_items_size); - f32 scroller_percent = scroller_norm * scrollable_space; - f32 scroller_second = scrollable_space - scroller_percent; - - ui_push_container(UI_CODE_LOC, ui_percent(0.03f), ui_percent(1)); - ui_spacer(UI_CODE_LOC, ui_percent(1), ui_percent(scroller_percent)); - ui_signal_t sig = ui_scroller_button(UI_CODE_LOC, ui_percent(1), ui_percent(scroller_size)); - if (sig.dragging) { - scroller_value += (ev->mouse_delta.y / item_box_size * 2) * (all_items_size); - scroller_value = CLAMP(scroller_value, 0, all_items_size); - } - ui_spacer(UI_CODE_LOC, ui_percent(1), ui_percent(scroller_second)); - ui_pop_parent(); - - item_box->view_offset.y = scroller_value; - } - } - } - } - - rn_begin(); - - ui_draw(); - rn_draw_stringf(&rn_state.main_font, v2f32(0,frame->window_size.y - 100), black_color_global, "ui_boxes: %d delta: %f update: %f event_count: %d, delta: %f %f dpr: %f", ui->allocated_boxes, frame->delta, frame->update, frame->event_count, frame->last_event->mouse_delta.x, frame->last_event->mouse_delta.y, frame->dpr); - rn_end(frame->window_size, white_color_global); - - ui_end_frame(); + ui_demo_update(frame); return true; } diff --git a/src/wasm_app/ui.c b/src/wasm_app/ui.c index 1c85237..2577a6e 100644 --- a/src/wasm_app/ui.c +++ b/src/wasm_app/ui.c @@ -1,8 +1,10 @@ +fn s8_t ui_tprint_loc(ui_code_loc_t loc) { + return s8_printf(tcx.temp, "%s(%d)", loc.file, loc.line); +} + fn s8_t ui_get_display_string(s8_t string) { s8_t result = string; - if (s8_seek(result, s8_lit("##"), s8_seek_none, &result.len)) { - int a = 10; - } + s8_seek(result, s8_lit("##"), s8_seek_none, &result.len); return result; } @@ -14,27 +16,27 @@ fn s8_t ui_get_hash_string(s8_t string) { return string; } -fn ui_id_t ui_find_valid_id(ui_box_t *box) { - for (ui_box_t *it = box; it; it = it->parent) { - if (!ui_is_null_box(it)) return it->id; - } - return ui_null_id; +fn ui_id_t ui_id_from_string(s8_t string) { + u64 value = hash_data(string); + ui_id_t result = {value}; + return result; } -fn ui_id_t ui_find_top_id(void) { - ui_id_t parent_id = ui_find_valid_id(ui->top); - if (ui_is_null_id(parent_id)) parent_id.value = 1423; - return parent_id; +fn u64 ui_hash_code_loc(ui_code_loc_t loc) { + u64 result = 4242843; + u64 file_hash = hash_data(s8_from_char(loc.file)); + u64 line_hash = hash_data(s8_struct(loc.line)); + u64 cont_hash = hash_data(s8_struct(loc.counter)); + result = hash_mix(result, file_hash); + result = hash_mix(result, line_hash); + result = hash_mix(result, cont_hash); + return result; } -fn ui_box_t *ui_find_box(ui_id_t id) { - if (id.value == 0) return NULL; - for (ui_box_t *it = ui->hash_first; it; it = it->hash_next) { - if (it->id.value == id.value) { - return it; - } - } - return NULL; +fn ui_id_t ui_id_from_code_loc(ui_code_loc_t loc) { + u64 id = ui_hash_code_loc(loc); + ui_id_t result = {id}; + return result; } fn ui_box_t *ui_alloc_box(void) { @@ -48,20 +50,24 @@ fn ui_box_t *ui_alloc_box(void) { return box; } -fn void ui_push(ui_box_t *parent, ui_box_t *box) { +fn ui_box_t *ui_find_box(ui_id_t id) { + if (id.value == 0) return NULL; + for (ui_box_t *it = ui->hash_first; it; it = it->hash_next) { + if (it->id.value == id.value) { + return it; + } + } + return NULL; +} + +fn void ui_push_box(ui_box_t *parent, ui_box_t *box) { box->parent = parent; DLLQ_APPEND(parent->first, parent->last, box); parent->node_count += 1; } -fn void ui_set_semantic_size(ui_box_t *box, ui_size_t x, ui_size_t y) { - box->semantic_size[0] = x; - box->semantic_size[1] = y; -} - -fn s8_t ui_tprint_loc(ui_code_loc_t loc) { - return s8_printf(tcx.temp, "%s(%d)", loc.file, loc.line); -} +fn void ui_push_top(ui_box_t *new_top) { ui->top = new_top; } +fn void ui_pop_top(void) { ui->top = ui->top->parent; } fn ui_box_t *ui_build_box_from_id(ui_code_loc_t loc, ui_box_flags_t flags, ui_id_t id) { ui_box_t *box = ui_find_box(id); @@ -79,34 +85,12 @@ fn ui_box_t *ui_build_box_from_id(ui_code_loc_t loc, ui_box_flags_t flags, ui_id box->last_touched_event_id = ui->event->id; box->id = id; box->flags = flags; - ui_push(ui->top, box); + ui_push_box(ui->top, box); return box; } -fn ui_id_t ui_gen_id(ui_id_flags_t flags, ui_code_loc_t loc, s8_t string) { - u64 result = 42523423493; - if (flags.use_string) { - u64 string_hash = hash_data(string); - result = hash_mix(string_hash, result); - } - if (flags.use_hierarchy) { - ui_id_t top_id = ui_find_top_id(); - result = hash_mix(top_id.value, result); - } - if (flags.use_code_loc) { - u64 file_hash = hash_data(s8_from_char(loc.file)); - u64 line_hash = hash_data(s8_struct(loc.line)); - u64 cont_hash = hash_data(s8_struct(loc.counter)); - result = hash_mix(result, file_hash); - result = hash_mix(result, line_hash); - result = hash_mix(result, cont_hash); - } - ui_id_t id = {result}; - return id; -} - fn ui_box_t *ui_build_box_from_string(ui_code_loc_t loc, ui_box_flags_t flags, s8_t string) { - ui_id_t id = ui_gen_id(ui->id_flags, loc, ui_get_hash_string(string)); + ui_id_t id = ui_id_from_string(ui_get_hash_string(string)); ui_box_t *box = ui_build_box_from_id(loc, flags, id); box->string = ui_get_display_string(string); return box; @@ -141,20 +125,18 @@ fn ui_signal_t ui_signal_from_box(ui_box_t *box) { return result; } -fn void ui_init(ma_arena_t *arena) { - assert(arena != tcx.temp); - - ui = ma_push_type(arena, ui_t); - ui->box_arena = arena; - ui->root = ma_push_type(arena, ui_box_t); - ui->id_flags = (ui_id_flags_t){.use_string = true, .use_code_loc = true}; - - ui->box_array = ma_push_type(arena, ui_box_t); - SLLS_PUSH(ui->free_first, ui->box_array); +fn ui_signal_t ui_button(ui_code_loc_t loc, char *str, ...) { + S8_FMT(tcx.temp, str, string); + ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_rect = true, .draw_text = true }, string); + { + box->full_rect = box->rect = r2f32_cut_top(&ui->top->rect, rn_state.main_font.size); + } + ui_signal_t signal = ui_signal_from_box(box); + return signal; } -fn void ui_begin_build(ui_code_loc_t loc, app_event_t *event) { - ui->event = event; +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; @@ -165,13 +147,14 @@ fn void ui_begin_build(ui_code_loc_t loc, app_event_t *event) { } } - zero_struct(ui->root); - ui->top = ui->root; - ui->root->loc = UI_CODE_LOC; + zero_struct(&ui->root); + ui->root.full_rect = ui->root.rect = window_rect; + ui->top = &ui->root; + ui->root.loc = loc; } fn void ui_end_build(void) { - assert(ui->top == ui->root); + assert(ui->top == &ui->root); for (ui_box_t *box = ui->hash_first, *next = NULL; box; box = next) { next = box->hash_next; @@ -184,189 +167,10 @@ fn void ui_end_build(void) { } } -fn void ui_begin_frame(app_frame_t *frame) { - ui->frame = frame; -} - -fn void ui_push_parent(ui_box_t *box) { - ui->top = box; -} - -fn ui_box_t *ui_pop_parent(void) { - ui_box_t *top = ui->top; - ui->top = ui->top->parent; - return top; -} - -fn ui_box_t *ui_spacer(ui_code_loc_t loc, ui_size_t x, ui_size_t y) { - ui_box_t *box = ui_build_box_from_id(loc, (ui_box_flags_t){.draw_rect = true, .draw_border = true}, ui_null_id); - ui_set_semantic_size(box, x, y); - return box; -} - -fn ui_signal_t ui_scroller_button(ui_code_loc_t loc, ui_size_t x, ui_size_t y) { - ui_id_t id = ui_gen_id(ui->id_flags, loc, s8_lit("spacer")); - ui_box_t *box = ui_build_box_from_id(loc, (ui_box_flags_t){.draw_rect = true, .draw_border = true}, id); - ui_set_semantic_size(box, x, y); - ui_signal_t signal = ui_signal_from_box(box); - return signal; -} - -fn ui_box_t *ui_push_container(ui_code_loc_t loc, ui_size_t x, ui_size_t y) { - ui_box_t *box = ui_build_box_from_id(loc, (ui_box_flags_t){.draw_rect = true}, ui_null_id); - ui_push_parent(box); - ui_set_semantic_size(box, x, y); - box->grow_axis = ui_axis2_y; - return box; -} - -fn ui_box_t *ui_push_xcontainer(ui_code_loc_t loc, ui_size_t x, ui_size_t y) { - ui_box_t *box = ui_push_container(loc, x, y); - box->grow_axis = ui_axis2_x; - return box; -} - -fn ui_box_t *ui_push_list_container(ui_code_loc_t loc, ui_size_t size) { - return ui_push_container(loc, size, ui_children_sum()); -} - -fn void ui_set_indented_string(ui_box_t *box, s8_t string) { box->string = s8_printf(tcx.temp, "%.*s%S", ui->indent_stack, " ", string); } - -fn ui_signal_t ui_push_exp(ui_code_loc_t loc, char *str, ...) { - S8_FMT(tcx.temp, str, string); - ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){.draw_text = true}, string); - ui_set_semantic_size(box, ui_percent(1), ui_text()); - - if (box->created_new) box->expanded = true; - - ui_signal_t signal = ui_signal_from_box(box); - if (signal.clicked) box->expanded = !box->expanded; - signal.clicked = box->expanded; - - if (signal.clicked) { - box->string = s8_printf(tcx.temp, "* %S", box->string); // ▼ - } else { - box->string = s8_printf(tcx.temp, "> %S", box->string); // ► - } - ui_set_indented_string(box, box->string); - - - if (signal.clicked) ui->indent_stack += 1; - return signal; -} - -fn void ui_pop_exp(void) { - ui->indent_stack -= 1; -} - -fn ui_box_t *ui_label(ui_code_loc_t loc, char *fmt, ...) { - S8_FMT(tcx.temp, fmt, string); - ui_box_t *box = ui_build_box_from_id(loc, (ui_box_flags_t){.draw_text = true}, ui_null_id); - ui_set_indented_string(box, string); - ui_set_semantic_size(box, ui_text(), ui_text()); - return box; -} - -fn void ui_end_frame(void) { - 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_layout(void) { - rn_font_t *font = &rn_state.main_font; - - // compute standalone sizes: (pixels, text_content) - for (ui_preorder_iter_t it = ui_iterate_preorder(ui->root); ui_preorder_iter_is_valid(it); ui_iter_advance_preorder(&it)) { - ui_box_t *box = it.box; - if (box == ui->root) continue; // @todo: remove somehow - for (ui_axis2_t axis = 0; axis < ui_axis2_count; axis += 1) { - ui_size_t sem = box->semantic_size[axis]; - assert(sem.kind != ui_size_kind_null); - if (sem.kind == ui_size_kind_pixels) { - box->computed_size[axis] = sem.value; - } else if (sem.kind == ui_size_kind_text_content) { - box->computed_size[axis] = rn_measure_string(font, box->string).e[axis]; - } - } - } - - // compute: (percent_of_parent) - for (ui_preorder_iter_t it = ui_iterate_preorder(ui->root); ui_preorder_iter_is_valid(it); ui_iter_advance_preorder(&it)) { - ui_box_t *box = it.box; - ui_box_t *parent = box->parent; // @todo: I'm not sure why Ryan uses a loop to find a parent with fixed size_kind - for (ui_axis2_t axis = 0; axis < ui_axis2_count; axis += 1) { - ui_size_t sem = box->semantic_size[axis]; - if (sem.kind == ui_size_kind_percent_of_parent) { - assert(parent->semantic_size[axis].kind == ui_size_kind_pixels || - parent->semantic_size[axis].kind == ui_size_kind_text_content || - parent->semantic_size[axis].kind == ui_size_kind_percent_of_parent); - box->computed_size[axis] = (sem.value) * parent->computed_size[axis]; - } - } - } - - // compute: (children_sum) - for (ui_postorder_iter_t it = ui_iterate_postorder(ui->root); ui_postorder_iter_is_valid(it); ui_iter_advance_postorder(&it)) { - ui_box_t *box = it.box; - for (ui_axis2_t axis = 0; axis < ui_axis2_count; axis += 1) { - ui_size_t sem = box->semantic_size[axis]; - if (sem.kind != ui_size_kind_children_sum) continue; - - for (ui_box_t *child = box->first; child; child = child->next) { - assert(child->computed_size[axis] != 0.f); - if (box->grow_axis == axis) { - box->computed_size[axis] += child->computed_size[axis]; - } else { - box->computed_size[axis] = MAX(box->computed_size[axis], child->computed_size[axis]); - } - } - } - } - - // solve violations - - // compute relative positions - for (ui_preorder_iter_t it = ui_iterate_preorder(ui->root); ui_preorder_iter_is_valid(it); ui_iter_advance_preorder(&it)) { - ui_box_t *box = it.box; - ui_box_t *parent = box->parent; - if (ui->root == box) continue; // @todo: how to remove this? - - for (ui_axis2_t axis = 0; axis < ui_axis2_count; axis += 1) { - f32 *pos = &box->computed_rel_pos[axis]; - f32 size = box->computed_size[axis]; - - f32 parent_pos = parent->computed_rel_pos[axis]; - f32 *iter_pos = &parent->iter_pos[axis]; - - *pos = parent_pos + *iter_pos; - if (parent->flags.scroll) { - *pos -= parent->view_offset.e[axis]; - } - - if (parent->grow_axis == axis) *iter_pos += size; - } - - v2f32_t pos = v2f32(box->computed_rel_pos[0], box->computed_rel_pos[1]); - v2f32_t size = v2f32(box->computed_size[0], box->computed_size[1]); - box->rect = r2f32_mindim(pos, size); - } -} - -fn void ui_draw(void) { - rn_font_t *font = &rn_state.main_font; - ui_test_iterator(); - ui_layout(); - - // actually draw - for (ui_preorder_iter_t it = ui_iterate_preorder(ui->root); ui_preorder_iter_is_valid(it); ui_iter_advance_preorder(&it)) { +fn void ui_draw(app_frame_t *frame) { + for (ui_preorder_iter_t it = ui_iterate_preorder(&ui->root); ui_preorder_iter_is_valid(it); ui_iter_advance_preorder(&it)) { ui_box_t *box = it.box; r2f32_t clip_rect = box->rect; - if (box->parent) { - clip_rect = r2f32_intersect(clip_rect, box->parent->rect); - } v4f32_t rect_color = primary_color_global; v4f32_t text_color = black_color_global; @@ -387,7 +191,32 @@ fn void ui_draw(void) { rn_draw_rect_border(box->rect, accent2_color_global); } if (box->flags.draw_text) { - rn_draw_string(font, box->rect.min, text_color, box->string); + rn_draw_string(&rn_state.main_font, box->rect.min, text_color, box->string); } } } + +fn void ui_demo_init(ma_arena_t *arena) { + ui = ma_push_type(arena, ui_t); + ui->box_arena = ma_push_arena(arena, mib(1)); +} + +fn void ui_demo_update(app_frame_t *frame) { + for (app_event_t *ev = frame->first_event; ev; ev = ev->next) { + ui_begin_build(UILOC, ev, r2f32_mindim(v2f32(0.f, 0.f), frame->window_size)); + ui_button(UILOC, "thing itself##id32"); + ui_end_build(); + } + + rn_begin(); + ui_draw(frame); + rn_end(frame->window_size, white_color_global); + + + // End frame + for (app_event_t *ev = frame->first_event; ev; ev = ev->next) { + if (ev_left_up(ev)) { + ui->active = ui_null_id; + } + } +} \ No newline at end of file diff --git a/src/wasm_app/ui.h b/src/wasm_app/ui.h index dc01c99..832e1f0 100644 --- a/src/wasm_app/ui.h +++ b/src/wasm_app/ui.h @@ -1,141 +1,74 @@ -/* -** [x] Choosing a keying strategy from user code -** [x] Using parents -** [x] Using file and line -** [ ] Keyboard friendliness -** [x] ui_em size -** [ ] use strictness to 'solve violations' -** [ ] scrolling -** [ ] vieweing type info -** [ ] slider -** [ ] button -** [ ] pernament state -*/ - -typedef struct ui_id_t ui_id_t; -struct ui_id_t { - u64 value; -}; - typedef struct ui_code_loc_t ui_code_loc_t; struct ui_code_loc_t { char *file; int line; int counter; }; -#define UI_CODE_LOC (ui_code_loc_t){.file = __FILE__, .line = __LINE__, .counter = __COUNTER__} +#define UILOC (ui_code_loc_t){.file = __FILE__, .line = __LINE__, .counter = __COUNTER__} -typedef enum { - ui_axis2_x, - ui_axis2_y, - ui_axis2_count, -} ui_axis2_t; -typedef enum { - ui_size_kind_null, - ui_size_kind_pixels, - ui_size_kind_text_content, - ui_size_kind_percent_of_parent, - ui_size_kind_children_sum, -} ui_size_kind_t; - -typedef struct ui_size_t ui_size_t; -struct ui_size_t { - ui_size_kind_t kind; - f32 value; - f32 strictness; +typedef struct ui_id_t ui_id_t; +struct ui_id_t { + u64 value; }; + typedef struct ui_box_flags_t ui_box_flags_t; struct ui_box_flags_t { - b8 draw_border : 1; - b8 draw_text : 1; - b8 draw_rect : 1; - - b8 scroll : 1; + b8 draw_rect: 1; + b8 draw_border: 1; + b8 draw_text: 1; }; typedef struct ui_box_t ui_box_t; struct ui_box_t { - // recreated every frame in building code - ui_box_t *next; - ui_box_t *prev; - ui_box_t *parent; - ui_box_t *first; - ui_box_t *last; - i32 node_count; + ui_box_t *next; + ui_box_t *prev; + ui_box_t *first; + ui_box_t *last; + ui_box_t *parent; + i32 node_count; - ui_box_flags_t flags; - s8_t string; - ui_size_t semantic_size[ui_axis2_count]; - ui_axis2_t grow_axis; ui_code_loc_t loc; - b32 created_new; + s8_t string; + r2f32_t full_rect; + r2f32_t rect; + ui_box_flags_t flags; + b8 created_new; - // layout - f32 iter_pos[ui_axis2_count]; - - // preserving state - ui_id_t id; // important position!: offset(id) used for partial zeroing - u64 last_touched_event_id; + ui_id_t id; ui_box_t *hash_next; ui_box_t *hash_prev; - - // layout - f32 computed_rel_pos[ui_axis2_count]; - f32 computed_size[ui_axis2_count]; - r2f32_t rect; - v2f32_t view_offset; - - // state - b32 expanded; + u64 last_touched_event_id; }; + typedef struct ui_signal_t ui_signal_t; struct ui_signal_t { ui_box_t *box; b8 clicked; b8 dragging; - - // b8 double_clicked; - // b8 right_clicked; - // b8 pressed; - // b8 released; - // b8 dragging; - // b8 hovering; -}; - -typedef struct ui_id_flags_t ui_id_flags_t; -struct ui_id_flags_t { - b8 use_hierarchy; - b8 use_code_loc; - b8 use_string; }; typedef struct ui_t ui_t; struct ui_t { - ma_arena_t *box_arena; // required to be only used for boxes - app_event_t *event; - app_frame_t *frame; - - i32 allocated_boxes; - ui_box_t *box_array; // first item on arena - ui_box_t *root; + ma_arena_t *box_arena; + ui_box_t root; ui_box_t *top; + app_event_t *event; + + i32 allocated_boxes; ui_box_t *free_first; ui_box_t *hash_first; ui_box_t *hash_last; ui_id_t hot; ui_id_t active; - - int indent_stack; - - ui_id_flags_t id_flags; }; -gb ui_t *ui = NULL; +ui_t *ui; + gb_read_only ui_id_t ui_null_id; gb_read_only ui_box_t ui_null_box; @@ -147,10 +80,3 @@ fn b32 ui_is_active_box(ui_box_t *box) { return !ui_is_null_box(box) && box->id. #define ev_left(ev) ((ev)->mouse_button == app_mouse_button_left) #define ev_left_up(ev) ((ev)->kind == app_event_kind_mouse_up && ev_left(ev)) #define ev_left_down(ev) ((ev)->kind == app_event_kind_mouse_down && ev_left(ev)) - -fn ui_size_t ui_size(ui_size_kind_t kind, f32 value) { return (ui_size_t){.kind = kind, .value = value}; } -#define ui_pixels(value) ui_size(ui_size_kind_pixels, value) -#define ui_em(value) ui_size(ui_size_kind_pixels, value * rn_state.main_font.size) -#define ui_text() ui_size(ui_size_kind_text_content, 0) -#define ui_children_sum() ui_size(ui_size_kind_children_sum, 0) -#define ui_percent(value) ui_size(ui_size_kind_percent_of_parent, value) diff --git a/src/wasm_app/ui_iter.c b/src/wasm_app/ui_iter.c index 4e0fa2a..8ab70f6 100644 --- a/src/wasm_app/ui_iter.c +++ b/src/wasm_app/ui_iter.c @@ -1,4 +1,3 @@ - typedef struct ui_preorder_iter_t ui_preorder_iter_t; struct ui_preorder_iter_t { ui_box_t *box; }; @@ -77,11 +76,11 @@ fn void ui_test_iterator(void) { ma_temp_t scratch = ma_begin_scratch(); sb8_t *sb = sb8_serial_begin(scratch.arena); - ui_test_stringify_preorder(sb, ui->root); + ui_test_stringify_preorder(sb, &ui->root); s8_t recursive_string = sb8_serial_end(scratch.arena, sb); sb = sb8_serial_begin(scratch.arena); - for (ui_preorder_iter_t it = ui_iterate_preorder(ui->root); ui_preorder_iter_is_valid(it); ui_iter_advance_preorder(&it)) { + for (ui_preorder_iter_t it = ui_iterate_preorder(&ui->root); ui_preorder_iter_is_valid(it); ui_iter_advance_preorder(&it)) { sb8_printf(sb, "%S\n", it.box->string); } s8_t iter_string = sb8_serial_end(scratch.arena, sb); @@ -94,11 +93,11 @@ fn void ui_test_iterator(void) { ma_temp_t scratch = ma_begin_scratch(); sb8_t *sb = sb8_serial_begin(scratch.arena); - ui_test_stringify_postorder(sb, ui->root); + ui_test_stringify_postorder(sb, &ui->root); s8_t recursive_string = sb8_serial_end(scratch.arena, sb); sb = sb8_serial_begin(scratch.arena); - for (ui_postorder_iter_t it = ui_iterate_postorder(ui->root); ui_postorder_iter_is_valid(it); ui_iter_advance_postorder(&it)) { + for (ui_postorder_iter_t it = ui_iterate_postorder(&ui->root); ui_postorder_iter_is_valid(it); ui_iter_advance_postorder(&it)) { sb8_printf(sb, "%S\n", it.box->string); } s8_t iter_string = sb8_serial_end(scratch.arena, sb);