fix: respect imperial units in wall panel (#321)
This commit is contained in:
@@ -14,6 +14,9 @@ import {
|
||||
import {
|
||||
ActionButton,
|
||||
ActionGroup,
|
||||
getLinearUnitLabel,
|
||||
linearControlValueToMeters,
|
||||
metersToLinearUnit,
|
||||
PanelSection,
|
||||
PanelWrapper,
|
||||
SliderControl,
|
||||
@@ -26,6 +29,7 @@ import { useCallback, useMemo, useRef } from 'react'
|
||||
|
||||
export default function WallPanel() {
|
||||
const selectedId = useViewer((s) => s.selection.selectedIds[0])
|
||||
const unit = useViewer((s) => s.unit)
|
||||
const setSelection = useViewer((s) => s.setSelection)
|
||||
const setCurvingWall = useEditor((s) => s.setCurvingWall)
|
||||
|
||||
@@ -117,14 +121,19 @@ export default function WallPanel() {
|
||||
|
||||
if (!(node && node.type === 'wall' && selectedId)) return null
|
||||
|
||||
const dx = node.end[0] - node.start[0]
|
||||
const dz = node.end[1] - node.start[1]
|
||||
const length = getWallCurveLength(node)
|
||||
|
||||
const height = node.height ?? 2.5
|
||||
const thickness = node.thickness ?? 0.1
|
||||
const curveOffset = getClampedWallCurveOffset(node)
|
||||
const maxCurveOffset = getMaxWallCurveOffset(node)
|
||||
const unitLabel = getLinearUnitLabel(unit)
|
||||
const displayLength = metersToLinearUnit(length, unit)
|
||||
const displayHeight = metersToLinearUnit(height, unit)
|
||||
const displayThickness = metersToLinearUnit(thickness, unit)
|
||||
const displayCurveOffset = metersToLinearUnit(curveOffset, unit)
|
||||
const displayMaxCurveOffset = metersToLinearUnit(maxCurveOffset, unit)
|
||||
const curveOffsetLimit = Math.max(0.01, maxCurveOffset)
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
@@ -136,44 +145,66 @@ export default function WallPanel() {
|
||||
<PanelSection title="Dimensions">
|
||||
<SliderControl
|
||||
label="Length"
|
||||
max={20}
|
||||
min={0.1}
|
||||
onChange={handleUpdateLength}
|
||||
max={metersToLinearUnit(20, unit)}
|
||||
min={metersToLinearUnit(0.1, unit)}
|
||||
onChange={(value) =>
|
||||
handleUpdateLength(
|
||||
linearControlValueToMeters(value, unit, { maxMeters: 20, minMeters: 0.1 }),
|
||||
)
|
||||
}
|
||||
precision={2}
|
||||
step={0.01}
|
||||
unit="m"
|
||||
value={length}
|
||||
step={unit === 'imperial' ? 0.1 : 0.01}
|
||||
unit={unitLabel}
|
||||
value={displayLength}
|
||||
/>
|
||||
<SliderControl
|
||||
label="Height"
|
||||
max={6}
|
||||
min={0.1}
|
||||
onChange={(v) => handleUpdate({ height: Math.max(0.1, v) })}
|
||||
max={metersToLinearUnit(6, unit)}
|
||||
min={metersToLinearUnit(0.1, unit)}
|
||||
onChange={(v) =>
|
||||
handleUpdate({
|
||||
height: linearControlValueToMeters(v, unit, { maxMeters: 6, minMeters: 0.1 }),
|
||||
})
|
||||
}
|
||||
precision={2}
|
||||
step={0.1}
|
||||
unit="m"
|
||||
value={Math.round(height * 100) / 100}
|
||||
unit={unitLabel}
|
||||
value={Math.round(displayHeight * 100) / 100}
|
||||
/>
|
||||
<SliderControl
|
||||
label="Thickness"
|
||||
max={1}
|
||||
min={0.05}
|
||||
onChange={(v) => handleUpdate({ thickness: Math.max(0.05, v) })}
|
||||
max={metersToLinearUnit(1, unit)}
|
||||
min={metersToLinearUnit(0.05, unit)}
|
||||
onChange={(v) =>
|
||||
handleUpdate({
|
||||
thickness: linearControlValueToMeters(v, unit, { maxMeters: 1, minMeters: 0.05 }),
|
||||
})
|
||||
}
|
||||
precision={3}
|
||||
step={0.01}
|
||||
unit="m"
|
||||
value={Math.round(thickness * 1000) / 1000}
|
||||
unit={unitLabel}
|
||||
value={Math.round(displayThickness * 1000) / 1000}
|
||||
/>
|
||||
{!hasWallChildrenBlockingCurve && (
|
||||
<SliderControl
|
||||
label="Curve"
|
||||
max={Math.max(0.01, maxCurveOffset)}
|
||||
min={-Math.max(0.01, maxCurveOffset)}
|
||||
onChange={(v) => handleUpdate({ curveOffset: normalizeWallCurveOffset(node, v) })}
|
||||
max={Math.max(metersToLinearUnit(0.01, unit), displayMaxCurveOffset)}
|
||||
min={-Math.max(metersToLinearUnit(0.01, unit), displayMaxCurveOffset)}
|
||||
onChange={(v) =>
|
||||
handleUpdate({
|
||||
curveOffset: normalizeWallCurveOffset(
|
||||
node,
|
||||
linearControlValueToMeters(v, unit, {
|
||||
maxMeters: curveOffsetLimit,
|
||||
minMeters: -curveOffsetLimit,
|
||||
}),
|
||||
),
|
||||
})
|
||||
}
|
||||
precision={2}
|
||||
step={0.1}
|
||||
unit="m"
|
||||
value={Math.round(curveOffset * 100) / 100}
|
||||
unit={unitLabel}
|
||||
value={Math.round(displayCurveOffset * 100) / 100}
|
||||
/>
|
||||
)}
|
||||
</PanelSection>
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
createWallOnCurrentLevel,
|
||||
EDITOR_LAYER,
|
||||
formatAngleRadians,
|
||||
formatLinearMeasurement,
|
||||
getAngleArcToSegmentReference,
|
||||
getAngleToSegmentReference,
|
||||
getSegmentAngleReferenceAtPoint,
|
||||
@@ -124,17 +125,6 @@ type AngleSource = {
|
||||
draftVector: WallPlanPoint
|
||||
}
|
||||
|
||||
function formatMeasurement(value: number, unit: 'metric' | 'imperial') {
|
||||
if (unit === 'imperial') {
|
||||
const feet = value * 3.280_84
|
||||
const wholeFeet = Math.floor(feet)
|
||||
const inches = Math.round((feet - wholeFeet) * 12)
|
||||
if (inches === 12) return `${wholeFeet + 1}'0"`
|
||||
return `${wholeFeet}'${inches}"`
|
||||
}
|
||||
return `${Number.parseFloat(value.toFixed(2))}m`
|
||||
}
|
||||
|
||||
function clamp(value: number, min: number, max: number) {
|
||||
return Math.min(max, Math.max(min, value))
|
||||
}
|
||||
@@ -426,7 +416,7 @@ function getDraftMeasurementState(
|
||||
const length = Math.hypot(dx, dz)
|
||||
if (length < 0.01) return null
|
||||
return {
|
||||
lengthLabel: formatMeasurement(length, unit),
|
||||
lengthLabel: formatLinearMeasurement(length, unit),
|
||||
lengthPosition: [
|
||||
(start[0] + end[0]) / 2,
|
||||
baseY + previewHeight + DRAFT_LABEL_Y_OFFSET,
|
||||
|
||||
Reference in New Issue
Block a user