feat: move shapes with the arrow keys the way the camera sees them - #93
Open
FutuRiata wants to merge 1 commit into
Open
feat: move shapes with the arrow keys the way the camera sees them#93FutuRiata wants to merge 1 commit into
FutuRiata wants to merge 1 commit into
Conversation
Arrow keys step along the world axes no matter where the camera stands. Orbit round to the Left view, press Right, and the shape walks away from you into the screen. The axis is correct; the key is not the one you pressed. This picks the workplane axis closest to the direction the arrow points on screen, which is the camera yaw rounded to the nearest 90 degrees. The step stays on an axis: no diagonals, so grid snapping and typed coordinates are untouched. Only which axis changes. Nothing changes in the two views people spend most of their time in. The Front view maps to the same axes as before, and so does the default home view: its yaw is exactly 45, halfway between two axes, and the tie rounds to the axis the editor already used. A user who never orbits never sees a difference. Details worth knowing: - Ctrl + Up/Down still lifts along world Y. Height does not depend on where you stand, so it must not turn. - On the pole, straight down or straight up, there is no horizontal offset to read a yaw from and atan2(0, 0) returns 0. That is the right answer: THREE.Matrix4.lookAt breaks the same tie towards the same axes, so Top view keeps screen right = +X and screen down = +Z. - Below the horizon the view is mirrored, so screen down is flipped. Right is not: it never depends on the pitch. - The orthographic camera shares position, target and up with the perspective one, so it needs nothing extra. - A workplane laid on a face keeps its own axes. Turning those with the camera would send arrows off the face the workplane was drawn on. The viewport did not expose the camera at all, so it now reports yaw and pitch through an optional onCameraOrientationChange, computed by the helper the view cube already used. The editor parks it in a ref, so a moving camera causes no renders. Without the callback the editor keeps the Front view mapping, which is exactly today's behaviour. The axis choice is a pure function in lib, covered by 26 tests: the four compass views, both poles, the 45 degree ties, negative yaw, a full turn, the below-horizon mirror, and a check that every result matches the screen axes three.js really builds for that camera, orthographic included. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TAoEuBEJyJtkEGapsp6G22
mhaeu
pushed a commit
to mhaeu/SketchForge-3D
that referenced
this pull request
Sep 9, 2026
Arrow keys step along the world axes no matter where the camera stands. Orbit round to the Left view, press Right, and the shape walks away from you into the screen. The axis is correct; the key is not the one you pressed. This picks the workplane axis closest to the direction the arrow points on screen, which is the camera yaw rounded to the nearest 90 degrees. The step stays on an axis: no diagonals, so grid snapping and typed coordinates are untouched. Only which axis changes. Nothing changes in the two views people spend most of their time in. The Front view maps to the same axes as before, and so does the default home view: its yaw is exactly 45, halfway between two axes, and the tie rounds to the axis the editor already used. A user who never orbits never sees a difference. Details worth knowing: - Ctrl + Up/Down still lifts along world Y. Height does not depend on where you stand, so it must not turn. - On the pole, straight down or straight up, there is no horizontal offset to read a yaw from and atan2(0, 0) returns 0. That is the right answer: THREE.Matrix4.lookAt breaks the same tie towards the same axes, so Top view keeps screen right = +X and screen down = +Z. - Below the horizon the view is mirrored, so screen down is flipped. Right is not: it never depends on the pitch. - The orthographic camera shares position, target and up with the perspective one, so it needs nothing extra. - A workplane laid on a face keeps its own axes. Turning those with the camera would send arrows off the face the workplane was drawn on. The viewport did not expose the camera at all, so it now reports yaw and pitch through an optional onCameraOrientationChange, computed by the helper the view cube already used. The editor parks it in a ref, so a moving camera causes no renders. Without the callback the editor keeps the Front view mapping, which is exactly today's behaviour. The axis choice is a pure function in lib, covered by 26 tests: the four compass views, both poles, the 45 degree ties, negative yaw, a full turn, the below-horizon mirror, and a check that every result matches the screen axes three.js really builds for that camera, orthographic included. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TAoEuBEJyJtkEGapsp6G22 Applied-from: Formsmith746#93 (upstream nicht gemergt) Applied-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Arrow keys step along the world axes no matter where the camera stands. Orbit round to the Left view, press →, and the shape walks away from you into the screen. The axis is correct; the key is not the one the user pressed.
This makes an arrow move the selection towards the workplane axis closest to the direction the arrow points on screen — the camera yaw rounded to the nearest 90°, the way Tinkercad does it.
Why this is a fix, not a preference
Nothing changes in the two views people spend most of their time in.
The step stays on an axis. No diagonals, ever — only which axis changes. Grid snapping, typed coordinates and the 1 mm / 5 mm step are all untouched. There is a test that walks the yaw in 3° increments through two full turns and asserts every result moves along exactly one axis by exactly the whole step.
Ctrl + ↑/↓ is untouched. Lift is along world Y, and height does not depend on where you stand, so it must not turn with the camera.
Corners worth calling out
atan2(0, 0)returns0. That happens to be the right answer:THREE.Matrix4.lookAtbreaks the same degenerate tie towards the same axes, so Top view keeps screen-right = +X and screen-down = +Z. Verified against the matrix three.js actually builds, not just derived on paper.How the camera gets out of the viewport
The viewport did not expose the camera at all — no ref, no event, no prop. It now reports yaw and pitch through an optional
onCameraOrientationChange, computed by the very helpersyncViewCubealready used (extracted, not duplicated) and emitted from the same throttled branch of the render loop. The editor parks it in a ref, so a moving camera causes no renders. With the callback absent the editor keeps the Front-view mapping, i.e. exactly today's behaviour.Tests
tests/unit/screenAlignedNudge.test.ts, 26 cases over the pure axis-choice function:npm test290 passed / 47 files,npm run typecheckclean,npm run buildclean.🤖 Generated with Claude Code
https://claude.ai/code/session_01TAoEuBEJyJtkEGapsp6G22