per-box tags -> per-box tags key; cache (key -> tags_list), and (key * string -> theme_pattern) separately; accelerate all theme lookups

This commit is contained in:
Ryan Fleury
2025-02-19 09:35:45 -08:00
parent 9805f8cd20
commit f87dd1be82
5 changed files with 274 additions and 78 deletions
+11 -15
View File
@@ -8119,7 +8119,7 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
Vec4F32 box_background_color = {0}; Vec4F32 box_background_color = {0};
if(box->flags & UI_BoxFlag_DrawBackground) if(box->flags & UI_BoxFlag_DrawBackground)
{ {
box_background_color = ui_color_from_tags_name(box->tags, str8_lit("background")); box_background_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("background"));
} }
// rjf: draw background // rjf: draw background
@@ -8141,7 +8141,7 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
// rjf: hot effect extension // rjf: hot effect extension
if(box->flags & UI_BoxFlag_DrawHotEffects) if(box->flags & UI_BoxFlag_DrawHotEffects)
{ {
Vec4F32 hover_color = ui_color_from_tags_name(box->tags, str8_lit("hover")); Vec4F32 hover_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("hover"));
// rjf: brighten // rjf: brighten
{ {
@@ -8239,11 +8239,9 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
ellipses_run = fnt_push_run_from_string(scratch.arena, ellipses_font, ellipses_size, 0, box->tab_size, ellipses_raster_flags, str8_lit("...")); ellipses_run = fnt_push_run_from_string(scratch.arena, ellipses_font, ellipses_size, 0, box->tab_size, ellipses_raster_flags, str8_lit("..."));
} }
dr_truncated_fancy_run_list(text_position, &box->display_fruns, max_x, ellipses_run); dr_truncated_fancy_run_list(text_position, &box->display_fruns, max_x, ellipses_run);
if(box->flags & UI_BoxFlag_HasFuzzyMatchRanges) if(box->flags & UI_BoxFlag_HasFuzzyMatchRanges) UI_TagF("pop")
{ {
String8 tags[] = {str8_lit("pop")}; Vec4F32 match_color = ui_color_from_tags_key_name(ui_top_tags_key(), str8_lit("background"));
String8Array tags_array = {tags, ArrayCount(tags)};
Vec4F32 match_color = ui_color_from_tags_name(tags_array, str8_lit("background"));
dr_truncated_fancy_run_fuzzy_matches(text_position, &box->display_fruns, max_x, &box->fuzzy_match_ranges, match_color); dr_truncated_fancy_run_fuzzy_matches(text_position, &box->display_fruns, max_x, &box->fuzzy_match_ranges, match_color);
} }
} }
@@ -8333,7 +8331,7 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
// rjf: draw border // rjf: draw border
if(b->flags & UI_BoxFlag_DrawBorder) if(b->flags & UI_BoxFlag_DrawBorder)
{ {
Vec4F32 border_color = ui_color_from_tags_name(box->tags, str8_lit("border")); Vec4F32 border_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("border"));
Rng2F32 b_border_rect = pad_2f32(b->rect, 1.f); Rng2F32 b_border_rect = pad_2f32(b->rect, 1.f);
R_Rect2DInst *inst = dr_rect(b_border_rect, border_color, 0, 1.f, 1.f); R_Rect2DInst *inst = dr_rect(b_border_rect, border_color, 0, 1.f, 1.f);
MemoryCopyArray(inst->corner_radii, b->corner_radii); MemoryCopyArray(inst->corner_radii, b->corner_radii);
@@ -8341,7 +8339,7 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
// rjf: hover effect // rjf: hover effect
if(b->flags & UI_BoxFlag_DrawHotEffects) if(b->flags & UI_BoxFlag_DrawHotEffects)
{ {
Vec4F32 color = ui_color_from_tags_name(box->tags, str8_lit("hover")); Vec4F32 color = ui_color_from_tags_key_name(box->tags_key, str8_lit("hover"));
color.w *= b->hot_t; color.w *= b->hot_t;
R_Rect2DInst *inst = dr_rect(b_border_rect, color, 0, 1.f, 1.f); R_Rect2DInst *inst = dr_rect(b_border_rect, color, 0, 1.f, 1.f);
inst->colors[Corner_01].w *= 0.2f; inst->colors[Corner_01].w *= 0.2f;
@@ -8360,7 +8358,7 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
// rjf: draw sides // rjf: draw sides
if(b->flags & UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DrawSideLeft|UI_BoxFlag_DrawSideRight) if(b->flags & UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DrawSideLeft|UI_BoxFlag_DrawSideRight)
{ {
Vec4F32 border_color = ui_color_from_tags_name(box->tags, str8_lit("border")); Vec4F32 border_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("border"));
Rng2F32 r = b->rect; Rng2F32 r = b->rect;
F32 half_thickness = 1.f; F32 half_thickness = 1.f;
F32 softness = 0.f; F32 softness = 0.f;
@@ -8385,7 +8383,7 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
// rjf: draw focus overlay // rjf: draw focus overlay
if(b->flags & UI_BoxFlag_Clickable && !(b->flags & UI_BoxFlag_DisableFocusOverlay) && b->focus_hot_t > 0.01f) if(b->flags & UI_BoxFlag_Clickable && !(b->flags & UI_BoxFlag_DisableFocusOverlay) && b->focus_hot_t > 0.01f)
{ {
Vec4F32 color = ui_color_from_tags_name(box->tags, str8_lit("focus")); Vec4F32 color = ui_color_from_tags_key_name(box->tags_key, str8_lit("focus"));
color.w *= 0.09f*b->focus_hot_t; color.w *= 0.09f*b->focus_hot_t;
R_Rect2DInst *inst = dr_rect(b->rect, color, 0, 0, 0.f); R_Rect2DInst *inst = dr_rect(b->rect, color, 0, 0, 0.f);
MemoryCopyArray(inst->corner_radii, b->corner_radii); MemoryCopyArray(inst->corner_radii, b->corner_radii);
@@ -8400,7 +8398,7 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
rect = pad_2f32(rect, 1.f); rect = pad_2f32(rect, 1.f);
rect = intersect_2f32(window_rect, rect); rect = intersect_2f32(window_rect, rect);
} }
Vec4F32 color = ui_color_from_tags_name(box->tags, str8_lit("focus")); Vec4F32 color = ui_color_from_tags_key_name(box->tags_key, str8_lit("focus"));
color.w *= b->focus_active_t; color.w *= b->focus_active_t;
R_Rect2DInst *inst = dr_rect(rect, color, 0, 1.f, 1.f); R_Rect2DInst *inst = dr_rect(rect, color, 0, 1.f, 1.f);
MemoryCopyArray(inst->corner_radii, b->corner_radii); MemoryCopyArray(inst->corner_radii, b->corner_radii);
@@ -8453,11 +8451,9 @@ ws->cfg_palettes[RD_PaletteCode_##name].selection = current->colors[RD_The
} }
//- rjf: draw border/overlay color to signify error //- rjf: draw border/overlay color to signify error
if(ws->error_t > 0.01f) if(ws->error_t > 0.01f) UI_TagF("bad")
{ {
String8 tags[] = {str8_lit("bad")}; Vec4F32 color = ui_color_from_name(str8_lit("text"));
String8Array tags_array = {tags, ArrayCount(tags)};
Vec4F32 color = ui_color_from_tags_name(tags_array, str8_lit("text"));
color.w *= ws->error_t; color.w *= ws->error_t;
Rng2F32 rect = os_client_rect_from_window(ws->os); Rng2F32 rect = os_client_rect_from_window(ws->os);
dr_rect(pad_2f32(rect, 24.f), color, 0, 16.f, 12.f); dr_rect(pad_2f32(rect, 24.f), color, 0, 16.f, 12.f);
+2 -4
View File
@@ -1046,12 +1046,10 @@ internal UI_BOX_CUSTOM_DRAW(rd_thread_box_draw_extensions)
} }
// rjf: locked icon on frozen threads // rjf: locked icon on frozen threads
if(u->is_frozen) if(u->is_frozen) UI_TagF("bad")
{ {
F32 lock_icon_off = ui_top_font_size()*0.2f; F32 lock_icon_off = ui_top_font_size()*0.2f;
String8 tags[] = {str8_lit("bad")}; Vec4F32 color = ui_color_from_name(str8_lit("text"));
String8Array tags_array = {tags, ArrayCount(tags)};
Vec4F32 color = ui_color_from_tags_name(tags_array, str8_lit("text"));
dr_text(rd_font_from_slot(RD_FontSlot_Icons), dr_text(rd_font_from_slot(RD_FontSlot_Icons),
box->font_size, 0, 0, FNT_RasterFlag_Smooth, box->font_size, 0, 0, FNT_RasterFlag_Smooth,
v2f32((box->rect.x0 + box->rect.x1)/2 + lock_icon_off/2, v2f32((box->rect.x0 + box->rect.x1)/2 + lock_icon_off/2,
+2 -2
View File
@@ -134,9 +134,9 @@ internal UI_BOX_CUSTOM_DRAW(ui_line_edit_draw)
FNT_Tag font = box->font; FNT_Tag font = box->font;
F32 font_size = box->font_size; F32 font_size = box->font_size;
F32 tab_size = box->tab_size; F32 tab_size = box->tab_size;
Vec4F32 cursor_color = ui_color_from_tags_name(box->tags, str8_lit("cursor")); Vec4F32 cursor_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("cursor"));
cursor_color.w *= box->parent->parent->focus_active_t; cursor_color.w *= box->parent->parent->focus_active_t;
Vec4F32 select_color = ui_color_from_tags_name(box->tags, str8_lit("selection")); Vec4F32 select_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("selection"));
select_color.w *= 0.1f*(box->parent->parent->focus_active_t*0.2f + 0.8f); select_color.w *= 0.1f*(box->parent->parent->focus_active_t*0.2f + 0.8f);
Vec2F32 text_position = ui_box_text_position(box); Vec2F32 text_position = ui_box_text_position(box);
String8 edited_string = draw_data->edited_string; String8 edited_string = draw_data->edited_string;
+184 -33
View File
@@ -797,6 +797,11 @@ ui_begin_build(OS_Handle window, UI_EventList *events, UI_IconInfo *icon_info, U
ui_state->ctx_menu_changed = 0; ui_state->ctx_menu_changed = 0;
ui_state->default_animation_rate = 1 - pow_f32(2, (-80.f * ui_state->animation_dt)); ui_state->default_animation_rate = 1 - pow_f32(2, (-80.f * ui_state->animation_dt));
ui_state->tooltip_can_overflow_window = 0; ui_state->tooltip_can_overflow_window = 0;
ui_state->tags_key_stack_top = ui_state->tags_key_stack_free = 0;
ui_state->tags_cache_slots_count = 512;
ui_state->tags_cache_slots = push_array(ui_build_arena(), UI_TagsCacheSlot, ui_state->tags_cache_slots_count);
ui_state->theme_pattern_cache_slots_count = 512;
ui_state->theme_pattern_cache_slots = push_array(ui_build_arena(), UI_ThemePatternCacheSlot, ui_state->theme_pattern_cache_slots_count);
} }
//- rjf: prune unused animation nodes //- rjf: prune unused animation nodes
@@ -2023,7 +2028,7 @@ ui_begin_ctx_menu(UI_Key key)
ui_state->ctx_menu_root->flags |= UI_BoxFlag_Clip; ui_state->ctx_menu_root->flags |= UI_BoxFlag_Clip;
ui_state->ctx_menu_root->flags |= UI_BoxFlag_Clickable; ui_state->ctx_menu_root->flags |= UI_BoxFlag_Clickable;
ui_state->ctx_menu_root->corner_radii[Corner_00] = ui_state->ctx_menu_root->corner_radii[Corner_01] = ui_state->ctx_menu_root->corner_radii[Corner_10] = ui_state->ctx_menu_root->corner_radii[Corner_11] = ui_top_font_size()*0.25f; ui_state->ctx_menu_root->corner_radii[Corner_00] = ui_state->ctx_menu_root->corner_radii[Corner_01] = ui_state->ctx_menu_root->corner_radii[Corner_10] = ui_state->ctx_menu_root->corner_radii[Corner_11] = ui_top_font_size()*0.25f;
ui_state->ctx_menu_root->tags = ui_top_tags(); ui_state->ctx_menu_root->tags_key = ui_top_tags_key();
ui_state->ctx_menu_root->palette = ui_top_palette(); ui_state->ctx_menu_root->palette = ui_top_palette();
ui_state->ctx_menu_root->blur_size = ui_top_blur_size(); ui_state->ctx_menu_root->blur_size = ui_top_blur_size();
ui_spacer(ui_em(1.f, 1.f)); ui_spacer(ui_em(1.f, 1.f));
@@ -2198,31 +2203,17 @@ ui_build_palette_(UI_Palette *base, UI_Palette *overrides)
return palette; return palette;
} }
//- rjf: tag gathering //- rjf: current style tags key
internal String8Array internal UI_Key
ui_top_tags(void) ui_top_tags_key(void)
{ {
if(ui_state->current_gen_tags_gen != ui_state->tag_stack.gen) UI_Key key = ui_key_zero();
if(ui_state->tags_key_stack_top != 0)
{ {
ui_state->current_gen_tags_gen = ui_state->tag_stack.gen; key = ui_state->tags_key_stack_top->key;
Temp scratch = scratch_begin(0, 0);
String8List tags = {0};
for(UI_TagNode *n = ui_state->tag_stack.top; n != 0; n = n->next)
{
if(n->v.size == 1 && n->v.str[0] == '.')
{
break;
} }
if(n->v.size != 0) return key;
{
str8_list_push(ui_build_arena(), &tags, push_str8_copy(ui_build_arena(), n->v));
}
}
ui_state->current_gen_tags = str8_array_from_list(ui_build_arena(), &tags);
scratch_end(scratch);
}
return ui_state->current_gen_tags;
} }
//- rjf: theme color lookups //- rjf: theme color lookups
@@ -2230,15 +2221,51 @@ ui_top_tags(void)
internal Vec4F32 internal Vec4F32
ui_color_from_name(String8 name) ui_color_from_name(String8 name)
{ {
Vec4F32 result = ui_color_from_tags_name(ui_top_tags(), name); Vec4F32 result = ui_color_from_tags_key_name(ui_top_tags_key(), name);
return result; return result;
} }
internal Vec4F32 internal Vec4F32
ui_color_from_tags_name(String8Array tags, String8 name) ui_color_from_tags_key_name(UI_Key key, String8 name)
{ {
Vec4F32 result = {0}; Vec4F32 result = {0};
{ {
//- rjf: compute final key, mixing (tags_key, name)
UI_Key final_key = ui_key_from_string(key, name);
//- rjf: map to existing node
U64 slot_idx = final_key.u64[0]%ui_state->theme_pattern_cache_slots_count;
UI_ThemePatternCacheSlot *slot = &ui_state->theme_pattern_cache_slots[slot_idx];
UI_ThemePatternCacheNode *node = 0;
for(UI_ThemePatternCacheNode *n = slot->first;
n != 0;
n = n->next)
{
if(ui_key_match(n->key, final_key))
{
node = n;
}
}
//- rjf: no node? create
if(node == 0)
{
// rjf: map tags_key (without name) -> full list of tags
String8Array tags = {0};
{
U64 tags_cache_slot_idx = key.u64[0]%ui_state->tags_cache_slots_count;
UI_TagsCacheSlot *tags_cache_slot = &ui_state->tags_cache_slots[tags_cache_slot_idx];
for(UI_TagsCacheNode *n = tags_cache_slot->first; n != 0; n = n->next)
{
if(ui_key_match(n->key, key))
{
tags = n->tags;
break;
}
}
}
// rjf: map tags to theme pattern
UI_Theme *theme = ui_state->theme; UI_Theme *theme = ui_state->theme;
UI_ThemePattern *pattern = 0; UI_ThemePattern *pattern = 0;
U64 best_match_count = 0; U64 best_match_count = 0;
@@ -2270,9 +2297,18 @@ ui_color_from_tags_name(String8Array tags, String8 name)
break; break;
} }
} }
if(pattern != 0)
// rjf: store in (key, name) -> (pattern) cache
node = push_array(ui_build_arena(), UI_ThemePatternCacheNode, 1);
SLLQueuePush(slot->first, slot->last, node);
node->key = final_key;
node->pattern = pattern;
}
//- rjf: grab resultant color
if(node != 0 && node->pattern != 0)
{ {
result = pattern->linear; result = node->pattern->linear;
} }
} }
return result; return result;
@@ -2438,7 +2474,11 @@ ui_build_box_from_key(UI_BoxFlags flags, UI_Key key)
box->text_padding = ui_state->text_padding_stack.top->v; box->text_padding = ui_state->text_padding_stack.top->v;
box->hover_cursor = ui_state->hover_cursor_stack.top->v; box->hover_cursor = ui_state->hover_cursor_stack.top->v;
box->custom_draw = 0; box->custom_draw = 0;
box->tags = ui_top_tags(); box->tags_key = ui_key_zero();
if(ui_state->tags_key_stack_top != 0)
{
box->tags_key = ui_state->tags_key_stack_top->key;
}
} }
//- rjf: auto-pop all stacks //- rjf: auto-pop all stacks
@@ -3145,7 +3185,7 @@ node->v = new_value;\
SLLStackPush(state->name_lower##_stack.top, node);\ SLLStackPush(state->name_lower##_stack.top, node);\
if(node->next == &state->name_lower##_nil_stack_top)\ if(node->next == &state->name_lower##_nil_stack_top)\
{\ {\
state->name_lower##_stack.bottom_val = (new_value);\ state->name_lower##_stack.bottom_val = (node->v);\
}\ }\
state->name_lower##_stack.auto_pop = 0;\ state->name_lower##_stack.auto_pop = 0;\
state->name_lower##_stack.gen += 1;\ state->name_lower##_stack.gen += 1;\
@@ -3173,13 +3213,124 @@ state->name_lower##_stack.auto_pop = 1;\
state->name_lower##_stack.gen += 1;\ state->name_lower##_stack.gen += 1;\
return old_value; return old_value;
internal void
ui__push_tags_key_from_appended_string(String8 string)
{
// rjf: generate new key, by combining hash of this new string with the top
// of the tags key stack
UI_Key seed_key = {0};
if(ui_state->tags_key_stack_top != 0)
{
seed_key = ui_state->tags_key_stack_top->key;
}
UI_Key key = seed_key;
if(!str8_match(str8_lit("."), string, 0) && string.size > 0)
{
key = ui_key_from_string(seed_key, string);
}
// rjf: push this new key onto the stack
{
UI_TagsKeyStackNode *node = ui_state->tags_key_stack_free;
if(node != 0)
{
SLLStackPop(ui_state->tags_key_stack_free);
}
else
{
node = push_array(ui_build_arena(), UI_TagsKeyStackNode, 1);
}
SLLStackPush(ui_state->tags_key_stack_top, node);
node->key = key;
}
// rjf: store in tags cache
U64 slot_idx = key.u64[0] % ui_state->tags_cache_slots_count;
UI_TagsCacheSlot *slot = &ui_state->tags_cache_slots[slot_idx];
UI_TagsCacheNode *node = 0;
for(UI_TagsCacheNode *n = slot->first; n != 0; n = n->next)
{
if(ui_key_match(n->key, key))
{
node = n;
break;
}
}
if(node == 0)
{
Temp scratch = scratch_begin(0, 0);
String8List tags = {0};
if(!str8_match(string, str8_lit("."), 0))
{
if(string.size != 0)
{
str8_list_push(scratch.arena, &tags, push_str8_copy(ui_build_arena(), string));
}
for(UI_TagNode *n = ui_state->tag_stack.top; n != 0; n = n->next)
{
if(n->v.size == 1 && n->v.str[0] == '.')
{
break;
}
if(n->v.size != 0)
{
str8_list_push(scratch.arena, &tags, push_str8_copy(ui_build_arena(), n->v));
}
}
}
node = push_array(ui_build_arena(), UI_TagsCacheNode, 1);
SLLQueuePush(slot->first, slot->last, node);
node->key = key;
node->tags = str8_array_from_list(ui_build_arena(), &tags);
scratch_end(scratch);
}
}
internal void
ui__pop_tags_key(void)
{
if(ui_state->tags_key_stack_top != 0)
{
UI_TagsKeyStackNode *popped = ui_state->tags_key_stack_top;
SLLStackPop(ui_state->tags_key_stack_top);
SLLStackPush(ui_state->tags_key_stack_free, popped);
}
}
//- rjf: manual implementations //- rjf: manual implementations
internal String8 ui_top_tag(void) { UI_StackTopImpl(ui_state, Tag, tag) } internal String8
internal String8 ui_bottom_tag(void) { UI_StackBottomImpl(ui_state, Tag, tag) } ui_top_tag(void)
internal String8 ui_push_tag(String8 v) { UI_StackPushImpl(ui_state, Tag, tag, String8, push_str8_copy(ui_build_arena(), v)) } {
internal String8 ui_pop_tag(void) { UI_StackPopImpl(ui_state, Tag, tag) } UI_StackTopImpl(ui_state, Tag, tag)
internal String8 ui_set_next_tag(String8 v) { UI_StackSetNextImpl(ui_state, Tag, tag, String8, push_str8_copy(ui_build_arena(), v)) } }
internal String8
ui_bottom_tag(void)
{
UI_StackBottomImpl(ui_state, Tag, tag)
}
internal String8
ui_push_tag(String8 v)
{
ui__push_tags_key_from_appended_string(v);
UI_StackPushImpl(ui_state, Tag, tag, String8, push_str8_copy(ui_build_arena(), v))
}
internal String8
ui_pop_tag(void)
{
ui__pop_tags_key();
UI_StackPopImpl(ui_state, Tag, tag)
}
internal String8
ui_set_next_tag(String8 v)
{
ui__push_tags_key_from_appended_string(v);
UI_StackSetNextImpl(ui_state, Tag, tag, String8, push_str8_copy(ui_build_arena(), v))
}
//- rjf: helpers //- rjf: helpers
+55 -4
View File
@@ -440,7 +440,7 @@ struct UI_Box
//- rjf: per-build equipment //- rjf: per-build equipment
UI_Key key; UI_Key key;
UI_BoxFlags flags; UI_BoxFlags flags;
String8Array tags; UI_Key tags_key;
String8 string; String8 string;
UI_TextAlign text_align; UI_TextAlign text_align;
Vec2F32 fixed_position; Vec2F32 fixed_position;
@@ -646,6 +646,49 @@ struct UI_AnimSlot
//////////////////////////////// ////////////////////////////////
//~ rjf: State Types //~ rjf: State Types
//- rjf: cache for mapping 64-bit key -> array of tags
typedef struct UI_TagsCacheNode UI_TagsCacheNode;
struct UI_TagsCacheNode
{
UI_TagsCacheNode *next;
UI_Key key;
String8Array tags;
};
typedef struct UI_TagsCacheSlot UI_TagsCacheSlot;
struct UI_TagsCacheSlot
{
UI_TagsCacheNode *first;
UI_TagsCacheNode *last;
};
typedef struct UI_TagsKeyStackNode UI_TagsKeyStackNode;
struct UI_TagsKeyStackNode
{
UI_TagsKeyStackNode *next;
UI_Key key;
};
//- rjf: cache for mapping 64-bit key * string -> theme pattern
typedef struct UI_ThemePatternCacheNode UI_ThemePatternCacheNode;
struct UI_ThemePatternCacheNode
{
UI_ThemePatternCacheNode *next;
UI_Key key;
UI_ThemePattern *pattern;
};
typedef struct UI_ThemePatternCacheSlot UI_ThemePatternCacheSlot;
struct UI_ThemePatternCacheSlot
{
UI_ThemePatternCacheNode *first;
UI_ThemePatternCacheNode *last;
};
//- rjf: cache for mapping 64-bit key -> box
typedef struct UI_BoxHashSlot UI_BoxHashSlot; typedef struct UI_BoxHashSlot UI_BoxHashSlot;
struct UI_BoxHashSlot struct UI_BoxHashSlot
{ {
@@ -653,6 +696,8 @@ struct UI_BoxHashSlot
UI_Box *hash_last; UI_Box *hash_last;
}; };
//- rjf: main state bundle
typedef struct UI_State UI_State; typedef struct UI_State UI_State;
struct UI_State struct UI_State
{ {
@@ -683,6 +728,12 @@ struct UI_State
B32 tooltip_can_overflow_window; B32 tooltip_can_overflow_window;
String8Array current_gen_tags; String8Array current_gen_tags;
U64 current_gen_tags_gen; U64 current_gen_tags_gen;
UI_TagsKeyStackNode *tags_key_stack_top;
UI_TagsKeyStackNode *tags_key_stack_free;
U64 tags_cache_slots_count;
UI_TagsCacheSlot *tags_cache_slots;
U64 theme_pattern_cache_slots_count;
UI_ThemePatternCacheSlot *theme_pattern_cache_slots;
//- rjf: build phase output //- rjf: build phase output
UI_Box *root; UI_Box *root;
@@ -911,12 +962,12 @@ internal void ui_set_auto_focus_hot_key(UI_Key key);
internal UI_Palette * ui_build_palette_(UI_Palette *base, UI_Palette *overrides); internal UI_Palette * ui_build_palette_(UI_Palette *base, UI_Palette *overrides);
#define ui_build_palette(base, ...) ui_build_palette_((base), &(UI_Palette){.text = v4f32(0, 0, 0, 0), __VA_ARGS__}) #define ui_build_palette(base, ...) ui_build_palette_((base), &(UI_Palette){.text = v4f32(0, 0, 0, 0), __VA_ARGS__})
//- rjf: tag gathering //- rjf: current style tags key
internal String8Array ui_top_tags(void); internal UI_Key ui_top_tags_key(void);
//- rjf: theme color lookups //- rjf: theme color lookups
internal Vec4F32 ui_color_from_name(String8 name); internal Vec4F32 ui_color_from_name(String8 name);
internal Vec4F32 ui_color_from_tags_name(String8Array tags, String8 name); internal Vec4F32 ui_color_from_tags_key_name(UI_Key key, String8 name);
//- rjf: box node construction //- rjf: box node construction
internal UI_Box * ui_build_box_from_key(UI_BoxFlags flags, UI_Key key); internal UI_Box * ui_build_box_from_key(UI_BoxFlags flags, UI_Key key);