floating ui boxes

This commit is contained in:
jacob 2025-11-02 21:23:29 -06:00
parent ef18cff56d
commit 9e2634dfab
9 changed files with 293 additions and 214 deletions

View File

@ -291,153 +291,6 @@ String PP_DebugStringFromEnt(Arena *arena, PP_Ent *ent)
return result; return result;
} }
////////////////////////////////////////////////////////////
//~ Console
//- Draw console
void PP_DrawDebugConsole(b32 minimized)
{
/* TODO: Remove this whole thing */
__prof;
PP_SharedUserState *g = &PP_shared_user_state;
TempArena scratch = BeginScratchNoConflict();
// i32 console_level = minimized ? LogLevel_Success : LogLevel_Debug;
i32 console_level = LogLevel_Debug;
u32 colors[LogLevel_Count][2] = ZI;
SetBytes(colors, 0xFF, sizeof(colors));
/* Debug colors */
colors[LogLevel_Debug][0] = Rgb32F(0.4, 0.1, 0.4);
colors[LogLevel_Debug][1] = Rgb32F(0.5, 0.2, 0.5);
/* Info colors */
colors[LogLevel_Info][0] = Rgb32F(0.4, 0.4, 0.4);
colors[LogLevel_Info][1] = Rgb32F(0.5, 0.5, 0.5);
/* Success colors */
colors[LogLevel_Success][0] = Rgb32F(0.1, 0.3, 0.1);
colors[LogLevel_Success][1] = Rgb32F(0.2, 0.4, 0.2);
/* Warning colors */
colors[LogLevel_Warning][0] = Rgb32F(0.4, 0.4, 0.1);
colors[LogLevel_Warning][1] = Rgb32F(0.5, 0.5, 0.2);
/* Error colors */
colors[LogLevel_Error][0] = Rgb32F(0.4, 0.1, 0.1);
colors[LogLevel_Error][1] = Rgb32F(0.5, 0.2, 0.2);
i64 max_time_ns = I64Max;
i64 fade_time_ns = max_time_ns;
if (minimized)
{
max_time_ns = NsFromSeconds(10);
fade_time_ns = max_time_ns;
}
f32 fade_curve = 0.5;
f32 spacing = 0;
f32 bg_margin = 5;
i64 now_ns = TimeNs();
UI_PushCheckpoint();
{
{
UI_SetNext(LayoutAxis, Axis_Y);
UI_SetNext(Border, 0);
if (minimized)
{
UI_SetNext(BackgroundColor, 0);
UI_SetNext(Width, UI_PIX(500, 0));
UI_SetNext(Height, UI_FIT(1));
}
else
{
UI_SetNext(BackgroundColor, Rgba32F(1, 1, 1, 0.02));
UI_SetNext(Width, UI_FILL(1, 0));
// UI_SetNext(Height, UI_FILL(0.33, 1));
UI_SetNext(Height, UI_FIT(1));
}
UI_Box *console_box = UI_BuildBox(0, UI_NilKey);
UI_Push(Parent, console_box);
}
{
/* Gather display logs */
u64 max = 20;
u64 display_count = 0;
LogEvent *display_logs = PushStructs(scratch.arena, LogEvent, max);
{
b32 done = 0;
if (minimized)
{
max = 5;
}
LogEventsArray logs = GetLogEvents();
for (u64 i = logs.count; i-- > 0 && display_count < max && !done;)
{
LogEvent ev = logs.logs[i];
if (ev.time_ns > (now_ns - max_time_ns))
{
if (ev.level <= console_level)
{
display_logs[display_count] = ev;
++display_count;
}
}
else
{
done = 1;
}
}
}
/* Display logs in reverse */
for (u64 i = display_count; i-- > 0;)
{
LogEvent log = display_logs[i];
f32 opacity = 0.75;
f32 lin = 1.0 - ClampF64((f64)(now_ns - log.time_ns) / (f64)fade_time_ns, 0, 1);
opacity *= PowF32(lin, fade_curve);
String text = log.msg;
if (!minimized)
{
DateTime datetime = log.datetime;
text = StringF(
scratch.arena,
"[%F:%F:%F.%F] %F",
FmtUintZ(datetime.hour, 2),
FmtUintZ(datetime.minute, 2),
FmtUintZ(datetime.second, 2),
FmtUintZ(datetime.milliseconds, 3),
FmtString(text));
}
UI_PushCheckpoint();
{
UI_Push(Tint, Alpha32F(0xFFFFFFFF, opacity));
{
u32 color = colors[log.level][log.level_id % 2];
UI_SetNext(BackgroundColor, color);
UI_SetNext(LayoutAxis, Axis_X);
UI_SetNext(Width, UI_FILL(1, 0));
UI_SetNext(Height, UI_FIT(1));
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_BoxFlag_None, UI_NilKey);
UI_Push(Parent, log_box);
}
{
UI_SetNext(BackgroundColor, 0);
UI_SetNext(Border, 0);
UI_SetNext(TextPadding, 6);
UI_SetNext(Text, text);
UI_SetNext(Width, UI_FILL(1, 0));
UI_SetNext(Height, UI_TXT(1));
UI_Box *log_textbox = UI_BuildBox(UI_BoxFlag_DrawText, UI_NilKey);
}
}
UI_PopCheckpoint();
}
}
}
UI_PopCheckpoint();
EndScratch(scratch);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Render buffers //~ Render buffers
@ -550,7 +403,7 @@ void PP_UpdateUser(void)
UI_SetNext(Border, 10); UI_SetNext(Border, 10);
UI_SetNext(BorderColor, Rgba32F(1, 0, 0, 0.5)); UI_SetNext(BorderColor, Rgba32F(1, 0, 0, 0.5));
} }
UI_Box *pp_root_box = UI_BuildBox(0, UI_NilKey); UI_Box *pp_root_box = UI_BuildBox(UI_NilKey);
PP_PushGameUiStyle(); PP_PushGameUiStyle();
UI_Push(Parent, pp_root_box); UI_Push(Parent, pp_root_box);
@ -825,6 +678,11 @@ void PP_UpdateUser(void)
g->debug_camera = !g->debug_camera; g->debug_camera = !g->debug_camera;
} }
if (g->bind_states[PP_BindKind_DebugLister].num_presses > 0)
{
g->debug_lister = !g->debug_lister;
}
{ {
if (g->bind_states[PP_BindKind_DebugFollow].num_presses > 0) if (g->bind_states[PP_BindKind_DebugFollow].num_presses > 0)
{ {
@ -2076,7 +1934,27 @@ void PP_UpdateUser(void)
/* Draw console */ /* Draw console */
{ {
b32 console_minimized = !g->debug_console; b32 console_minimized = !g->debug_console;
PP_DrawDebugConsole(console_minimized); PP_BuildDebugConsole(console_minimized);
}
/* Draw lister */
if (g->debug_lister)
{
g->debug_lister_pos = g->ui_cursor;
g->debug_lister_pos.x -= 50;
UI_SetNext(LayoutAxis, Axis_Y);
UI_SetNext(Tint, Alpha32F(0xFFFFFFFF, 0.5));
UI_SetNext(BackgroundColor, Rgba32F(0.3, 0.3, 0.3, 1));
UI_SetNext(BorderColor, Rgba32F(0.4, 0.4, 0.4, 1));
UI_SetNext(Border, 2);
UI_SetNext(Rounding, 0.25);
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(100, 1));
UI_SetNext(Height, UI_PIX(100, 1));
UI_Box *lister_box = UI_BuildBox(UI_NilKey);
} }
/* Draw debug info */ /* Draw debug info */
@ -2092,7 +1970,7 @@ void PP_UpdateUser(void)
UI_SetNext(Width, UI_FIT(0)); UI_SetNext(Width, UI_FIT(0));
UI_SetNext(Height, UI_FIT(1)); UI_SetNext(Height, UI_FIT(1));
UI_SetNext(Tint, 0); UI_SetNext(Tint, 0);
UI_Box *dbg_box = UI_BuildBox(0, UI_NilKey); UI_Box *dbg_box = UI_BuildBox(UI_NilKey);
UI_PushCheckpoint(); UI_PushCheckpoint();
{ {
UI_Push(Parent, dbg_box); UI_Push(Parent, dbg_box);

View File

@ -25,6 +25,7 @@ Enum(PP_BindKind)
PP_BindKind_DebugDraw, PP_BindKind_DebugDraw,
PP_BindKind_DebugConsole, PP_BindKind_DebugConsole,
PP_BindKind_DebugCamera, PP_BindKind_DebugCamera,
PP_BindKind_DebugLister,
PP_BindKind_DebugPause, PP_BindKind_DebugPause,
PP_BindKind_DebugStep, PP_BindKind_DebugStep,
PP_BindKind_DebugDrag, PP_BindKind_DebugDrag,
@ -80,6 +81,7 @@ Global Readonly PP_BindKind g_binds[Btn_Count] = {
[Btn_F1] = PP_BindKind_DebugPause, [Btn_F1] = PP_BindKind_DebugPause,
[Btn_F2] = PP_BindKind_DebugCamera, [Btn_F2] = PP_BindKind_DebugCamera,
[Btn_F3] = PP_BindKind_DebugDraw, [Btn_F3] = PP_BindKind_DebugDraw,
[Btn_Tab] = PP_BindKind_DebugLister,
[Btn_F4] = PP_BindKind_DebugToggleTopmost, [Btn_F4] = PP_BindKind_DebugToggleTopmost,
[Btn_GraveAccent] = PP_BindKind_DebugConsole, [Btn_GraveAccent] = PP_BindKind_DebugConsole,
[Btn_Alt] = PP_BindKind_FullscreenMod, [Btn_Alt] = PP_BindKind_FullscreenMod,
@ -241,15 +243,17 @@ Struct(PP_SharedUserState)
//- Persist start //- Persist start
StructRegion(AUTO_PERSIST_START); StructRegion(AUTO_PERSIST_START);
//- Debug camera //- Debug ui
PP_EntKey debug_following; PP_EntKey debug_following;
b32 debug_camera;
b32 debug_camera_panning;
Vec2 debug_camera_pan_start; Vec2 debug_camera_pan_start;
b32 debug_draw; b32 debug_camera_panning;
b32 debug_camera;
//- Debug console b32 debug_lister;
Vec2 debug_lister_pos;
b32 debug_draw;
b32 debug_console; b32 debug_console;
//- Per frame //- Per frame
@ -302,11 +306,6 @@ void PP_DrawDebugXform(Xform xf, u32 color_x, u32 color_y);
void PP_DrawDebugMovement(PP_Ent *ent); void PP_DrawDebugMovement(PP_Ent *ent);
String PP_DebugStringFromEnt(Arena *arena, PP_Ent *ent); String PP_DebugStringFromEnt(Arena *arena, PP_Ent *ent);
////////////////////////////////////////////////////////////
//~ Console draw operations
void PP_DrawDebugConsole(b32 minimized);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Gpu buffer helpers //~ Gpu buffer helpers

View File

@ -19,6 +19,7 @@
@IncludeC pp_space.h @IncludeC pp_space.h
@IncludeC pp_ent.h @IncludeC pp_ent.h
@IncludeC pp_step.h @IncludeC pp_step.h
@IncludeC pp_widgets.h
@IncludeC pp_draw.h @IncludeC pp_draw.h
@IncludeC pp.h @IncludeC pp.h
@IncludeGpu pp_draw.h @IncludeGpu pp_draw.h
@ -29,6 +30,7 @@
@IncludeC pp_space.c @IncludeC pp_space.c
@IncludeC pp_ent.c @IncludeC pp_ent.c
@IncludeC pp_step.c @IncludeC pp_step.c
@IncludeC pp_widgets.c
@IncludeC pp.c @IncludeC pp.c
@IncludeGpu pp_draw.gpu @IncludeGpu pp_draw.gpu

View File

@ -1148,7 +1148,7 @@ void PP_StepSim(PP_SimStepCtx *ctx)
} }
if (flags & PP_ControlFlag_TestExplode) if (flags & PP_ControlFlag_TestExplode)
{ {
LogDebugF("Explosion test"); LogSuccessF("Explosion test");
PP_SpawnTestExplosion(root, player->player_cursor_pos, 100, 2); PP_SpawnTestExplosion(root, player->player_cursor_pos, 100, 2);
} }
} }

146
src/pp/pp_widgets.c Normal file
View File

@ -0,0 +1,146 @@
////////////////////////////////////////////////////////////
//~ Console
void PP_BuildDebugConsole(b32 minimized)
{
/* TODO: Remove this whole thing */
__prof;
PP_SharedUserState *g = &PP_shared_user_state;
TempArena scratch = BeginScratchNoConflict();
// i32 console_level = minimized ? LogLevel_Success : LogLevel_Debug;
i32 console_level = LogLevel_Debug;
u32 colors[LogLevel_Count][2] = ZI;
SetBytes(colors, 0xFF, sizeof(colors));
/* Debug colors */
colors[LogLevel_Debug][0] = Rgb32F(0.4, 0.1, 0.4);
colors[LogLevel_Debug][1] = Rgb32F(0.5, 0.2, 0.5);
/* Info colors */
colors[LogLevel_Info][0] = Rgb32F(0.4, 0.4, 0.4);
colors[LogLevel_Info][1] = Rgb32F(0.5, 0.5, 0.5);
/* Success colors */
colors[LogLevel_Success][0] = Rgb32F(0.1, 0.3, 0.1);
colors[LogLevel_Success][1] = Rgb32F(0.2, 0.4, 0.2);
/* Warning colors */
colors[LogLevel_Warning][0] = Rgb32F(0.4, 0.4, 0.1);
colors[LogLevel_Warning][1] = Rgb32F(0.5, 0.5, 0.2);
/* Error colors */
colors[LogLevel_Error][0] = Rgb32F(0.4, 0.1, 0.1);
colors[LogLevel_Error][1] = Rgb32F(0.5, 0.2, 0.2);
i64 max_time_ns = I64Max;
i64 fade_time_ns = max_time_ns;
if (minimized)
{
max_time_ns = NsFromSeconds(10);
fade_time_ns = max_time_ns;
}
f32 fade_curve = 0.5;
f32 spacing = 0;
f32 bg_margin = 5;
i64 now_ns = TimeNs();
UI_PushCheckpoint();
{
{
UI_SetNext(LayoutAxis, Axis_Y);
UI_SetNext(Border, 0);
if (minimized)
{
UI_SetNext(BackgroundColor, 0);
UI_SetNext(Width, UI_PIX(500, 0));
UI_SetNext(Height, UI_FIT(1));
}
else
{
UI_SetNext(BackgroundColor, Rgba32F(1, 1, 1, 0.02));
UI_SetNext(Width, UI_FILL(1, 0));
// UI_SetNext(Height, UI_FILL(0.33, 1));
UI_SetNext(Height, UI_FIT(1));
}
UI_Box *console_box = UI_BuildBox(UI_NilKey);
UI_Push(Parent, console_box);
}
{
/* Gather display logs */
u64 max = 20;
u64 display_count = 0;
LogEvent *display_logs = PushStructs(scratch.arena, LogEvent, max);
{
b32 done = 0;
if (minimized)
{
max = 5;
}
LogEventsArray logs = GetLogEvents();
for (u64 i = logs.count; i-- > 0 && display_count < max && !done;)
{
LogEvent ev = logs.logs[i];
if (ev.time_ns > (now_ns - max_time_ns))
{
if (ev.level <= console_level)
{
display_logs[display_count] = ev;
++display_count;
}
}
else
{
done = 1;
}
}
}
/* Display logs in reverse */
for (u64 i = display_count; i-- > 0;)
{
LogEvent log = display_logs[i];
f32 opacity = 0.75;
f32 lin = 1.0 - ClampF64((f64)(now_ns - log.time_ns) / (f64)fade_time_ns, 0, 1);
opacity *= PowF32(lin, fade_curve);
String text = log.msg;
if (!minimized)
{
DateTime datetime = log.datetime;
text = StringF(
scratch.arena,
"[%F:%F:%F.%F] %F",
FmtUintZ(datetime.hour, 2),
FmtUintZ(datetime.minute, 2),
FmtUintZ(datetime.second, 2),
FmtUintZ(datetime.milliseconds, 3),
FmtString(text));
}
UI_PushCheckpoint();
{
UI_Push(Tint, Alpha32F(0xFFFFFFFF, opacity));
{
u32 color = colors[log.level][log.level_id % 2];
UI_SetNext(BackgroundColor, color);
UI_SetNext(LayoutAxis, Axis_X);
UI_SetNext(Width, UI_FILL(1, 0));
UI_SetNext(Height, UI_FIT(1));
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_Push(Parent, log_box);
}
{
UI_SetNext(BackgroundColor, 0);
UI_SetNext(Border, 0);
UI_SetNext(TextPadding, 6);
UI_SetNext(Text, text);
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_PopCheckpoint();
}
}
}
UI_PopCheckpoint();
EndScratch(scratch);
}

4
src/pp/pp_widgets.h Normal file
View File

@ -0,0 +1,4 @@
////////////////////////////////////////////////////////////
//~ Console
void PP_BuildDebugConsole(b32 minimized);

View File

@ -7,7 +7,8 @@ UI_Box *UI_BuildLabel(String text)
UI_SetNext(Width, UI_TXT(0)); UI_SetNext(Width, UI_TXT(0));
UI_SetNext(Height, UI_TXT(0)); UI_SetNext(Height, UI_TXT(0));
UI_SetNext(Text, text); UI_SetNext(Text, text);
UI_Box *box = UI_BuildBox(UI_BoxFlag_DrawText, UI_NilKey); UI_SetNext(Flags, UI_BoxFlag_DrawText);
UI_Box *box = UI_BuildBox(UI_NilKey);
return box; return box;
} }
@ -40,6 +41,6 @@ UI_Box *UI_BuildSpacer(UI_Size size)
{ {
UI_SetNext(Height, size); UI_SetNext(Height, size);
} }
UI_Box *box = UI_BuildBox(0, UI_NilKey); UI_Box *box = UI_BuildBox(UI_NilKey);
return box; return box;
} }

