Shelf had the floating action menu (move/delete) showing thanks to
the previous registry-driven selection commit, but clicking move
did nothing and duplicate silently failed. Two hardcoded chains:
1) FloatingActionMenu.handleMove guarded `setMovingNode` behind a
hardcoded `node.type === 'item' || ... || node.type === 'spawn'`
chain. Added `|| isRegistrySelectable(node.type)` so any
registry kind triggers the move flow.
2) MoveTool dispatched per-kind components (MoveItemContent,
MoveColumnTool, MoveWallTool, ...). The default fallback
mounted MoveItemContent, which assumes the node is an ItemNode
with asset/scale/metadata — crashes for shelf. Added a generic
MoveRegistryNodeTool (kind-agnostic clone of MoveColumnTool):
pure position+rotation drag with grid snap, re-parses orphan
re-creates via `nodeRegistry.get(kind).schema.parse(...)`.
MoveTool dispatches to it for any `nodeRegistry.has(movingNode.type)`
before the MoveItemContent fallback.
3) FloatingActionMenu.handleDuplicate had a hardcoded
`node.type === 'door' ? DoorNode.parse(...) : ...` chain. Added
a registry-driven fallback after it:
`const def = nodeRegistry.get(node.type); duplicate = def.schema.parse(duplicateInfo)`.
Then the createNode + setMovingNode branches also augment with
`nodeRegistry.has(duplicate.type)` so the new shelf gets
created in the scene and handed off to the move tool for
placement.
After this:
- Click shelf → move icon in floating menu → cursor follows mouse,
click to place at new position.
- Click shelf → duplicate icon → new shelf appears, offset by (1,0,1),
handed to move tool so the user can position it.
Phase 4 will collapse MoveRegistryNodeTool with the per-kind movers
once they all reduce to the same position+rotation shape, and read
`capabilities.movable` to gate handleMove instead of the OR chain.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wholesale swap of packages/{core,viewer,editor,mcp} and apps/editor with the
versions from the private editor repo, which is the production source of truth.
Setup changes:
- packages/{core,viewer,editor} versions held at 0.7.0 baseline (matching
the most recent published release) so a bump=minor publishes 0.8.0
- packages/mcp held at 0.1.1 (never published; first publish will go through
the new release.yml flow)
- peerDependencies and devDependencies for inter-package @pascal-app/*
references pinned to ^0.7.0 instead of '*' / 'workspace:*' so they are
valid for npm consumers
- Root package.json: TypeScript bumped to 6.0.2, added overrides for
@types/react, @types/react-dom, @types/three to prevent JSX namespace
fragmentation across the workspace
- release.yml extended to also publish editor and mcp; 'both' option renamed
to 'all'; added a sync step that updates inter-package peerDeps/devDeps to
match the new versions on every bump (so viewer/editor/mcp tarballs always
reference the version of core they were built against)
- Root scripts gained release:editor and release:mcp shortcuts
Verification:
- bun install --frozen-lockfile is consistent
- packages/{core,viewer,mcp} build cleanly, dist/index.d.ts emitted
- packages/editor check-types reports 21 pre-existing errors, identical to
what private-editor currently reports
Open PRs against editor-v2 will need rebasing/conflict resolution.
* feat: add polygon movement support to editor and implement dedicated move tools for walls, slabs, and ceilings
* feat: add uv2 attribute to ceiling and slab geometries for lightmap support
* Fix curved wall miters and align roof position sliders
* Fix wall measurement label and extension anchors
* Fix WebGPU renderer initialization order
* fix(editor): scope wall movement to the selected level
---------
Co-authored-by: Pascal <open@pascal.app>
* feat: railing on the straight stairs and new fence
* feat: added spiral and curved stairs with bug fix for fence
* feat:fence are linked to each other ... so moving one move the other sharing the same coordinate
* fix: update stair railing logic to include front-side attachments for terminal landings
* Integrate fence rendering into the fence system
* fix: pass nodeId instead of undefined node to WallTreeNode and FenceTreeNode
TreeNode was passing `node` (undefined variable) instead of `nodeId` to
WallTreeNode and FenceTreeNode, causing a runtime ReferenceError.
Updated FenceTreeNode to accept nodeId and look up the node from the
scene store internally, consistent with all other tree node components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: update fence icon with new isometric design
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Aymeric Rabot <aymeric@pascal.app>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sync monorepo PRs #243 and #248 to the open-source editor.
Move/Rotate Building:
- New move-building-tool with grid snapping, R/T rotation, and Esc cancel
- Floating building action menu with move button
- Building helper with keyboard shortcut hints
- BuildingRenderer now applies position and rotation from node data
Building-Relative Coordinate System:
- GridEvent gains localPosition (building-local coords)
- use-grid-events computes building-local intersection from building mesh
- ToolManager wraps building-relative tools in a building-local <group>
- All tools (wall, slab, ceiling, stair, roof, zone, polygon-editor,
placement coordinator) updated to use event.localPosition
- Placement coordinator adds worldToBuildingLocal helper for cursor
position conversion
2D Floorplan Fix:
- SVG layers wrapped in <g transform=rotate(...)> for building rotation
- Pointer-to-plan conversion un-rotates when building is rotated
- Grid events from 2D include localPosition
Store Changes:
- useEditor movingNode union includes BuildingNode
- NodeActionMenu onDelete is now optional (buildings can move but not delete)