Round number fields to the precision they display
`decimals` only reached `formatNumber`, so it changed the label and nothing else: typing 640.5 into a field with `decimals: 0` stored 640.5 and displayed 641. The two existing users got away with it because rounding happened outside the widget (`normalizeFrameRect`, the slice dialog), which their comments had to point out. `NumberField.clampValue` now rounds before it clamps, and every path that sets a value goes through it (typing, scrubbing, arrow keys, the constructor), so the stored number matches the shown one and `min`/`max` stay exact. The rounding is `roundTo` in math.ts, which `snapToStep` already did inline. With that safe, camera `View width`/`View height` and text `Font size` become integers – they were showing 640.000 and 32.000. Everything else that looked integral is not: positions, sprite and collider sizes and zoom are all scrubbed, and `z` is a summed coordinate (walk.ts), not a layer. Verified remotely against the RTX 4070 host: 270 checks, all passed (step 10 gained a check that the field text has no decimal point and survives a reopen). `npm run check` green, 407 tests.
This commit is contained in:
1 parent
6cf47fd2ae
commit
1b16a55ffc
8 files changed
+80
-19
No files matched your search
+28
-1
@@ -1,5 +1,13 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { clamp, centreY, formatNumber, NUMBER_DECIMALS, snapToStep, zoomFactor } from '../../src/ui/math';
|
||||
import {
|
||||
clamp,
|
||||
centreY,
|
||||
formatNumber,
|
||||
NUMBER_DECIMALS,
|
||||
roundTo,
|
||||
snapToStep,
|
||||
zoomFactor,
|
||||
} from '../../src/ui/math';
|
||||
|
||||
describe('clamp', () => {
|
||||
it('keeps a value inside the range', () => {
|
||||
@@ -60,6 +68,25 @@ describe('formatNumber', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('roundTo', () => {
|
||||
it('keeps a value at the precision its field shows', () => {
|
||||
// Why the field rounds instead of only formatting: a `decimals: 0` field used to display
|
||||
// "641" while the project still held 640.5.
|
||||
expect(roundTo(640.5, 0)).toBe(641);
|
||||
expect(roundTo(32.4, 0)).toBe(32);
|
||||
expect(roundTo(1.2345)).toBe(1.234);
|
||||
});
|
||||
|
||||
it('removes binary-float noise', () => {
|
||||
expect(roundTo(0.30000000000000004)).toBe(0.3);
|
||||
});
|
||||
|
||||
it('passes non-finite values through', () => {
|
||||
expect(roundTo(NaN)).toBeNaN();
|
||||
expect(roundTo(Infinity)).toBe(Infinity);
|
||||
});
|
||||
});
|
||||
|
||||
describe('snapToStep', () => {
|
||||
it('lands on whole numbers for a step-1 field', () => {
|
||||
// The bug: a scrub added fractional device pixels to an already fractional value, so
|
||||
|
||||
Reference in new issue
Block a user