97 Commits

Author SHA1 Message Date
Wassim SAMAD
586cec8ad7 registry/move-tool: fix 3D drag — keep rotation + stop transform reset
Two bugs caused dragged shelves to snap to a weird position on commit:

1. `MoveRegistryNodeTool` wrote `useLiveTransforms.set(id, { ..., rotation: 0 })`,
   so during the drag `ParametricNodeRenderer` applied `<group rotation={[0,0,0]}>`
   and the shelf visually un-rotated. On commit the live transform cleared
   and the renderer re-read the node's true rotation — the snap-back read
   as "reverts to a weird position." Now we capture `originalRotationY`
   from the node at mount time and forward it on every set.

2. `<GeometrySystem>` reset `group.position.set(0,0,0)` /
   `group.rotation.set(0,0,0)` after every rebuild. That was carry-over
   from legacy per-kind systems that didn't bind `position` on the group.
   `ParametricNodeRenderer` now drives the transform via JSX prop, and
   the reset clobbered it — React doesn't necessarily re-render on a
   rebuild tick, so R3F never re-applied the prop and the registered
   `<group>` stayed at the origin. Removed the reset; builders are
   expected to emit local-space children.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:11:26 -04:00
Wassim SAMAD
56e022a093 Phase 5 Stage D wall: port endpoint move, whole-move, placement (1:1 legacy)
Three remaining wall affordances ported into nodes/src/wall/ as
direct copies of the legacy implementations. Wall D is now complete.

  - move-endpoint-tool.tsx (426 LoC) — linked-wall corner cascade +
    Alt-detach + angle label. Mounted via `affordanceTools.move-endpoint`.
  - move-tool.tsx (804 LoC, the most complex tool in the editor) —
    center-drag with axis lock, linked-wall corner cascade via
    `planWallMoveJunctions`, bridge wall ghost previews, auto-slab
    live preview via `planAutoSlabsForLevel`, R/T rotation in 45°
    steps, Shift to bypass grid snap, isNew metadata strip on first
    commit. Mounted via `affordanceTools.move`.
  - tool.tsx (332 LoC) — two-click placement with length/angle HUD,
    Shift to bypass angle snap. Mounted via `def.tool`.

Editor public surface gains:
  - createWallOnCurrentLevel, snapWallDraftPoint, WallPlanPoint
  - MovingWallEndpoint type

ToolManager dispatch for `movingWallEndpoint` routes through the
registry with the legacy fallback (same shape as the fence
move-endpoint dispatch).

Wall is now A ✅ C ✅ D ✅. Stage B still pending (geometry depends on
level-batch miter data, blocked on `ctx.levelData` design decision).
Stage E pending (drop WallPanel — has slider drags + actions).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 10:52:30 -04:00
Wassim SAMAD
7f2f9c685b Phase 5 Stage D wall: port CurveWallTool to DragAction (first wall D)
Direct copy of the fence curve recipe — pure
`curveWallDragAction` (chord-perpendicular projection + clamp +
normalize + single-undo dance) plus a thin wrapper feeding
`useDragAction`. Mounted via `def.affordanceTools.curve`.

Slight precision difference vs legacy: the legacy CurveWallTool snapped
the pointer position to `getWallGridStep()` before projecting onto the
chord normal; the ported action skips that pre-snap and relies on
`normalizeWallCurveOffset` to settle the final value. The user-visible
result is the same magnitude of step, just with the snap applied at
the offset level instead of the position level.

Remaining wall D affordances (endpoint move, whole-wall move,
placement) are larger and queued for future sessions — wall's move
tool alone is 804 LoC with the linked-wall corner-cascade logic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 18:34:40 -04:00
Wassim SAMAD
de3efa1b53 Phase 5 Stage D ceiling: port placement + move + boundary/hole editors
Replicates the slab Stage D recipe for ceiling: four affordances
routed through the registry — def.tool for the placement flow,
def.affordanceTools for boundary edit / hole edit / whole-ceiling move.

Ceiling-specific bits preserved:
- Placement tool keeps the dual-cursor + vertical TSL-gradient
  connector + ground-shadow lines (1:1 with legacy).
