ui control testing
This commit is contained in:
parent
687cc88a64
commit
67ba54274f
@ -614,6 +614,7 @@ ForceInline void UnlockTicketMutex(TicketMutex *tm)
|
||||
#if LanguageIsC
|
||||
|
||||
#define STRING(size, data) ((String) { (size), (data) })
|
||||
#define Zstr ((String) { 0, 0})
|
||||
#define Lit(cstr_lit) (String) { (sizeof((cstr_lit)) - 1), (u8 *)(cstr_lit) }
|
||||
#define LitNoCast(cstr_lit) { .len = (sizeof((cstr_lit)) - 1), .text = (u8 *)(cstr_lit) }
|
||||
#define StringFromPointers(p0, p1) ((String) { (u8 *)(p1) - (u8 *)(p0), (u8 *)p0 })
|
||||
|
||||
@ -146,9 +146,6 @@ Struct(ControllerEvent)
|
||||
|
||||
/* ControllerEventKind_MouseMove */
|
||||
Vec2I32 mouse_delta;
|
||||
|
||||
/* Should be incremented by systems that want to consume the input */
|
||||
u32 consumed;
|
||||
};
|
||||
|
||||
Struct(ControllerEventsArray)
|
||||
|
||||
47
src/pp/pp.c
47
src/pp/pp.c
@ -395,14 +395,14 @@ void PP_UpdateUser(void)
|
||||
g->screen_size.y = MaxI32(g->screen_size.y, 1);
|
||||
|
||||
//- Begin UI
|
||||
UI_BeginBuild(&controller_events);
|
||||
UI_BeginBuild(controller_events);
|
||||
UI_Push(LayoutAxis, Axis_Y);
|
||||
if (window_frame.forced_top)
|
||||
{
|
||||
UI_SetNext(Border, 10);
|
||||
UI_SetNext(BorderColor, Rgba32F(1, 0, 0, 0.5));
|
||||
}
|
||||
UI_Box *pp_root_box = UI_BuildBox(UI_NilKey);
|
||||
UI_Box *pp_root_box = UI_BuildBox(Lit("pp root"));
|
||||
PP_PushGameUiStyle();
|
||||
UI_Push(Parent, pp_root_box);
|
||||
|
||||
@ -679,7 +679,7 @@ void PP_UpdateUser(void)
|
||||
|
||||
if (g->bind_states[PP_BindKind_DebugLister].num_presses > 0)
|
||||
{
|
||||
g->debug_lister = !g->debug_lister;
|
||||
g->lister_active = !g->lister_active;
|
||||
}
|
||||
|
||||
{
|
||||
@ -1938,21 +1938,32 @@ void PP_UpdateUser(void)
|
||||
}
|
||||
|
||||
/* Draw lister */
|
||||
if (g->debug_lister)
|
||||
if (g->lister_active)
|
||||
{
|
||||
Vec2 size = VEC2(400, 500);
|
||||
UI_PushCheckpoint();
|
||||
{
|
||||
Vec2 size = VEC2(400, 500);
|
||||
|
||||
UI_SetNext(LayoutAxis, Axis_Y);
|
||||
UI_SetNext(BackgroundColor, Rgba32F(0.075, 0.075, 0.075, 0.99));
|
||||
UI_SetNext(BorderColor, Rgba32F(0.2, 0.2, 0.2, 1));
|
||||
UI_SetNext(Border, 2);
|
||||
UI_SetNext(Rounding, 0.1);
|
||||
UI_SetNext(Parent, pp_root_box);
|
||||
UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_ClampFloatingX | UI_BoxFlag_ClampFloatingY);
|
||||
UI_SetNext(FloatingPos, g->debug_lister_pos);
|
||||
UI_SetNext(Width, UI_PIX(size.x, 0));
|
||||
UI_SetNext(Height, UI_PIX(size.y, 0));
|
||||
UI_Box *lister_box = UI_BuildBox(UI_NilKey);
|
||||
UI_Event ev = UI_EventFromKey(g->lister_key);
|
||||
if (ev.flags & UI_EventFlag_Active)
|
||||
{
|
||||
g->lister_pos = SubVec2(g->ui_cursor, ev.activation_offset);
|
||||
}
|
||||
|
||||
UI_SetNext(LayoutAxis, Axis_Y);
|
||||
UI_SetNext(BackgroundColor, Rgba32F(0.075, 0.075, 0.075, 0.99));
|
||||
UI_SetNext(BorderColor, Rgba32F(0.2, 0.2, 0.2, 1));
|
||||
UI_SetNext(Border, 2);
|
||||
UI_SetNext(Rounding, 0.1);
|
||||
UI_SetNext(Parent, pp_root_box);
|
||||
UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_ClampFloatingX | UI_BoxFlag_ClampFloatingY);
|
||||
UI_SetNext(FloatingPos, g->lister_pos);
|
||||
UI_SetNext(Width, UI_PIX(size.x, 0));
|
||||
UI_SetNext(Height, UI_PIX(size.y, 0));
|
||||
UI_Box *lister_box = UI_BuildBox(Lit("lister"));
|
||||
g->lister_key = lister_box->key;
|
||||
}
|
||||
UI_PopCheckpoint();
|
||||
}
|
||||
|
||||
/* Draw debug info */
|
||||
@ -1968,7 +1979,7 @@ void PP_UpdateUser(void)
|
||||
UI_SetNext(Width, UI_FIT(0));
|
||||
UI_SetNext(Height, UI_FIT(1));
|
||||
UI_SetNext(Tint, 0);
|
||||
UI_Box *dbg_box = UI_BuildBox(UI_NilKey);
|
||||
UI_Box *dbg_box = UI_BuildBox(Lit("dbg"));
|
||||
UI_PushCheckpoint();
|
||||
{
|
||||
UI_Push(Parent, dbg_box);
|
||||
@ -2272,7 +2283,7 @@ void PP_UpdateUser(void)
|
||||
}
|
||||
|
||||
/* Render UI */
|
||||
g->gpu_submit_fence_target = UI_EndBuild(g->ui_target);
|
||||
g->gpu_submit_fence_target = UI_EndBuild(g->ui_target, g->ui_to_screen_xf);
|
||||
|
||||
//////////////////////////////
|
||||
//- Present & end frame
|
||||
|
||||
@ -250,8 +250,9 @@ Struct(PP_SharedUserState)
|
||||
b32 debug_camera_panning;
|
||||
b32 debug_camera;
|
||||
|
||||
b32 debug_lister;
|
||||
Vec2 debug_lister_pos;
|
||||
b32 lister_active;
|
||||
Vec2 lister_pos;
|
||||
UI_Key lister_key;
|
||||
|
||||
b32 debug_draw;
|
||||
b32 debug_console;
|
||||
|
||||
@ -60,7 +60,7 @@ UI_Box *PP_BuildDebugConsole(b32 minimized)
|
||||
// UI_SetNext(Height, UI_FILL(0.33, 1));
|
||||
UI_SetNext(Height, UI_FIT(1));
|
||||
}
|
||||
console_box = UI_BuildBox(UI_NilKey);
|
||||
console_box = UI_BuildBox(Lit("Console box"));
|
||||
UI_Push(Parent, console_box);
|
||||
}
|
||||
{
|
||||
@ -124,7 +124,7 @@ UI_Box *PP_BuildDebugConsole(b32 minimized)
|
||||
UI_SetNext(BorderColor, Rgba32F(0.25, 0.25, 0.25, 1));
|
||||
UI_SetNext(Rounding, 0);
|
||||
UI_SetNext(Border, 1);
|
||||
UI_Box *log_box = UI_BuildBox(UI_NilKey);
|
||||
UI_Box *log_box = UI_BuildBox(Zstr);
|
||||
UI_Push(Parent, log_box);
|
||||
}
|
||||
{
|
||||
@ -135,7 +135,7 @@ UI_Box *PP_BuildDebugConsole(b32 minimized)
|
||||
UI_SetNext(Width, UI_FILL(1, 0));
|
||||
UI_SetNext(Height, UI_TXT(1));
|
||||
UI_SetNext(Flags, UI_BoxFlag_DrawText);
|
||||
UI_Box *log_textbox = UI_BuildBox(UI_NilKey);
|
||||
UI_Box *log_textbox = UI_BuildBox(Zstr);
|
||||
}
|
||||
}
|
||||
UI_PopCheckpoint();
|
||||
|
||||
@ -3,12 +3,11 @@
|
||||
|
||||
UI_Box *UI_BuildLabel(String text)
|
||||
{
|
||||
UI_Key key = UI_KeyFromString(0, text);
|
||||
UI_SetNext(Width, UI_TXT(0));
|
||||
UI_SetNext(Height, UI_TXT(0));
|
||||
UI_SetNext(Text, text);
|
||||
UI_SetNext(Flags, UI_BoxFlag_DrawText);
|
||||
UI_Box *box = UI_BuildBox(UI_NilKey);
|
||||
UI_Box *box = UI_BuildBox(Zstr);
|
||||
return box;
|
||||
}
|
||||
|
||||
@ -41,6 +40,6 @@ UI_Box *UI_BuildSpacer(UI_Size size)
|
||||
{
|
||||
UI_SetNext(Height, size);
|
||||
}
|
||||
UI_Box *box = UI_BuildBox(UI_NilKey);
|
||||
UI_Box *box = UI_BuildBox(Zstr);
|
||||
return box;
|
||||
}
|
||||
|
||||
393
src/ui/ui_core.c
393
src/ui/ui_core.c
@ -21,27 +21,42 @@ ResourceKey UI_GetDefaultFontResource(void)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Key helpers
|
||||
|
||||
u64 UI_HashFromTop(void)
|
||||
UI_Box *UI_BackBoxFromKey(UI_Key key)
|
||||
{
|
||||
UI_Box *parent_box = UI_PeekTop(Parent);
|
||||
u64 tag_hash = UI_PeekTop(Tag);
|
||||
return RandU64FromSeeds(parent_box->key.hash, tag_hash);
|
||||
}
|
||||
|
||||
u64 UI_HashFromString(u64 seed, String str)
|
||||
{
|
||||
if (seed == 0)
|
||||
UI_SharedState *g = &UI_shared_state;
|
||||
UI_Box *back_box = 0;
|
||||
if (key.hash != 0)
|
||||
{
|
||||
seed = UI_HashFromTop();
|
||||
UI_BoxBin *back_bin = &g->back_box_bins[key.hash % UI_NumBoxLookupBins];
|
||||
for (UI_Box *tmp = back_bin->first; tmp; tmp = tmp->next_in_bin)
|
||||
{
|
||||
if (tmp->key.hash == key.hash)
|
||||
{
|
||||
back_box = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HashFnv64(seed, str);
|
||||
return back_box;
|
||||
}
|
||||
|
||||
UI_Key UI_KeyFromString(u64 seed, String str)
|
||||
UI_Box *UI_FrontBoxFromKey(UI_Key key)
|
||||
{
|
||||
UI_Key result = ZI;
|
||||
result.hash = UI_HashFromString(seed, str);
|
||||
return result;
|
||||
UI_SharedState *g = &UI_shared_state;
|
||||
UI_Box *front_box = 0;
|
||||
if (key.hash != 0)
|
||||
{
|
||||
UI_BoxBin *front_bin = &g->box_bins[key.hash % UI_NumBoxLookupBins];
|
||||
for (UI_Box *tmp = front_bin->first; tmp; tmp = tmp->next_in_bin)
|
||||
{
|
||||
if (tmp->key.hash == key.hash)
|
||||
{
|
||||
front_box = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return front_box;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -70,10 +85,7 @@ void UI_PopCheckpoint(void)
|
||||
UI_SharedState *g = &UI_shared_state;
|
||||
UI_Checkpoint *cp = g->top_checkpoint;
|
||||
u64 v = cp->v;
|
||||
if (v == 0)
|
||||
{
|
||||
DEBUGBREAKABLE;
|
||||
}
|
||||
/* Pop styles */
|
||||
for (UI_StyleKind kind = UI_StyleKind_None; kind < UI_StyleKind_Count; ++kind)
|
||||
{
|
||||
UI_StyleNode *n = g->style_tops[kind];
|
||||
@ -100,26 +112,30 @@ UI_StyleNode *UI_PushStyleNode(UI_Style desc)
|
||||
UI_StyleNode *n = g->style_tops[desc.kind];
|
||||
if (!n->style.forced)
|
||||
{
|
||||
if (n->style.pop_when_used)
|
||||
{
|
||||
ZeroStruct(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = g->first_free_style_node;
|
||||
if (n)
|
||||
if (n->style.pop_when_used)
|
||||
{
|
||||
g->first_free_style_node = n->next;
|
||||
ZeroStruct(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = PushStruct(g->build_arena, UI_StyleNode);
|
||||
n = g->first_free_style_node;
|
||||
if (n)
|
||||
{
|
||||
g->first_free_style_node = n->next;
|
||||
ZeroStruct(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = PushStruct(g->build_arena, UI_StyleNode);
|
||||
}
|
||||
n->next = g->style_tops[desc.kind];
|
||||
}
|
||||
n->next = g->style_tops[desc.kind];
|
||||
n->style = desc;
|
||||
n->checkpoint = g->top_checkpoint->v;
|
||||
}
|
||||
n->style = desc;
|
||||
n->checkpoint = g->top_checkpoint->v;
|
||||
|
||||
/* Initialize style data from desc */
|
||||
switch (desc.kind)
|
||||
{
|
||||
default: break;
|
||||
@ -128,6 +144,15 @@ UI_StyleNode *UI_PushStyleNode(UI_Style desc)
|
||||
{
|
||||
n->style.Text = PushString(g->build_arena, desc.Text);
|
||||
} break;
|
||||
|
||||
case UI_StyleKind_Tag:
|
||||
{
|
||||
n->style.Tag.name = PushString(g->build_arena, desc.Tag.name);
|
||||
if (n->style.Tag.hash == 0)
|
||||
{
|
||||
n->style.Tag.hash = HashFnv64(g->style_tops[desc.kind]->style.Tag.hash, n->style.Tag.name);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
g->style_tops[desc.kind] = n;
|
||||
@ -169,13 +194,25 @@ UI_Style UI_StyleFromTopNode(UI_StyleKind kind, b32 use)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Box helpers
|
||||
|
||||
UI_Box *UI_BuildBox(UI_Key key)
|
||||
UI_Box *UI_BuildBox(String seed)
|
||||
{
|
||||
UI_SharedState *g = &UI_shared_state;
|
||||
UI_BoxBin *bin = &g->box_bins[key.hash % UI_NumBoxLookupBins];
|
||||
UI_BoxBin *back_bin = &g->back_box_bins[key.hash % UI_NumBoxLookupBins];
|
||||
|
||||
/* Calculate key */
|
||||
UI_Box *parent = UI_UseTop(Parent);
|
||||
UI_Tag tag = UI_UseTop(Tag);
|
||||
UI_Key key = ZI;
|
||||
if (seed.len > 0)
|
||||
{
|
||||
key.hash = RandU64FromSeeds(key.hash, parent->key.hash);
|
||||
key.hash = RandU64FromSeeds(key.hash, tag.hash);
|
||||
key.hash = HashFnv64(key.hash, seed);
|
||||
}
|
||||
|
||||
/* Insert into lookup */
|
||||
UI_BoxBin *bin = &g->box_bins[key.hash % UI_NumBoxLookupBins];
|
||||
UI_Box *box = PushStruct(g->build_arena, UI_Box);
|
||||
UI_Box *back_box = 0;
|
||||
if (key.hash != 0)
|
||||
{
|
||||
#if RtcIsEnabled
|
||||
@ -190,33 +227,20 @@ UI_Box *UI_BuildBox(UI_Key key)
|
||||
}
|
||||
#endif
|
||||
DllPushBackNP(bin->first, bin->last, box, next_in_bin, prev_in_bin);
|
||||
back_box = UI_BackBoxFromKey(key);
|
||||
}
|
||||
|
||||
/* Find previous build's box from hash */
|
||||
UI_Box *back_box = 0;
|
||||
if (key.hash != 0)
|
||||
{
|
||||
for (UI_Box *tmp = back_bin->first; tmp; tmp = tmp->next_in_bin)
|
||||
{
|
||||
if (tmp->key.hash == key.hash)
|
||||
{
|
||||
back_box = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (back_box)
|
||||
{
|
||||
*box = *back_box;
|
||||
}
|
||||
box->parent = parent;
|
||||
box->key = key;
|
||||
++g->boxes_count;
|
||||
|
||||
box->key = key;
|
||||
/* Persist data from back box */
|
||||
if (back_box != 0)
|
||||
{
|
||||
box->event = back_box->event;
|
||||
}
|
||||
|
||||
/* Pull from style stack */
|
||||
box->flags = UI_UseTop(Flags);
|
||||
box->parent = UI_UseTop(Parent);
|
||||
box->pref_size[Axis_X] = UI_UseTop(Width);
|
||||
box->pref_size[Axis_Y] = UI_UseTop(Height);
|
||||
box->layout_axis = UI_UseTop(LayoutAxis);
|
||||
@ -237,8 +261,8 @@ UI_Box *UI_BuildBox(UI_Key key)
|
||||
box->font = F_LoadFontAsync(box->font_resource, box->font_size);
|
||||
}
|
||||
|
||||
DllPushBack(box->parent->first, box->parent->last, box);
|
||||
++box->parent->count;
|
||||
DllPushBack(parent->first, parent->last, box);
|
||||
++parent->count;
|
||||
|
||||
return box;
|
||||
}
|
||||
@ -250,69 +274,209 @@ void UI_SetBackgroundTexture(UI_Box *box, GPU_Resource *texture, Vec2 uv0, Vec2
|
||||
box->background_texture_uv1 = uv1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Event
|
||||
|
||||
UI_Event UI_EventFromKey(UI_Key key)
|
||||
{
|
||||
UI_SharedState *g = &UI_shared_state;
|
||||
UI_Event result = ZI;
|
||||
|
||||
UI_Box *back_box = UI_BackBoxFromKey(key);
|
||||
if (back_box)
|
||||
{
|
||||
result = back_box->event;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Begin build
|
||||
|
||||
void UI_BeginBuild(ControllerEventsArray *controller_events)
|
||||
void UI_BeginBuild(ControllerEventsArray controller_events)
|
||||
{
|
||||
UI_SharedState *g = &UI_shared_state;
|
||||
|
||||
/* Swap front & back build states */
|
||||
//////////////////////////////
|
||||
//- Process controller events
|
||||
|
||||
if (g->build_arena != 0 && g->back_build_arena != 0)
|
||||
{
|
||||
Arena *swp = g->build_arena;
|
||||
g->build_arena = g->back_build_arena;
|
||||
g->back_build_arena = swp;
|
||||
}
|
||||
g->back_box_bins = g->box_bins;
|
||||
g->back_root_box = g->root_box;
|
||||
g->back_boxes_count = g->boxes_count;
|
||||
Xform screen_to_ui_xf = InvertXform(g->ui_to_screen_xf);
|
||||
|
||||
/* Reset front build state */
|
||||
if (!g->build_arena)
|
||||
{
|
||||
g->build_arena = AcquireArena(Gibi(64));
|
||||
}
|
||||
ResetArena(g->build_arena);
|
||||
g->boxes_count = 0;
|
||||
g->first_free_style_node = 0;
|
||||
g->first_free_checkpoint = 0;
|
||||
|
||||
/* Init bins */
|
||||
g->box_bins = PushStructs(g->build_arena, UI_BoxBin, UI_NumBoxLookupBins);
|
||||
|
||||
/* Init root box */
|
||||
g->root_box = PushStruct(g->build_arena, UI_Box);
|
||||
g->root_box->key = UI_RootKey;
|
||||
UI_BoxBin *bin = &g->box_bins[g->root_box->key.hash % UI_NumBoxLookupBins];
|
||||
DllPushBackNP(bin->first, bin->last, g->root_box, next_in_bin, prev_in_bin);
|
||||
++g->boxes_count;
|
||||
|
||||
/* Init checkpoints */
|
||||
g->top_checkpoint = PushStruct(g->build_arena, UI_Checkpoint);
|
||||
|
||||
/* Init styles */
|
||||
{
|
||||
UI_StyleNode *nodes = PushStructs(g->build_arena, UI_StyleNode, UI_StyleKind_Count);
|
||||
for (UI_StyleKind kind = UI_StyleKind_None; kind < UI_StyleKind_Count; ++kind)
|
||||
/* Locate boxes */
|
||||
UI_Box *hovered_box = 0;
|
||||
UI_Box *active_box = 0;
|
||||
for (u64 pre_index = g->boxes_count; pre_index-- > 0;)
|
||||
{
|
||||
UI_StyleNode *n = &nodes[kind];
|
||||
UI_Style *style = &n->style;
|
||||
style->kind = kind;
|
||||
g->style_tops[kind] = n;
|
||||
UI_Box *box = g->boxes_pre[pre_index];
|
||||
if (hovered_box == 0 && box->event.flags & UI_EventFlag_Hovered)
|
||||
{
|
||||
hovered_box = box;
|
||||
}
|
||||
if (active_box == 0 && box->event.flags & UI_EventFlag_Active)
|
||||
{
|
||||
active_box = box;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// /* Refresh initial box events */
|
||||
// for (u64 pre_index = g->boxes_count; pre_index-- > 0;)
|
||||
// {
|
||||
// UI_Box *box = g->boxes_pre[pre_index];
|
||||
// if (g->cursor_pos.x > box->p0.x && g->cursor_pos.x < box->p1.x &&
|
||||
// g->cursor_pos.y > box->p0.y && g->cursor_pos.y < box->p1.y)
|
||||
// {
|
||||
// box->event.flags |= UI_EventFlag_Hovered;
|
||||
// hovered_box = box;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// box->event.flags &= ~UI_EventFlag_Hovered;
|
||||
// hovered_box = 0;
|
||||
// }
|
||||
|
||||
// if (box->event.flags & UI_EventFlag_Active)
|
||||
// {
|
||||
// active_box = box;
|
||||
// }
|
||||
// }
|
||||
|
||||
/* Update state from controller events */
|
||||
for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index)
|
||||
{
|
||||
ControllerEvent cev = controller_events.events[cev_index];
|
||||
switch (cev.kind)
|
||||
{
|
||||
default: break;
|
||||
|
||||
case ControllerEventKind_CursorMove:
|
||||
{
|
||||
|
||||
g->cursor_pos = MulXformV2(screen_to_ui_xf, Vec2FromFields(cev.cursor_pos));
|
||||
/* Iterate boxes in reverse render order */
|
||||
for (u64 pre_index = g->boxes_count; pre_index-- > 0;)
|
||||
{
|
||||
UI_Box *box = g->boxes_pre[pre_index];
|
||||
if (g->cursor_pos.x > box->p0.x && g->cursor_pos.x < box->p1.x &&
|
||||
g->cursor_pos.y > box->p0.y && g->cursor_pos.y < box->p1.y)
|
||||
{
|
||||
if (hovered_box)
|
||||
{
|
||||
hovered_box->event.flags &= ~UI_EventFlag_Hovered;
|
||||
}
|
||||
box->event.flags |= UI_EventFlag_Hovered;
|
||||
hovered_box = box;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case ControllerEventKind_ButtonDown:
|
||||
{
|
||||
if (cev.button == Btn_M1)
|
||||
{
|
||||
UI_Box *box = hovered_box;
|
||||
if (box)
|
||||
{
|
||||
box->event.flags |= UI_EventFlag_Active;
|
||||
box->event.activation_offset = SubVec2(g->cursor_pos, box->p0);
|
||||
active_box = box;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case ControllerEventKind_ButtonUp:
|
||||
{
|
||||
if (cev.button == Btn_M1)
|
||||
{
|
||||
UI_Box *box = active_box;
|
||||
if (box)
|
||||
{
|
||||
box->event.flags &= ~UI_EventFlag_Active;
|
||||
active_box = 0;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
g->style_tops[UI_StyleKind_Tag]->style.Tag = HashFnv64(Fnv64Basis, Lit("root"));
|
||||
g->style_tops[UI_StyleKind_Parent]->style.Parent = g->root_box;
|
||||
g->style_tops[UI_StyleKind_Width]->style.Width = UI_FILL(1, 0);
|
||||
g->style_tops[UI_StyleKind_Height]->style.Height = UI_FILL(1, 0);
|
||||
g->style_tops[UI_StyleKind_Font]->style.Font = UI_GetDefaultFontResource();
|
||||
g->style_tops[UI_StyleKind_FontSize]->style.FontSize = 16.0f;
|
||||
g->style_tops[UI_StyleKind_Tint]->style.Tint = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
if (!g->back_build_arena)
|
||||
//////////////////////////////
|
||||
//- Swap front & back
|
||||
|
||||
{
|
||||
/* Back buffer not initialized, swap again */
|
||||
UI_BeginBuild(controller_events);
|
||||
{
|
||||
Arena *swp = g->build_arena;
|
||||
g->build_arena = g->back_build_arena;
|
||||
g->back_build_arena = swp;
|
||||
}
|
||||
g->back_box_bins = g->box_bins;
|
||||
g->back_root_box = g->root_box;
|
||||
g->back_boxes_count = g->boxes_count;
|
||||
g->back_boxes_pre = g->boxes_pre;
|
||||
g->back_boxes_post = g->boxes_post;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Reset build state
|
||||
|
||||
{
|
||||
if (!g->build_arena)
|
||||
{
|
||||
g->build_arena = AcquireArena(Gibi(64));
|
||||
}
|
||||
ResetArena(g->build_arena);
|
||||
g->boxes_count = 0;
|
||||
g->first_free_style_node = 0;
|
||||
g->first_free_checkpoint = 0;
|
||||
|
||||
/* Init bins */
|
||||
g->box_bins = PushStructs(g->build_arena, UI_BoxBin, UI_NumBoxLookupBins);
|
||||
|
||||
/* Init root box */
|
||||
g->root_box = PushStruct(g->build_arena, UI_Box);
|
||||
g->root_box->key = UI_RootKey;
|
||||
UI_BoxBin *bin = &g->box_bins[g->root_box->key.hash % UI_NumBoxLookupBins];
|
||||
DllPushBackNP(bin->first, bin->last, g->root_box, next_in_bin, prev_in_bin);
|
||||
++g->boxes_count;
|
||||
|
||||
if (!g->back_build_arena)
|
||||
{
|
||||
/* Back buffer not initialized, swap again */
|
||||
UI_BeginBuild(controller_events);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Init style stack
|
||||
|
||||
{
|
||||
/* Init checkpoints */
|
||||
g->top_checkpoint = PushStruct(g->build_arena, UI_Checkpoint);
|
||||
|
||||
/* Init styles */
|
||||
{
|
||||
UI_StyleNode *nodes = PushStructs(g->build_arena, UI_StyleNode, UI_StyleKind_Count);
|
||||
for (UI_StyleKind kind = UI_StyleKind_None; kind < UI_StyleKind_Count; ++kind)
|
||||
{
|
||||
UI_StyleNode *n = &nodes[kind];
|
||||
UI_Style *style = &n->style;
|
||||
style->kind = kind;
|
||||
g->style_tops[kind] = n;
|
||||
}
|
||||
g->style_tops[UI_StyleKind_Parent]->style.Parent = g->root_box;
|
||||
g->style_tops[UI_StyleKind_Width]->style.Width = UI_FILL(1, 0);
|
||||
g->style_tops[UI_StyleKind_Height]->style.Height = UI_FILL(1, 0);
|
||||
g->style_tops[UI_StyleKind_Font]->style.Font = UI_GetDefaultFontResource();
|
||||
g->style_tops[UI_StyleKind_FontSize]->style.FontSize = 16.0f;
|
||||
g->style_tops[UI_StyleKind_Tint]->style.Tint = 0xFFFFFFFF;
|
||||
g->style_tops[UI_StyleKind_Tag]->style.Tag.name = Lit("root");
|
||||
g->style_tops[UI_StyleKind_Tag]->style.Tag.hash = HashFnv64(Fnv64Basis, g->style_tops[UI_StyleKind_Tag]->style.Tag.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,10 +493,11 @@ GPU_ResourceDesc UI_GetRenderTargetDesc(Vec2I32 size)
|
||||
return desc;
|
||||
}
|
||||
|
||||
i64 UI_EndBuild(GPU_Resource *render_target)
|
||||
i64 UI_EndBuild(GPU_Resource *render_target, Xform ui_to_screen_xf)
|
||||
{
|
||||
TempArena scratch = BeginScratchNoConflict();
|
||||
UI_SharedState *g = &UI_shared_state;
|
||||
g->ui_to_screen_xf = ui_to_screen_xf;
|
||||
|
||||
Vec2I32 render_target_size = GPU_GetTextureSize2D(render_target);
|
||||
Rect render_viewport = ZI;
|
||||
@ -352,8 +517,10 @@ i64 UI_EndBuild(GPU_Resource *render_target)
|
||||
|
||||
/* Build pre-order & post-order box arrays */
|
||||
u64 boxes_count = g->boxes_count;
|
||||
UI_Box **boxes_pre = PushStructsNoZero(scratch.arena, UI_Box *, boxes_count);
|
||||
UI_Box **boxes_post = PushStructsNoZero(scratch.arena, UI_Box *, boxes_count);
|
||||
UI_Box **boxes_pre = PushStructsNoZero(g->build_arena, UI_Box *, boxes_count);
|
||||
UI_Box **boxes_post = PushStructsNoZero(g->build_arena, UI_Box *, boxes_count);
|
||||
g->boxes_pre = boxes_pre;
|
||||
g->boxes_post = boxes_post;
|
||||
{
|
||||
Struct(BoxNode) { BoxNode *next; b32 visited; UI_Box *box; };
|
||||
BoxNode *first_dfs = 0;
|
||||
@ -390,13 +557,15 @@ i64 UI_EndBuild(GPU_Resource *render_target)
|
||||
StackPush(first_dfs, child_n);
|
||||
}
|
||||
}
|
||||
boxes_pre[pre_index++] = box;
|
||||
box->pre_index = pre_index++;
|
||||
boxes_pre[box->pre_index] = box;
|
||||
n->visited = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
StackPop(first_dfs);
|
||||
boxes_post[post_index++] = box;
|
||||
box->post_index = post_index++;
|
||||
boxes_post[box->post_index] = box;
|
||||
}
|
||||
}
|
||||
Assert(pre_index == boxes_count);
|
||||
|
||||
@ -44,9 +44,9 @@ Enum(UI_BoxFlag)
|
||||
//~ Style types
|
||||
|
||||
#define UI_StyleKindsXMacro(x) \
|
||||
x(Tag, u64) \
|
||||
x(Flags, UI_BoxFlag) \
|
||||
x(Parent, struct UI_Box *) \
|
||||
x(Tag, UI_Tag) \
|
||||
x(LayoutAxis, Axis) \
|
||||
x(Width, UI_Size) \
|
||||
x(Height, UI_Size) \
|
||||
@ -63,6 +63,12 @@ Enum(UI_BoxFlag)
|
||||
x(FloatingPos, Vec2) \
|
||||
/* ------------------------------------------- */
|
||||
|
||||
Struct(UI_Tag)
|
||||
{
|
||||
String name;
|
||||
u64 hash;
|
||||
};
|
||||
|
||||
Enum(UI_StyleKind)
|
||||
{
|
||||
#define X(name, type) UI_StyleKind_##name,
|
||||
@ -93,6 +99,31 @@ Struct(UI_StyleNode)
|
||||
UI_Style style;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Checkpoint types
|
||||
|
||||
Struct(UI_Checkpoint)
|
||||
{
|
||||
UI_Checkpoint *next;
|
||||
u64 v;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Event types
|
||||
|
||||
Enum(UI_EventFlag)
|
||||
{
|
||||
UI_EventFlag_None = 0,
|
||||
UI_EventFlag_Active = (1 << 0),
|
||||
UI_EventFlag_Hovered = (1 << 1),
|
||||
};
|
||||
|
||||
Struct(UI_Event)
|
||||
{
|
||||
UI_EventFlag flags;
|
||||
Vec2 activation_offset;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Box types
|
||||
|
||||
@ -112,18 +143,15 @@ Struct(UI_Box)
|
||||
|
||||
//- Persistent data
|
||||
UI_Key key;
|
||||
UI_Event event;
|
||||
|
||||
//- Per-build data
|
||||
UI_BoxFlag flags;
|
||||
|
||||
String display_text;
|
||||
|
||||
GPU_Resource *background_texture;
|
||||
Vec2 background_texture_uv0;
|
||||
Vec2 background_texture_uv1;
|
||||
|
||||
Axis layout_axis;
|
||||
|
||||
UI_Size pref_size[Axis_CountXY];
|
||||
u32 background_color;
|
||||
u32 border_color;
|
||||
@ -133,35 +161,32 @@ Struct(UI_Box)
|
||||
f32 text_padding;
|
||||
f32 rounding;
|
||||
Vec2 floating_pos;
|
||||
|
||||
String display_text;
|
||||
Axis layout_axis;
|
||||
ResourceKey font_resource;
|
||||
f32 font_size;
|
||||
|
||||
//- Pre-layout data
|
||||
u64 pre_index;
|
||||
u64 post_index;
|
||||
|
||||
//- Layout data
|
||||
F_Run glyph_run;
|
||||
F_Font *font;
|
||||
f32 solved_dims[Axis_CountXY];
|
||||
f32 layout_cursor;
|
||||
|
||||
//- Post-solve data
|
||||
//- Post-layout data
|
||||
Vec2 p0;
|
||||
Vec2 p1;
|
||||
};
|
||||
|
||||
Struct(UI_BoxBin)
|
||||
{
|
||||
UI_Box *first;
|
||||
UI_Box *last;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Checkpoint types
|
||||
|
||||
Struct(UI_Checkpoint)
|
||||
{
|
||||
UI_Checkpoint *next;
|
||||
u64 v;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ State types
|
||||
|
||||
@ -169,6 +194,10 @@ Struct(UI_Checkpoint)
|
||||
|
||||
Struct(UI_SharedState)
|
||||
{
|
||||
//- Control state
|
||||
Vec2 cursor_pos;
|
||||
Xform ui_to_screen_xf;
|
||||
|
||||
//- Build state
|
||||
Arena *build_arena;
|
||||
Arena *back_build_arena;
|
||||
@ -183,11 +212,16 @@ Struct(UI_SharedState)
|
||||
u64 back_boxes_count;
|
||||
|
||||
UI_Checkpoint *top_checkpoint;
|
||||
UI_Checkpoint *first_free_checkpoint;
|
||||
|
||||
UI_StyleNode *style_tops[UI_StyleKind_Count];
|
||||
UI_Checkpoint *first_free_checkpoint;
|
||||
UI_StyleNode *first_free_style_node;
|
||||
|
||||
//- Layout state
|
||||
UI_Box **boxes_pre;
|
||||
UI_Box **boxes_post;
|
||||
UI_Box **back_boxes_pre;
|
||||
UI_Box **back_boxes_post;
|
||||
|
||||
//- Render state
|
||||
i64 gpu_submit_fence_target;
|
||||
GPU_TransientBuffer draw_rects_tbuff;
|
||||
@ -208,9 +242,8 @@ ResourceKey UI_GetDefaultFontResource(void);
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Key helpers
|
||||
|
||||
u64 UI_HashFromTop(void);
|
||||
u64 UI_HashFromString(u64 seed, String str);
|
||||
UI_Key UI_KeyFromString(u64 seed, String str);
|
||||
UI_Box *UI_BackBoxFromKey(UI_Key key);
|
||||
UI_Box *UI_FrontBoxFromKey(UI_Key key);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Checkpoint helpers
|
||||
@ -248,17 +281,22 @@ UI_Style UI_StyleFromTopNode(UI_StyleKind kind, b32 use);
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Box
|
||||
|
||||
UI_Box *UI_BuildBox(UI_Key key);
|
||||
UI_Box *UI_BuildBox(String seed);
|
||||
|
||||
void UI_SetBackgroundTexture(UI_Box *box, GPU_Resource *texture, Vec2 uv0, Vec2 uv1);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Event
|
||||
|
||||
UI_Event UI_EventFromKey(UI_Key key);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Begin build
|
||||
|
||||
void UI_BeginBuild(ControllerEventsArray *controller_events);
|
||||
void UI_BeginBuild(ControllerEventsArray controller_events);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ End build
|
||||
|
||||
GPU_ResourceDesc UI_GetRenderTargetDesc(Vec2I32 size);
|
||||
i64 UI_EndBuild(GPU_Resource *render_target);
|
||||
i64 UI_EndBuild(GPU_Resource *render_target, Xform ui_to_screen_xf);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user