float parsing fixes

This commit is contained in:
jacob 2026-01-01 23:56:54 -06:00
parent 818de65813
commit 003a77d410
5 changed files with 57 additions and 36 deletions

View File

@ -98,17 +98,18 @@ String StringFromSints(Arena *arena, u64 sints_count, i64 *sints, u64 base, u64
return result; return result;
} }
String StringFromFloat(Arena *arena, f64 f, u32 precision) String StringFromFloat(Arena *arena, f64 src, u32 precision)
{ {
String result = Zi; String result = Zi;
precision = MinU32(precision, 16);
if (IsNan(f)) if (IsNan(src))
{ {
result = PushString(arena, Lit("NaN")); result = PushString(arena, Lit("NaN"));
} }
else if (IsInf(f)) else if (IsInf(src))
{ {
if (f >= 0) if (src >= 0)
{ {
result = PushString(arena, Lit("inf")); result = PushString(arena, Lit("inf"));
} }
@ -121,21 +122,30 @@ String StringFromFloat(Arena *arena, f64 f, u32 precision)
{ {
result.text = ArenaNext(arena, u8); result.text = ArenaNext(arena, u8);
i32 sign = (f >= 0) - (f < 0); if (src < 0)
u64 part_whole = 0;
u64 part_frac = 0;
if (precision > 0)
{ {
part_whole = f * sign; DEBUGBREAKABLE;
part_frac = RoundF64(((f * sign) - part_whole) * PowU64(10, precision));
}
else
{
part_whole = RoundF64(f * sign);
} }
u64 p = PowU64(10, precision);
f64 multiplied = RoundF64(src * p);
// f64 multiplied_rounded = RoundF64(multiplied);
result.len += StringFromSint(arena, (i64)part_whole * sign, 10, 0).len; i32 sign = (src >= 0) - (src < 0);
u64 part_whole = TruncF64(AbsF64(multiplied) / p);
u64 part_frac = TruncF64(AbsF64(AbsF64(src) - part_whole) * p);
// Push sign
if (sign < 0 && (part_whole != 0 || part_frac != 0))
{
result.len += StringFromChar(arena, '-').len;
}
// Push whole part
result.len += StringFromUint(arena, part_whole, 10, 0).len;
// Push frac part
if (part_frac != 0) if (part_frac != 0)
{ {
result.len += StringFromChar(arena, '.').len; result.len += StringFromChar(arena, '.').len;

View File

@ -82,7 +82,7 @@ String StringFromChar(Arena *arena, char c);
String StringFromUint(Arena *arena, u64 n, u64 base, u64 zfill); String StringFromUint(Arena *arena, u64 n, u64 base, u64 zfill);
String StringFromUints(Arena *arena, u64 uints_count, u64 *uints, u64 base, u64 zfill); String StringFromUints(Arena *arena, u64 uints_count, u64 *uints, u64 base, u64 zfill);
String StringFromSint(Arena *arena, i64 n, u64 base, u64 zfill); String StringFromSint(Arena *arena, i64 n, u64 base, u64 zfill);
String StringFromFloat(Arena *arena, f64 f, u32 precision); String StringFromFloat(Arena *arena, f64 src, u32 precision);
String StringFromPtr(Arena *arena, void *ptr); String StringFromPtr(Arena *arena, void *ptr);
String StringFromhandle(Arena *arena, u64 v0, u64 v1); String StringFromhandle(Arena *arena, u64 v0, u64 v1);
String StringFromUid(Arena *arena, Uid uid); String StringFromUid(Arena *arena, Uid uid);

View File

@ -107,6 +107,6 @@ f64 TweakFloat_(String name, f64 initial, TweakFloatDesc desc);
.category = Lit("Debug"), \ .category = Lit("Debug"), \
.min = (_min), \ .min = (_min), \
.max = (_max), \ .max = (_max), \
.precision = 6, \ .precision = 2, \
__VA_ARGS__ \ __VA_ARGS__ \
}) })

View File

@ -83,7 +83,7 @@ V_WidgetTheme V_GetWidgetTheme(void)
theme.icon_font = UI_BuiltinIconFont(); theme.icon_font = UI_BuiltinIconFont();
// theme.font_size = 14; // theme.font_size = 14;
theme.font_size = TweakFloat("Font size", 16, 6, 50, .precision = 0); theme.font_size = TweakFloat("Font size", 14, 6, 50, .precision = 0);
theme.h1 = 2.00; theme.h1 = 2.00;
theme.h2 = 1.50; theme.h2 = 1.50;
theme.h3 = 1.25; theme.h3 = 1.25;
@ -1331,8 +1331,8 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Push(BorderColor, window_border_color); UI_Push(BorderColor, window_border_color);
UI_Push(BorderSize, theme.window_bd_sz); UI_Push(BorderSize, theme.window_bd_sz);
// UI_Push(Rounding, UI_RPIX(15 * theme.rounding)); // UI_Push(Rounding, UI_RPIX(15 * theme.rounding));
UI_Push(Rounding, UI_RGROW(0.1 * theme.rounding)); UI_Push(Rounding, UI_RGROW(0.075 * theme.rounding));
UI_Push(Width, UI_FNT(50, 0)); UI_Push(Width, UI_FNT(40, 0));
UI_Push(Height, UI_SHRINK(0, 0)); UI_Push(Height, UI_SHRINK(0, 0));
UI_Push(ChildLayoutAxis, Axis_Y); UI_Push(ChildLayoutAxis, Axis_Y);
UI_Push(FloatingPos, palette->pos); UI_Push(FloatingPos, palette->pos);
@ -1526,17 +1526,26 @@ void V_TickForever(WaveLaneCtx *lane)
b32 is_default = MatchString(new_tweak_str, tweak_var.initial); b32 is_default = MatchString(new_tweak_str, tweak_var.initial);
// Tweak label // Tweak label
UI_BuildSpacer(UI_PIX(spacing, 1), Axis_X);
if (is_default)
{ {
UI_SetNext(TextColor, theme.col.hint); UI_BuildSpacer(UI_PIX(spacing, 1), Axis_X);
UI_SetNext(FontSize, UI_Top(FontSize) * theme.h5); if (is_default)
{
UI_SetNext(TextColor, theme.col.hint);
UI_SetNext(FontSize, UI_Top(FontSize) * theme.h5);
}
else
{
UI_SetNext(TextColor, Color_White);
}
UI_SetNext(ChildAlignment, UI_Region_Left);
UI_SetNext(Width, UI_SHRINK(0, 1));
UI_SetNext(Height, UI_SHRINK(0, 1));
UI_SetNext(Text, new_tweak_str);
UI_SetNext(Flags, UI_BoxFlag_DrawText);
UI_SetNext(BackgroundColor, 0);
UI_SetNext(BorderColor, 0);
UI_BuildBox();
} }
else
{
UI_SetNext(TextColor, Color_White);
}
UI_BuildLabel(new_tweak_str);
// Reset button // Reset button
if (!is_default) if (!is_default)
@ -1641,7 +1650,7 @@ void V_TickForever(WaveLaneCtx *lane)
f64 tweak_float = FloatFromString(new_tweak_str); f64 tweak_float = FloatFromString(new_tweak_str);
{ {
if (is_active && (frame->ui_cursor.x != last_frame->ui_cursor.x)) if (is_active)
{ {
f64 initial_slider_pos = slider_reps.drag.screen_rect.p0.x; f64 initial_slider_pos = slider_reps.drag.screen_rect.p0.x;
f64 initial_marker_width = DimsFromRng2(marker_reps.drag.screen_rect).x; f64 initial_marker_width = DimsFromRng2(marker_reps.drag.screen_rect).x;
@ -1655,7 +1664,10 @@ void V_TickForever(WaveLaneCtx *lane)
tweak_float = LerpF64(range_min, range_max, virtual_cursor_ratio); tweak_float = LerpF64(range_min, range_max, virtual_cursor_ratio);
tweak_float = ClampF64(tweak_float, range_min, range_max); tweak_float = ClampF64(tweak_float, range_min, range_max);
new_tweak_str = StringFromFloat(frame->arena, tweak_float, tweak_var.precision); if (frame->ui_cursor.x != last_frame->ui_cursor.x)
{
new_tweak_str = StringFromFloat(frame->arena, tweak_float, tweak_var.precision);
}
} }
if (is_hot) if (is_hot)
{ {
@ -1881,8 +1893,8 @@ void V_TickForever(WaveLaneCtx *lane)
colors[LogLevel_Debug][0] = Rgb(0.4, 0.1, 0.4); colors[LogLevel_Debug][0] = Rgb(0.4, 0.1, 0.4);
colors[LogLevel_Debug][1] = Rgb(0.5, 0.2, 0.5); colors[LogLevel_Debug][1] = Rgb(0.5, 0.2, 0.5);
// Info colors // Info colors
colors[LogLevel_Info][0] = Rgb(0.4, 0.4, 0.4); colors[LogLevel_Info][0] = Rgb(0.2, 0.2, 0.2);
colors[LogLevel_Info][1] = Rgb(0.5, 0.5, 0.5); colors[LogLevel_Info][1] = Rgb(0.25, 0.25, 0.25);
// Success colors // Success colors
colors[LogLevel_Success][0] = Rgb(0.1, 0.3, 0.1); colors[LogLevel_Success][0] = Rgb(0.1, 0.3, 0.1);
colors[LogLevel_Success][1] = Rgb(0.2, 0.4, 0.2); colors[LogLevel_Success][1] = Rgb(0.2, 0.4, 0.2);

View File

@ -1129,7 +1129,7 @@ void UI_EndFrame(UI_Frame *frame)
box->solved_scale = MulVec2Vec2(parent->solved_scale, box->solved_scale); box->solved_scale = MulVec2Vec2(parent->solved_scale, box->solved_scale);
} }
f32 scale_snap = TweakFloat("UI scale snap", 0.0050, 0, 0.01); f32 scale_snap = TweakFloat("UI scale snap threshold", 0.0050, 0, 0.01, .precision = 6);
if (AbsF32(1.0 - box->solved_scale.x) < scale_snap) if (AbsF32(1.0 - box->solved_scale.x) < scale_snap)
{ {
box->solved_scale.x = 1; box->solved_scale.x = 1;
@ -1575,8 +1575,7 @@ void UI_EndFrame(UI_Frame *frame)
if (should_truncate) if (should_truncate)
{ {
// Get elipses run // Get elipses run
// GC_Run elipses_run_unscaled = GC_RunFromString(scratch.arena, Lit("..."), box->desc.font, box->desc.font_size); GC_Run elipses_run_unscaled = GC_RunFromString32(scratch.arena, String32FromString(scratch.arena, Lit("...")), box->desc.font, box->desc.font_size);
GC_Run elipses_run_unscaled = Zi;
GC_Run elipses_run = UI_ScaleRun(frame->arena, elipses_run_unscaled, box->solved_scale); GC_Run elipses_run = UI_ScaleRun(frame->arena, elipses_run_unscaled, box->solved_scale);
f32 truncation_offset = max_baseline_length - elipses_run.baseline_length; f32 truncation_offset = max_baseline_length - elipses_run.baseline_length;