diff --git a/src/glyph_cache/glyph_cache.c b/src/glyph_cache/glyph_cache.c index 6d5b2bf7..e0eb81a7 100644 --- a/src/glyph_cache/glyph_cache.c +++ b/src/glyph_cache/glyph_cache.c @@ -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); } diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 68b1d095..5d649bb7 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -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_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)); - + UI_Report vis_box_rep = UI_ReportFromKey(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)); + 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_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 + 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) diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 64b47c61..65413c5a 100644 --- a/src/ui/ui_core.c +++ b/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; - for (UI_Box *child = box->first; child; child = child->next) + f32 violation = 0; { - if (!AnyBit(child->desc.flags, UI_BoxFlag_Floating)) - { - 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; - flex_accum += flex; - } - else - { - size_accum = MaxF32(size_accum, size); - flex_accum = MaxF32(flex_accum, flex); - } - } - } - f32 violation = size_accum - box_size; - if (violation > 0 && flex_accum > 0) - { - f32 adjusted_size_accum = 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); - f32 new_size = size; if (axis == box->desc.child_layout_axis) { - f32 chopoff = MinF32(flex, violation * (flex / flex_accum)); - new_size = size - chopoff; + unconstrained_size_accum += size; + flex_accum += flex; } else { - if (size > box_size) - { - new_size = MaxF32(size - flex, box_size); - } + unconstrained_size_accum = MaxF32(unconstrained_size_accum, size); + flex_accum = MaxF32(flex_accum, flex); } - adjusted_size_accum += new_size; - child->solved_dims.v[axis] = new_size; } } - size_accum = adjusted_size_accum; + violation = unconstrained_size_accum - box_size; } - 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 size_accum = 0; + for (UI_Box *child = box->first; child; child = child->next) { + 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); - child->solved_dims.v[axis] = MaxF32(size - flex, box_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 = new_size - chopoff; + } + else if (new_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(new_size - flex, box_size); + } + if (!is_floating) + { + size_accum += new_size; + } + child->solved_dims.v[axis] = new_size; } + box->final_children_size_accum[axis] = size_accum; } } } } - // 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); diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 9d0caee7..879a4458 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -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;