fix box dims for odd font sizes
This commit is contained in:
parent
b3012c37bd
commit
78d0a8b832
@ -179,16 +179,16 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size
|
||||
GC_Glyph *glyph = ready_glyphs[glyph_idx];
|
||||
GC_RunRect *rect = &result.rects[glyph_idx];
|
||||
|
||||
f32 advance = advance = glyph->advance;
|
||||
f32 advance = glyph->advance;
|
||||
if (TweakB32("Ceil glyph advances", 0))
|
||||
{
|
||||
advance = CeilF32(advance);
|
||||
}
|
||||
if (TweakB32("Floor glyph advances", 1))
|
||||
if (TweakB32("Floor glyph advances", 0))
|
||||
{
|
||||
advance = FloorF32(advance);
|
||||
}
|
||||
if (TweakB32("Round glyph advances", 0))
|
||||
if (TweakB32("Round glyph advances", 1))
|
||||
{
|
||||
advance = RoundF32(advance);
|
||||
}
|
||||
|
||||
@ -82,13 +82,15 @@ V_WidgetTheme V_GetWidgetTheme(void)
|
||||
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/fixedsys.ttf")));
|
||||
// theme.font_size = 16;
|
||||
|
||||
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/seguisb.ttf")));
|
||||
// theme.font_size = 16;
|
||||
|
||||
theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/seguisb.ttf")));
|
||||
theme.font_size = 16;
|
||||
theme.font_size = 14;
|
||||
|
||||
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/seguisb.ttf")));
|
||||
// theme.font_size = 12;
|
||||
|
||||
|
||||
// theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/seguisb.ttf")));
|
||||
// theme.font_size = 30;
|
||||
|
||||
@ -253,7 +255,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
frame->tick = V.current_frame_tick;
|
||||
frame->time_ns = TimeNs();
|
||||
frame->dt_ns = frame->time_ns - last_frame->time_ns;
|
||||
frame->dt_ns = ClampI64(frame->time_ns - last_frame->time_ns, 1, NsFromSeconds(1.0 / 50));
|
||||
frame->dt = SecondsFromNs(frame->dt_ns);
|
||||
|
||||
if (S_IsKeyNil(V.player_key))
|
||||
@ -341,18 +343,18 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
V_WidgetTheme theme = V_GetWidgetTheme();
|
||||
V_PushWidgetThemeStyles(theme);
|
||||
|
||||
UI_Key vis_box = UI_KeyF("vis box");
|
||||
UI_Report vis_box_rep = UI_ReportFromKey(vis_box);
|
||||
{
|
||||
UI_Push(ChildLayoutAxis, Axis_Y);
|
||||
UI_Push(Width, UI_GROW(1, 0));
|
||||
UI_Push(Height, UI_GROW(1, 0));
|
||||
UI_SetNext(Flags, UI_BoxFlag_Interactable);
|
||||
UI_Key vis_box = UI_KeyF("vis box");
|
||||
UI_Push(Parent, UI_BuildColumnEx(vis_box));
|
||||
|
||||
{
|
||||
// TODO: Don't rely on ui report for draw size since it introduces one frame of delay when resizing
|
||||
UI_Report vis_rep = UI_ReportFromKey(vis_box);
|
||||
frame->ui_dims = RoundVec2ToI32(DimsFromRng2(vis_rep.screen_rect));
|
||||
}
|
||||
|
||||
// TODO: Don't rely on ui report for draw size since it introduces one frame of delay when resizing
|
||||
frame->ui_dims = RoundVec2ToI32(DimsFromRng2(vis_box_rep.screen_rect));
|
||||
frame->ui_dims.x = MaxI32(frame->ui_dims.x, 64);
|
||||
frame->ui_dims.y = MaxI32(frame->ui_dims.y, 64);
|
||||
frame->draw_dims = frame->ui_dims;
|
||||
@ -1284,7 +1286,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
//- Build command palette
|
||||
|
||||
V_Palette *palette = &frame->palette;
|
||||
palette->show = LerpF32(palette->show, palette->pref_show, 50.0 * frame->dt);
|
||||
palette->show = LerpF32(palette->show, palette->pref_show, 30.0 * frame->dt);
|
||||
if (palette->show > 0.001)
|
||||
{
|
||||
palette->key = UI_KeyF("command palette");
|
||||
@ -1307,7 +1309,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
window_border_color = LerpSrgb(window_border_color, Rgb32(0x0078a6), titlebar_rep.hot);
|
||||
|
||||
UI_Push(Tint, VEC4(1, 1, 1, palette->show));
|
||||
UI_SetNext(Scale, LerpF32(0.75, 1, palette->show));
|
||||
UI_SetNext(Scale, LerpF32(0.85, 1, palette->show));
|
||||
|
||||
UI_Push(BackgroundColor, window_background_color);
|
||||
UI_Push(BorderColor, window_border_color);
|
||||
@ -1318,7 +1320,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
UI_Push(ChildLayoutAxis, Axis_Y);
|
||||
UI_Push(FloatingPos, palette->pos);
|
||||
UI_SetNext(FloatingPosAnchor, UI_Region_Center);
|
||||
UI_SetNext(Flags, UI_BoxFlag_Floating);
|
||||
UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_Interactable);
|
||||
UI_PushCP(UI_BuildBoxEx(palette->key));
|
||||
{
|
||||
// Title bar
|
||||
@ -1442,7 +1444,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
for (PaletteItem *item = first_item; item; item = item->next)
|
||||
{
|
||||
UI_BuildDivider(UI_PIX(1, 1), theme.divider_color, Axis_Y);
|
||||
// Divider
|
||||
UI_BuildDivider(UI_PIX(1, 1), divider_color, Axis_Y);
|
||||
|
||||
UI_Report item_rep = UI_ReportFromKey(item->key);
|
||||
if (item_rep.m1.presses)
|
||||
|
||||
190
src/ui/ui_core.c
190
src/ui/ui_core.c
@ -1112,6 +1112,18 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
box->cursor = 0;
|
||||
ZeroStructs(box->final_children_size_accum, countof(box->final_children_size_accum));
|
||||
box->solved_dims = VEC2(0, 0);
|
||||
|
||||
// Compute scale
|
||||
UI_Box *parent = box->parent;
|
||||
box->solved_scale = box->desc.scale;
|
||||
if (parent)
|
||||
{
|
||||
box->solved_scale *= parent->solved_scale;
|
||||
}
|
||||
if (AbsF32(1.0 - box->solved_scale) < 0.003)
|
||||
{
|
||||
box->solved_scale = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1124,7 +1136,7 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
Assert(post_index == boxes_count);
|
||||
}
|
||||
|
||||
// Compute independent sizes
|
||||
// Solve independent sizes
|
||||
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
|
||||
{
|
||||
UI_Box *box = boxes_pre[pre_index];
|
||||
@ -1141,7 +1153,7 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
f32 text_size = 0;
|
||||
if (axis == Axis_X)
|
||||
{
|
||||
text_size = CeilF32(box->glyph_run.baseline_length);
|
||||
text_size = box->glyph_run.baseline_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1152,7 +1164,7 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
}
|
||||
}
|
||||
|
||||
// Compute upwards-dependent sizes along layout axis
|
||||
// Solve upwards-dependent sizes along layout axis
|
||||
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
|
||||
{
|
||||
UI_Box *box = boxes_pre[pre_index];
|
||||
@ -1179,7 +1191,7 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
}
|
||||
}
|
||||
|
||||
// Compute downwards-dependent sizes
|
||||
// Solve downwards-dependent sizes
|
||||
for (u64 post_index = 0; post_index < boxes_count; ++post_index)
|
||||
{
|
||||
UI_Box *box = boxes_post[post_index];
|
||||
@ -1193,22 +1205,23 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
{
|
||||
if (!AnyBit(child->desc.flags, UI_BoxFlag_Floating))
|
||||
{
|
||||
f32 child_size = child->solved_dims.v[axis];
|
||||
if (axis == box->desc.child_layout_axis)
|
||||
{
|
||||
accum += child->solved_dims.v[axis];
|
||||
accum += child_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
accum = MaxF32(child->solved_dims.v[axis], accum);
|
||||
accum = MaxF32(child_size, accum);
|
||||
}
|
||||
}
|
||||
}
|
||||
box->solved_dims.v[axis] = accum + (sem_dims.v * 2);
|
||||
box->solved_dims.v[axis] = CeilF32(accum + (sem_dims.v * 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute upwards-dependent sizes along non-layout axis
|
||||
// Solve upwards-dependent sizes along non-layout axis
|
||||
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
|
||||
{
|
||||
UI_Box *box = boxes_pre[pre_index];
|
||||
@ -1230,108 +1243,76 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
for (Axis axis = 0; axis < Axis_COUNTXY; ++axis)
|
||||
{
|
||||
f32 box_size = box->solved_dims.v[axis];
|
||||
// Solve non-floating violations
|
||||
// Accumulate non-floating sizes
|
||||
{
|
||||
f32 size_accum = 0;
|
||||
f32 unconstrained_size_accum = 0;
|
||||
f32 flex_accum = 0;
|
||||
f32 violation = 0;
|
||||
{
|
||||
for (UI_Box *child = box->first; child; child = child->next)
|
||||
{
|
||||
if (!AnyBit(child->desc.flags, UI_BoxFlag_Floating))
|
||||
b32 is_floating = AnyBit(child->desc.flags, UI_BoxFlag_Floating);
|
||||
if (!is_floating)
|
||||
{
|
||||
child->solved_dims.v[axis] = RoundF32(child->solved_dims.v[axis]);
|
||||
|
||||
f32 size = child->solved_dims.v[axis];
|
||||
f32 strictness = child->desc.pref_semantic_dims[axis].strictness;
|
||||
f32 flex = size * (1.0 - strictness);
|
||||
if (axis == box->desc.child_layout_axis)
|
||||
{
|
||||
size_accum += size;
|
||||
unconstrained_size_accum += size;
|
||||
flex_accum += flex;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_accum = MaxF32(size_accum, size);
|
||||
unconstrained_size_accum = MaxF32(unconstrained_size_accum, size);
|
||||
flex_accum = MaxF32(flex_accum, flex);
|
||||
}
|
||||
}
|
||||
}
|
||||
f32 violation = size_accum - box_size;
|
||||
if (violation > 0 && flex_accum > 0)
|
||||
violation = unconstrained_size_accum - box_size;
|
||||
}
|
||||
{
|
||||
f32 adjusted_size_accum = 0;
|
||||
f32 size_accum = 0;
|
||||
for (UI_Box *child = box->first; child; child = child->next)
|
||||
{
|
||||
if (!AnyBit(child->desc.flags, UI_BoxFlag_Floating))
|
||||
{
|
||||
f32 size = child->solved_dims.v[axis];
|
||||
b32 is_floating = AnyBit(child->desc.flags, UI_BoxFlag_Floating);
|
||||
f32 unconstrained_size = child->solved_dims.v[axis];
|
||||
f32 strictness = child->desc.pref_semantic_dims[axis].strictness;
|
||||
f32 flex = size * (1.0 - strictness);
|
||||
f32 new_size = size;
|
||||
f32 flex = unconstrained_size * (1.0 - strictness);
|
||||
f32 new_size = unconstrained_size;
|
||||
// Solve non-floating violation
|
||||
if (!is_floating && violation > 0 && flex_accum > 0)
|
||||
{
|
||||
if (axis == box->desc.child_layout_axis)
|
||||
{
|
||||
f32 chopoff = MinF32(flex, violation * (flex / flex_accum));
|
||||
new_size = size - chopoff;
|
||||
new_size = new_size - chopoff;
|
||||
}
|
||||
else
|
||||
else if (new_size > box_size)
|
||||
{
|
||||
if (size > box_size)
|
||||
new_size = MaxF32(new_size - flex, box_size);
|
||||
}
|
||||
}
|
||||
// Solve floating violation
|
||||
if (is_floating && new_size > box_size && !AnyBit(child->desc.flags, UI_BoxFlag_NoFloatingClamp))
|
||||
{
|
||||
new_size = MaxF32(size - flex, box_size);
|
||||
new_size = MaxF32(new_size - flex, box_size);
|
||||
}
|
||||
if (!is_floating)
|
||||
{
|
||||
size_accum += new_size;
|
||||
}
|
||||
adjusted_size_accum += new_size;
|
||||
child->solved_dims.v[axis] = new_size;
|
||||
}
|
||||
}
|
||||
size_accum = adjusted_size_accum;
|
||||
}
|
||||
box->final_children_size_accum[axis] = size_accum;
|
||||
}
|
||||
// Solve floating violations
|
||||
for (UI_Box *child = box->first; child; child = child->next)
|
||||
{
|
||||
if (AnyBit(child->desc.flags, UI_BoxFlag_Floating) && !AnyBit(child->desc.flags, UI_BoxFlag_NoFloatingClamp))
|
||||
{
|
||||
f32 size = child->solved_dims.v[axis];
|
||||
if (size > box_size)
|
||||
{
|
||||
f32 strictness = child->desc.pref_semantic_dims[axis].strictness;
|
||||
f32 flex = size * (1.0 - strictness);
|
||||
child->solved_dims.v[axis] = MaxF32(size - flex, box_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply scale
|
||||
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
|
||||
{
|
||||
UI_Box *box = boxes_pre[pre_index];
|
||||
UI_Box *parent = box->parent;
|
||||
|
||||
box->solved_scale = box->desc.scale;
|
||||
if (parent)
|
||||
{
|
||||
box->solved_scale *= parent->solved_scale;
|
||||
}
|
||||
|
||||
for (Axis axis = 0; axis < Axis_COUNTXY; ++axis)
|
||||
{
|
||||
UI_Size sem_dims = box->desc.pref_semantic_dims[axis];
|
||||
f32 unscaled_size = box->solved_dims.v[axis];
|
||||
f32 scaled_size = unscaled_size * box->solved_scale;
|
||||
// if (AbsF32(1.0 - box->solved_scale) < 0.001)
|
||||
// {
|
||||
// scaled_size = unscaled_size;
|
||||
// }
|
||||
if (unscaled_size >= 1)
|
||||
{
|
||||
scaled_size = MaxF32(scaled_size, 1);
|
||||
}
|
||||
box->solved_dims.v[axis] = scaled_size;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute final positions
|
||||
// Solve final positions
|
||||
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
|
||||
{
|
||||
UI_Box *box = boxes_pre[pre_index];
|
||||
@ -1348,6 +1329,22 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
alignment_in_parent = UI_PairFromRegion(UI_Region_TopLeft);
|
||||
}
|
||||
|
||||
// Apply scale
|
||||
for (Axis axis = 0; axis < Axis_COUNTXY; ++axis)
|
||||
{
|
||||
f32 unscaled_size = box->solved_dims.v[axis];
|
||||
f32 scaled_size = 0;
|
||||
if (box->solved_scale == 1)
|
||||
{
|
||||
scaled_size = CeilF32(unscaled_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
scaled_size = unscaled_size * box->solved_scale;
|
||||
}
|
||||
box->solved_dims.v[axis] = scaled_size;
|
||||
}
|
||||
|
||||
// Initialize layout cursor based on alignment
|
||||
{
|
||||
Axis axis = box->desc.child_layout_axis;
|
||||
@ -1366,13 +1363,16 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
box->cursor = box_size - size_accum;
|
||||
} break;
|
||||
}
|
||||
// box->cursor = FloorF32(box->cursor);
|
||||
}
|
||||
|
||||
// Position
|
||||
{
|
||||
Vec2 final_pos = Zi;
|
||||
Vec2 screen_pos = Zi;
|
||||
Vec2 offset = Zi;
|
||||
Vec2 anchor_offset = Zi;
|
||||
// Vec2 screen_dims = CeilVec2(box->solved_dims);
|
||||
Vec2 screen_dims = box->solved_dims;
|
||||
|
||||
// Floating box position
|
||||
if (AnyBit(box->desc.flags, UI_BoxFlag_Floating))
|
||||
@ -1387,28 +1387,31 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
default: break;
|
||||
case UI_AxisRegion_Center:
|
||||
{
|
||||
anchor_offset.v[axis] = box->solved_dims.v[axis] * 0.5;
|
||||
anchor_offset.v[axis] = screen_dims.v[axis] * 0.5;
|
||||
} break;
|
||||
case UI_AxisRegion_End:
|
||||
{
|
||||
anchor_offset.v[axis] = box->solved_dims.v[axis];
|
||||
anchor_offset.v[axis] = screen_dims.v[axis];
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
offset = SubVec2(box->desc.floating_pos, anchor_offset);
|
||||
offset = FloorVec2(offset);
|
||||
if (box->solved_scale == 1)
|
||||
{
|
||||
offset = RoundVec2(offset);
|
||||
}
|
||||
|
||||
final_pos = AddVec2(parent->screen_rect.p0, offset);
|
||||
screen_pos = AddVec2(parent->screen_rect.p0, offset);
|
||||
if (!AnyBit(box->desc.flags, UI_BoxFlag_NoFloatingClamp))
|
||||
{
|
||||
{
|
||||
f32 overshoot = MaxF32(0, (final_pos.x + box->solved_dims.x) - parent->screen_rect.p1.x);
|
||||
final_pos.x = MaxF32(parent->screen_rect.p0.x, final_pos.x - overshoot);
|
||||
f32 overshoot = MaxF32(0, (screen_pos.x + screen_dims.x) - parent->screen_rect.p1.x);
|
||||
screen_pos.x = MaxF32(parent->screen_rect.p0.x, screen_pos.x - overshoot);
|
||||
}
|
||||
{
|
||||
f32 overshoot = MaxF32((final_pos.y + box->solved_dims.y) - parent->screen_rect.p1.y, 0);
|
||||
final_pos.y = MaxF32(parent->screen_rect.p0.y, final_pos.y - overshoot);
|
||||
f32 overshoot = MaxF32((screen_pos.y + screen_dims.y) - parent->screen_rect.p1.y, 0);
|
||||
screen_pos.y = MaxF32(parent->screen_rect.p0.y, screen_pos.y - overshoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1431,28 +1434,27 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
case UI_AxisRegion_Center:
|
||||
{
|
||||
f32 parent_size = parent->solved_dims.v[axis];
|
||||
f32 box_size = box->solved_dims.v[axis];
|
||||
f32 box_size = screen_dims.v[axis];
|
||||
offset.v[axis] = parent_size / 2 - box_size / 2;
|
||||
} break;
|
||||
case UI_AxisRegion_End:
|
||||
{
|
||||
f32 parent_size = parent->solved_dims.v[axis];
|
||||
f32 box_size = box->solved_dims.v[axis];
|
||||
f32 box_size = screen_dims.v[axis];
|
||||
offset.v[axis] = parent_size - box_size;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
offset = RoundVec2(offset);
|
||||
final_pos.x = parent->screen_rect.p0.x + offset.x;
|
||||
final_pos.y = parent->screen_rect.p0.y + offset.y;
|
||||
parent->cursor += box->solved_dims.v[parent->desc.child_layout_axis];
|
||||
// offset = RoundVec2(offset);
|
||||
// offset = FloorVec2(offset);
|
||||
screen_pos.x = parent->screen_rect.p0.x + offset.x;
|
||||
screen_pos.y = parent->screen_rect.p0.y + offset.y;
|
||||
parent->cursor += screen_dims.v[parent->desc.child_layout_axis];
|
||||
}
|
||||
|
||||
// Submit position
|
||||
Vec2 rounded_final_pos = final_pos;
|
||||
box->screen_rect.p0 = rounded_final_pos;
|
||||
box->screen_rect.p1 = AddVec2(rounded_final_pos, box->solved_dims);
|
||||
|
||||
box->screen_rect.p0 = screen_pos;
|
||||
box->screen_rect.p1 = AddVec2(box->screen_rect.p0, screen_dims);
|
||||
box->screen_anchor = AddVec2(box->screen_rect.p0, anchor_offset);
|
||||
}
|
||||
|
||||
@ -1522,9 +1524,9 @@ void UI_EndFrame(UI_Frame *frame)
|
||||
UI_RegionPair child_alignment = UI_PairFromRegion(box->desc.child_alignment);
|
||||
|
||||
b32 is_visible = 1;
|
||||
is_visible = is_visible && (box->desc.tint.w >= 0.001);
|
||||
is_visible = is_visible && (box->screen_rect.p1.x - box->screen_rect.p0.x >= 1);
|
||||
is_visible = is_visible && (box->screen_rect.p1.y - box->screen_rect.p0.y >= 1);
|
||||
is_visible = is_visible && (box->desc.tint.w >= 0.005);
|
||||
is_visible = is_visible && (box->screen_rect.p1.x - box->screen_rect.p0.x > 0.001);
|
||||
is_visible = is_visible && (box->screen_rect.p1.y - box->screen_rect.p0.y > 0.001);
|
||||
if (is_visible || AnyBit(frame->frame_flags, UI_FrameFlag_Debug))
|
||||
{
|
||||
Vec4 debug_lin = is_visible ? LinearFromSrgb(box->desc.debug_color) : LinearFromSrgb(box->desc.invisible_debug_color);
|
||||
|
||||
@ -307,10 +307,10 @@ Struct(UI_Box)
|
||||
u64 post_index;
|
||||
|
||||
//- Layout data
|
||||
f32 cursor;
|
||||
f32 final_children_size_accum[Axis_COUNTXY];
|
||||
f32 solved_scale;
|
||||
f32 final_children_size_accum[Axis_COUNTXY];
|
||||
Vec2 solved_dims;
|
||||
f32 cursor;
|
||||
|
||||
//- Layout results
|
||||
Rng2 screen_rect;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user