Repository navigation
Label snap step units and keep typed Rotate steps - #1109
Devin T. Currie (DTCurrie) wants to merge 3 commits into
Conversation
🦋 Changeset detectedLatest commit: 597df51 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
|
Claude (@claude) review |
|
Claude finished Devin T. Currie (@DTCurrie)'s task in 2m 16s —— View job ReviewClean, well-scoped PR. The extraction into
Tests — good coverage. The five cases pin: pass-through in metres, radian conversion (literal Comments — both the HTML comment in
Summary: Two nits (inline), both optional. Ready to merge as-is. |
| settings.snapping && value > 0 ? toSceneUnits(value) : null | ||
|
|
||
| return { | ||
| translation: step(settings.snapTranslate, (metres) => metres), |
There was a problem hiding this comment.
Nit: The identity closures (metres) => metres and (factor) => factor are readable as documentation of intent, but toSceneUnits implies conversion is happening — which isn't true for these two. You could drop the callback for the pass-through axes and name the helper snap instead:
| translation: step(settings.snapTranslate, (metres) => metres), | |
| translation: settings.snapping && settings.snapTranslate > 0 ? settings.snapTranslate : null, |
Or, keeping the helper but removing the identity wrapping:
const snap = (value: number) => settings.snapping && value > 0 ? value : null
return {
translation: snap(settings.snapTranslate),
rotation: snap(settings.snapRotate) !== null ? MathUtils.degToRad(settings.snapRotate) : null,
scale: snap(settings.snapScale),
}Current code is correct and readable — just noting the slight tension between the callback name and what it does for translation/scale.
| }) | ||
|
|
||
| const snapping = $derived(settings.current.snapping) | ||
| const snaps = $derived(transformSnaps(settings.current)) |
There was a problem hiding this comment.
Nit: snaps.scale is computed here but MoveGizmo only binds translationSnap and rotationSnap — there's no scale handle on this gizmo. Negligible since transformSnaps is pure and cheap, but if you wanted to keep the abstraction tight you could destructure only what's used:
| const snaps = $derived(transformSnaps(settings.current)) | |
| const { translation, rotation } = $derived(transformSnaps(settings.current)) |
Then bind translationSnap={translation} and rotationSnap={rotation} below.
Claude (@claude) resolve these |
|
Claude finished Devin T. Currie (@DTCurrie)'s task in 3s —— View job Resolved
const snap = (value: number, convert: (v: number) => number = (v) => v) =>
settings.snapping && value > 0 ? convert(value) : null
return {
translation: snap(settings.snapTranslate),
rotation: snap(settings.snapRotate, MathUtils.degToRad),
scale: snap(settings.snapScale),
}
|
- transformSnaps: rename `step`/`toSceneUnits` to `snap`/`convert`
with an identity default, so only rotation passes a converter.
- MoveGizmo: destructure `{ translation, rotation }` from transformSnaps
result instead of binding the full object and dropping scale unused.
Co-authored-by: Devin T. Currie <DTCurrie@users.noreply.github.com>
Labels the snap step fields with their units and keeps a typed Rotate step instead of reverting it. Before this, Move showed a bare number with no unit, and a step typed into Rotate snapped back to its old value.
Hooks
transformSnaps(settings)is new. It turns the snap settings into the steps a Three.js gizmo takes: the Move step passes through in metres, the Rotate step converts from degrees to radians, and an axis with snapping off or a step of 0 getsnull.Settings.snapTranslatedocuments that it is in metres.Plugins
TransformDashboardlabels the snap fieldsMove (m)andRotate (°), and drops the Rotateformatcallback.MoveGizmoreads its translation and rotation steps fromtransformSnaps.Components
SelectedTransformControlsreads all three steps fromtransformSnaps.Why?
Why is Move in metres when every pose field is in mm?
Millimetres are the unit Viam's APIs speak, and pose fields show them because they round-trip through those APIs. The snap step never reaches a Viam API. Keeping it in metres leaves every saved step unchanged, and the label says which unit it is.
Why move the units into the labels?
Tweakpane parses typed text as a bare number. The Rotate
formatcallback appended°to the value, so an edit to that text no longer parsed and reverted. A label carries the unit without touching the value.Why not stack this on #1108?
The two PRs edit separate hunks of
SelectedTransformControls.svelte, but both change itsthreeimport. #1108 dropsGroupand this PR dropsMathUtils. Whichever merges second resolves that one line toimport { Matrix4 } from 'three'.Testing
Added
transformSnaps.spec.tsfor the pass-through and degree conversions and the off and zero cases. Scaling the Move step by0.001insidetransformSnapsfails its pass-through case.Ran the binaries behind
pnpm checkandpnpm testdirectly, since this was a worktree:svelte-check(0 errors) and the fullvitest --run(134 files, 1974 tests). Raneslintandprettier --checkon the changed files. No Go changed, sogo vetandgolangci-lintdid not run.