View File

@ -169,7 +169,7 @@ UI_Style UI_StyleFromTopNode(UI_StyleKind kind, b32 use)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Box helpers //~ Box helpers
UI_Box *UI_BuildBox(UI_BoxFlag flags, UI_Key key) UI_Box *UI_BuildBox(UI_Key key)
{ {
UI_SharedState *g = &UI_shared_state; UI_SharedState *g = &UI_shared_state;
UI_BoxBin *bin = &g->box_bins[key.hash % UI_NumBoxLookupBins]; UI_BoxBin *bin = &g->box_bins[key.hash % UI_NumBoxLookupBins];
@ -213,9 +213,9 @@ UI_Box *UI_BuildBox(UI_BoxFlag flags, UI_Key key)
++g->boxes_count; ++g->boxes_count;
box->key = key; box->key = key;
box->flags = flags;
/* Pull from style stack */ /* Pull from style stack */
box->flags = UI_UseTop(Flags);
box->parent = UI_UseTop(Parent); box->parent = UI_UseTop(Parent);
box->pref_size[Axis_X] = UI_UseTop(Width); box->pref_size[Axis_X] = UI_UseTop(Width);
box->pref_size[Axis_Y] = UI_UseTop(Height); box->pref_size[Axis_Y] = UI_UseTop(Height);
@ -229,6 +229,7 @@ UI_Box *UI_BuildBox(UI_BoxFlag flags, UI_Key key)
box->text_padding = UI_UseTop(TextPadding); box->text_padding = UI_UseTop(TextPadding);
box->rounding = UI_UseTop(Rounding); box->rounding = UI_UseTop(Rounding);
box->display_text = UI_UseTop(Text); box->display_text = UI_UseTop(Text);
box->floating_pos = UI_UseTop(FloatingPos);
/* Prefetch font */ /* Prefetch font */
if (box->display_text.len > 0) if (box->display_text.len > 0)
@ -369,12 +370,25 @@ i64 UI_EndBuild(GPU_Resource *render_target)
UI_Box *box = n->box; UI_Box *box = n->box;
if (!n->visited) if (!n->visited)
{ {
/* Push children to dfs stack */ /* Push floating children to dfs stack */
for (UI_Box *child = box->last; child; child = child->prev) for (UI_Box *child = box->last; child; child = child->prev)
{ {
BoxNode *child_n = PushStruct(scratch.arena, BoxNode); if ((child->flags & UI_BoxFlag_Floating) != 0)
child_n->box = child; {
StackPush(first_dfs, child_n); BoxNode *child_n = PushStruct(scratch.arena, BoxNode);
child_n->box = child;
StackPush(first_dfs, child_n);
}
}
/* Push non-floating children to dfs stack */
for (UI_Box *child = box->last; child; child = child->prev)
{
if ((child->flags & UI_BoxFlag_Floating) == 0)
{
BoxNode *child_n = PushStruct(scratch.arena, BoxNode);
child_n->box = child;
StackPush(first_dfs, child_n);
}
} }
boxes_pre[pre_index++] = box; boxes_pre[pre_index++] = box;
n->visited = 1; n->visited = 1;
@ -465,13 +479,16 @@ i64 UI_EndBuild(GPU_Resource *render_target)
f32 accum = 0; f32 accum = 0;
for (UI_Box *child = box->first; child; child = child->next) for (UI_Box *child = box->first; child; child = child->next)
{ {
if (axis == box->layout_axis) if (!(child->flags & UI_BoxFlag_Floating))
{ {
accum += child->solved_dims[axis]; if (axis == box->layout_axis)
} {
else accum += child->solved_dims[axis];
{ }
accum = MaxF32(child->solved_dims[axis], accum); else
{
accum = MaxF32(child->solved_dims[axis], accum);
}
} }
} }
box->solved_dims[axis] = accum; box->solved_dims[axis] = accum;
@ -489,18 +506,21 @@ i64 UI_EndBuild(GPU_Resource *render_target)
f32 flex_accum = 0; f32 flex_accum = 0;
for (UI_Box *child = box->first; child; child = child->next) for (UI_Box *child = box->first; child; child = child->next)
{ {
f32 size = child->solved_dims[axis]; if (!(child->flags & UI_BoxFlag_Floating))
f32 strictness = child->pref_size[axis].strictness;
f32 flex = size * (1.0 - strictness);
if (axis == box->layout_axis)
{ {
size_accum += size; f32 size = child->solved_dims[axis];
flex_accum += flex; f32 strictness = child->pref_size[axis].strictness;
} f32 flex = size * (1.0 - strictness);
else if (axis == box->layout_axis)
{ {
size_accum = MaxF32(size_accum, size); size_accum += size;
flex_accum = MaxF32(flex_accum, flex); flex_accum += flex;
}
else
{
size_accum = MaxF32(size_accum, size);
flex_accum = MaxF32(flex_accum, flex);
}
} }
} }
f32 violation = size_accum - box->solved_dims[axis]; f32 violation = size_accum - box->solved_dims[axis];
@ -508,20 +528,23 @@ i64 UI_EndBuild(GPU_Resource *render_target)
{ {
for (UI_Box *child = box->first; child; child = child->next) for (UI_Box *child = box->first; child; child = child->next)
{ {
f32 size = child->solved_dims[axis]; if (!(child->flags & UI_BoxFlag_Floating))
f32 strictness = child->pref_size[axis].strictness;
f32 flex = size * (1.0 - strictness);
f32 new_size = size;
if (axis == box->layout_axis)
{ {
f32 chopoff = MinF32(flex, violation * (flex / flex_accum)); f32 size = child->solved_dims[axis];
new_size = size - chopoff; f32 strictness = child->pref_size[axis].strictness;
f32 flex = size * (1.0 - strictness);
f32 new_size = size;
if (axis == box->layout_axis)
{
f32 chopoff = MinF32(flex, violation * (flex / flex_accum));
new_size = size - chopoff;
}
else
{
new_size = MinF32(flex, box->solved_dims[axis]);
}
child->solved_dims[axis] = new_size;
} }
else
{
new_size = MinF32(flex, box->solved_dims[axis]);
}
child->solved_dims[axis] = new_size;
} }
} }
} }
@ -533,15 +556,34 @@ i64 UI_EndBuild(GPU_Resource *render_target)
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_Box *parent = box->parent; UI_Box *parent = box->parent;
Vec2 final_size = VEC2(box->solved_dims[0], box->solved_dims[1]); Vec2 final_size = VEC2(box->solved_dims[0], box->solved_dims[1]);
if (parent) if (box->flags & UI_BoxFlag_Floating)
{ {
b32 is_layout_x = parent->layout_axis == Axis_X; Vec2 offset = box->floating_pos;
f32 layout_cursor = parent->layout_cursor;
Vec2 offset = VEC2(layout_cursor * is_layout_x, layout_cursor * !is_layout_x);
parent->layout_cursor += final_size.x * is_layout_x + final_size.y * !is_layout_x;
box->p0 = AddVec2(parent->p0, offset); box->p0 = AddVec2(parent->p0, offset);
if (box->flags & UI_BoxFlag_ClampFloatingX)
{
f32 overshoot = MaxF32(0, (box->p0.x + final_size.x) - parent->p1.x);
box->p0.x = MaxF32(parent->p0.x, box->p0.x - overshoot);
}
if (box->flags & UI_BoxFlag_ClampFloatingY)
{
f32 overshoot = MaxF32((box->p0.y + final_size.y) - parent->p1.y, 0);
box->p0.y = MaxF32(parent->p0.y, box->p0.y - overshoot);
}
box->p1 = AddVec2(box->p0, final_size);
}
else
{
if (parent)
{
b32 is_layout_x = parent->layout_axis == Axis_X;
f32 layout_cursor = parent->layout_cursor;
Vec2 offset = VEC2(layout_cursor * is_layout_x, layout_cursor * !is_layout_x);
parent->layout_cursor += final_size.x * is_layout_x + final_size.y * !is_layout_x;
box->p0 = AddVec2(parent->p0, offset);
}
box->p1 = AddVec2(box->p0, final_size);
} }
box->p1 = AddVec2(box->p0, final_size);
} }
////////////////////////////// //////////////////////////////

