Skip to content

editor: add Blender-style custom mesh editing - #638

Open
sudhir9297 wants to merge 43 commits into
pascalorg:mainfrom
sudhir9297:t3code/research-blender-edit-mode
Open

editor: add Blender-style custom mesh editing#638
sudhir9297 wants to merge 43 commits into
pascalorg:mainfrom
sudhir9297:t3code/research-blender-edit-mode

Conversation

@sudhir9297

@sudhir9297 sudhir9297 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

  • Adds a registry-driven Custom Mesh node with 3D placement, floor-plan rendering, paint support, and Blender-style vertex, edge, and face editing.
  • Adds mesh transforms and topology operations including extrude, inset, bevel, loop cut, merge, dissolve, and delete, with an interaction-scoped floating toolbar and keyboard controls.
  • Supports elevated and registry-declared top surfaces for stairs and other floor-placed nodes, including plugin-defined surfaces and Alt force placement without hardcoded node-kind dispatch.
  • Refines the edit/selection menus, removes the obstructive secondary help strip, and documents the interaction-scope and custom-mesh design.

How to test

  1. Run bun dev, open the editor, choose Custom Mesh from the build palette, and place it on the ground and on an elevated top surface; verify the preview follows the pointed surface and commits without an error overlay.
  2. During Custom Mesh placement, hold Alt over an otherwise invalid or overlapping position; verify snapping is bypassed and the mesh can be force-placed.
  3. Select a Custom Mesh, choose Edit mesh, switch between vertex/edge/face selection, and exercise translate, rotate, scale, extrude, inset, bevel, loop cut, merge, dissolve, and delete; verify Tab or the check button exits edit mode.
  4. Place or move a stair over a Custom Mesh/elevated surface and verify a single click commits it at that elevation without the floating helper blocking the pointer.
  5. Run bun run check, bun run check-types, and bun run build.

Screenshots / screen recording

A short screen recording will be added before review. The interactive placement and helper UI were smoke-tested in the local collaborative preview.

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
Changes core spatial support election, wall/fence commit paths, and global selection/pointer behavior; incorrect pinning or surface resolution could misplace structure or break plugin surfaces.

Overview
Introduces a custom-mesh scene node (validated topology, materials, floor placement with supportSlabId) and wires it through the event bus, schema union, and site tree.

Placement and support gain pinSupport, resolveFrozenFloorPlacementPatch, and consolidated wall/fence construction helpers so items, stairs, columns, fences, and moves can commit at an exact elevation on slabs, ground, or registry-declared top surfaces without being re-lifted when overlapping slabs appear later. getTopSurfaceHeight now receives the full node map for context-aware surface heights.

Editor interaction: a mesh-editing scope blocks scene selection and click routing while editing; undo/redo stays in edit mode. Placement/move/stair tools use generic node:click / node:move, RegistryToolProvider, and optional Edit mesh on the floating action menu. Pointer raycasting discovers top surfaces from nodeRegistry capabilities (not a fixed kind list). Alt force-place is shown only when floorPlaced.collides is true. The build tab defers registry-driven palette entries until client mount via useSyncExternalStore.

Reviewed by Cursor Bugbot for commit 3a33729. 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>
Comment thread packages/nodes/src/custom-mesh/tool.tsx
: Array.from(nodeRegistry.entries())
.filter(([, definition]) => definition.capabilities.surfaces?.top !== undefined)
.map(([kind]) => kind)
if (nodeTopSurfaceKinds.some((kind) => (sceneRegistry.byType[kind]?.size ?? 0) > 0)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ceilings intercept floor placement

High Severity

resolvePointerSupportSurface now treats every registry surfaces.top as a walkable surface by default, including ceilings. A downward camera ray hits the ceiling top before the floor, so floor placement, moves, stairs, columns, and fences can freeze onto ceiling height whenever a ceiling exists on the active level.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 78935c1. 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 2 total unresolved issues (including 1 from previous review).

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 32dc57c. Configure here.

emitter.on('ceiling:click', commitFloorOnSurfaceClick as never)
emitter.on('roof:click', commitFloorOnSurfaceClick as never)
emitter.on('shelf:click', commitFloorOnSurfaceClick as never)
emitter.on('node:click', commitFloorOnSurfaceClick as never)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Item floor commit can double-place

Medium Severity

Floor item placement now commits from generic node:click without a one-shot guard or follow-up click swallow. node:click is synthesized on pointer-up and grid:click still fires from the canvas click, so one physical click can run onGridClick twice. Move and shared floor-placement helpers already defend against that; in repeat mode this can create two items when dropping on a custom mesh or other newly covered surface.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 32dc57c. 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