Skip to content

Commit d3ca8e2

Browse files
committed
fix(nodes): recreate door draft on wall:move when null after placement
Mirror of the window fix one commit back: after click-to-place the DoorTool deletes its transient draft and relies on the wall-rebuild \u2192 R3F pointer-enter cascade to spawn a fresh draft for the next placement. When that cascade doesn't fire synchronously, the next wall:move sees a null draftRef and bails \u2014 forcing a leave/re-enter to place again. Recreate the draft in onWallMove when null and over a valid wall on the current level. Idempotent with onWallEnter (destroyDraft cleans up if both fire).
1 parent 05a89b9 commit d3ca8e2

1 file changed

Lines changed: 20 additions & 0 deletions

File tree

packages/nodes/src/door/tool.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,26 @@ const DoorTool: React.FC = () => {
172172

173173
const { clampedX, clampedY } = clampToWall(event.node, localX, width, height)
174174

175+
// Draft may be null after a successful placement (the click handler
176+
// deletes it and relies on the wall rebuild → pointer-enter cascade to
177+
// recreate it). Recreate it here on the first subsequent move so the
178+
// preview is ready for the next click without requiring a leave/enter.
179+
if (!draftRef.current) {
180+
const levelId = getLevelId()
181+
if (levelId && event.node.parentId === levelId) {
182+
const node = DoorNode.parse({
183+
position: [clampedX, clampedY, 0],
184+
rotation: [0, itemRotation, 0],
185+
side,
186+
wallId: event.node.id,
187+
parentId: event.node.id,
188+
metadata: { isTransient: true },
189+
})
190+
useScene.getState().createNode(node, event.node.id as AnyNodeId)
191+
draftRef.current = node
192+
}
193+
}
194+
175195
if (draftRef.current) {
176196
// Update the scene store on every move so the 2D floor plan
177197
// stays in sync (it re-renders from `node.position`). Only

0 commit comments

Comments
 (0)