ui padding fixes

This commit is contained in:
jacob 2025-11-04 11:15:05 -06:00
parent f825cc918c
commit 53d315e9ff
4 changed files with 195 additions and 162 deletions

View File

@ -792,10 +792,15 @@ 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_SetNext(Width, UI_PIX(g->ui_size.x, 1));
UI_SetNext(Height, UI_PIX(g->ui_size.y, 1)); UI_Box *pp_root_box = 0;
UI_SetNext(Padding, UI_PADALL(UI_FILL(1, 0))); {
UI_Box *pp_root_box = UI_BuildBox(Lit("pp root")); UI_SetNext(Width, UI_PIX(g->ui_size.x, 1));
UI_SetNext(Height, UI_PIX(g->ui_size.y, 1));
UI_SetNext(Padding, UI_PADALL(UI_FILL(1, 0)));
pp_root_box = UI_BuildBox(Lit("pp root"));
}
PP_PushGameUiStyle(); PP_PushGameUiStyle();
UI_Push(Parent, pp_root_box); UI_Push(Parent, pp_root_box);
@ -1962,6 +1967,7 @@ void PP_UpdateUser(void)
UI_Push(BackgroundColor, 0xfa1a1d1e); UI_Push(BackgroundColor, 0xfa1a1d1e);
UI_Push(BorderColor, 0xff343a3b); UI_Push(BorderColor, 0xff343a3b);
UI_Push(Border, 1); UI_Push(Border, 1);
UI_SetNext(Rounding, UI_RPIX(15));
UI_Push(Width, UI_PIX(size.x, 0)); UI_Push(Width, UI_PIX(size.x, 0));
UI_Push(Height, UI_PIX(size.y, 0)); UI_Push(Height, UI_PIX(size.y, 0));
@ -1969,7 +1975,6 @@ void PP_UpdateUser(void)
UI_Push(LayoutAxis, Axis_Y); UI_Push(LayoutAxis, Axis_Y);
UI_Push(FloatingPos, g->lister_pos); UI_Push(FloatingPos, g->lister_pos);
UI_SetNext(Flags, UI_BoxFlag_Floating); UI_SetNext(Flags, UI_BoxFlag_Floating);
UI_SetNext(Rounding, UI_RPIX(15));
// UI_SetNext(Rounding, UI_RFILL(1)); // UI_SetNext(Rounding, UI_RFILL(1));
UI_Box *lister_box = UI_BuildBox(Lit("lister")); UI_Box *lister_box = UI_BuildBox(Lit("lister"));
UI_Box *lister_pad = lister_box; UI_Box *lister_pad = lister_box;

View File

@ -33,12 +33,10 @@ UI_Box *PP_BuildDebugConsole(b32 minimized)
i64 fade_time_ns = max_time_ns; i64 fade_time_ns = max_time_ns;
if (minimized) if (minimized)
{ {
max_time_ns = NsFromSeconds(10); // max_time_ns = NsFromSeconds(10);
fade_time_ns = max_time_ns; // fade_time_ns = max_time_ns;
} }
f32 fade_curve = 0.5; f32 fade_curve = 0.5;
f32 spacing = 0;
f32 bg_margin = 5;
i64 now_ns = TimeNs(); i64 now_ns = TimeNs();
UI_Box *console_box = 0; UI_Box *console_box = 0;

View File

