Skip to content

editor: stop wall endpoint drag snapping back to the stale junction corner#533

Merged
wass08 merged 2 commits into
mainfrom
fix/endpoint-move-stale-junction-snap
Jul 22, 2026
Merged

editor: stop wall endpoint drag snapping back to the stale junction corner#533
wass08 merged 2 commits into
mainfrom
fix/endpoint-move-stale-junction-snap

Conversation

@wass08

@wass08 wass08 commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Fixes an endpoint-drag trap that made small corner corrections impossible: walls attached to the moving corner cascade with the drag, but the snap pipeline reads the scene store, which keeps their pre-drag coordinates until commit. Their stale corners recreated the old junction as a snap/alignment target, so inside the connect radius (5cm in grid/angles/off, up to 70cm magnetic) the endpoint always got sucked back to exactly where it started. Any sub-5cm fix — e.g. squaring a scan-imported 91° junction — was unreachable in every snapping mode (the angle badge oscillates 89° ↔ 91°, 90° is a dead zone).

Both endpoint-move paths (3D move-endpoint-tool.tsx + 2D wallMoveEndpointAffordance) now exclude the walls linked at the moving corner from wall-snap candidates and alignment anchors while attached. Under Alt-detach they remain candidates — they stay put in that mode, so they're live geometry.

The 2D path also over-excluded in the other direction: it dropped all linked walls from the alignment pool, including walls linked at the fixed corner. Those don't move, and their anchors are exactly the axes that let the dragged corner self-heal onto a true 90°. They're back in the pool now, restoring 2D/3D parity.

Includes a regression test pinning the mechanism (a 3cm correction next to a stale linked corner is swallowed when the linked wall is a snap candidate, lands when ignored).

How to test

  1. Draw three walls meeting at one corner: two axis-aligned (one horizontal, one vertical) and a third that arrives ~1° off-axis (e.g. its far end 3cm off the horizontal's z line). The angle badge at the junction reads 91°.
  2. In 3D, drag the tilted wall's far endpoint with snapping in lines mode: the alignment guide from the axis-aligned wall should grab the corner ~3cm away and the badge should land on exactly 90° (previously it jumped 89° ↔ 91° and could never settle).
  3. Repeat in grid, angles, and off modes — the endpoint no longer sticks back to its original position within 5cm; angles mode locks onto the 15° ray and stays there.
  4. Repeat the drag in the 2D floor plan — same behaviour.
  5. Hold Alt while dragging the shared corner: the detached endpoint still snaps onto the stationary corner it left (unchanged behaviour).
  6. cd packages/editor && bun test src/components/tools/wall/ and cd packages/nodes && bun test src/wall/.

Screenshots / screen recording

N/A — interaction change; verified live on a RoomPlan-imported scene where a 91° junction could not be squared before this fix and self-heals to 90° with it.

Checklist

  • I've tested this locally with bun dev
  • My code follows the existing code style (run bun check to verify)
  • I've updated relevant documentation (if applicable)
  • This PR targets the main branch

🤖 Generated with Claude Code


Note

Medium Risk
Touches core wall snapping and alignment during endpoint drags in both 3D and 2D affordances; behavior change is localized to move-endpoint flows with a targeted regression test.

Overview
Fixes endpoint drag snapping back to the old junction when linked walls move with the corner but the snap pipeline still reads pre-drag scene coordinates, so sub–connect-radius corrections (e.g. squaring a ~91° scan corner) could never land.

3D (move-endpoint-tool.tsx) and 2D floor plan (wallMoveEndpointAffordance) now pass walls attached only at the moving corner into ignoreWallIds / alignment excludeIds while attached; Alt-detach drops that exclusion so stationary corners stay valid snap targets. The 2D path no longer excludes all linked walls from alignment—walls tied at the fixed corner are candidates again so the dragged corner can align to true axes (2D/3D parity).

The 3D tool extracts resolveDragPoint and re-runs the full snap pipeline from lastRawPoint on Alt changes (not the last snapped point), since the candidate set flips with the modifier.

Adds a snapWallDraftPointDetailed regression test for the stale-corner swallow vs ignore behavior.

Reviewed by Cursor Bugbot for commit 36fc931. Bugbot is set up for automated code reviews on this repo. Configure here.

Walls attached to the moving corner cascade with the drag, but the snap
pipeline reads the scene store, which keeps their pre-drag coordinates
until commit. Their stale corners recreated the old junction as a snap /
alignment target, so inside the connect radius (5cm, 70cm magnetic) the
endpoint could never land closer than that to where it started — sub-5cm
corrections (e.g. squaring a scan-imported 91° junction) were impossible
in every snapping mode.

Both endpoint-move paths (3D tool + 2D floorplan affordance) now exclude
the walls linked at the moving corner from snap candidates and alignment
anchors while attached; Alt-detach keeps them (they stay put, so they're
live geometry). The 2D path previously over-excluded: walls linked at the
FIXED corner don't move, and their anchors are exactly what lets the
dragged corner align back onto a true axis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 82a3160. Configure here.

Comment thread packages/nodes/src/wall/move-endpoint-tool.tsx
The snap/alignment candidate set now depends on Alt (stale-junction
exclusion), so a keyboard detach/re-attach must re-resolve from the raw
cursor point instead of re-applying the previously snapped one — matching
what the 2D dispatcher already does by re-invoking apply() with the raw
planPoint on modifier changes. Flagged by Bugbot on #533.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wass08
wass08 merged commit 2adb50a into main Jul 22, 2026
2 checks passed
@wass08
wass08 deleted the fix/endpoint-move-stale-junction-snap branch July 22, 2026 13:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant