Skip to content

editor: compass sync + fast align-to-north#478

Merged
Aymericr merged 2 commits into
mainfrom
fix/compass-sync
Jul 9, 2026
Merged

editor: compass sync + fast align-to-north#478
Aymericr merged 2 commits into
mainfrom
fix/compass-sync

Conversation

@Aymericr

@Aymericr Aymericr commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes the compass widget lagging behind and desyncing from the 2D/3D view orientation:

  • Removes the 150ms CSS transition on the compass needle — the rotation is updated per-frame during orbits, so the transition permanently rubber-banded the needle behind the camera.
  • Keeps the compass live in 3D-only view mode: the per-frame floorplan viewport sync is intentionally skipped while the 2D panel is hidden (perf), which also froze the needle. The needle is now driven imperatively (direct DOM transform write from the store subscription) with no React re-render cost; a layout effect prevents unrelated re-renders from snapping it to a stale angle.
  • Click-to-north in 3D-only mode now derives the target from the live camera pose instead of the stale 2D viewport.
  • Matches 2D/3D convergence on align-to-north (and any 2D-origin navigation): the 3D camera transition temporarily uses smoothTime = 0.18 (SmoothDamp effective τ = 90ms, matching the 2D panel's exponential decay constant), restored on completion or interruption. All pending-pose cancel paths route through clearPendingFloorplanNavigationPose, and a controlstart listener catches user drags mid-transition, so the override can't leak into normal camera feel.

How to test

  1. bun dev, open a scene with a building.
  2. In 3D view, orbit with right-click — the compass needle should track the camera exactly, with no trailing.
  3. Switch to 2D and split view — needle stays in sync with the floorplan rotation (rotate with R/drag).
  4. Click the compass in each view mode — both panes and the needle should settle to north together in ~350–400ms, no pane trailing the other.
  5. In 3D-only mode: orbit, switch tools/selection (needle must not flicker or snap), then reopen 2D — the floorplan catches up to the camera orientation.
  6. Start a 2D-origin transition (e.g. click-to-north in split view), then immediately right-click-drag or scroll in the 3D pane — drag feel stays normal afterwards (no permanently snappier programmatic moves).

Screenshots / screen recording

N/A — verified locally by @aymericrabot (interactive change; recording can be added if needed).

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 per-frame navigation sync and global camera damping; incorrect smoothTime cleanup could affect normal 3D navigation feel, but changes are scoped to editor camera/floorplan UX with explicit restore paths.

Overview
Fixes compass lag and 2D/3D orientation drift when the floorplan panel is hidden or during synced navigation moves.

The compass needle drops its CSS transition and, in 3D-only mode, updates via a ref + inline transform from the navigation-sync store so it tracks the camera every frame without re-rendering the floorplan SVG. A layout effect reapplies the authoritative rotation ref so unrelated React renders do not snap the needle to stale state. Align-to-north while the panel is closed now publishes from the live 3D pose instead of a stale 2D viewport; reopening the floorplan still catches up from 3D-originated sync when the panel is open.

2D-originated camera moves temporarily set CameraControls smoothTime to 0.18 (matched to the 2D panel decay); clearPendingFloorplanNavigationPose restores the saved value on completion or interruption (keyboard pan, wheel, pointer, and new controlstart for user orbit/pan/touch mid-transition).

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

Aymericr and others added 2 commits July 9, 2026 13:09
- Remove CSS transition on compass needle SVG so rotation tracks
  exactly without rubber-band lag (was transition-transform 150ms)
- Drive compass needle imperatively via ref when floorplan panel is
  hidden (3D-only mode), avoiding per-frame React re-renders of the
  full SVG while keeping the needle live
- Align-to-north in 3D-only mode derives from latestNavigationSyncPose
  instead of stale viewport, publishes directly to the 3D camera
- Temporarily lower camera-controls smoothTime from 0.25s to 0.18s
  during 2D-origin transitions (SmoothDamp τ≈90ms matches the 2D
  exponential decay), restoring on completion or cancellation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Route all pending-pose cancellations through clearPendingFloorplanNavigationPose()
so savedSmoothTime is always restored. Add a controlstart listener to catch
right-click orbit and other pointer drags that weren't handled. Guard the
rotation-degree ref mirror to prevent React re-renders from clobbering the
imperative 3D-owned value when the panel is hidden, and add a useLayoutEffect
to keep the needle DOM in sync. Make the catch-up effect re-run directly on
panel reopen.

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 2 potential issues.

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 d4f1053. Configure here.

azimuth: northAzimuth,
viewWidth: pose.viewWidth,
})
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Compass stuck after 3D north

Medium Severity

After an 'align to north' action, the compass needle and floorplan view can become stale or jump. The action publishes a source: '2d' navigation pose, but the floorplan's update logic (for the hidden compass and re-opened view) expects source: '3d' poses. This mismatch, compounded by 3d pose suppression during camera damping, prevents proper synchronization.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d4f1053. Configure here.

// When hidden, the imperative 3D path owns the ref and must not be clobbered.
if (isFloorplanOpenRef.current) {
latestFloorplanUserRotationDegRef.current = floorplanUserRotationDeg
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale compass on panel reopen

Medium Severity

When the 2D panel opens after 3D-only orbit, the first render copies stale floorplanUserRotationDeg state into latestFloorplanUserRotationDegRef and reapplies it on the compass via React style, overwriting the live imperative rotation. Catch-up runs in a later useEffect, so the needle (and floorplan rotation) can visibly snap or flash wrong for at least one paint.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d4f1053. Configure here.

@Aymericr Aymericr merged commit 2d4e7be into main Jul 9, 2026
2 checks passed
@Aymericr Aymericr deleted the fix/compass-sync branch July 9, 2026 14:20
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