fix(nodes/wall): let a hovered wall out of its batch so it can outline - #687
Merged
Conversation
Hover feedback for a wall is an outline, nothing else: `SelectionMaterialSync` skips walls outright and the cutaway pass tints only a selection or a delete hover, so `default`, `paint-ready` and `paint-disabled` all reduce to `outliner.hoveredObjects` and a colour. `MergedOutlineNode` draws that mask with `renderer.render(scene, camera)` on the main camera, which enables no `BATCHED_LAYER`. Once #608 sews a level's walls (wall mode `up`, 8+ walls, 180ms quiet) every wall on the floor is on that layer alone, so it reaches neither the depth pass nor a mask pass and hovering it lights up nothing at all. Selection looks fine only because `collectTintedWalls` already pulls a selected wall back out of the batch — the click lands, the wall starts drawing itself, and the outline appears. Hover had no such release, so on any finished floor the wall you point at goes dark: no hover outline in select mode, and in paint mode no preview of the surface the next click will paint. Release on any hover, not just a delete one. Same mechanism, one more reason: selection and delete tint through materials the merged mesh never reads, a plain hover outlines through a camera that never sees it, and both are fixed by the wall drawing its own geometry while it is lit. One wall is lit at a time, so the cost is the one extra draw call the delete path already accepted. Verified on a 12-wall level in the community editor: before, hovering a wall in `Full height` produced no outline in select or paint mode while `Cutaway` (where batching stands down) outlined correctly; after, both modes outline in `Full height`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hovering a wall on a finished floor lights up nothing — no hover outline in select mode, and in paint mode no preview of the surface the next click will paint. Selection looks fine, which is what makes it confusing.
Why
Hover feedback for a wall is an outline and nothing else.
SelectionMaterialSyncskips walls outright, and the cutaway pass tints only a selection or a delete hover — sodefault,paint-readyandpaint-disabledall reduce tooutliner.hoveredObjectsplus a colour.MergedOutlineNodedraws that mask withrenderer.render(scene, camera)on the main camera, which enables noBATCHED_LAYER. Once #608 sews a level's walls (wall modeup, 8+ walls, 180ms quiet) every wall on the floor is on that layer alone, so it reaches neither the depth pass nor a mask pass.Selection escapes this only because
collectTintedWallsalready pulls a selected wall back out of the batch: the click lands, the wall starts drawing itself, and the outline appears. Hover had no such release.Worth noting for anyone tracing this from #686: wall picking was never affected. The pointer handlers live on the
collision-meshchild, which batching never moves offSCENE_LAYER, and R3F raycasts each interaction object directly — so clicks always landed. Only the feedback was missing.Fix
Release on any hover, not just a delete one. Same mechanism, one more reason: selection and delete tint through materials the merged mesh never reads, a plain hover outlines through a camera that never sees it, and both are answered by the wall drawing its own geometry while it is lit. One wall is lit at a time, so the cost is the one extra draw call the delete path already accepted.
Verification
12-wall single-level project in the community editor, headless Chromium against a local dev server:
Full height(batching on)Cutaway(batching stands down)bun test srcinpackages/nodes: 1052 pass. Regression test added overcollectTintedWallsfor all four hover modes.🤖 Generated with Claude Code
Note
Low Risk
Small, localized change to wall batch exclusion logic with regression tests; no auth, data, or API impact.
Overview
Fixes missing hover outlines on batched walls when wall mode is
upand a level’s walls are merged into the batch mesh.collectTintedWallsnow treats any hovered wall ID like a lit wall (not only delete-mode hovers), so the batch system releases that wall to draw its own geometry again. That matches how selection already worked and is required for default/paint hovers, where feedback is an outline rendered through the main camera—which does not see walls on the batched layer.The function is exported for tests. New regression tests cover all four
hoverHighlightModevalues plus hovers on non-wall nodes (no release).Reviewed by Cursor Bugbot for commit e555cf6. Bugbot is set up for automated code reviews on this repo. Configure here.