diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 3fdce14e..0e8865f3 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -94,6 +94,8 @@ V_WidgetTheme V_GetWidgetTheme(void) // theme.font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/seguisb.ttf"))); // theme.font_size = 30; + // theme.font_size = TweakI32("Font size", 14, RNGI32(5, 100)); + theme.window_background_color = Rgb32(0xff1a1d1e); theme.window_border_color = Rgb32(0xff343a3b); theme.window_border = 1; @@ -1093,11 +1095,15 @@ void V_TickForever(WaveLaneCtx *lane) bg_color.w *= 0.5; Vec4 border_color = LerpSrgb(VEC4(0, 0, 0, 0), theme.button_active_color, rep.exists); - UI_SetNext(Scale, rep.exists); + // UI_SetNext(Anchor, UI_Region_Center); + UI_SetNext(Anchor, UI_Region_TopRight); + + UI_SetNext(Scale, VEC2(rep.exists, 1)); UI_SetNext(BackgroundColor, bg_color); UI_SetNext(BorderColor, border_color); UI_SetNext(Border, 2); - UI_SetNext(Width, UI_PIX(30, 0)); + // UI_SetNext(Width, UI_PIX(30, 0)); + UI_SetNext(Width, UI_PIX(100, 0)); UI_SetNext(Height, UI_GROW(1, 0)); UI_SetNext(ChildAlignment, UI_Region_Center); // UI_SetNext(FontSize, theme.font_size * 1.5); @@ -1314,8 +1320,9 @@ void V_TickForever(WaveLaneCtx *lane) } window_border_color = LerpSrgb(window_border_color, Rgb32(0x0078a6), titlebar_rep.hot); + f32 scale = LerpF32(0.85, 1, palette->show); UI_Push(Tint, VEC4(1, 1, 1, palette->show)); - UI_SetNext(Scale, LerpF32(0.85, 1, palette->show)); + UI_SetNext(Scale, VEC2(scale, scale)); UI_Push(BackgroundColor, window_background_color); UI_Push(BorderColor, window_border_color); @@ -1325,7 +1332,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_Push(Height, UI_SHRINK(0, 0)); UI_Push(ChildLayoutAxis, Axis_Y); UI_Push(FloatingPos, palette->pos); - UI_SetNext(FloatingPosAnchor, UI_Region_Center); + UI_SetNext(Anchor, UI_Region_Center); UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_Interactable); UI_PushCP(UI_BuildBoxEx(palette->key)); { @@ -1510,10 +1517,14 @@ void V_TickForever(WaveLaneCtx *lane) // Tweak checkbox case TweakKind_Bool: { - Vec4 tweak_bg_color = LerpSrgb(theme.color_negative, theme.color_positive, new_tweak_value.x); - Vec4 tweak_border_color = Zi; - tweak_border_color = LerpSrgb(tweak_border_color, theme.button_hot_color, tweak_rep.hot); - tweak_border_color = LerpSrgb(tweak_border_color, theme.button_active_color, tweak_rep.active); + // Vec4 tweak_bg_color = LerpSrgb(theme.color_negative, theme.color_positive, new_tweak_value.x); + Vec4 tweak_bg_color = Zi; + tweak_bg_color = LerpSrgb(tweak_bg_color, theme.color_positive, new_tweak_value.x); + + Vec4 tweak_border_color = theme.window_border_color; + // tweak_border_color = LerpSrgb(tweak_border_color, theme.button_hot_color, tweak_rep.hot); + // tweak_border_color = LerpSrgb(tweak_border_color, theme.button_active_color, tweak_rep.active); + tweak_border_color = LerpSrgb(tweak_border_color, theme.button_active_color, tweak_rep.hot); if (tweak_rep.m1.downs) { @@ -1522,8 +1533,8 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(BackgroundColor, tweak_bg_color); UI_SetNext(BorderColor, tweak_border_color); - UI_SetNext(Rounding, UI_RGROW(0.5)); - UI_SetNext(Border, 2); + UI_SetNext(Rounding, UI_RGROW(0.8)); + UI_SetNext(Border, 1); UI_SetNext(Width, UI_FNT(1.25, 1)); UI_SetNext(Height, UI_FNT(1.25, 1)); UI_SetNext(Flags, UI_BoxFlag_Interactable); diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index c26201de..ec68ecce 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -344,7 +344,7 @@ void UI_PushDefaults(void) case UI_StyleKind_Parent: { desc.style.Parent = UI_RootKey; } break; case UI_StyleKind_Width: { desc.style.Width = UI_GROW(1, 0); } break; case UI_StyleKind_Height: { desc.style.Height = UI_GROW(1, 0); } - case UI_StyleKind_Scale: { desc.style.Scale = 1; } break; + case UI_StyleKind_Scale: { desc.style.Scale = VEC2(1, 1); } break; case UI_StyleKind_Font: { desc.style.Font = UI_GetDefaultFont(); } break; u8 prefetch[127] = Zi; @@ -520,7 +520,7 @@ UI_Key UI_BuildBoxEx(UI_Key semantic_key) n->cmd.box.font_size = UI_UseTop(FontSize); n->cmd.box.rounding = UI_UseTop(Rounding); n->cmd.box.text = UI_UseTop(Text); - n->cmd.box.floating_pos_anchor = UI_UseTop(FloatingPosAnchor); + n->cmd.box.anchor = UI_UseTop(Anchor); n->cmd.box.floating_pos = UI_UseTop(FloatingPos); } ++frame->cmds_count; @@ -812,11 +812,11 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) f32 target_active = box == active_box; f32 target_selected = report->is_selected; - f32 exists_blend_rate = (40 * frame->dt); + f32 exists_blend_rate = (30 * frame->dt); f32 hot_blend_rate = target_hot == 1 ? 1 : (15 * frame->dt); f32 active_blend_rate = target_active == 1 ? 1 : (15 * frame->dt); f32 hovered_blend_rate = target_hovered == 1 ? 1 : (15 * frame->dt); - f32 selected_blend_rate = (40 * frame->dt); + f32 selected_blend_rate = (30 * frame->dt); report->exists = LerpF32(report->exists, target_exists, exists_blend_rate); report->hot = LerpF32(report->hot, target_hot, hot_blend_rate); @@ -876,16 +876,16 @@ Vec2 UI_CursorPos(void) //////////////////////////////////////////////////////////// //~ Text layout helpers -GC_Run UI_ScaleRun(Arena *arena, GC_Run unscaled_run, f32 scale) +GC_Run UI_ScaleRun(Arena *arena, GC_Run unscaled_run, Vec2 scale) { GC_Run result = Zi; result = unscaled_run; - result.font_size *= scale; - result.font_ascent *= scale; - result.font_descent *= scale; - result.font_cap *= scale; - result.baseline_length *= scale; + result.font_size *= scale.y; + result.font_ascent *= scale.y; + result.font_descent *= scale.y; + result.font_cap *= scale.y; + result.baseline_length *= scale.x; result.rects_count = unscaled_run.rects_count; result.rects = PushStructsNoZero(arena, GC_RunRect, result.rects_count); @@ -895,9 +895,9 @@ GC_Run UI_ScaleRun(Arena *arena, GC_Run unscaled_run, f32 scale) GC_RunRect *dst = &result.rects[rect_idx]; *dst = *src; - dst->bounds = MulRng2Vec2(dst->bounds, VEC2(scale, scale)); - dst->advance *= scale; - dst->baseline_pos *= scale; + dst->bounds = MulRng2Vec2(dst->bounds, scale); + dst->advance *= scale.x; + dst->baseline_pos *= scale.x; } return result; @@ -1110,19 +1110,25 @@ void UI_EndFrame(UI_Frame *frame) // Reset layout data box->cursor = 0; - ZeroStructs(box->final_children_size_accum, countof(box->final_children_size_accum)); + box->final_children_size_accum = VEC2(0, 0); box->solved_dims = VEC2(0, 0); - // Compute scale - UI_Box *parent = box->parent; - box->solved_scale = box->desc.scale; - if (parent) + // Solve scale { - box->solved_scale *= parent->solved_scale; - } - if (AbsF32(1.0 - box->solved_scale) < 0.001) - { - box->solved_scale = 1; + UI_Box *parent = box->parent; + box->solved_scale = box->desc.scale; + if (parent) + { + box->solved_scale = MulVec2Vec2(parent->solved_scale, box->solved_scale); + } + if (AbsF32(1.0 - box->solved_scale.x) < 0.001) + { + box->solved_scale.x = 1; + } + if (AbsF32(1.0 - box->solved_scale.y) < 0.001) + { + box->solved_scale.y = 1; + } } } else @@ -1306,7 +1312,7 @@ void UI_EndFrame(UI_Frame *frame) } child->solved_dims.v[axis] = new_size; } - box->final_children_size_accum[axis] = size_accum; + box->final_children_size_accum.v[axis] = size_accum; } } } @@ -1319,38 +1325,58 @@ void UI_EndFrame(UI_Frame *frame) UI_Box *parent = box->parent; UI_RegionPair child_alignment = UI_PairFromRegion(box->desc.child_alignment); - UI_RegionPair alignment_in_parent = Zi; - if (parent) - { - alignment_in_parent = UI_PairFromRegion(parent->desc.child_alignment); - } - else - { - alignment_in_parent = UI_PairFromRegion(UI_Region_TopLeft); - } + UI_RegionPair alignment_in_parent = UI_PairFromRegion(parent ? parent->desc.child_alignment : UI_Region_TopLeft); + + Axis child_layout_axis = box->desc.child_layout_axis; + Axis layout_axis_in_parent = parent ? parent->desc.child_layout_axis : Axis_X; + + b32 is_floating = AnyBit(box->desc.flags, UI_BoxFlag_Floating); + // 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) + if (box->solved_scale.v[axis] == 1) { - scaled_size = CeilF32(unscaled_size); + scaled_size = RoundF32(unscaled_size); } else { - scaled_size = unscaled_size * box->solved_scale; + scaled_size = unscaled_size * box->solved_scale.v[axis]; } box->solved_dims.v[axis] = scaled_size; } + // Compute anchor offset + Vec2 anchor_offset = Zi; + { + UI_RegionPair anchor_region = UI_PairFromRegion(box->desc.anchor); + for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) + { + UI_AxisRegion anchor = anchor_region.v[axis]; + switch (anchor) + { + default: break; + case UI_AxisRegion_Center: + { + anchor_offset.v[axis] = box->solved_dims.v[axis] * 0.5; + } break; + case UI_AxisRegion_End: + { + anchor_offset.v[axis] = box->solved_dims.v[axis]; + } break; + } + } + } + // Initialize layout cursor based on alignment { - Axis axis = box->desc.child_layout_axis; + Axis axis = child_layout_axis; UI_AxisRegion alignment = child_alignment.v[axis]; f32 box_size = box->solved_dims.v[axis]; - f32 size_accum = box->final_children_size_accum[axis]; + f32 size_accum = box->final_children_size_accum.v[axis]; switch(alignment) { default: break; @@ -1366,99 +1392,76 @@ void UI_EndFrame(UI_Frame *frame) // box->cursor = FloorF32(box->cursor); } - // Position + // Solve screen rect { - Vec2 screen_pos = Zi; + // Compute offset 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)) { - UI_RegionPair floating_anchor = UI_PairFromRegion(box->desc.floating_pos_anchor); - - for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) + // Floating box offset + if (is_floating) { - UI_AxisRegion anchor = floating_anchor.v[axis]; - switch (anchor) + offset = box->desc.floating_pos; + offset = SubVec2(offset, anchor_offset); + } + // Non-floating box offset + else if (parent) + { + // Compute offset in layout direction (based on parent cursor) + offset.v[layout_axis_in_parent] = parent->cursor; + // Compute offset in non-layout direction (based on alignment) { - default: break; - case UI_AxisRegion_Center: + Axis axis = !layout_axis_in_parent; + UI_AxisRegion alignment = alignment_in_parent.v[axis]; + switch(alignment) { - anchor_offset.v[axis] = screen_dims.v[axis] * 0.5; - } break; - case UI_AxisRegion_End: - { - anchor_offset.v[axis] = screen_dims.v[axis]; - } break; + default: break; + case UI_AxisRegion_Center: + { + f32 parent_size = parent->solved_dims.v[axis]; + f32 box_size = box->solved_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]; + offset.v[axis] = parent_size - box_size; + } break; + } } } - - offset = SubVec2(box->desc.floating_pos, anchor_offset); - if (box->solved_scale == 1) + if (box->solved_scale.x == 1) { - offset = RoundVec2(offset); + offset.x = RoundF32(offset.x); } - - screen_pos = AddVec2(parent->screen_rect.p0, offset); - if (!AnyBit(box->desc.flags, UI_BoxFlag_NoFloatingClamp)) + if (box->solved_scale.y == 1) { - { - 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((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); - } + offset.y = RoundF32(offset.y); } } - // Non-floating box position - else if (parent) - { - f32 layout_cursor = parent->cursor; - // Compute offset in layout direction - { - Axis axis = parent->desc.child_layout_axis; - offset.v[axis] = layout_cursor; - } - // Compute offset in non-layout direction (based on alignment) - { - Axis axis = !parent->desc.child_layout_axis; - UI_AxisRegion alignment = alignment_in_parent.v[axis]; - switch(alignment) - { - default: break; - case UI_AxisRegion_Center: - { - f32 parent_size = parent->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 = screen_dims.v[axis]; - offset.v[axis] = parent_size - box_size; - } break; - } - } - // 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 + // Compute rect + Vec2 screen_pos = parent ? AddVec2(parent->screen_rect.p0, offset) : VEC2(0, 0); + if (is_floating && !AnyBit(box->desc.flags, UI_BoxFlag_NoFloatingClamp)) + { + Vec2 overshoot = Zi; + overshoot.x = MaxF32(0, (screen_pos.x + box->solved_dims.x) - parent->screen_rect.p1.x); + overshoot.y = MaxF32((screen_pos.y + box->solved_dims.y) - parent->screen_rect.p1.y, 0); + screen_pos.x = MaxF32(parent->screen_rect.p0.x, screen_pos.x - overshoot.x); + screen_pos.y = MaxF32(parent->screen_rect.p0.y, screen_pos.y - overshoot.y); + } box->screen_rect.p0 = screen_pos; - box->screen_rect.p1 = AddVec2(box->screen_rect.p0, screen_dims); + box->screen_rect.p1 = AddVec2(box->screen_rect.p0, box->solved_dims); box->screen_anchor = AddVec2(box->screen_rect.p0, anchor_offset); + + // Update parent cursor + if (parent && !is_floating) + { + parent->cursor += box->solved_dims.v[layout_axis_in_parent]; + } } - // Rounding + // Solve screen rounding { UI_Round rounding = box->desc.rounding; Vec2 half_dims = MulVec2(SubVec2(box->screen_rect.p1, box->screen_rect.p0), 0.5); @@ -1499,7 +1502,6 @@ void UI_EndFrame(UI_Frame *frame) final_rounding_bl = MaxF32(final_rounding_bl, parent->rounding_bl - Vec2Len(vbl)); } - // Submit rounding box->rounding_tl = final_rounding_tl; box->rounding_tr = final_rounding_tr; box->rounding_br = final_rounding_br; diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 879a4458..2ca1ca70 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -107,14 +107,14 @@ Enum(UI_BoxFlag) X(ChildAlignment, UI_Region) \ X(Width, UI_Size) \ X(Height, UI_Size) \ - X(Scale, f32) \ + X(Scale, Vec2) \ X(BackgroundColor, Vec4) \ X(BorderColor, Vec4) \ X(DebugColor, Vec4) \ X(InvisibleDebugColor, Vec4) \ X(Tint, Vec4) \ X(Border, f32) \ - X(FloatingPosAnchor, UI_Region) \ + X(Anchor, UI_Region) \ X(FloatingPos, Vec2) \ X(Rounding, UI_Round) \ X(Font, GC_FontKey) \ @@ -241,14 +241,14 @@ Struct(UI_BoxDesc) Vec4 invisible_debug_color; Vec4 tint; f32 border; - f32 scale; - Vec2 floating_pos; + Vec2 scale; String text; GC_FontKey font; f32 font_size; Axis child_layout_axis; UI_Region child_alignment; - UI_Region floating_pos_anchor; + UI_Region anchor; + Vec2 floating_pos; }; Struct(UI_Cmd) @@ -307,8 +307,8 @@ Struct(UI_Box) u64 post_index; //- Layout data - f32 solved_scale; - f32 final_children_size_accum[Axis_COUNTXY]; + Vec2 solved_scale; + Vec2 final_children_size_accum; Vec2 solved_dims; f32 cursor; @@ -533,7 +533,7 @@ Vec2 UI_CursorPos(void); //////////////////////////////////////////////////////////// //~ Text layout helpers -GC_Run UI_ScaleRun(Arena *arena, GC_Run unscaled_run, f32 scale); +GC_Run UI_ScaleRun(Arena *arena, GC_Run unscaled_run, Vec2 scale); //////////////////////////////////////////////////////////// //~ End frame diff --git a/src/ui/ui_extras.c b/src/ui/ui_extras.c index bbd09327..d3fc7387 100644 --- a/src/ui/ui_extras.c +++ b/src/ui/ui_extras.c @@ -6,7 +6,7 @@ UI_Key UI_BuildLabel(String text) UI_Key parent = UI_UseTop(Parent); GC_FontKey font = UI_UseTop(Font); f32 font_size = UI_UseTop(FontSize); - f32 scale = UI_UseTop(Scale); + Vec2 scale = UI_UseTop(Scale); Vec4 tint = UI_UseTop(Tint); UI_Region alignment = UI_UseTop(ChildAlignment); @@ -52,7 +52,7 @@ UI_Key UI_BuildSpacer(UI_Size size, Axis axis) { UI_Key parent = UI_UseTop(Parent); UI_Key key = Zi; - f32 scale = UI_UseTop(Scale); + Vec2 scale = UI_UseTop(Scale); UI_PushCP(UI_NilKey); { UI_PushDefaults(); @@ -71,7 +71,7 @@ UI_Key UI_BuildDivider(UI_Size size, Vec4 color, Axis axis) { UI_Key key = Zi; UI_Key parent = UI_UseTop(Parent); - f32 scale = UI_UseTop(Scale); + Vec2 scale = UI_UseTop(Scale); Vec4 tint = UI_UseTop(Tint); UI_PushCP(UI_NilKey); {