- Move tool wrapper renders the translucent preview fill + outline
  overlay so the user sees the destination before clicking.

ToolManager mount sites for CeilingBoundaryEditor / CeilingHoleEditor
now route through `getRegistryAffordanceTool` with legacy fallback.

Per-kind progress: ceiling A ✅ B (n/a, def.renderer escape hatch
preserved) C ✅ D ✅; E + F pending.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 18:31:40 -04:00
Wassim SAMAD
b2e5d84986 Phase 5 Stage D slab: port placement + move + boundary/hole editors
Replicates the fence Stage D recipe for slab — three drag affordances
+ one placement tool, all routed through the registry:

  affordanceTools:
    'boundary-edit' → thin <PolygonEditor> wrapper (vertex/edge drag)
    'hole-edit'     → same for a single hole polygon
    move            → DragAction with single-undo dance
  tool: () => placement (multi-click polygon with axis/45° snap)

`PolygonEditor` + `PolygonEditorProps` exported from
`@pascal-app/editor` as Stage D transitional surface (Stage F cleanup
moves them into `@pascal-app/nodes`).

ToolManager mount sites for SlabBoundaryEditor / SlabHoleEditor now
route through `getRegistryAffordanceTool` with legacy fallback.

Slab move action does not use the live-drag exception (polygon CSG
rebuild every tick) — matches legacy behavior; optimization is a
separate task once we measure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 18:27:31 -04:00
Wassim SAMAD
c16878c876 Phase 5 Stage D fence: port MoveFenceTool to DragAction (whole-fence move)
Third Stage D affordance port (302 LoC legacy → action + thin wrapper).

The action (`actions/move.ts`) uses the live-drag exception documented
in editor/wiki/architecture/tools.md: visual-only updates via
`sceneRegistry.nodes.get(id).position` + `useLiveTransforms` during
the drag, no scene mutations. Avoids re-rebuilding the fence geometry
(many posts + infill panels) every pointer tick. Commit performs the
single-undo dance — writes final start/end to scene, geometry rebuilds
once, Ctrl-Z reverses the whole drag.

Linked-fence cascade follows the same shape as MoveFenceEndpoint —
any fence in the same parent that shared an endpoint at activation
moves with the drag.

`getRegistryAffordanceTool` extracted to
`tools/shared/affordance-dispatch.ts` so move-tool.tsx and
tool-manager.tsx share the lazy-load helper (no duplicate caches).

MoveTool dispatch gains a generic `affordanceTools.move` check after
the capability-driven `movable` shortcut — fence routes through here;
wall / slab / etc. fall through to their legacy per-kind chain until
their D ports land.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 18:19:51 -04:00
Wassim SAMAD
36c48b7fc9 chore: biome auto-format pass (resolve persistent dirty-tree noise)
These files had been showing as modified in every dev session — biome's
canonical formatting (line-length collapses, import sort, type-modifier
placement) didn't match the committed state. No semantic changes.
Committing now so the working tree stays clean across sessions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 18:19:15 -04:00
Wassim SAMAD
05efa25edb Phase 5 Stage D fence: port MoveFenceEndpointTool to DragAction
Second Stage D affordance port (425 LoC legacy → ~430 split across
action + wrapper). All math (snap, linked-fence cascade, alt-detach,
min-length gate, single-undo dance) lives in the pure
`moveFenceEndpointDragAction`. The React wrapper handles the UI
overlays (cursor sphere, Drag/Detach badge, angle label) and the live
state subscriptions.

The action introduces the single-undo dance pattern for multi-write
commits: `commit()` calls `scene.restoreAll()` → `resumeHistory()` →
re-applies the final draft so zundo records the entire drag as one
undo step. Reusable shape for slab/wall/door endpoint ports.

Transitional exports added to `@pascal-app/editor`'s public surface
(`snapFenceDraftPoint`, `isWallLongEnough`, the segment-angle helpers,
`MovingFenceEndpoint`). Stage F cleanup moves these into
`@pascal-app/nodes` once every consumer is registry-driven.

