From be2537b73c48c37e4a171a9bae7988d4dffb1044 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Thu, 30 Jan 2025 09:54:18 +0100 Subject: [PATCH] ui_tree_table --- src/app/app_win32.c | 6 +- src/core/core_platform_win32.c | 3 +- src/render/render.h | 1 + src/render/render_opengl.c | 2 + src/ui/ui.c | 119 ++++++++++++++++++++++++--------- src/ui/ui.gen.c | 7 ++ src/ui/ui.gen.h | 3 + src/ui/ui.h | 3 +- src/ui/ui.meta.c | 1 + todo.txt | 5 +- 10 files changed, 112 insertions(+), 38 deletions(-) diff --git a/src/app/app_win32.c b/src/app/app_win32.c index 503ad41..613f45a 100644 --- a/src/app/app_win32.c +++ b/src/app/app_win32.c @@ -336,11 +336,13 @@ fn void w32_try_reloading_library(w32_library_t *lib, app_frame_t frame) { s8_t base_name = s8_chop_last_period(lib->dll_name); s8_t new_dll_name = s8_printf(tcx->temp, "%S_temp_%u.dll", base_name, random_value); - os_copy(lib->dll_name, new_dll_name, true); + b32 ok = os_copy(lib->dll_name, new_dll_name, true); + if (!ok) debugf("failed to copy from %S to %S", lib->dll_name, new_dll_name); s8_t pdb_name = s8_printf(tcx->temp, "%S.pdb", base_name); s8_t new_pdb_name = s8_printf(tcx->temp, "%S_temp_%u.pdb", base_name, random_value); - os_copy(pdb_name, new_pdb_name, true); + ok = os_copy(pdb_name, new_pdb_name, true); + if (!ok) debugf("failed to copy from %S to %S", pdb_name, new_pdb_name); HMODULE library = LoadLibraryA(new_dll_name.str); if (!library) { diff --git a/src/core/core_platform_win32.c b/src/core/core_platform_win32.c index df9336e..e610723 100644 --- a/src/core/core_platform_win32.c +++ b/src/core/core_platform_win32.c @@ -18,9 +18,10 @@ fn b32 os_vmem_decommit(void *p, usize size) { } fn void os_error_box(char *str) { - MessageBoxA(NULL, str, "fatal error", MB_OK); + OutputDebugStringA(str); fprintf(stderr, "%s", str); fflush(stderr); + MessageBoxA(NULL, str, "fatal error", MB_OK); } fn void os_console_log(char *str) { diff --git a/src/render/render.h b/src/render/render.h index eba03c6..c0c179b 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -15,6 +15,7 @@ struct rn_font_t { u32 first_char, last_char; u32 texture_id; + f32 computed_xchar_size; f32 size; f32 descent; f32 ascent; diff --git a/src/render/render_opengl.c b/src/render/render_opengl.c index 3b246fd..5bf620f 100644 --- a/src/render/render_opengl.c +++ b/src/render/render_opengl.c @@ -50,6 +50,8 @@ fn void rn_reload_font(f32 font_size, f32 dpr) { glTextureStorage2D(atlas->texture_id, 1, GL_R8, (GLsizei)atlas->size.x, (GLsizei)atlas->size.y); glTextureSubImage2D(atlas->texture_id, 0, 0, 0, (GLsizei)atlas->size.x, (GLsizei)atlas->size.y, GL_RED, GL_UNSIGNED_BYTE, atlas->bitmap); rn->main_font->texture_id = atlas->texture_id; + rn->main_font->computed_xchar_size = rn_measure_string(rn->main_font, s8_lit("_")).x; + ma_end_scratch(scratch); } diff --git a/src/ui/ui.c b/src/ui/ui.c index 617e231..f8fff26 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -109,6 +109,17 @@ fn ui_id_t ui_idf(char *str, ...) { fn void ui_push_id_string(s8_t string) { ui_push_id(ui_id(string)); } +#define ui_set_top_ex(x) defer_block(ui_push_top_ex(x), ui_pop_top_ex()) +fn void ui_push_top_ex(ui_box_t *box) { + assert(ui->top == ui->top); + ui->top = box; +} +fn ui_box_t *ui_pop_top_ex(void) { + ui_box_t *result = ui->top; + ui->top = ui->top->parent; + return result; +} + #define ui_set_top(x) defer_block(ui_push_top(x), ui_pop_top()) fn void ui_push_top(ui_box_t *new_top) { assert(new_top->parent == ui->top); @@ -116,10 +127,12 @@ fn void ui_push_top(ui_box_t *new_top) { ui_push_id(new_top->id); ui_push_rect(new_top->rect); } -fn void ui_pop_top(void) { +fn ui_box_t *ui_pop_top(void) { + ui_box_t *result = ui->top; ui->top = ui->top->parent; ui_pop_id(); ui_pop_rect(); + return result; } fn r2f32_t *ui_top_rectp(void) { @@ -132,15 +145,27 @@ fn void ui_set_children_sums(ui_box_t *box) { } if (box->flags.children_sum_x) { - f32 min = MIN(box->first->rect.min.x, box->last->rect.min.x); - f32 max = MAX(box->first->rect.max.x, box->last->rect.max.x); + f32 min = box->rect.min.x; + f32 max = box->rect.max.x; + if (box->first) { + f32 min_child = MIN(box->first->rect.min.x, box->last->rect.min.x); + f32 max_child = MAX(box->first->rect.max.x, box->last->rect.max.x); + min = MIN(box->rect.min.x, min_child); + max = MAX(box->rect.max.x, max_child); + } box->rect.min.x = min; box->rect.max.x = max; } if (box->flags.children_sum_y) { - f32 min = MIN(box->first->rect.min.y, box->last->rect.min.y); - f32 max = MAX(box->first->rect.max.y, box->last->rect.max.y); + f32 min = box->rect.min.y; + f32 max = box->rect.max.y; + if (box->first) { + f32 min_child = MIN(box->first->rect.min.y, box->last->rect.min.y); + f32 max_child = MAX(box->first->rect.max.y, box->last->rect.max.y); + min = MIN(box->rect.min.y, min_child); + max = MAX(box->rect.max.y, max_child); + } box->rect.min.y = min; box->rect.max.y = max; } @@ -239,6 +264,19 @@ fn ui_box_t *ui_build_box_from_id(ui_code_loc_t loc, ui_box_flags_t flags, ui_id box->text_align = ui_top_text_align(); 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; @@ -272,10 +310,12 @@ fn ui_box_t *ui__make_box(ui_box_params_t params) { ui_id_t id = params.id; if (ui_id_is_null(id) && params.null_id == false) { if (params.string.len != 0) { - id = ui_id(params.string); + id = ui_id(ui_get_hash_string(params.string)); + id.value = hash_mix(id.value, ui_hash_from_stack()); } if (ui_id_is_null(id)) { id = ui_id_from_loc(params.loc); + id.value = hash_mix(id.value, ui_hash_from_stack()); } } ui_box_t *box = ui_build_box_from_id(params.loc, params.flags, id); @@ -576,28 +616,44 @@ fn ui_box_t *ui__label(ui_code_loc_t loc, char *str, ...) { return box; } -#define ui_expander(...) defer_if (ui_begin_expander(__VA_ARGS__).clicked, ui_end_expander()) -#define ui_begin_expander(...) ui__begin_expander(UILOC, __VA_ARGS__) -fn ui_signal_t ui__begin_expander(ui_code_loc_t loc, char *str, ...) { - S8_FMT(tcx->temp, str, string); - ui_box_t *box = ui_box(.loc = loc, .string = string, .flags = { .draw_text = true, .keyboard_nav = true }); - 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 ( box->expanded) box->string = s8_printf(tcx->temp, "* %S", box->string); - if (!box->expanded) box->string = s8_printf(tcx->temp, "> %S", box->string); - if (box->expanded) { - ui_push_string_pos_offset(ui_top_string_pos_offset() + ui_em(0.5f)); - ui_push_id(box->id); - } - return signal; +#define ui_tree_table() defer_block(ui_tree_table_begin(UILOC), ui_tree_table_end()) +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_push_top(box); } -fn void ui_end_expander(void) { - ui_pop_string_pos_offset(); +fn void ui_tree_table_end(void) { + ui_box_t *box = ui_pop_top(); + ui_set_children_sums(box); + ui_next_rect(ui_top_lop(), ui_top_rectp(), r2f32_get_size(box->rect)); +} + +#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)); + ui_tree_table_end(); ui_pop_id(); } +fn ui_signal_t ui_tree_table_push_expandable(ui_code_loc_t loc, char *str, ...) { + S8_FMT(tcx->temp, str, string); + ui_id_t id = ui_id(ui_get_hash_string(string)); + ui_push_id(id); + ui_tree_table_begin(loc); + ui_box_t *box = ui_box(.loc = loc, .string = string, .flags = { .draw_rect = true, .draw_text = true, .keyboard_nav = true}); + ui_signal_t button = ui_signal_from_box(box); + if (button.box->created_new) button.box->expanded = true; + if (button.clicked) button.box->expanded = !button.box->expanded; + button.clicked = button.box->expanded; + + r2f32_cut_left(ui_top_rectp(), ui_dm(1)); + + if (button.clicked == false) { + ui_tree_table_pop_expandable(); + } + if ( button.box->expanded) button.box->string = s8_printf(tcx->temp, "* %S", button.box->string); + if (!button.box->expanded) button.box->string = s8_printf(tcx->temp, "> %S", button.box->string); + return button; +} fn ui_box_t *ui_get_prev_box(ui_box_t *box, b32 (*match)(ui_box_t *)) { for (ui_box_t *it = box; it;) { @@ -917,7 +973,7 @@ fn void ui_serial_subtype(void *p, type_t *type, s8_t name) { } if (type->kind == type_kind_array) { - ui_expander("%S:", name) { + ui_tree_table_expandable("%S:", name) { for (i32 i = 0; i < type->count; i += 1) { ma_temp_t scratch = ma_begin_scratch(); s8_t index_name = s8_printf(scratch.arena, "[%d]", i); @@ -930,7 +986,7 @@ fn void ui_serial_subtype(void *p, type_t *type, s8_t name) { } if (type->kind == type_kind_struct) { - ui_expander("%S:", name) { + ui_tree_table_expandable("%S:", name) { for (i32 i = 0; i < type->count; i += 1) { type_member_t *tm = type->members + i; void *tmp = ti_extract_member(p, tm); @@ -943,8 +999,8 @@ fn void ui_serial_subtype(void *p, type_t *type, s8_t name) { } } -fn void ui_serial_type(void *p, type_t *type) { - ui_serial_subtype(p, type, type->name); +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); } fn void ui_reload(void) { @@ -1064,10 +1120,8 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co } else_is_invalid; } ui_label("allocated boxes: %d", ui->allocated_boxes); - ui_serial_type(&ui_test_event, type(app_event_t)); - ui_set_id(ui_id_from_loc(UILOC)) { - ui_serial_type(&ui_test_event, type(app_event_t)); - } + ui_serial_type(UILOC, &ui_test_event, type(app_event_t)); + ui_serial_type(UILOC, &ui_test_event, type(app_event_t)); } locl f32 scroller_value; @@ -1419,7 +1473,6 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co ui_label_button("a"); ui_label_button("memes"); } - } diff --git a/src/ui/ui.gen.c b/src/ui/ui.gen.c index d95ac55..17cdf47 100644 --- a/src/ui/ui.gen.c +++ b/src/ui/ui.gen.c @@ -78,6 +78,10 @@ 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; } @@ -116,6 +120,7 @@ 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); @@ -131,6 +136,7 @@ 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]); @@ -146,6 +152,7 @@ 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 5ccbc6d..c15e588 100644 --- a/src/ui/ui.gen.h +++ b/src/ui/ui.gen.h @@ -20,6 +20,7 @@ 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;\ @@ -28,6 +29,7 @@ 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;\ @@ -45,6 +47,7 @@ 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 ccbe13d..92206bc 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -12,6 +12,7 @@ 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; @@ -79,7 +80,6 @@ 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; @@ -160,6 +160,7 @@ fn b32 ui_is_focused_box(ui_box_t *box) { return !ui_is_null_box(box) && box->id #define UILOC (ui_code_loc_t){.file = __FILE__, .line = __LINE__, .counter = __COUNTER__} #define ui_em(x) ((x) * rn->main_font->size) +#define ui_dm(V) ((V) * rn->main_font->computed_xchar_size) #define ui_max 200000000.f #define ui_children_sum 0 #define ui_box_flags(...) (ui_box_flag_t){__VA_ARGS__} diff --git a/src/ui/ui.meta.c b/src/ui/ui.meta.c index 7dd9c0a..0592602 100644 --- a/src/ui/ui.meta.c +++ b/src/ui/ui.meta.c @@ -42,6 +42,7 @@ 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 bc1480d..084b491 100644 --- a/todo.txt +++ b/todo.txt @@ -10,6 +10,7 @@ [ ] drag and drop [ ] open file dialog [ ] os + [ ] DELETE ALL PDBS\DLLS ON START [?] wasm (explore) [ ] win32 [ ] linux @@ -22,7 +23,8 @@ [ ] maybe copy package stuff to build? [ ] ui - [ ] RECT STACK + [ ] jumping between nodes (get_prev, get_next) needs a fix + [ ] bring back also the old expander? [ ] table [ ] vertical scroll [x] working @@ -55,6 +57,7 @@ [ ] color picker [ ] slider [ ] draw image in box ui + [x] rect stack [ ] core [ ] ast