Skip to content

fix: hidden walls stay ray targets while a door/window tool is active - #689

Open
Snoopy147 wants to merge 2 commits into
mainfrom
fix/door-drag-xray
Open

fix: hidden walls stay ray targets while a door/window tool is active#689
Snoopy147 wants to merge 2 commits into
mainfrom
fix/door-drag-xray

Conversation

@Snoopy147

@Snoopy147 Snoopy147 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

User report with Bones' X-ray on: dragging a door/window "disconnects, rotates in place in red 90° from the wall".

Root cause: #683 made hidden walls pointer-transparent (the outlet-click fix) — but the door/window MOVE and PLACE tools drive their entire cursor model from the wall pointer events those handlers emit. With hidden walls silent, the ray falls through to the ground grid, grid:move free-follows, and the opening detaches as a red world-axis-aligned ghost instead of sliding along its wall. Before #683 those drags worked in X-ray only by accident of the same defect that misfired outlet clicks.

Fix: a counter-based hidden-wall pointer HOLD in core (holdHiddenWallPointerEvents). The four wall-opening tools acquire it for their active lifetime; the wall renderer keeps pointer events flowing while a hold is live. No tool active = no hold, so plain selection clicks still pass through hidden walls — the night-5 outlet fix is intact (MoveRegistryNodeTool never touches the hold). Delete-mode hover keeps its exception. The gate predicate is extracted (wallPointerEventsSuppressed) so the truth table is pinned by tests without an R3F rig.

Tests: hold compose/idempotence + the suppression truth table. Verified live in X-ray: doors slide along their wall and commit with framing recomputing around the new opening; outlet click-through unchanged.

🤖 Generated with Claude Code


Note

Medium Risk
Touches editor pointer routing on hidden wall collision meshes across four tools and the wall renderer; behavior is test-backed but regressions could affect X-ray selection vs opening placement.

Overview
Fixes door/window move and place tools breaking in X-ray when walls are visually hidden but still have collision: those tools depend on wall:* events, so pointer-transparent hidden walls caused floor free-follow and a detached red ghost instead of sliding along the wall.

Adds a counter-based holdHiddenWallPointerEvents / hiddenWallPointerEventsHeld API in core (exported from @pascal-app/core). All four opening tools acquire a hold for their effect lifetime and release it on cleanup (idempotent release for safe React teardown).

Refactors the wall renderer gate into wallPointerEventsSuppressed: hidden walls stay pointer-transparent for plain selection (outlet click-through unchanged), but keep events when delete hover mode is active or any hidden-wall hold is live. Unit tests cover hold compose/idempotence and the suppression truth table.

Reviewed by Cursor Bugbot for commit 96d518e. Bugbot is set up for automated code reviews on this repo. Configure here.

Snoopy147 and others added 2 commits August 20, 2026 00:13
…ol is active

#683 made walls hidden by the wall-mode pass ('down' X-ray mode, cutaway
faces, auto-mode interior partitions) pointer-transparent so clicks reach
the visible device/service boxes behind their invisible full-height
collision meshes. But the door/window MOVE and PLACE tools drive their
whole cursor model from the wall pointer events those handlers emit
(wall:enter/move/click/leave): with hidden walls silent, the ray falls
through to the ground grid, grid:move free-follows, and the opening
detaches from its wall as a red world-axis-aligned ghost ("rotates in
place in red 90 degrees") instead of sliding along the wall. Before #683
those drags worked in X-ray only by accident of the same defect that
misfired outlet clicks.

Fix: a counter-based hidden-wall pointer HOLD in core
(holdHiddenWallPointerEvents / hiddenWallPointerEventsHeld). The four
wall-opening tools (door + window, move + place) acquire it for their
active lifetime; the wall renderer's gated handlers keep events flowing
while a hold is live. No tool active means no hold, so plain selection
clicks still pass through hidden walls — the night-5 D4 outlet fix is
intact (MoveRegistryNodeTool never touches the hold; its cursor is the
ground plane). Delete-mode hover keeps its existing exception. The gate
predicate is extracted to wallPointerEventsSuppressed so the truth table
is pinned by tests without an R3F rig.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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