Skip to content

editor: improve floorplan modes and annotations - #549

Open
sudhir9297 wants to merge 45 commits into
pascalorg:mainfrom
sudhir9297:floor-plan
Open

editor: improve floorplan modes and annotations#549
sudhir9297 wants to merge 45 commits into
pascalorg:mainfrom
sudhir9297:floor-plan

Conversation

@sudhir9297

@sudhir9297 sudhir9297 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

  • Adds context-aware floorplan modes and coordinates mode state across the toolbar, settings, registered tool layers, measurements, and annotation visibility.
  • Improves floorplan editing with live override previews, mode-driven move and angle snapping, a snapped cursor anchor, zoom-safe handles, crisp wall selection hatching, and zone labels that remain readable after rotation.
  • Moves contextual dimensions and referenced annotations into registry-driven node definitions, with coverage for floorplan modes, registry layers, visibility, exports, wall rendering, and opening dimensions.
  • Updates the editor's React Scan tooling and pins React Grab consistently to remove the stale runtime warning.

How to test

  1. Run bun run check, bun run check-types, and bun run build; all commands should complete successfully.
  2. Run bun run dev, open http://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.
  3. Rotate a zone through 180 degrees and confirm its label flips to remain readable; zoom in and out and confirm selection handles remain usable and wall hatching stays crisp.
  4. Switch between the floorplan display and measurement modes and confirm registered annotations/contextual dimensions appear consistently in the editor and floorplan export.

Screenshots / screen recording

A screen recording will be added for the visual and interactive changes.

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

Note

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 a FloorplanModeCoordinator that 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-sheet node model and related clone/remap paths; strips wall assemblyLayers and datum helpers in favor of plain thickness, with setScene migration that drops drawing sheets and sums assembly layers into thickness. Angle snapping moves behind isAngleSnapActive instead 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.

sudhir9297 and others added 30 commits May 19, 2026 02:59
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])

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 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.

Fix in Cursor Fix in Web

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
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c2c7b86. Configure here.


const toolLabel = getToolLabel(tool)
emitter.emit('tool:cancel')
useEditor.getState().setMode('select')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c2c7b86. Configure here.

extensions: {
'pascal:editor/floorplan': {
tool: () => import('./floorplan-tool'),
availableModes: ['expert'],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c2c7b86. Configure here.

@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.

There are 5 total unresolved issues (including 4 from previous reviews).

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 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
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ad8b4db. Configure here.

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