@ -217,6 +217,18 @@ void UI_PushStyle(UI_Style desc)
UI_PushCopy(LeftPadding, desc, pad.left); UI_PushCopy(LeftPadding, desc, pad.left);
UI_PushCopy(RightPadding, desc, pad.right); UI_PushCopy(RightPadding, desc, pad.right);
} break; } break;
case UI_StyleKind_AxisSize:
{
if (desc.AxisSize.axis == Axis_X)
{
UI_PushCopy(Width, desc, desc.AxisSize.size);
}
else
{
UI_PushCopy(Height, desc, desc.AxisSize.size);
}
} break;
} }
} }
else else
@ -316,181 +328,194 @@ UI_Style UI_FetchStyle(UI_StyleKind kind, b32 use)
n->next = g->first_free_style_node; n->next = g->first_free_style_node;
g->first_free_style_node = n; g->first_free_style_node = n;
} }
} }
return result; return result;
} }
////////////////////////////////////////////////////////////
//~ Padding helpers
UI_Box *UI_BuildPadAlongAxis(UI_Box *parent, UI_Size start, UI_Size end, Axis final_layout_axis)
{
UI_Box *pad = parent;
b32 has_start_padding = !(start.kind == UI_SizeKind_Pixel && start.v == 0);
b32 has_end_padding = !(end.kind == UI_SizeKind_Pixel && end.v == 0);
UI_Size old_width = UI_PeekTop(Width);
UI_Size old_height = UI_PeekTop(Height);
{
UI_PushStack();
{
UI_Push(Parent, parent);
{
/* Start */
if (has_start_padding)
{
if (parent->layout_axis == Axis_X)
{
UI_SetNext(Width, start);
UI_SetNext(Height, old_height);
}
else
{
UI_SetNext(Width, old_width);
UI_SetNext(Height, start);
}
UI_BuildBox(Zstr);
}
/* Pad */
{
UI_SetNext(Width, old_width);
UI_SetNext(Height, old_height);
UI_SetNext(LayoutAxis, final_layout_axis);
pad = UI_BuildBox(Zstr);
}
/* End */
if (has_end_padding)
{
if (parent->layout_axis == Axis_X)
{
UI_SetNext(Width, end);
UI_SetNext(Height, old_height);
}
else
{
UI_SetNext(Width, old_width);
UI_SetNext(Height, end);
}
UI_BuildBox(Zstr);
}
}
}
UI_PopStack();
}
return pad;
}
UI_Box *UI_BuildPad(UI_Box *parent, UI_Pad padding)
{
UI_Box *pad = parent;
b32 has_top_padding = !(padding.top.kind == UI_SizeKind_Pixel && padding.top.v == 0);
b32 has_bottom_padding = !(padding.bottom.kind == UI_SizeKind_Pixel && padding.bottom.v == 0);
b32 has_left_padding = !(padding.left.kind == UI_SizeKind_Pixel && padding.left.v == 0);
b32 has_right_padding = !(padding.right.kind == UI_SizeKind_Pixel && padding.right.v == 0);
if (has_top_padding || has_bottom_padding || has_left_padding || has_right_padding)
{
if (parent->layout_axis == Axis_X)
{
b32 needs_second_pass = has_top_padding || has_bottom_padding;
pad = UI_BuildPadAlongAxis(pad, padding.left, padding.right, needs_second_pass ? Axis_Y : Axis_X);
if (needs_second_pass)
{
pad = UI_BuildPadAlongAxis(pad, padding.top, padding.bottom, Axis_X);
}
}
else
{
b32 needs_second_pass = has_left_padding || has_right_padding;
pad = UI_BuildPadAlongAxis(pad, padding.top, padding.bottom, needs_second_pass ? Axis_X : Axis_Y);
if (needs_second_pass)
{
pad = UI_BuildPadAlongAxis(pad, padding.left, padding.right, Axis_Y);
}
}
}
return pad;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Box //~ Box
UI_Box *UI_BuildBox(String seed) UI_Box *UI_BuildBox(String seed)
{ {
UI_SharedState *g = &UI_shared_state; UI_SharedState *g = &UI_shared_state;
UI_Box *parent = UI_UseTop(Parent);
/* Create padding */
UI_Pad padding = UI_UseTop(Padding); UI_Pad padding = UI_UseTop(Padding);
parent = UI_BuildPad(parent, padding); UI_BoxFlag flags = UI_UseTop(Flags);
UI_Size width = UI_UseTop(Width);
UI_Size height = UI_UseTop(Height);
/* Calculate key */ /* Create initial padding boxes */
UI_Tag tag = UI_UseTop(Tag); UI_Size start_padding = ZI;
UI_Key key = ZI; UI_Size end_padding = ZI;
if (seed.len > 0) b32 has_start_padding = 0;
b32 has_end_padding = 0;
UI_Box *parent = UI_UseTop(Parent);
{ {
key.hash = RandU64FromSeeds(key.hash, parent->key.hash); Axis axis = parent->layout_axis;
key.hash = RandU64FromSeeds(key.hash, tag.hash); UI_Size axis_size = width;
key.hash = HashFnv64(key.hash, seed); UI_Size axis_start_padding = padding.left;
UI_Size axis_end_padding = padding.right;
UI_Size non_axis_start_padding = padding.top;
UI_Size non_axis_end_padding = padding.bottom;
if (axis == Axis_Y)
{
axis_size = height;
axis_start_padding = padding.top;
axis_end_padding = padding.bottom;
non_axis_start_padding = padding.left;
non_axis_end_padding = padding.right;
}
b32 has_axis_start_padding = !(axis_start_padding.kind == UI_SizeKind_Pixel && axis_start_padding.v == 0);
b32 has_axis_end_padding = !(axis_end_padding.kind == UI_SizeKind_Pixel && axis_end_padding.v == 0);
b32 has_non_axis_start_padding = !(non_axis_start_padding.kind == UI_SizeKind_Pixel && non_axis_start_padding.v == 0);
b32 has_non_axis_end_padding = !(non_axis_end_padding.kind == UI_SizeKind_Pixel && non_axis_end_padding.v == 0);
if (has_axis_start_padding || has_axis_end_padding || has_non_axis_start_padding || has_non_axis_end_padding)
{
UI_PushStack();
UI_PushCP(parent);
{
if (has_non_axis_start_padding || has_non_axis_end_padding)
{
if (has_axis_start_padding)
{
UI_SetNext(AxisSize, UI_AXSIZE(axis, axis_start_padding));
UI_SetNext(AxisSize, UI_AXSIZE(!axis, UI_PIX(0, 0)));
UI_BuildBox(Zstr);
}
{
UI_Pad subpad = ZI;
if (has_axis_end_padding)
{
if (axis == Axis_X)
{
subpad.right = axis_end_padding;
}
else
{
subpad.bottom = axis_end_padding;
}
}
UI_SetNext(Padding, subpad);
UI_SetNext(AxisSize, UI_AXSIZE(axis, axis_size));
UI_SetNext(AxisSize, UI_AXSIZE(!axis, UI_FIT(0)));
UI_SetNext(LayoutAxis, !axis);
parent = UI_BuildBox(Zstr);
}
start_padding = non_axis_start_padding;
end_padding = non_axis_end_padding;
has_start_padding = has_non_axis_start_padding;
has_end_padding = has_non_axis_end_padding;
}
else
{
start_padding = axis_start_padding;
end_padding = axis_end_padding;
has_start_padding = has_axis_start_padding;
has_end_padding = has_axis_end_padding;
}
}
UI_PopStack();
}
} }
/* Insert into lookup */ /* Build start padding */
UI_BoxBin *bin = &g->box_bins[key.hash % UI_NumBoxLookupBins]; if (has_start_padding)
UI_Box *box = PushStruct(g->build_arena, UI_Box);
UI_Box *back_box = 0;
if (key.hash != 0)
{ {
#if RtcIsEnabled UI_PushStack();
/* Validate box not already built */ UI_PushCP(parent);
for (UI_Box *tmp = bin->first; tmp; tmp = tmp->next_in_bin)
{ {
if (tmp->key.hash == key.hash) UI_SetNext(AxisSize, UI_AXSIZE(parent->layout_axis, start_padding));
UI_SetNext(AxisSize, UI_AXSIZE(!parent->layout_axis, UI_PIX(0, 0)));
UI_BuildBox(Zstr);
}
UI_PopStack();
}
/* Create box */
UI_Box *box = 0;
{
/* Calculate key */
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];
box = PushStruct(g->build_arena, UI_Box);
UI_Box *back_box = 0;
if (key.hash != 0)
{
#if RtcIsEnabled
/* Validate box not already built */
for (UI_Box *tmp = bin->first; tmp; tmp = tmp->next_in_bin)
{ {
Assert(0); /* Box with matching key already built */ if (tmp->key.hash == key.hash)
break; {
Assert(0); /* Box with matching key already built */
break;
}
}
#endif
DllPushBackNP(bin->first, bin->last, box, next_in_bin, prev_in_bin);
back_box = UI_BackBoxFromKey(key);
}
box->key = key;
++g->boxes_count;
/* Insert into parent */
DllPushBack(parent->first, parent->last, box);
box->parent = parent;
++parent->count;
/* Persist data from back box */
if (back_box != 0)
{
box->report = back_box->report;
}
/* Pull from style stack */
box->flags = flags;
box->pref_size[Axis_X] = width;
box->pref_size[Axis_Y] = height;
box->layout_axis = UI_UseTop(LayoutAxis);
box->background_color = UI_UseTop(BackgroundColor);
box->border_color = UI_UseTop(BorderColor);
box->tint = UI_UseTop(Tint);
box->border = UI_UseTop(Border);
box->font_resource = UI_UseTop(Font);
box->font_size = UI_UseTop(FontSize);
box->rounding = UI_UseTop(Rounding);
box->text = UI_UseTop(Text);
box->floating_pos = UI_UseTop(FloatingPos);
box->text_alignment = UI_UseTop(TextAlignment);
/* Prefetch font */
if (box->text.len > 0)
{
box->font = F_LoadFontAsync(box->font_resource, box->font_size);
if (box->font)
{
box->glyph_run = F_RunFromString(g->build_arena, box->font, box->text);
} }
} }
#endif
DllPushBackNP(bin->first, bin->last, box, next_in_bin, prev_in_bin);
back_box = UI_BackBoxFromKey(key);
}
box->key = key;
++g->boxes_count;
/* Insert into parent */
DllPushBack(parent->first, parent->last, box);
box->parent = parent;
++parent->count;
/* Persist data from back box */
if (back_box != 0)
{
box->report = back_box->report;
} }
/* Pull from style stack */ /* Build end padding */
box->flags = UI_UseTop(Flags); if (has_end_padding)
box->pref_size[Axis_X] = UI_UseTop(Width);
box->pref_size[Axis_Y] = UI_UseTop(Height);
box->layout_axis = UI_UseTop(LayoutAxis);
box->background_color = UI_UseTop(BackgroundColor);
box->border_color = UI_UseTop(BorderColor);
box->tint = UI_UseTop(Tint);
box->border = UI_UseTop(Border);
box->font_resource = UI_UseTop(Font);
box->font_size = UI_UseTop(FontSize);
box->rounding = UI_UseTop(Rounding);
box->text = UI_UseTop(Text);
box->floating_pos = UI_UseTop(FloatingPos);
box->text_alignment = UI_UseTop(TextAlignment);
/* Prefetch font */
if (box->text.len > 0)
{ {
box->font = F_LoadFontAsync(box->font_resource, box->font_size); UI_PushStack();
if (box->font) UI_PushCP(parent);
{ {
box->glyph_run = F_RunFromString(g->build_arena, box->font, box->text); UI_SetNext(AxisSize, UI_AXSIZE(parent->layout_axis, end_padding));
UI_SetNext(AxisSize, UI_AXSIZE(!parent->layout_axis, UI_PIX(0, 0)));
UI_BuildBox(Zstr);
} }
UI_PopStack();
} }
return box; return box;
@ -1128,7 +1153,7 @@ i64 UI_EndFrame(UI_Frame frame)
Vec2 inv_font_image_size = VEC2(1.0f / (f32)box->font->image_width, 1.0f / (f32)box->font->image_height); Vec2 inv_font_image_size = VEC2(1.0f / (f32)box->font->image_width, 1.0f / (f32)box->font->image_height);
F_Run run = box->glyph_run; F_Run run = box->glyph_run;
f32 max_baseline = box->p1.x; f32 max_baseline = box->p1.x - box->p0.x;
b32 should_truncate = run.count > 0 && (run.rects[run.count - 1].pos + run.rects[run.count - 1].advance) > max_baseline; b32 should_truncate = run.count > 0 && (run.rects[run.count - 1].pos + run.rects[run.count - 1].advance) > max_baseline;
/* Truncate run */ /* Truncate run */

View File

@ -113,6 +113,7 @@ Enum(UI_BoxFlag)
/* ----------------------------------- */ \ /* ----------------------------------- */ \
x(BeginVirtualStyles_, i8) \ x(BeginVirtualStyles_, i8) \
x(Padding, UI_Pad) \ x(Padding, UI_Pad) \
x(AxisSize, UI_AxisSize) \
/* ------------------------------------------- */ /* ------------------------------------------- */
Struct(UI_Tag) Struct(UI_Tag)
@ -121,6 +122,12 @@ Struct(UI_Tag)
u64 hash; u64 hash;
}; };
Struct(UI_AxisSize)
{
Axis axis;
UI_Size size;
};
Enum(UI_StyleKind) Enum(UI_StyleKind)
{ {
#define X(name, type) UI_StyleKind_##name, #define X(name, type) UI_StyleKind_##name,
@ -357,6 +364,7 @@ UI_Style UI_FetchStyle(UI_StyleKind kind, b32 use);
//~ Size helpers //~ Size helpers
#define UI_SIZE(_kind, _v, _s) (UI_Size) { .kind = (_kind), .v = (_v), .strictness = (_s) } #define UI_SIZE(_kind, _v, _s) (UI_Size) { .kind = (_kind), .v = (_v), .strictness = (_s) }
#define UI_AXSIZE(_axis, _size) (UI_AxisSize) { .axis = (_axis), .size = (_size) }
#define UI_PIX(_v, _s) UI_SIZE(UI_SizeKind_Pixel, (_v), (_s)) #define UI_PIX(_v, _s) UI_SIZE(UI_SizeKind_Pixel, (_v), (_s))
#define UI_FIT(_s) UI_SIZE(UI_SizeKind_Fit, 0, (_s)) #define UI_FIT(_s) UI_SIZE(UI_SizeKind_Fit, 0, (_s))
@ -377,9 +385,6 @@ UI_Style UI_FetchStyle(UI_StyleKind kind, b32 use);
#define UI_PAD(...) ((UI_Pad) { __VA_ARGS__ }) #define UI_PAD(...) ((UI_Pad) { __VA_ARGS__ })
#define UI_PADALL(size) ((UI_Pad) { .top = size, .bottom = size, .left = size, .right = size }) #define UI_PADALL(size) ((UI_Pad) { .top = size, .bottom = size, .left = size, .right = size })
UI_Box *UI_BuildPadAlongAxis(UI_Box *parent, UI_Size start, UI_Size end, Axis final_layout_axis);
UI_Box *UI_BuildPad(UI_Box *parent, UI_Pad padding);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Box //~ Box