`getRegistryAffordanceTool` is now generic (`ComponentType<any>`) so
affordances with different prop shapes (`{ node }`, `{ target }`, …)
all dispatch through the same helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 17:51:04 -04:00
Wassim SAMAD
8ca9686b27 Phase 5 Stage D: fence curve affordance → registry DragAction
First Stage D port — `CurveFenceTool` (178 LoC legacy) split into a pure
`DragAction` primitive (`packages/nodes/src/fence/actions/curve.ts`) plus
a thin React wrapper (`packages/nodes/src/fence/curve-tool.tsx`) that
feeds it through `useDragAction`. The kind declares the affordance via
`def.affordanceTools.curve`; ToolManager lazy-loads it at runtime when
`useEditor.curvingFence` activates. Falls back to the legacy
`CurveFenceTool` for any kind that hasn't been ported.

The lazy-load dispatch dodges the editor→nodes circular dep (nodes
already depends on editor for `useDragAction` + `CursorSphere`).

Establishes the pattern for the remaining fence affordances
(`MoveFenceEndpoint`, `MoveFence`, placement) and for slab/ceiling/wall
D ports.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 17:18:30 -04:00
Wassim SAMAD
fc9a5d02a0 MoveTool: dispatch by capabilities.movable, not nodeRegistry.has
User report: after wall registered, the move tool's smart sims-style
arrow UX (endpoint handles + linked-wall corner cascade + ALT-detach)
was replaced by a generic whole-wall-translate. The dispatch was
unconditionally routing every registered kind through
MoveRegistryNodeTool — but MoveRegistryNodeTool is for kinds whose
move semantics are "translate position on X/Z plane" (shelf, spawn,
single-position items). Wall / fence / slab / stair endpoint drags
are bespoke and need their legacy movers until each gets a proper
DragAction-based affordance port.

Fix: gate the registry-mover dispatch on `def.capabilities.movable`.
When a kind opts in (`movable: { axes, gridSnap }`), use the generic
mover; when a kind omits the capability deliberately (wall and fence
do), fall through to the legacy per-kind branch below.

This is the registry-aware analogue of "the registry doesn't limit
custom behavior — it lets kinds opt in to generic dispatch". Adding
`movable` is an opt-in; omitting it is an opt-out.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 14:02:29 -04:00
Wassim SAMAD
d254582597 MoveTool: dispatch registry-first so spawn move uses MoveRegistryNodeTool
Shim ordering bug: the `nodeRegistry.has(movingNode.type)` check sat at
the END of the dispatch chain, AFTER the per-kind `if (movingNode.type
=== 'spawn') return <MoveSpawnTool>` branches. Spawn (now registered
in builtinPlugin) was therefore still routing to the legacy
MoveSpawnTool — which uses the broken useLiveTransforms pattern and
makes the spawn mesh disappear during drag.

Moved the registry check to the TOP, matching the registry-first
dispatch model the Phase 0 shims use everywhere else (NodeRenderer,
ToolManager, system guards). Now any kind registered via
@pascal-app/nodes routes to MoveRegistryNodeTool — same smooth
imperative drag for shelf, spawn, and every future kind. Legacy
per-kind movers below run only for kinds not yet in the registry.

This is exactly how the Phase 5 progressive consolidation works: as
kinds migrate to the registry, their legacy movers stop being reached
and can be deleted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:26:29 -04:00
Wassim SAMAD
166e860bfe Move: pure imperative via sceneRegistry (smooth, zero re-renders); drop dev logs
User feedback: updating the store per tick caused tons of React
re-renders → laggy drag. Switched to pure imperative.

MoveRegistryNodeTool now:
- Mutates `sceneRegistry.nodes.get(id).position` directly per
  grid:move tick. No useScene.updateNode during drag. No store
  change → no renderer re-render → R3F doesn't reapply
  `position={node.position}` → the imperative mutation sticks.
- On commit: single tracked `useScene.updateNode(id, { position })`.
  Undo replays one step (original → final), no per-tick spam.
- On cancel / unmount: imperatively snap the mesh back to original.
  Store was never touched so no data revert needed.

