fix(editor): shelf deletion plays item-delete SFX; refresh delete sounds (#379)
* fix(editor): shelf deletion plays item-delete SFX; refresh delete sounds Shelves are furniture-like placeable objects, so deleting one should use the lighter item-delete cue instead of the structure-delete one. Add a shared emitDeleteSFX(nodeType) helper that maps item-like node types (item, shelf) to item-delete and everything else to structure-delete, and route the three delete sites (sledgehammer, floating action menu, keyboard) through it. Also refresh the item_delete/structure_delete audio assets and reduce their pan jitter for a steadier delete cue. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(editor): update item_delete SFX asset Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1419709131
commit
dd0215643b
Binary file not shown.
Binary file not shown.
@@ -33,7 +33,7 @@ import { useFrame } from '@react-three/fiber'
|
|||||||
import { useCallback, useRef } from 'react'
|
import { useCallback, useRef } from 'react'
|
||||||
import * as THREE from 'three'
|
import * as THREE from 'three'
|
||||||
import { duplicateRoofSubtree } from '../../lib/roof-duplication'
|
import { duplicateRoofSubtree } from '../../lib/roof-duplication'
|
||||||
import { sfxEmitter } from '../../lib/sfx-bus'
|
import { emitDeleteSFX, sfxEmitter } from '../../lib/sfx-bus'
|
||||||
import { duplicateStairSubtree } from '../../lib/stair-duplication'
|
import { duplicateStairSubtree } from '../../lib/stair-duplication'
|
||||||
import useEditor from '../../store/use-editor'
|
import useEditor from '../../store/use-editor'
|
||||||
import { formatMeasurement, MeasurementPill } from './measurement-pill'
|
import { formatMeasurement, MeasurementPill } from './measurement-pill'
|
||||||
@@ -514,11 +514,7 @@ export function FloatingActionMenu() {
|
|||||||
(e: React.MouseEvent) => {
|
(e: React.MouseEvent) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
if (!selectedId) return
|
if (!selectedId) return
|
||||||
if (node?.type === 'item') {
|
emitDeleteSFX(node?.type)
|
||||||
sfxEmitter.emit('sfx:item-delete')
|
|
||||||
} else {
|
|
||||||
sfxEmitter.emit('sfx:structure-delete')
|
|
||||||
}
|
|
||||||
setSelection({ selectedIds: [] })
|
setSelection({ selectedIds: [] })
|
||||||
useScene.getState().deleteNode(selectedId as AnyNodeId)
|
useScene.getState().deleteNode(selectedId as AnyNodeId)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ import {
|
|||||||
hasActivePaintMaterial,
|
hasActivePaintMaterial,
|
||||||
resolveActivePaintMaterialFromSelection,
|
resolveActivePaintMaterialFromSelection,
|
||||||
} from '../../lib/material-paint'
|
} from '../../lib/material-paint'
|
||||||
import { sfxEmitter } from '../../lib/sfx-bus'
|
import { emitDeleteSFX } from '../../lib/sfx-bus'
|
||||||
import useEditor, {
|
import useEditor, {
|
||||||
type MaterialTargetRole,
|
type MaterialTargetRole,
|
||||||
type Phase,
|
type Phase,
|
||||||
@@ -1555,11 +1555,7 @@ export const SelectionManager = () => {
|
|||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
|
||||||
// Play appropriate SFX
|
// Play appropriate SFX
|
||||||
if (node.type === 'item') {
|
emitDeleteSFX(node.type)
|
||||||
sfxEmitter.emit('sfx:item-delete')
|
|
||||||
} else {
|
|
||||||
sfxEmitter.emit('sfx:structure-delete')
|
|
||||||
}
|
|
||||||
|
|
||||||
useScene.getState().deleteNode(node.id as AnyNodeId)
|
useScene.getState().deleteNode(node.id as AnyNodeId)
|
||||||
if (node.parentId) useScene.getState().dirtyNodes.add(node.parentId as AnyNodeId)
|
if (node.parentId) useScene.getState().dirtyNodes.add(node.parentId as AnyNodeId)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
copySelectedNodesToEditorClipboard,
|
copySelectedNodesToEditorClipboard,
|
||||||
pasteEditorClipboardToLevel,
|
pasteEditorClipboardToLevel,
|
||||||
} from '../lib/scene-clipboard'
|
} from '../lib/scene-clipboard'
|
||||||
import { sfxEmitter } from '../lib/sfx-bus'
|
import { emitDeleteSFX, sfxEmitter } from '../lib/sfx-bus'
|
||||||
import { toggleWindowOpenState } from '../lib/window-interaction'
|
import { toggleWindowOpenState } from '../lib/window-interaction'
|
||||||
import useEditor from '../store/use-editor'
|
import useEditor from '../store/use-editor'
|
||||||
|
|
||||||
@@ -322,11 +322,7 @@ export const useKeyboard = ({
|
|||||||
// Play appropriate SFX based on what's being deleted
|
// Play appropriate SFX based on what's being deleted
|
||||||
if (selectedNodeIds.length === 1) {
|
if (selectedNodeIds.length === 1) {
|
||||||
const node = useScene.getState().nodes[selectedNodeIds[0]!]
|
const node = useScene.getState().nodes[selectedNodeIds[0]!]
|
||||||
if (node?.type === 'item') {
|
emitDeleteSFX(node?.type)
|
||||||
sfxEmitter.emit('sfx:item-delete')
|
|
||||||
} else {
|
|
||||||
sfxEmitter.emit('sfx:structure-delete')
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
sfxEmitter.emit('sfx:structure-delete')
|
sfxEmitter.emit('sfx:structure-delete')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,3 +55,19 @@ export function initSFXBus() {
|
|||||||
export function triggerSFX(event: keyof SFXEvents) {
|
export function triggerSFX(event: keyof SFXEvents) {
|
||||||
sfxEmitter.emit(event)
|
sfxEmitter.emit(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node types whose deletion should use the lighter item-delete cue rather
|
||||||
|
* than the heavier structure-delete one. Shelves are furniture-like placeable
|
||||||
|
* objects, so they sound like items being removed, not structures demolished.
|
||||||
|
*/
|
||||||
|
const ITEM_DELETE_NODE_TYPES = new Set(['item', 'shelf'])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emit the delete SFX appropriate for a deleted node's type.
|
||||||
|
*/
|
||||||
|
export function emitDeleteSFX(nodeType: string | undefined) {
|
||||||
|
sfxEmitter.emit(
|
||||||
|
nodeType && ITEM_DELETE_NODE_TYPES.has(nodeType) ? 'sfx:item-delete' : 'sfx:structure-delete',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export const SFX: Record<string, SFXConfig> = {
|
|||||||
src: '/audios/sfx/item_delete.mp3',
|
src: '/audios/sfx/item_delete.mp3',
|
||||||
rateRange: [0.9, 1.1],
|
rateRange: [0.9, 1.1],
|
||||||
volumeRange: [0.9, 1.0],
|
volumeRange: [0.9, 1.0],
|
||||||
panJitter: 0.15,
|
panJitter: 0.05,
|
||||||
},
|
},
|
||||||
itemPick: {
|
itemPick: {
|
||||||
src: '/audios/sfx/item_pick.mp3',
|
src: '/audios/sfx/item_pick.mp3',
|
||||||
@@ -77,7 +77,7 @@ export const SFX: Record<string, SFXConfig> = {
|
|||||||
src: '/audios/sfx/structure_delete.mp3',
|
src: '/audios/sfx/structure_delete.mp3',
|
||||||
rateRange: [0.9, 1.1],
|
rateRange: [0.9, 1.1],
|
||||||
volumeRange: [0.9, 1.0],
|
volumeRange: [0.9, 1.0],
|
||||||
panJitter: 0.15,
|
panJitter: 0.08,
|
||||||
},
|
},
|
||||||
snapshotCapture: {
|
snapshotCapture: {
|
||||||
// Shutter should sound consistent — no variation.
|
// Shutter should sound consistent — no variation.
|
||||||
|
|||||||
Reference in New Issue
Block a user