editor: improve floorplan modes and annotations - #549
Conversation
Items (e.g. solar panels) can now be placed on sloped roof surfaces. The placement system computes euler rotation from the roof surface normal so items sit flush on the slope instead of going inside. - Add roofStrategy to placement-strategies with enter/move/click/leave - Wire roof:enter/move/click/leave events in the placement coordinator - Add calculateRoofRotation in placement-math using surface normals - Support full 3D cursor rotation for sloped surfaces - Items on roofs are parented to the level with world-space rotation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| ? currentPosition | ||
| : nextPosition, | ||
| ) | ||
| }, [cursorPoint, cursorPosition]) |
There was a problem hiding this comment.
Cursor pin stale after zoom
Medium Severity
The cursor indicator's projected position becomes misaligned after panning or zooming the floorplan. The useLayoutEffect calculating this position uses getScreenCTM() but doesn't re-evaluate when the floorplan's transform changes, because its dependencies (cursorPoint, cursorPosition) are unchanged. This leaves the indicator anchored to stale screen coordinates until the cursor moves.
Reviewed by Cursor Bugbot for commit c2c7b86. Configure here.
| if (!e.shiftKey) delta = Math.round(delta / DEFAULT_ANGLE_STEP) * DEFAULT_ANGLE_STEP | ||
| if (isAngleSnapActive()) { | ||
| delta = Math.round(delta / DEFAULT_ANGLE_STEP) * DEFAULT_ANGLE_STEP | ||
| } |
There was a problem hiding this comment.
Shift hint mismatches 2D rotate
Medium Severity
During 2D group and direct rotation, angle stepping now follows isAngleSnapActive() only, but the contextual helper still shows “Hold Shift to rotate freely” for group-rotate-handle drags. On the floorplan, Shift no longer bypasses the angle step while that hint remains visible.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit c2c7b86. Configure here.
|
|
||
| const toolLabel = getToolLabel(tool) | ||
| emitter.emit('tool:cancel') | ||
| useEditor.getState().setMode('select') |
There was a problem hiding this comment.
Expert tool left armed
Medium Severity
When Default mode disables the active build tool, the coordinator emits tool:cancel and sets editor mode to select but leaves tool unchanged. Expert-only tools such as construction-dimension do not listen for that event, so re-entering build can keep a hidden tool armed with no floorplan tool layer mounted.
Reviewed by Cursor Bugbot for commit c2c7b86. Configure here.
| extensions: { | ||
| 'pascal:editor/floorplan': { | ||
| tool: () => import('./floorplan-tool'), | ||
| availableModes: ['expert'], |
There was a problem hiding this comment.
Referenced dims stay hidden
Medium Severity
Default mode is meant to reveal manual dimensions when a referenced object is selected, but construction dimensions never register referencedSelectionAnnotationRole, unlike measurements. Selecting a wall they anchor to therefore keeps those expert manual dimensions filtered out.
Reviewed by Cursor Bugbot for commit c2c7b86. Configure here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
There are 5 total unresolved issues (including 4 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ad8b4db. Configure here.
| if (!e.shiftKey) delta = Math.round(delta / DEFAULT_ANGLE_STEP) * DEFAULT_ANGLE_STEP | ||
| if (isAngleSnapActive()) { | ||
| delta = Math.round(delta / DEFAULT_ANGLE_STEP) * DEFAULT_ANGLE_STEP | ||
| } |
There was a problem hiding this comment.
Group rotate never angle-snaps
Medium Severity
2D direct and group rotations now default to free rotation, rather than the expected 15° angle snapping. This occurs because the logic switched from checking the Shift key to !isAngleSnapActive(), and the interaction scopes for these gestures typically don't enable angle snapping.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit ad8b4db. Configure here.


What does this PR do?
How to test
bun run check,bun run check-types, andbun run build; all commands should complete successfully.bun run dev, openhttp://localhost:3002, switch to the 2D floorplan, and move or rotate walls, openings, items, shelves, stairs, and zones; previews and snapping should follow the active floorplan mode.Screenshots / screen recording
A screen recording will be added for the visual and interactive changes.
Checklist
bun devbun checkto verify)mainbranchNote
High Risk
Removes persisted node types and wall assembly data with load-time migration, and changes floorplan tooling, annotations, and snapping across a large editor surface area.
Overview
Introduces Default vs Expert floor plan modes (
useFloorplanMode), wired through the viewer settings menu, build palette, registered tools, annotation visibility, and aFloorplanModeCoordinatorthat cancels expert-only drafts and surfaces “switch to Expert” notices. Default keeps a cleaner plan (selection-driven dimensions on group moves; expert-only annotation and wall-dimension submenus); expert restores full documentation controls. The coordinated drawing type toolbar control and runtime construction preflight hook are removed from the open editor app.Core/schema cleanup: deletes the
drawing-sheetnode model and related clone/remap paths; strips wallassemblyLayersand datum helpers in favor of plainthickness, withsetScenemigration that drops drawing sheets and sums assembly layers into thickness. Angle snapping moves behindisAngleSnapActiveinstead of Shift-for-free-rotate in several 2D drag paths.2D polish: placement cursor pin follows the snapped plan point; selection handles are capped at extreme zoom-out; registry entries subscribe to hover/selection locally; annotation collision layout no longer feeds a preflight issue store; zone background picks use registry hit testing. Bumps react-grab / react-scan dev tooling.
Reviewed by Cursor Bugbot for commit ad8b4db. Bugbot is set up for automated code reviews on this repo. Configure here.