nodes: improve block mesh editing UX - #691
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>
… github.com:pascalorg/editor
| const localPoint = target.worldToLocal( | ||
| worldOrigin.clone().add(currentHit.clone().sub(startPlaneHit)), | ||
| ) | ||
| delta = [localPoint.x - origin[0], localPoint.y - origin[1], localPoint.z - origin[2]] |
There was a problem hiding this comment.
Plane lock ignored when ray misses
Medium Severity
Shift+axis plane lock only applies when startRay hits the constraint plane. A miss leaves lockedTranslationInitialHit null, so preview falls through to unconstrained view-plane movement while the HUD still shows the plane lock.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 6c7452d. Configure here.
| } else if (key === 'd') { | ||
| actions.dissolveSelection() | ||
| } else if (event.key === 'Delete' || event.key === 'Backspace' || key === 'x') { | ||
| } else if (event.key === 'Delete' || key === 'x') { |
There was a problem hiding this comment.
Mesh edit swallows modifier G shortcut
Medium Severity
The mesh-edit capture handler treats every g key as handled, including Ctrl/Cmd+G and presses with an empty selection. It always preventDefaults and stopImmediatePropagations, so the editor’s capture-phase group shortcut never runs while a block is in edit mode.
Reviewed by Cursor Bugbot for commit 6c7452d. Configure here.
| ) | ||
| if (!result.ok) { | ||
| setError(result.error) | ||
| return |
There was a problem hiding this comment.
Failed preview still commits prior value
Medium Severity
When a live modal command fails validation, the error is shown but latestTopology / latestCommand / latestValue are left on the last successful preview. Confirm still commits that older result even though the current typed or pointer value is invalid.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 6c7452d. 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 4 total unresolved issues (including 3 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 384eb92. Configure here.
| return ( | ||
| <div className="space-y-1"> | ||
| {(['X', 'Y', 'Z'] as const).map((axis, index) => | ||
| input(`${axis} distance`, command.delta[index]!, (value) => ({ |
There was a problem hiding this comment.
Adjust panel rejects typed values
Medium Severity
The F9 last-operation inputs call onChange on every keystroke with Number(event.target.value). Empty text, a lone -, or 0. become NaN or 0, so applyBlockCommand fails and adjustLastOperation closes the panel. Typed negatives and in-progress decimals cannot be entered.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 384eb92. Configure here.


What does this PR do?
How to test
bun dev, add and select a Block, then press Tab to enter mesh edit mode.G,R, andS; constrain with X/Y/Z or Shift+axis, enter numeric values, hold Shift for precision, and confirm/cancel with click, Enter, Escape, or right-click.bun run check,bun run lint,bun run check-types, andbun run build; all should pass.Screenshots / screen recording
Recording to be added — this PR changes visual and interactive block-editing behavior.
Checklist
bun devbun checkto verify)mainbranchNote
High Risk
Large changes to block topology commands, scene history replacement, and mesh-edit interaction; incorrect behavior could corrupt geometry or undo stacks.
Overview
Block mesh editing gains modal move/rotate/scale and face ops (extrude/inset) via new
modal-transform,modal-face-operation,modal-session, and geometry snapping (geometry-snap). The edit session trackslastOperation(replacing per-slot material focus) so committed ops can be adjusted in-place on the undo stack or repeated (last-operation+ historyreplaceLatest). Topology commands are renamed and pluralized (extrude-faces,inset-faces,bevel-edges,dissolve-edges, plusdissolve-faces) with multi-ID support, connected-region extrude, and merge keeping the last-selected vertex.Editor integration:
SelectionAffordanceManagerinjectsnode,sceneApi,readOnly, andhistoryApiinto selection affordances (exported asSelectionAffordanceProps). Global shortcuts yield during mesh edit: R is reserved in mesh mode; Shift snap cycling is disabled while a mesh operating modal is active.Materials panel is streamlined: Add slot creates a slot, assigns selected faces, and applies a default accent material; rows apply a slot to the selection (reusable-material picker and select/deselect-by-slot removed).
createAssignedBlockMaterialSlotand unpainted-slot tint helpers support this.Item on block faces:
shouldDetachBlockFaceOnLeavenow detaches wall/ceiling-hosted items when the pointer leaves the face (no longer sticky across transient leave).Reviewed by Cursor Bugbot for commit 6c7452d. Bugbot is set up for automated code reviews on this repo. Configure here.