From d17e083c7738d9f1e4d88c914a44ea0925b73ff8 Mon Sep 17 00:00:00 2001 From: Wassim SAMAD Date: Thu, 14 May 2026 15:01:56 -0400 Subject: [PATCH] Add sfx:grid-snap on cursor cell-cross for shelf + spawn Matches the wall / slab / curve-wall tool pattern: emit sfx:grid-snap only when the snapped position changes (cursor crosses a grid cell), not every frame of mouse movement within the same cell. Tracked via a `previousSnapRef` per tool, reset when the tool re-activates. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/nodes/src/shelf/tool.tsx | 10 ++++++++++ packages/nodes/src/spawn/tool.tsx | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/packages/nodes/src/shelf/tool.tsx b/packages/nodes/src/shelf/tool.tsx index f79bcf8e..769c5045 100644 --- a/packages/nodes/src/shelf/tool.tsx +++ b/packages/nodes/src/shelf/tool.tsx @@ -50,13 +50,23 @@ const PREVIEW_BRACKET_DEPTH = PREVIEW_DEPTH * 0.7 const ShelfTool = () => { const activeLevelId = useViewer((state) => state.selection.levelId) const cursorRef = useRef(null) + const previousSnapRef = useRef<[number, number] | null>(null) useEffect(() => { if (!activeLevelId) return + previousSnapRef.current = null const onGridMove = (event: GridEvent) => { const [sx, sz] = snapPointToGrid([event.localPosition[0], event.localPosition[2]], GRID_STEP) cursorRef.current?.position.set(sx, event.localPosition[1], sz) + + // Fire grid-snap SFX only when the snapped position crosses a cell, + // matching the wall / slab / curve tools. + const prev = previousSnapRef.current + if (!prev || prev[0] !== sx || prev[1] !== sz) { + triggerSFX('sfx:grid-snap') + previousSnapRef.current = [sx, sz] + } } const onGridClick = (event: GridEvent) => { diff --git a/packages/nodes/src/spawn/tool.tsx b/packages/nodes/src/spawn/tool.tsx index e441750b..21f98a23 100644 --- a/packages/nodes/src/spawn/tool.tsx +++ b/packages/nodes/src/spawn/tool.tsx @@ -41,9 +41,11 @@ function getLevelLocalPosition(levelId: string, event: GridEvent): [number, numb const SpawnTool = () => { const activeLevelId = useViewer((state) => state.selection.levelId) const cursorRef = useRef(null) + const previousSnapRef = useRef<[number, number] | null>(null) useEffect(() => { if (!activeLevelId) return + previousSnapRef.current = null const onGridMove = (event: GridEvent) => { // Cursor lives in the ToolManager's building-local group. Use @@ -52,6 +54,15 @@ const SpawnTool = () => { const nextX = roundToHalf(event.localPosition[0]) const nextZ = roundToHalf(event.localPosition[2]) cursorRef.current?.position.set(nextX, event.localPosition[1], nextZ) + + // Fire grid-snap SFX only when the snapped position crosses a cell, + // not every frame the mouse moves within the same cell. Matches the + // wall / slab / curve tools. + const prev = previousSnapRef.current + if (!prev || prev[0] !== nextX || prev[1] !== nextZ) { + triggerSFX('sfx:grid-snap') + previousSnapRef.current = [nextX, nextZ] + } } const onGridClick = (event: GridEvent) => {