Trade-off vs the items pattern (which does update the store per tick
and re-renders per tick): our approach is faster but assumes the
renderer doesn't re-render mid-drag. Items get away with constant
re-renders because their renderer is heavily optimized; for parametric
shelves (and future kinds) the imperative path is simpler and faster.

Cleanup: removed the dev `[shelf] rendered` and `[shelf] placed`
console.info logs from the shelf renderer and tool. They were Phase 2
verification scaffolding — no longer needed now that everything works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:19:37 -04:00
Wassim SAMAD
7bd34e5ff0 Move: update node.position directly per tick (matches item pattern)
The useLiveTransforms + sceneRegistry.position.set approach used by
MoveColumnTool is broken — column ALSO disappears during move, per
user observation. The mesh doesn't visibly follow the cursor.

Items work because their move tool directly updates the scene store's
node.position on every grid:move tick (with history paused), and the
renderer reads node.position. Matching that pattern here.

MoveRegistryNodeTool now:
- Snapshots the original position at mount (for cancel / commit
  revert path).
- Pauses scene history so per-tick updateNode calls don't fill undo.
- On grid:move: `useScene.updateNode(id, { position })`. The kind's
  registered renderer reads node.position and re-renders, so the
  actual mesh visibly follows the cursor.
- On commit: revert to original while still paused → resume → final
  update (single tracked action) → re-pause. Undo replays one step,
  not the per-tick spam.
