From 531dbb6e68e21f240fa1c517ea2f2f0c14835279 Mon Sep 17 00:00:00 2001 From: Wassim SAMAD Date: Wed, 17 Jun 2026 09:36:58 -0400 Subject: [PATCH] perf(post-processing): don't rebuild the pipeline on hover + temp paint debug logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - post-processing: hoverHighlightMode was a dependency of the pipeline-build effect, so every hover rebuilt the entire pipeline. The hover style is already pushed to uniforms in a separate effect, so the rebuild was pure waste — removed it from the deps (and the build log). - selection-manager: temporary [paint-debug] logs for window/door hover to trace why their paint dispatch drops (to be removed once diagnosed). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../components/editor/selection-manager.tsx | 24 +++++++++++++++++++ .../src/components/viewer/post-processing.tsx | 6 +++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/components/editor/selection-manager.tsx b/packages/editor/src/components/editor/selection-manager.tsx index ffaf5aa8..a7b28095 100644 --- a/packages/editor/src/components/editor/selection-manager.tsx +++ b/packages/editor/src/components/editor/selection-manager.tsx @@ -871,6 +871,14 @@ export const SelectionManager = () => { const activePaintMaterial = resolveActivePaintMaterial() const node = event.node + // TEMP paint debug + if (node.type === 'window' || node.type === 'door') { + // biome-ignore lint/suspicious/noConsole: temporary paint diagnostics + console.log('[paint-debug] event arrived', node.type, { + inLevel: isNodeInCurrentLevel(node), + }) + } + if (!isNodeInCurrentLevel(node)) return null // The eraser clears a surface back to its default by painting with an @@ -898,6 +906,18 @@ export const SelectionManager = () => { // roof / stair / single-surface arms below stay until they // migrate too. const paintCap = nodeRegistry.get(node.type)?.capabilities?.paint + // TEMP paint debug + if (node.type === 'window' || node.type === 'door') { + const ho = getEventObject(event) + // biome-ignore lint/suspicious/noConsole: temporary paint diagnostics + console.log('[paint-debug] getPaintInteraction', node.type, { + hasPaintCap: !!paintCap, + hitObjName: ho?.name, + hitSlotId: (ho?.userData as { slotId?: string } | undefined)?.slotId, + eventObjName: event.nativeEvent.object?.name, + paintEnabled, + }) + } if (paintCap) { const materialIndex = getIntersectionMaterialIndex(getEventObject(event), event.faceIndex) const role = paintCap.resolveRole({ @@ -908,6 +928,10 @@ export const SelectionManager = () => { hitObjectName: event.nativeEvent.object?.name, hitObject: getEventObject(event), }) + if (node.type === 'window' || node.type === 'door') { + // biome-ignore lint/suspicious/noConsole: temporary paint diagnostics + console.log('[paint-debug] resolved role', node.type, role) + } const compatible = role !== null && paintEnabled return { key: `${node.type}:${node.id}:${role ?? 'unsupported'}:${eraser ? 'erase' : 'paint'}`, diff --git a/packages/viewer/src/components/viewer/post-processing.tsx b/packages/viewer/src/components/viewer/post-processing.tsx index 67645cf5..301ccec4 100644 --- a/packages/viewer/src/components/viewer/post-processing.tsx +++ b/packages/viewer/src/components/viewer/post-processing.tsx @@ -280,7 +280,6 @@ const PostProcessingPasses = ({ denoise: denoiseEnabled, outline: outlineEnabled, perfDisable, - hoverHighlightMode, projectId, shading, rendererCtor: (renderer as any).constructor?.name, @@ -487,9 +486,12 @@ const PostProcessingPasses = ({ renderPipelineRef.current = null } }, [ + // NOTE: hoverHighlightMode intentionally excluded — the hover style is + // pushed to uniforms in a separate effect, so a hover must NOT rebuild the + // whole pipeline. The uniform refs below are stable (useMemo), so they + // never trigger a rebuild either. camera, hoverHiddenColor, - hoverHighlightMode, hoverPulseMix, hoverStrength, hoverVisibleColor,