View File

@ -27,11 +27,25 @@ Struct(UI_Size)
f32 strictness; f32 strictness;
}; };
////////////////////////////////////////////////////////////
//~ Box flag types
Enum(UI_BoxFlag)
{
UI_BoxFlag_None = 0,
UI_BoxFlag_DrawText = (1 << 0),
UI_BoxFlag_NoTextTruncation = (1 << 1),
UI_BoxFlag_Floating = (1 << 2),
UI_BoxFlag_ClampFloatingX = (1 << 3),
UI_BoxFlag_ClampFloatingY = (1 << 4),
};
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Style types //~ Style types
#define UI_StyleKindsXMacro(x) \ #define UI_StyleKindsXMacro(x) \
x(Tag, u64) \ x(Tag, u64) \
x(Flags, UI_BoxFlag) \
x(Parent, struct UI_Box *) \ x(Parent, struct UI_Box *) \
x(LayoutAxis, Axis) \ x(LayoutAxis, Axis) \
x(Width, UI_Size) \ x(Width, UI_Size) \
@ -46,6 +60,7 @@ Struct(UI_Size)
x(Text, String) \ x(Text, String) \
x(TextPadding, f32) \ x(TextPadding, f32) \
x(Rounding, f32) \ x(Rounding, f32) \
x(FloatingPos, Vec2) \
/* ------------------------------------------- */ /* ------------------------------------------- */
Enum(UI_StyleKind) Enum(UI_StyleKind)
@ -81,15 +96,6 @@ Struct(UI_StyleNode)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Box types //~ Box types
/* NOTE: UI flags are located here since they are shared between application & shader code */
Enum(UI_BoxFlag)
{
UI_BoxFlag_None = 0,
UI_BoxFlag_DrawText = (1 << 0),
UI_BoxFlag_NoTextTruncation = (1 << 1),
};
Struct(UI_Box) Struct(UI_Box)
{ {
//- Hash list //- Hash list
@ -126,6 +132,7 @@ Struct(UI_Box)
f32 border; f32 border;
f32 text_padding; f32 text_padding;
f32 rounding; f32 rounding;
Vec2 floating_pos;
ResourceKey font_resource; ResourceKey font_resource;
f32 font_size; f32 font_size;
@ -241,7 +248,7 @@ UI_Style UI_StyleFromTopNode(UI_StyleKind kind, b32 use);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Box //~ Box
UI_Box *UI_BuildBox(UI_BoxFlag flags, UI_Key key); UI_Box *UI_BuildBox(UI_Key key);
void UI_SetBackgroundTexture(UI_Box *box, GPU_Resource *texture, Vec2 uv0, Vec2 uv1); void UI_SetBackgroundTexture(UI_Box *box, GPU_Resource *texture, Vec2 uv0, Vec2 uv1);