- On cancel / unmount-without-commit: restore original position with
  history still paused (won't enter undo), then resume.

The cursor sphere stays as the aim indicator alongside the moving
mesh. No translucent ghost — the actual mesh IS the preview now.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:12:42 -04:00
Wassim SAMAD
c792f9cff2 Move: drop preview overlay, let the actual mesh follow via live transforms
User feedback: the move tool shouldn't render a separate translucent
preview. The actual mesh (registered with sceneRegistry through the
kind's renderer) should follow the cursor — that's what's already
happening via useLiveTransforms + the imperative position.set on the
registered Object3D.

Removed from MoveRegistryNodeTool:
- The lazy `def.preview` load + Suspense-wrapped <Preview> render.
- Now only CursorSphere shows as the aim indicator. The shelf's
  actual rendered mesh follows the cursor via:
  - `useLiveTransforms.set(...)` triggers ShelfRenderer to re-render
    with `position={liveTransform.position}`.
  - `sceneRegistry.nodes.get(node.id).position.set(...)` is a
    defensive imperative update so motion feels snappy.

Added: `sfx:grid-snap` emit on grid-cell cross, matching the placement
tools' behavior. Move now sounds like placement.

The `preview` slot on NodeDefinition stays — still used by ShelfTool
for the placement cursor (where no real mesh exists yet). Phase 4 may
consolidate placement preview with the renderer too.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:05:40 -04:00
Wassim SAMAD
e84b1ec8bc Add preview slot to NodeDefinition; show translucent shape during move
User feedback: the move tool's CursorSphere is just a vertical line,
hard to tell what you're moving. Placement gets a translucent shape
that follows the cursor; move should too.

NodeDefinition.preview?: () => Promise<{ default: ComponentType<{ node }> }>
opt-in lazy component that renders a translucent ghost of the node.
Used by:
- The placement tool (ShelfTool) — renders the preview at the cursor
  position so the user sees the shape they're placing.
- The move tool (MoveRegistryNodeTool) — renders the preview at the
  drag target alongside the CursorSphere. Plus the original node is
  also dragged via live transforms, so the user sees both: the actual
  node moving + a translucent ghost at the same spot.

Implementation:
- New nodes/shelf/preview.tsx: ShelfPreview component. Renders the
  same shape as ShelfRenderer but `transparent: true, opacity: 0.5`.
- shelfDefinition.preview = () => import('./preview').
- ShelfTool's placement preview now uses <ShelfPreview node={defaults} />
  instead of an inline copy of the box geometry.
- MoveRegistryNodeTool lazy-loads `def.preview` (cached by loader,
  Suspense-wrapped). If a kind doesn't define `preview`, only the
  CursorSphere shows — matches today's behavior.

Phase 4 may merge `preview` with `renderer` behind an `opacity` prop
so kinds don't duplicate JSX between the solid and translucent
versions; until then defining `preview` is opt-in and one extra file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:01:32 -04:00
Wassim SAMAD
a090c22f42 Move + duplicate for registry kinds via MoveRegistryNodeTool
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>
2026-05-14 15:39:36 -04:00
Wassim SAMAD
2a8eb3e1de Registry-first dispatch in ToolManager (shim 4/4)
Before mounting any legacy build tool, ToolManager checks whether the
active tool's kind has a registered NodeDefinition with a tool
contribution. If yes, the registry tool wins; the legacy tool map and
special-cased spawn/column/elevator branches are skipped for that kind.

Lazy-loaded via React.lazy (cached by loader) and wrapped in Suspense.

Today the registry is empty, so useRegistryTool is always false and
every code path renders unchanged. The moment a kind registers (Phase
2+), its registry tool takes over without further edits here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:39:31 -04:00
sudhir
1ffa3d2d73 Restore item controls and guard placement asset bounds 2026-05-13 22:45:58 +05:30
sudhir
ce69433a1a Refine elevator sync and viewer rebuild handling 2026-05-13 22:28:19 +05:30
sudhir
b782ce9cf2 Merge branch 'main' into feat/elevator-system
# Conflicts:
#	packages/editor/src/components/tools/item/move-tool.tsx
#	packages/editor/src/components/tools/tool-manager.tsx
#	packages/editor/src/components/ui/panels/panel-manager.tsx
#	packages/editor/src/store/use-editor.tsx
#	packages/viewer/src/components/renderers/site/site-renderer.tsx
#	packages/viewer/src/components/viewer/ground-occluder.tsx
#	packages/viewer/src/components/viewer/index.tsx
#	packages/viewer/src/components/viewer/post-processing.tsx
2026-05-13 01:38:55 +05:30
sudhir
70c85d7760 Refine wall move previews and expose auto-slab planning 2026-05-12 12:15:45 +05:30
sudhir
f3444d4275 Add wall drag previews and fix move arrow handles 2026-05-12 11:00:27 +05:30
sudhir
564bfa229e Merge remote-tracking branch 'origin/main' into fix/fri-8-may
# Conflicts:
#	packages/editor/src/components/tools/fence/move-fence-endpoint-tool.tsx
#	packages/editor/src/components/tools/select/box-select-tool.tsx
#	packages/editor/src/components/tools/wall/move-wall-tool.tsx
#	packages/editor/src/components/ui/panels/column-panel.tsx
#	packages/editor/src/components/ui/panels/door-panel.tsx
#	packages/editor/src/components/ui/panels/window-panel.tsx
#	packages/viewer/src/components/renderers/column/column-renderer.tsx
#	packages/viewer/src/components/viewer/index.tsx
#	packages/viewer/src/systems/slab/slab-system.tsx
2026-05-12 00:27:06 +05:30
sudhir
be41511474 Fix wall move junction ownership 2026-05-11 23:46:57 +05:30
sudhir
92a9846193 Refactor elevator systems across core, viewer, and editor 2026-05-10 12:38:44 +05:30
sudhir
263228cbf0 Add cab door-open control and align elevator buttons 2026-05-10 02:28:00 +05:30
Wawa
e618175bba Reset core/viewer/editor/mcp packages and apps/editor from private-editor
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.
2026-05-09 20:52:26 +00:00
sudhir
2480be91b1 Optimize elevator editing performance with live previews 2026-05-09 19:09:48 +05:30
sudhir
0514363136 Add column hit testing and align column defaults 2026-05-08 14:31:58 +05:30
Wassim SAMAD
e348ccdb08
Merge pull request #296 from sudhir9297/wed-6-may-bug-fix
fix: Improve item surface placement, floorplan resizing, and placement preview stability
2026-05-07 13:09:20 -04:00
sudhir
c0a21058d4 fix list 2026-05-07 17:01:06 +05:30
sudhir
133d81e563 Refine window corner shape support 2026-05-07 13:34:16 +05:30
sudhir
eef19804d1 Merge branch 'main' into feat/door-improvement
# Conflicts:
#	packages/core/src/events/bus.ts
#	packages/viewer/src/systems/door/door-system.tsx
2026-05-07 10:40:51 +05:30
sudhir
34c847620f Fix floor item placement cursor height 2026-05-06 15:56:46 +05:30
sudhir
7e86e4628c Fix item surface placement and remove item height annotations 2026-05-06 15:13:37 +05:30
sudhir
d403606b72 Add floorplan side resizing handles 2026-05-06 14:18:44 +05:30
sudhir
70933adf9d Fix floorplan player move and action menu anchoring 2026-05-06 13:54:05 +05:30
Wassim SAMAD
5f57e9bb09
Merge pull request #292 from sudhir9297/feat/mon-4-feat-fix
feat: column node with door/window nodes improvement
2026-05-05 16:39:21 -04:00
sudhir
0ef2254e6b Fix first-person door toggles and colliders 2026-05-05 17:14:28 +05:30
sudhir
1490d280d4 Refine editor layer boundaries and selection handling 2026-05-05 13:26:39 +05:30
Pascal
1002a0a980 feat(editor): precise item dimensions — static bounding boxes, placement-math, remove item-mesh-metadata system
- Replace runtime mesh-based bounding-box computation with static dimension-based polygons for item footprints
- Add snapUpToGridStep() and getGridAlignedDimensions() to placement-math for grid-cell-aligned placement wireframes
- Add expandBoundsToGrid() to use-placement-coordinator for consistent wireframe snapping
- Add currentCursorRotationY to PlacementContext; preserve world orientation across item-surface transitions
- Fix item detach from surface: use worldToBuildingLocal() instead of event.localPosition to avoid coordinate-space jump
- Subscribe to useLiveTransforms in FloorplanPanel during placement so R/T keyboard rotation refreshes the 2D overlay immediately
- Fix FloorplanItemImage rotation (+180° to account for top-down camera capture orientation)
- Simplify spatial-grid-manager: single dimension-based getItemLocalBounds(), removes runtime mesh-metadata path
- Remove item-mesh-metadata system (compute-item-mesh-metadata, item-mesh-metadata-system, sync-request)
2026-05-04 19:35:41 +00:00
sudhir
762c9fc763 Refactor guide events and column placement handling 2026-05-04 23:06:23 +05:30
sudhir
848529acb0 Add column presets and procedural shaft controls 2026-05-04 16:38:52 +05:30
sudhir
46548c35e5 Fix curved wall and fence angle measurements 2026-05-04 11:29:01 +05:30
sudhir
f375861439 Merge branch 'main' of github.com:sudhir9297/editor into feat/improvement-and-fixes 2026-04-30 22:59:10 +05:30
sudhir
3d0000f93f Disable pointer events on item placement labels 2026-04-30 10:11:39 +05:30
Sudhir Yadav
9ff657419c
Merge branch 'main' into feat/upgrade-and-bug-fix 2026-04-29 10:49:11 +05:30
sudhir
e688792c34 Refactor first-person and spawn selection handling 2026-04-29 10:35:34 +05:30
Aymeric Rabot
2b588cd30f
fix: WebGPU renderer race on Canvas remount & duplicate item scale loss (#284)
Backport from monorepo PR #310 (fix/april-pass):

1. WebGPU renderer race on Canvas remount
   Cache the in-flight WebGPURenderer promise per canvas element so
   concurrent configure() calls from R3F's useLayoutEffect await the
   same init() instead of creating duplicate renderers. Fixes
   intermittent 'resolve target size does not match' errors when
   navigating between projects and home.

2. Duplicate item loses its scale
   Add scale to the field set in useDraftNode.commit() so duplicated
   items preserve their original scale instead of falling back to
   [1,1,1].

Co-authored-by: Pascal <open@pascal.app>
2026-04-28 12:42:08 -04:00
sudhir
15daeaace6 Standardize stair controls on slider inputs 2026-04-28 14:50:51 +05:30