diff --git a/packages/editor/src/components/ui/controls/metric-control.tsx b/packages/editor/src/components/ui/controls/metric-control.tsx index e48e398802..797ea8e835 100644 --- a/packages/editor/src/components/ui/controls/metric-control.tsx +++ b/packages/editor/src/components/ui/controls/metric-control.tsx @@ -2,11 +2,7 @@ import { useScene } from '@pascal-app/core' import { useCallback, useEffect, useRef, useState } from 'react' -import { - lingoUnitSpec, - measurementHint, - parseMeasurement, -} from '../../../lib/measurement-parser' +import { lingoUnitSpec, measurementHint, parseMeasurement } from '../../../lib/measurement-parser' import { useLinearDisplay } from '../../../lib/use-linear-display' import { cn } from '../../../lib/utils' @@ -31,8 +27,8 @@ export function MetricControl({ onCommit, min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY, - precision = 2, - step = 1, + precision: storedPrecision = 2, + step: storedStep = 1, className, unit = '', restoreOnCommit = true, @@ -40,9 +36,12 @@ export function MetricControl({ const { isImperial, displayUnit, + parseUnit, + precision, + step, toDisplay: toDisplayValue, toStored: toStoredValue, - } = useLinearDisplay(unit, precision) + } = useLinearDisplay(unit, storedPrecision, storedStep) const clamp = useCallback( (val: number) => { @@ -110,7 +109,14 @@ export function MetricControl({ container.addEventListener('wheel', handleWheel, { passive: false }) return () => container.removeEventListener('wheel', handleWheel) - }, [isEditing, step, clamp, applyCommittedValue, toStoredValue, roundStoredValueForDisplayPrecision]) + }, [ + isEditing, + step, + clamp, + applyCommittedValue, + toStoredValue, + roundStoredValueForDisplayPrecision, + ]) useEffect(() => { if (!isHovered || isEditing) return @@ -226,7 +232,7 @@ export function MetricControl({ const spec = lingoUnitSpec(unit) let stored = spec ? parseMeasurement(inputValue, spec, { - bareUnit: isImperial ? 'ft' : spec.unitId, + bareUnit: parseUnit ?? spec.unitId, system: isImperial ? 'us' : 'metric', }) : null @@ -244,6 +250,7 @@ export function MetricControl({ inputValue, unit, isImperial, + parseUnit, applyCommittedValue, clamp, toStoredValue, @@ -256,9 +263,9 @@ export function MetricControl({ const hint = isEditing && spec ? measurementHint(inputValue, spec, { - bareUnit: isImperial ? 'ft' : spec.unitId, + bareUnit: parseUnit ?? spec.unitId, system: isImperial ? 'us' : 'metric', - displayUnit: isImperial ? 'ft' : spec.unitId, + displayUnit: parseUnit ?? spec.unitId, precision, clamp, }) @@ -287,7 +294,16 @@ export function MetricControl({ setInputValue(toDisplayValue(newV).toFixed(precision)) } }, - [submitValue, value, toDisplayValue, precision, step, clamp, applyCommittedValue, toStoredValue], + [ + submitValue, + value, + toDisplayValue, + precision, + step, + clamp, + applyCommittedValue, + toStoredValue, + ], ) return ( diff --git a/packages/editor/src/components/ui/controls/slider-control.tsx b/packages/editor/src/components/ui/controls/slider-control.tsx index a3c5d06d70..e89b84f17f 100644 --- a/packages/editor/src/components/ui/controls/slider-control.tsx +++ b/packages/editor/src/components/ui/controls/slider-control.tsx @@ -2,11 +2,7 @@ import { useScene } from '@pascal-app/core' import { useCallback, useEffect, useRef, useState } from 'react' -import { - lingoUnitSpec, - measurementHint, - parseMeasurement, -} from '../../../lib/measurement-parser' +import { lingoUnitSpec, measurementHint, parseMeasurement } from '../../../lib/measurement-parser' import { useLinearDisplay } from '../../../lib/use-linear-display' import { cn } from '../../../lib/utils' @@ -60,19 +56,16 @@ export function SliderControl({ onCommit, min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY, - precision = 0, - step = 1, + precision: storedPrecision = 0, + step: storedStep = 1, className, unit = '', restoreOnCommit = true, mixed = false, }: SliderControlProps) { - // Display/storage conversion so the value honors the metric/imperial toggle. - // `value`, `onChange`, `onCommit`, `min`/`max`/`clamp` are always in the - // stored unit (meters for `unit === 'm'`); the step, drag deltas, text field - // and rendered number are in the DISPLAY unit (feet when imperial). For - // metric and non-length units these conversions are the identity. - const { isImperial, displayUnit, toDisplay, toStored } = useLinearDisplay(unit, precision) + // Values and bounds stay in meters; gestures and input use the displayed unit. + const { isImperial, displayUnit, parseUnit, precision, step, toDisplay, toStored } = + useLinearDisplay(unit, storedPrecision, storedStep) const [isEditing, setIsEditing] = useState(false) const [isDragging, setIsDragging] = useState(false) @@ -106,7 +99,9 @@ export function SliderControl({ (storedValue: number, displayDelta: number, displayStep: number) => clamp( toStored( - Number.parseFloat((toDisplay(storedValue) + displayDelta).toFixed(stepPrecision(displayStep))), + Number.parseFloat( + (toDisplay(storedValue) + displayDelta).toFixed(stepPrecision(displayStep)), + ), ), ), [clamp, toDisplay, toStored], @@ -231,7 +226,7 @@ export function SliderControl({ const spec = lingoUnitSpec(unit) let stored = spec ? parseMeasurement(inputValue, spec, { - bareUnit: isImperial ? 'ft' : spec.unitId, + bareUnit: parseUnit ?? spec.unitId, system: isImperial ? 'us' : 'metric', }) : null @@ -248,15 +243,27 @@ export function SliderControl({ onCommit?.(nextValue) } setIsEditing(false) - }, [inputValue, unit, isImperial, onChange, onCommit, clamp, precision, value, toDisplay, toStored]) + }, [ + inputValue, + unit, + isImperial, + parseUnit, + onChange, + onCommit, + clamp, + precision, + value, + toDisplay, + toStored, + ]) const spec = lingoUnitSpec(unit) const hint = isEditing && spec ? measurementHint(inputValue, spec, { - bareUnit: isImperial ? 'ft' : spec.unitId, + bareUnit: parseUnit ?? spec.unitId, system: isImperial ? 'us' : 'metric', - displayUnit: isImperial ? 'ft' : spec.unitId, + displayUnit: parseUnit ?? spec.unitId, precision, clamp, }) diff --git a/packages/editor/src/components/ui/floating-level-selector.tsx b/packages/editor/src/components/ui/floating-level-selector.tsx index 7e88c4af06..de3eaec260 100644 --- a/packages/editor/src/components/ui/floating-level-selector.tsx +++ b/packages/editor/src/components/ui/floating-level-selector.tsx @@ -145,11 +145,14 @@ function LevelRow({ const [duplicateDialogOpen, setDuplicateDialogOpen] = useState(false) const [isEditing, setIsEditing] = useState(false) const updateNode = useScene((s) => s.updateNode) - const { isImperial, toDisplay, displayUnit } = useLinearDisplay('m', 2) + const { isImperial, toDisplay, displayUnit, precision: displayPrecision } = useLinearDisplay('m', 2) const storeyHeight = getStoredLevelHeight(level) - // toFixed(2) + strip one trailing zero: "2.50" → "2.5", "2.75" stays. - const storeyHeightLabel = `${toDisplay(storeyHeight).toFixed(2).replace(/0$/, '')} ${displayUnit}` + // Decimal units keep the compact readout; integer millimeters must retain trailing zeroes. + const formattedStoreyHeight = toDisplay(storeyHeight).toFixed(displayPrecision) + const storeyHeightLabel = `${ + displayPrecision > 0 ? formattedStoreyHeight.replace(/0$/, '') : formattedStoreyHeight + } ${displayUnit}` // Same rule as the site panel and command palette: the ordinal-0 ground // floor is the vertical model's zero anchor and must never be deletable. const canDeleteLevel = level.level !== 0 @@ -244,7 +247,7 @@ function LevelRow({ precision={3} step={0.1} unit="m" - value={Math.round(storeyHeight * 1000) / 1000} + value={storeyHeight} />
{heightPresets.map((preset) => ( diff --git a/packages/editor/src/components/ui/panels/multi-parametric-inspector.tsx b/packages/editor/src/components/ui/panels/multi-parametric-inspector.tsx index 7246aab6f4..bab0b2ace8 100644 --- a/packages/editor/src/components/ui/panels/multi-parametric-inspector.tsx +++ b/packages/editor/src/components/ui/panels/multi-parametric-inspector.tsx @@ -254,7 +254,7 @@ function MultiVec3Field({ restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(axisValue * 100) / 100} + value={axisValue} /> ) })} diff --git a/packages/editor/src/components/ui/panels/parametric-field-control.tsx b/packages/editor/src/components/ui/panels/parametric-field-control.tsx index 4defaeeccf..4dc18ee7ee 100644 --- a/packages/editor/src/components/ui/panels/parametric-field-control.tsx +++ b/packages/editor/src/components/ui/panels/parametric-field-control.tsx @@ -159,7 +159,7 @@ export function ParametricFieldControl({ restoreOnCommit={!onCommit} step={0.05} unit="m" - value={Math.round(axisValue * 100) / 100} + value={axisValue} /> ) })} diff --git a/packages/editor/src/components/ui/panels/reference-panel.tsx b/packages/editor/src/components/ui/panels/reference-panel.tsx index 86da5ccd89..e18df87827 100644 --- a/packages/editor/src/components/ui/panels/reference-panel.tsx +++ b/packages/editor/src/components/ui/panels/reference-panel.tsx @@ -376,7 +376,7 @@ export function ReferencePanel() { precision={2} step={0.1} unit="m" - value={Math.round(node.position[0] * 100) / 100} + value={node.position[0]} /> diff --git a/packages/editor/src/components/ui/sidebar/panels/site-panel/index.tsx b/packages/editor/src/components/ui/sidebar/panels/site-panel/index.tsx index 7520477e95..d05658b63c 100644 --- a/packages/editor/src/components/ui/sidebar/panels/site-panel/index.tsx +++ b/packages/editor/src/components/ui/sidebar/panels/site-panel/index.tsx @@ -949,7 +949,7 @@ const LevelItem = memo(function LevelItem({ precision={2} step={0.05} unit="m" - value={Math.round((level.baseElevation ?? 0) * 100) / 100} + value={(level.baseElevation ?? 0)} />
{ + test('keeps meter storage while displaying and accepting millimeters', () => { + const display = getLinearDisplay('m', 'metric', 'millimeters', 2, 0.05) + expect(display.displayUnit).toBe('mm') + expect(display.parseUnit).toBe('mm') + expect(display.toDisplay(2.5)).toBe(2500) + expect(display.toStored(1800)).toBe(1.8) + expect(display.toStored(-250)).toBe(-0.25) + expect(display.precision).toBe(0) + expect(display.step).toBe(50) + expect(display.toStored(display.step)).toBe(0.05) + }) + + test('retains sub-millimeter precision when the field supports it', () => { + const display = getLinearDisplay('m', 'metric', 'millimeters', 4, 0.0001) + expect(display.precision).toBe(1) + expect(display.step).toBe(0.1) + expect(display.toDisplay(0.0125)).toBe(12.5) + expect(display.roundStored(0.01254)).toBe(0.0125) + }) + + test('imperial preference takes precedence over the saved metric notation', () => { + const display = getLinearDisplay('m', 'imperial', 'millimeters', 2, 0.05) + expect(display.displayUnit).toBe('ft') + expect(display.parseUnit).toBe('ft') + expect(display.toDisplay(0.9144)).toBeCloseTo(3, 10) + expect(display.toStored(7)).toBeCloseTo(2.1336, 10) + expect(display.precision).toBe(2) + expect(display.step).toBe(0.05) + }) + + test('switching notation round-trips the same stored dimensions', () => { + for (const stored of [0, 0.01, 0.125, 0.9, 2.1, -0.25]) { + for (const [unit, notation] of [ + ['metric', 'meters'], + ['metric', 'millimeters'], + ['imperial', 'meters'], + ] as const) { + const display = getLinearDisplay('m', unit, notation, 2, 0.01) + expect(display.toStored(display.toDisplay(stored))).toBeCloseTo(stored, 12) + } + } + }) + + test('leaves non-meter fields and their gesture steps unchanged', () => { + for (const unit of ['°', 'rad', '%', '', 'in', 'cm']) { + const display = getLinearDisplay(unit, 'metric', 'millimeters', 2, 0.05) + expect(display.displayUnit).toBe(unit) + expect(display.parseUnit).toBeUndefined() + expect(display.toDisplay(12.5)).toBe(12.5) + expect(display.toStored(12.5)).toBe(12.5) + expect(display.precision).toBe(2) + expect(display.step).toBe(0.05) + } + }) +}) diff --git a/packages/editor/src/lib/linear-display.ts b/packages/editor/src/lib/linear-display.ts new file mode 100644 index 0000000000..a2fd50e352 --- /dev/null +++ b/packages/editor/src/lib/linear-display.ts @@ -0,0 +1,39 @@ +import { + getLinearUnitLabel, + type LinearUnit, + linearUnitToMeters, + type MetricNotation, + metersToLinearUnit, +} from './measurements' + +export function getLinearDisplay( + unit: string, + viewerUnit: LinearUnit, + metricNotation: MetricNotation, + precision: number, + step: number, +) { + const isImperial = unit === 'm' && viewerUnit === 'imperial' + const isMillimeters = unit === 'm' && viewerUnit === 'metric' && metricNotation === 'millimeters' + const displayUnit = isImperial ? getLinearUnitLabel('imperial') : isMillimeters ? 'mm' : unit + const displayPrecision = isMillimeters ? Math.max(0, precision - 3) : precision + const displayStep = isMillimeters ? step * 1000 : step + const parseUnit = isImperial ? 'ft' : isMillimeters ? 'mm' : undefined + const toDisplay = (stored: number) => + isImperial ? metersToLinearUnit(stored, 'imperial') : isMillimeters ? stored * 1000 : stored + const toStored = (display: number) => + isImperial ? linearUnitToMeters(display, 'imperial') : isMillimeters ? display / 1000 : display + const roundStored = (stored: number) => + toStored(Number.parseFloat(toDisplay(stored).toFixed(displayPrecision))) + + return { + isImperial, + displayUnit, + parseUnit, + precision: displayPrecision, + step: displayStep, + toDisplay, + toStored, + roundStored, + } +} diff --git a/packages/editor/src/lib/use-linear-display.ts b/packages/editor/src/lib/use-linear-display.ts index 6578ea30a3..f7512903df 100644 --- a/packages/editor/src/lib/use-linear-display.ts +++ b/packages/editor/src/lib/use-linear-display.ts @@ -1,40 +1,16 @@ 'use client' import { useViewer } from '@pascal-app/viewer' -import { useCallback } from 'react' -import { getLinearUnitLabel, linearUnitToMeters, metersToLinearUnit } from './measurements' +import { useMemo } from 'react' +import { getLinearDisplay } from './linear-display' -/** - * Shared display/storage conversion for numeric property controls so that - * every length input honors the metric/imperial toggle identically. - * - * Values are always STORED in the field's own unit (meters for `unit === 'm'`). - * When the viewer preference is imperial AND the field is a meter length, the - * value is DISPLAYED (and edited) in feet; otherwise the conversions are the - * identity, so metric fields and non-length units (`'°'`, `'%'`, `'in'`, `''`, - * …) behave exactly as before. - * - * Used by both `SliderControl` and `MetricControl` — keep the two in sync via - * this single source of truth. - */ -export function useLinearDisplay(unit: string, precision: number) { +/** Shared display/input conversion; values and bounds stay in the stored unit. */ +export function useLinearDisplay(unit: string, precision: number, step = 1) { const viewerUnit = useViewer((state) => state.unit) - const isImperial = viewerUnit === 'imperial' && unit === 'm' - const displayUnit = isImperial ? getLinearUnitLabel('imperial') : unit + const metricNotation = useViewer((state) => state.metricNotation) - const toDisplay = useCallback( - (stored: number) => (isImperial ? metersToLinearUnit(stored, 'imperial') : stored), - [isImperial], + return useMemo( + () => getLinearDisplay(unit, viewerUnit, metricNotation, precision, step), + [unit, viewerUnit, metricNotation, precision, step], ) - const toStored = useCallback( - (display: number) => (isImperial ? linearUnitToMeters(display, 'imperial') : display), - [isImperial], - ) - // Round a stored value so it lands on a clean number of DISPLAY-unit digits. - const roundStored = useCallback( - (stored: number) => toStored(Number.parseFloat(toDisplay(stored).toFixed(precision))), - [toDisplay, toStored, precision], - ) - - return { isImperial, displayUnit, toDisplay, toStored, roundStored } } diff --git a/packages/nodes/src/box-vent/panel.tsx b/packages/nodes/src/box-vent/panel.tsx index 537496152f..bb6a757eda 100644 --- a/packages/nodes/src/box-vent/panel.tsx +++ b/packages/nodes/src/box-vent/panel.tsx @@ -193,7 +193,7 @@ export default function BoxVentPanel() { restoreOnCommit={false} step={0.01} unit="m" - value={Math.round(node.width * 100) / 100} + value={node.width} /> {/* Hood Overhang is `cap`-only — the dome shape rolls down to the body footprint without a flange skirt, and `box` doesn't @@ -234,7 +234,7 @@ export default function BoxVentPanel() { restoreOnCommit={false} step={0.005} unit="m" - value={Math.round((node.hoodOverhang ?? 0) * 1000) / 1000} + value={node.hoodOverhang ?? 0} /> )} {node.style === 'box' && ( @@ -249,7 +249,7 @@ export default function BoxVentPanel() { restoreOnCommit={false} step={0.005} unit="m" - value={Math.round((node.baseInset ?? 0.06) * 1000) / 1000} + value={node.baseInset ?? 0.06} /> )} @@ -292,7 +292,7 @@ export default function BoxVentPanel() { restoreOnCommit={false} step={0.005} unit="m" - value={Math.round((node.capHeight ?? 0.07) * 1000) / 1000} + value={node.capHeight ?? 0.07} /> )} @@ -369,7 +369,7 @@ export default function BoxVentPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round((node.position[0] ?? 0) * 100) / 100} + value={node.position[0] ?? 0} /> )} diff --git a/packages/nodes/src/chimney/panel.tsx b/packages/nodes/src/chimney/panel.tsx index d706dbd5e8..d97af04fe7 100644 --- a/packages/nodes/src/chimney/panel.tsx +++ b/packages/nodes/src/chimney/panel.tsx @@ -377,7 +377,7 @@ export default function ChimneyPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(node.width * 100) / 100} + value={node.width} /> {(node.bodyShape ?? 'square') !== 'round' && ( )} {(node.bodyShape ?? 'square') !== 'round' && ( )} @@ -444,7 +444,7 @@ export default function ChimneyPanel() { restoreOnCommit={false} step={0.1} unit="m" - value={Math.round(node.heightAboveRidge * 100) / 100} + value={node.heightAboveRidge} /> @@ -478,7 +478,7 @@ export default function ChimneyPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(worldX_now * 100) / 100} + value={worldX_now} /> )} @@ -620,7 +620,7 @@ export default function ChimneyPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round((node.shoulderHeight ?? 0.5) * 100) / 100} + value={node.shoulderHeight ?? 0.5} /> )} @@ -673,7 +673,7 @@ export default function ChimneyPanel() { restoreOnCommit={false} step={0.01} unit="m" - value={Math.round((node.flueDiameter ?? 0.22) * 100) / 100} + value={node.flueDiameter ?? 0.22} /> {(node.flueCount ?? 1) > 1 && ( )} @@ -741,7 +741,7 @@ export default function ChimneyPanel() { restoreOnCommit={false} step={0.01} unit="m" - value={Math.round((node.bandHeight ?? 0.1) * 100) / 100} + value={node.bandHeight ?? 0.1} /> )} @@ -804,7 +804,7 @@ export default function ChimneyPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round((node.cricketLength ?? 0.6) * 100) / 100} + value={node.cricketLength ?? 0.6} /> )} @@ -846,7 +846,7 @@ export default function ChimneyPanel() { restoreOnCommit={false} step={0.005} unit="m" - value={Math.round((node.panelDepth ?? 0.03) * 1000) / 1000} + value={node.panelDepth ?? 0.03} /> )} diff --git a/packages/nodes/src/cupola/panel.tsx b/packages/nodes/src/cupola/panel.tsx index 2d5913a341..bc2aead4db 100644 --- a/packages/nodes/src/cupola/panel.tsx +++ b/packages/nodes/src/cupola/panel.tsx @@ -173,7 +173,7 @@ export default function CupolaPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(node.width * 100) / 100} + value={node.width} /> @@ -216,7 +216,7 @@ export default function CupolaPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round((node.position[0] ?? 0) * 100) / 100} + value={node.position[0] ?? 0} /> {showFlipSide && (
@@ -726,7 +726,7 @@ export default function DoorPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(node.width * 100) / 100} + value={node.width} /> @@ -799,7 +799,7 @@ export default function DoorPanel() { precision={2} step={0.05} unit="m" - value={Math.round(cornerRadius * 100) / 100} + value={cornerRadius} /> ) : ( <> @@ -817,7 +817,7 @@ export default function DoorPanel() { precision={2} step={0.05} unit="m" - value={Math.round((openingTopRadii[index as number] ?? 0) * 100) / 100} + value={openingTopRadii[index as number] ?? 0} /> ))} @@ -831,7 +831,7 @@ export default function DoorPanel() { precision={3} step={0.005} unit="m" - value={Math.round(openingRevealRadius * 1000) / 1000} + value={openingRevealRadius} /> )} @@ -845,7 +845,7 @@ export default function DoorPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(archHeight * 100) / 100} + value={archHeight} /> )} @@ -896,7 +896,7 @@ export default function DoorPanel() { precision={2} step={0.05} unit="m" - value={Math.round(cornerRadius * 100) / 100} + value={cornerRadius} /> ) : ( <> @@ -914,7 +914,7 @@ export default function DoorPanel() { precision={2} step={0.05} unit="m" - value={Math.round((openingTopRadii[index as number] ?? 0) * 100) / 100} + value={openingTopRadii[index as number] ?? 0} /> ))} @@ -928,7 +928,7 @@ export default function DoorPanel() { precision={3} step={0.005} unit="m" - value={Math.round(openingRevealRadius * 1000) / 1000} + value={openingRevealRadius} /> )} @@ -942,7 +942,7 @@ export default function DoorPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(archHeight * 100) / 100} + value={archHeight} /> )} @@ -960,7 +960,7 @@ export default function DoorPanel() { precision={3} step={0.01} unit="m" - value={Math.round(node.frameThickness * 1000) / 1000} + value={node.frameThickness} /> )} @@ -985,7 +985,7 @@ export default function DoorPanel() { precision={3} step={0.005} unit="m" - value={Math.round(node.contentPadding[0] * 1000) / 1000} + value={node.contentPadding[0]} /> )} @@ -1052,7 +1052,7 @@ export default function DoorPanel() { precision={3} step={0.005} unit="m" - value={Math.round(node.thresholdHeight * 1000) / 1000} + value={node.thresholdHeight} />
)} @@ -1078,7 +1078,7 @@ export default function DoorPanel() { precision={2} step={0.05} unit="m" - value={Math.round(node.handleHeight * 100) / 100} + value={node.handleHeight} /> {supportsHandleSide && (
@@ -1122,7 +1122,7 @@ export default function DoorPanel() { precision={2} step={0.05} unit="m" - value={Math.round(node.panicBarHeight * 100) / 100} + value={node.panicBarHeight} />
)} @@ -1211,7 +1211,7 @@ export default function DoorPanel() { precision={3} step={0.005} unit="m" - value={Math.round(seg.dividerThickness * 1000) / 1000} + value={seg.dividerThickness} /> )} @@ -1231,7 +1231,7 @@ export default function DoorPanel() { precision={3} step={0.005} unit="m" - value={Math.round(seg.panelInset * 1000) / 1000} + value={seg.panelInset} /> )} diff --git a/packages/nodes/src/dormer/panel-position-section.tsx b/packages/nodes/src/dormer/panel-position-section.tsx index 545d55f15f..a2f95ee440 100644 --- a/packages/nodes/src/dormer/panel-position-section.tsx +++ b/packages/nodes/src/dormer/panel-position-section.tsx @@ -180,7 +180,7 @@ export function DormerPositionSection({ restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(worldX_now * 100) / 100} + value={worldX_now} /> diff --git a/packages/nodes/src/eyebrow-vent/panel.tsx b/packages/nodes/src/eyebrow-vent/panel.tsx index 5ced7043e8..7e4c600fab 100644 --- a/packages/nodes/src/eyebrow-vent/panel.tsx +++ b/packages/nodes/src/eyebrow-vent/panel.tsx @@ -192,7 +192,7 @@ export default function EyebrowVentPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(node.width * 100) / 100} + value={node.width} /> @@ -235,7 +235,7 @@ export default function EyebrowVentPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round((node.position[0] ?? 0) * 100) / 100} + value={node.position[0] ?? 0} /> ) } diff --git a/packages/nodes/src/item/panel.tsx b/packages/nodes/src/item/panel.tsx index 60f8d93f7b..cffbe56435 100644 --- a/packages/nodes/src/item/panel.tsx +++ b/packages/nodes/src/item/panel.tsx @@ -120,7 +120,7 @@ export default function ItemPanel() { precision={2} step={0.01} unit="m" - value={Math.round(node.position[0] * 100) / 100} + value={node.position[0]} /> diff --git a/packages/nodes/src/ridge-vent/panel.tsx b/packages/nodes/src/ridge-vent/panel.tsx index fb8e41b373..1a17150ed1 100644 --- a/packages/nodes/src/ridge-vent/panel.tsx +++ b/packages/nodes/src/ridge-vent/panel.tsx @@ -165,7 +165,7 @@ export default function RidgeVentPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(node.length * 100) / 100} + value={node.length} /> @@ -212,7 +212,7 @@ export default function RidgeVentPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round((node.position[0] ?? 0) * 100) / 100} + value={node.position[0] ?? 0} /> ) : ( <> @@ -409,7 +409,7 @@ export default function RoofSegmentPanel() { precision={2} step={0.5} unit="m" - value={Math.round(node.width * 100) / 100} + value={node.width} /> )} @@ -475,7 +475,7 @@ export default function RoofSegmentPanel() { precision={2} step={0.1} unit="m" - value={Math.round(node.wallHeight * 100) / 100} + value={node.wallHeight} /> @@ -595,11 +595,7 @@ export default function RoofSegmentPanel() { precision={2} step={0.01} unit="m" - value={ - Math.round( - (node.dutchTopRakeThickness ?? ROOF_SHAPE_DEFAULTS.dutchTopRakeThickness) * 100, - ) / 100 - } + value={node.dutchTopRakeThickness ?? ROOF_SHAPE_DEFAULTS.dutchTopRakeThickness} /> )} @@ -625,7 +619,7 @@ export default function RoofSegmentPanel() { precision={2} step={0.05} unit="m" - value={Math.round(node.wallThickness * 100) / 100} + value={node.wallThickness} /> @@ -670,7 +664,7 @@ export default function RoofSegmentPanel() { precision={2} step={0.05} unit="m" - value={Math.round(node.position[0] * 100) / 100} + value={node.position[0]} /> {(node.roofType !== 'conical' || !conicalCoverage.fullCircle) && ( <> diff --git a/packages/nodes/src/roof/panel.tsx b/packages/nodes/src/roof/panel.tsx index ac07a728d1..cfca19a34a 100644 --- a/packages/nodes/src/roof/panel.tsx +++ b/packages/nodes/src/roof/panel.tsx @@ -281,7 +281,7 @@ export default function RoofPanel() { precision={2} step={0.05} unit="m" - value={Math.round(node.position[0] * 100) / 100} + value={node.position[0]} /> {activeSkylightType === 'lantern' && ( <> @@ -311,7 +311,7 @@ export default function SkylightPanel() { restoreOnCommit={false} step={0.01} unit="m" - value={Math.round((node.lanternHeight ?? 0.25) * 1000) / 1000} + value={node.lanternHeight ?? 0.25} /> )} @@ -419,7 +419,7 @@ export default function SkylightPanel() { restoreOnCommit={false} step={0.005} unit="m" - value={Math.round((node.trackWidth ?? 0.045) * 1000) / 1000} + value={node.trackWidth ?? 0.045} /> )} @@ -436,7 +436,7 @@ export default function SkylightPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(node.width * 100) / 100} + value={node.width} /> @@ -463,7 +463,7 @@ export default function SkylightPanel() { restoreOnCommit={false} step={0.005} unit="m" - value={Math.round((node.frameThickness ?? 0.05) * 1000) / 1000} + value={node.frameThickness ?? 0.05} /> @@ -511,7 +511,7 @@ export default function SkylightPanel() { restoreOnCommit={false} step={0.005} unit="m" - value={Math.round((node.curbHeight ?? 0.1) * 1000) / 1000} + value={node.curbHeight ?? 0.1} /> )} @@ -531,7 +531,7 @@ export default function SkylightPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(worldX_now * 100) / 100} + value={worldX_now} /> {node.recessed ? ( @@ -312,7 +312,7 @@ export function SlabPanel() { precision={2} step={0.01} unit="m" - value={Math.round(getSlabRecessDepth(node) * 100) / 100} + value={getSlabRecessDepth(node)} /> ) : ( )} diff --git a/packages/nodes/src/solar-panel/panel.tsx b/packages/nodes/src/solar-panel/panel.tsx index aa7d7c913d..37aee8e087 100644 --- a/packages/nodes/src/solar-panel/panel.tsx +++ b/packages/nodes/src/solar-panel/panel.tsx @@ -255,7 +255,7 @@ export default function SolarPanelPanel() { restoreOnCommit={false} step={0.005} unit="m" - value={Math.round(num(node.gapX, 0.02) * 1000) / 1000} + value={num(node.gapX, 0.02)} /> @@ -286,7 +286,7 @@ export default function SolarPanelPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(num(node.panelWidth, 1) * 100) / 100} + value={num(node.panelWidth, 1)} /> @@ -313,7 +313,7 @@ export default function SolarPanelPanel() { restoreOnCommit={false} step={0.005} unit="m" - value={Math.round(num(node.frameThickness, 0.04) * 1000) / 1000} + value={num(node.frameThickness, 0.04)} /> @@ -362,7 +362,7 @@ export default function SolarPanelPanel() { restoreOnCommit={false} step={0.005} unit="m" - value={Math.round(num(node.standoffHeight, 0.05) * 1000) / 1000} + value={num(node.standoffHeight, 0.05)} /> diff --git a/packages/nodes/src/spawn/panel.tsx b/packages/nodes/src/spawn/panel.tsx index de8e49d093..bfdcba9e6d 100644 --- a/packages/nodes/src/spawn/panel.tsx +++ b/packages/nodes/src/spawn/panel.tsx @@ -111,7 +111,7 @@ export default function SpawnPanel() { precision={2} step={0.01} unit="m" - value={Math.round(node.position[0] * 100) / 100} + value={node.position[0]} /> diff --git a/packages/nodes/src/stair-segment/panel.tsx b/packages/nodes/src/stair-segment/panel.tsx index daad0fa4b2..5ff957ddc0 100644 --- a/packages/nodes/src/stair-segment/panel.tsx +++ b/packages/nodes/src/stair-segment/panel.tsx @@ -166,7 +166,7 @@ export default function StairSegmentPanel() { precision={2} step={0.1} unit="m" - value={Math.round(node.width * 100) / 100} + value={node.width} /> {node.segmentType === 'stair' && ( <> @@ -188,7 +188,7 @@ export default function StairSegmentPanel() { precision={2} step={0.1} unit="m" - value={Math.round(node.height * 100) / 100} + value={node.height} /> )} @@ -237,7 +237,7 @@ export default function StairSegmentPanel() { precision={2} step={0.05} unit="m" - value={Math.round(node.position[0] * 100) / 100} + value={node.position[0]} /> ) : null} @@ -411,7 +411,7 @@ export default function StairPanel() { precision={2} step={0.05} unit="m" - value={Math.round((node.topLandingDepth ?? 0.9) * 100) / 100} + value={node.topLandingDepth ?? 0.9} /> )} @@ -459,7 +459,7 @@ export default function StairPanel() { precision={2} step={0.05} unit="m" - value={Math.round((node.width ?? 1) * 100) / 100} + value={node.width ?? 1} /> )} )} diff --git a/packages/nodes/src/turbine-vent/panel.tsx b/packages/nodes/src/turbine-vent/panel.tsx index fc23df3142..50418742d4 100644 --- a/packages/nodes/src/turbine-vent/panel.tsx +++ b/packages/nodes/src/turbine-vent/panel.tsx @@ -189,7 +189,7 @@ export default function TurbineVentPanel() { restoreOnCommit={false} step={0.01} unit="m" - value={Math.round(node.diameter * 100) / 100} + value={node.diameter} /> {showFlipSide && (
@@ -570,7 +570,7 @@ export default function WindowPanel() { restoreOnCommit={false} step={0.1} unit="m" - value={Math.round(node.width * 100) / 100} + value={node.width} /> @@ -631,7 +631,7 @@ export default function WindowPanel() { precision={2} step={0.05} unit="m" - value={Math.round(cornerRadius * 100) / 100} + value={cornerRadius} /> ) : ( <> @@ -651,7 +651,7 @@ export default function WindowPanel() { precision={2} step={0.05} unit="m" - value={Math.round((openingCornerRadii[index as number] ?? 0) * 100) / 100} + value={openingCornerRadii[index as number] ?? 0} /> ))} @@ -665,7 +665,7 @@ export default function WindowPanel() { precision={3} step={0.005} unit="m" - value={Math.round(openingRevealRadius * 1000) / 1000} + value={openingRevealRadius} />
)} @@ -680,7 +680,7 @@ export default function WindowPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(archHeight * 100) / 100} + value={archHeight} /> )} @@ -722,7 +722,7 @@ export default function WindowPanel() { precision={2} step={0.05} unit="m" - value={Math.round(cornerRadius * 100) / 100} + value={cornerRadius} /> ) : ( <> @@ -742,7 +742,7 @@ export default function WindowPanel() { precision={2} step={0.05} unit="m" - value={Math.round((openingCornerRadii[index as number] ?? 0) * 100) / 100} + value={openingCornerRadii[index as number] ?? 0} /> ))} @@ -756,7 +756,7 @@ export default function WindowPanel() { precision={3} step={0.005} unit="m" - value={Math.round(openingRevealRadius * 1000) / 1000} + value={openingRevealRadius} /> )} @@ -771,7 +771,7 @@ export default function WindowPanel() { restoreOnCommit={false} step={0.05} unit="m" - value={Math.round(archHeight * 100) / 100} + value={archHeight} /> )} @@ -789,7 +789,7 @@ export default function WindowPanel() { precision={3} step={0.01} unit="m" - value={Math.round(node.frameThickness * 1000) / 1000} + value={node.frameThickness} /> )} @@ -857,7 +857,7 @@ export default function WindowPanel() { precision={3} step={0.01} unit="m" - value={Math.round((node.columnDividerThickness ?? 0.03) * 1000) / 1000} + value={node.columnDividerThickness ?? 0.03} /> @@ -890,7 +890,7 @@ export default function WindowPanel() { precision={3} step={0.01} unit="m" - value={Math.round((node.rowDividerThickness ?? 0.03) * 1000) / 1000} + value={node.rowDividerThickness ?? 0.03} /> @@ -914,7 +914,7 @@ export default function WindowPanel() { precision={3} step={0.01} unit="m" - value={Math.round(node.sillDepth * 1000) / 1000} + value={node.sillDepth} /> )}