@pascal-app/viewer 1.0.7 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +209 -19
- package/dist/components/viewer/drone-controller.d.ts.map +1 -1
- package/dist/components/viewer/drone-controller.js +1 -5
- package/dist/components/viewer/first-person/build-collider-world.d.ts +14 -0
- package/dist/components/viewer/first-person/build-collider-world.d.ts.map +1 -0
- package/dist/components/viewer/first-person/build-collider-world.js +426 -0
- package/dist/components/viewer/first-person/ground-holes.d.ts +22 -0
- package/dist/components/viewer/first-person/ground-holes.d.ts.map +1 -0
- package/dist/components/viewer/first-person/ground-holes.js +116 -0
- package/dist/components/viewer/first-person/mechanism-targets.d.ts +27 -0
- package/dist/components/viewer/first-person/mechanism-targets.d.ts.map +1 -0
- package/dist/components/viewer/first-person/mechanism-targets.js +79 -0
- package/dist/components/viewer/first-person/terrain-collider.d.ts +32 -0
- package/dist/components/viewer/first-person/terrain-collider.d.ts.map +1 -0
- package/dist/components/viewer/first-person/terrain-collider.js +175 -0
- package/dist/components/viewer/glb-replace-instances.d.ts +6 -3
- package/dist/components/viewer/glb-replace-instances.d.ts.map +1 -1
- package/dist/components/viewer/glb-replace-instances.js +5 -4
- package/dist/components/viewer/glb-scene.d.ts +3 -1
- package/dist/components/viewer/glb-scene.d.ts.map +1 -1
- package/dist/components/viewer/glb-scene.js +2 -1
- package/dist/components/viewer/glb-walkthrough-controller.d.ts +1 -1
- package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -1
- package/dist/components/viewer/glb-walkthrough-controller.js +3 -4
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +8 -4
- package/dist/components/viewer/live-walkthrough-controller.d.ts +17 -0
- package/dist/components/viewer/live-walkthrough-controller.d.ts.map +1 -0
- package/dist/components/viewer/live-walkthrough-controller.js +1449 -0
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +22 -1
- package/dist/components/viewer/registered-systems.d.ts.map +1 -1
- package/dist/components/viewer/registered-systems.js +2 -2
- package/dist/components/viewer/unsupported-gpu-fallback.d.ts.map +1 -1
- package/dist/components/viewer/unsupported-gpu-fallback.js +21 -1
- package/dist/components/viewer/use-daylight-rooms.d.ts.map +1 -1
- package/dist/components/viewer/use-daylight-rooms.js +75 -33
- package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
- package/dist/hooks/use-gltf-ktx2.js +2 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/lib/asset-url.d.ts +0 -1
- package/dist/lib/asset-url.d.ts.map +1 -1
- package/dist/lib/asset-url.js +3 -3
- package/dist/lib/daylight/room-context.d.ts.map +1 -1
- package/dist/lib/daylight/room-context.js +3 -2
- package/dist/lib/daylight/room-map.d.ts +149 -0
- package/dist/lib/daylight/room-map.d.ts.map +1 -0
- package/dist/lib/daylight/room-map.js +813 -0
- package/dist/lib/daylight/room-scene.d.ts +4 -2
- package/dist/lib/daylight/room-scene.d.ts.map +1 -1
- package/dist/lib/daylight/room-scene.js +81 -40
- package/dist/lib/daylight/rooms.d.ts +71 -32
- package/dist/lib/daylight/rooms.d.ts.map +1 -1
- package/dist/lib/daylight/rooms.js +371 -286
- package/dist/lib/ktx2-loader.d.ts.map +1 -1
- package/dist/lib/ktx2-loader.js +2 -1
- package/dist/lib/measurement-label.d.ts +4 -0
- package/dist/lib/measurement-label.d.ts.map +1 -0
- package/dist/lib/measurement-label.js +54 -0
- package/dist/lib/measurement-presentation.d.ts +7 -0
- package/dist/lib/measurement-presentation.d.ts.map +1 -0
- package/dist/lib/measurement-presentation.js +14 -0
- package/dist/lib/pointer-events.d.ts.map +1 -1
- package/dist/lib/pointer-events.js +3 -3
- package/dist/lib/texture-reference.d.ts.map +1 -1
- package/dist/lib/texture-reference.js +4 -3
- package/dist/lib/typing-target.d.ts +2 -0
- package/dist/lib/typing-target.d.ts.map +1 -0
- package/dist/lib/typing-target.js +7 -0
- package/dist/lib/viewer-config.d.ts +27 -0
- package/dist/lib/viewer-config.d.ts.map +1 -0
- package/dist/lib/viewer-config.js +23 -0
- package/dist/lib/viewer-preference-storage.d.ts +7 -0
- package/dist/lib/viewer-preference-storage.d.ts.map +1 -0
- package/dist/lib/viewer-preference-storage.js +23 -0
- package/dist/sfx/audio-settings.d.ts +81 -0
- package/dist/sfx/audio-settings.d.ts.map +1 -0
- package/dist/sfx/audio-settings.js +166 -0
- package/dist/sfx/index.d.ts +6 -0
- package/dist/sfx/index.d.ts.map +1 -0
- package/dist/sfx/index.js +5 -0
- package/dist/sfx/interaction-sounds.d.ts +7 -0
- package/dist/sfx/interaction-sounds.d.ts.map +1 -0
- package/dist/sfx/interaction-sounds.js +39 -0
- package/dist/sfx/player.d.ts +31 -0
- package/dist/sfx/player.d.ts.map +1 -0
- package/dist/sfx/player.js +255 -0
- package/dist/sfx/sounds.d.ts +60 -0
- package/dist/sfx/sounds.d.ts.map +1 -0
- package/dist/sfx/sounds.js +25 -0
- package/dist/sfx/use-viewer-ui-sounds.d.ts +8 -0
- package/dist/sfx/use-viewer-ui-sounds.d.ts.map +1 -0
- package/dist/sfx/use-viewer-ui-sounds.js +42 -0
- package/dist/store/use-first-person-hud.d.ts +13 -0
- package/dist/store/use-first-person-hud.d.ts.map +1 -0
- package/dist/store/use-first-person-hud.js +21 -0
- package/dist/store/use-viewer.d.ts +2 -56
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +3 -1
- package/dist/systems/elevator/elevator-interaction-system.d.ts +16 -2
- package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -1
- package/dist/systems/elevator/elevator-interaction-system.js +41 -8
- package/dist/systems/geometry/geometry-status.d.ts +8 -0
- package/dist/systems/geometry/geometry-status.d.ts.map +1 -0
- package/dist/systems/geometry/geometry-status.js +24 -0
- package/dist/systems/roof/roof-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-system.js +134 -78
- package/dist/systems/wall/wall-system.d.ts +11 -0
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +56 -10
- package/dist/ui/components/action-button.d.ts +14 -0
- package/dist/ui/components/action-button.d.ts.map +1 -0
- package/dist/ui/components/action-button.js +21 -0
- package/dist/ui/components/action-menu-placement.d.ts +7 -0
- package/dist/ui/components/action-menu-placement.d.ts.map +1 -0
- package/dist/ui/components/action-menu-placement.js +10 -0
- package/dist/ui/components/floorplan-compass-button.d.ts +10 -0
- package/dist/ui/components/floorplan-compass-button.d.ts.map +1 -0
- package/dist/ui/components/floorplan-compass-button.js +22 -0
- package/dist/ui/components/follow-pascal-toggle.d.ts +6 -0
- package/dist/ui/components/follow-pascal-toggle.d.ts.map +1 -0
- package/dist/ui/components/follow-pascal-toggle.js +21 -0
- package/dist/ui/components/localized-html.d.ts +9 -0
- package/dist/ui/components/localized-html.d.ts.map +1 -0
- package/dist/ui/components/localized-html.js +16 -0
- package/dist/ui/components/render-settings-menu.d.ts +9 -0
- package/dist/ui/components/render-settings-menu.d.ts.map +1 -0
- package/dist/ui/components/render-settings-menu.js +145 -0
- package/dist/ui/components/rooms/room-highlight.d.ts +10 -0
- package/dist/ui/components/rooms/room-highlight.d.ts.map +1 -0
- package/dist/ui/components/rooms/room-highlight.js +56 -0
- package/dist/ui/components/rooms/room-labels.d.ts +278 -0
- package/dist/ui/components/rooms/room-labels.d.ts.map +1 -0
- package/dist/ui/components/rooms/room-labels.js +1295 -0
- package/dist/ui/components/rooms/viewer-rooms.d.ts +14 -0
- package/dist/ui/components/rooms/viewer-rooms.d.ts.map +1 -0
- package/dist/ui/components/rooms/viewer-rooms.js +123 -0
- package/dist/ui/components/scene-loader.d.ts +18 -0
- package/dist/ui/components/scene-loader.d.ts.map +1 -0
- package/dist/ui/components/scene-loader.js +29 -0
- package/dist/ui/components/sky-control.d.ts +37 -0
- package/dist/ui/components/sky-control.d.ts.map +1 -0
- package/dist/ui/components/sky-control.js +382 -0
- package/dist/ui/components/use-viewer-camera-navigation-sync.d.ts +4 -0
- package/dist/ui/components/use-viewer-camera-navigation-sync.d.ts.map +1 -0
- package/dist/ui/components/use-viewer-camera-navigation-sync.js +117 -0
- package/dist/ui/components/viewer-controls-bar.d.ts +20 -0
- package/dist/ui/components/viewer-controls-bar.d.ts.map +1 -0
- package/dist/ui/components/viewer-controls-bar.js +130 -0
- package/dist/ui/components/viewer-hover-label.d.ts +14 -0
- package/dist/ui/components/viewer-hover-label.d.ts.map +1 -0
- package/dist/ui/components/viewer-hover-label.js +28 -0
- package/dist/ui/components/viewer-scene-header.d.ts +34 -0
- package/dist/ui/components/viewer-scene-header.d.ts.map +1 -0
- package/dist/ui/components/viewer-scene-header.js +92 -0
- package/dist/ui/components/viewer-selection-manager.d.ts +7 -0
- package/dist/ui/components/viewer-selection-manager.d.ts.map +1 -0
- package/dist/ui/components/viewer-selection-manager.js +116 -0
- package/dist/ui/components/viewer-stage-modes.d.ts +7 -0
- package/dist/ui/components/viewer-stage-modes.d.ts.map +1 -0
- package/dist/ui/components/viewer-stage-modes.js +42 -0
- package/dist/ui/components/viewer-stage-switcher.d.ts +10 -0
- package/dist/ui/components/viewer-stage-switcher.d.ts.map +1 -0
- package/dist/ui/components/viewer-stage-switcher.js +16 -0
- package/dist/ui/components/viewer-stage.d.ts +25 -0
- package/dist/ui/components/viewer-stage.d.ts.map +1 -0
- package/dist/ui/components/viewer-stage.js +107 -0
- package/dist/ui/components/walkthrough-hud.d.ts +29 -0
- package/dist/ui/components/walkthrough-hud.d.ts.map +1 -0
- package/dist/ui/components/walkthrough-hud.js +55 -0
- package/dist/ui/floorplan/floorplan-camera-sync.d.ts +22 -0
- package/dist/ui/floorplan/floorplan-camera-sync.d.ts.map +1 -0
- package/dist/ui/floorplan/floorplan-camera-sync.js +157 -0
- package/dist/ui/floorplan/floorplan-dimension-renderer.d.ts +61 -0
- package/dist/ui/floorplan/floorplan-dimension-renderer.d.ts.map +1 -0
- package/dist/ui/floorplan/floorplan-dimension-renderer.js +280 -0
- package/dist/ui/floorplan/floorplan-geometry-renderer.d.ts +54 -0
- package/dist/ui/floorplan/floorplan-geometry-renderer.d.ts.map +1 -0
- package/dist/ui/floorplan/floorplan-geometry-renderer.js +317 -0
- package/dist/ui/floorplan/floorplan-label-angle.d.ts +24 -0
- package/dist/ui/floorplan/floorplan-label-angle.d.ts.map +1 -0
- package/dist/ui/floorplan/floorplan-label-angle.js +60 -0
- package/dist/ui/floorplan/floorplan-navigation-sync.d.ts +18 -0
- package/dist/ui/floorplan/floorplan-navigation-sync.d.ts.map +1 -0
- package/dist/ui/floorplan/floorplan-navigation-sync.js +41 -0
- package/dist/ui/floorplan/floorplan-preview-geometry.d.ts +26 -0
- package/dist/ui/floorplan/floorplan-preview-geometry.d.ts.map +1 -0
- package/dist/ui/floorplan/floorplan-preview-geometry.js +173 -0
- package/dist/ui/floorplan/floorplan-preview-navigation.d.ts +22 -0
- package/dist/ui/floorplan/floorplan-preview-navigation.d.ts.map +1 -0
- package/dist/ui/floorplan/floorplan-preview-navigation.js +41 -0
- package/dist/ui/floorplan/floorplan-preview-visibility.d.ts +8 -0
- package/dist/ui/floorplan/floorplan-preview-visibility.d.ts.map +1 -0
- package/dist/ui/floorplan/floorplan-preview-visibility.js +21 -0
- package/dist/ui/floorplan/floorplan-preview.d.ts +19 -0
- package/dist/ui/floorplan/floorplan-preview.d.ts.map +1 -0
- package/dist/ui/floorplan/floorplan-preview.js +700 -0
- package/dist/ui/hooks/use-mobile.d.ts +2 -0
- package/dist/ui/hooks/use-mobile.d.ts.map +1 -0
- package/dist/ui/hooks/use-mobile.js +14 -0
- package/dist/ui/index.d.ts +49 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +48 -0
- package/dist/ui/lib/below-grade.d.ts +38 -0
- package/dist/ui/lib/below-grade.d.ts.map +1 -0
- package/dist/ui/lib/below-grade.js +102 -0
- package/dist/ui/lib/camera-pose.d.ts +19 -0
- package/dist/ui/lib/camera-pose.d.ts.map +1 -0
- package/dist/ui/lib/camera-pose.js +113 -0
- package/dist/ui/lib/cn.d.ts +3 -0
- package/dist/ui/lib/cn.d.ts.map +1 -0
- package/dist/ui/lib/cn.js +5 -0
- package/dist/ui/lib/level-name.d.ts +10 -0
- package/dist/ui/lib/level-name.d.ts.map +1 -0
- package/dist/ui/lib/level-name.js +33 -0
- package/dist/ui/lib/node-display-label.d.ts +8 -0
- package/dist/ui/lib/node-display-label.d.ts.map +1 -0
- package/dist/ui/lib/node-display-label.js +36 -0
- package/dist/ui/lib/room-area.d.ts +3 -0
- package/dist/ui/lib/room-area.d.ts.map +1 -0
- package/dist/ui/lib/room-area.js +8 -0
- package/dist/ui/lib/room-assembly-overlay.d.ts +46 -0
- package/dist/ui/lib/room-assembly-overlay.d.ts.map +1 -0
- package/dist/ui/lib/room-assembly-overlay.js +222 -0
- package/dist/ui/lib/room-name-messages.d.ts +28 -0
- package/dist/ui/lib/room-name-messages.d.ts.map +1 -0
- package/dist/ui/lib/room-name-messages.js +112 -0
- package/dist/ui/lib/room-selection.d.ts +58 -0
- package/dist/ui/lib/room-selection.d.ts.map +1 -0
- package/dist/ui/lib/room-selection.js +297 -0
- package/dist/ui/lib/scene-theme-name.d.ts +4 -0
- package/dist/ui/lib/scene-theme-name.d.ts.map +1 -0
- package/dist/ui/lib/scene-theme-name.js +22 -0
- package/dist/ui/lib/selection-modifiers.d.ts +20 -0
- package/dist/ui/lib/selection-modifiers.d.ts.map +1 -0
- package/dist/ui/lib/selection-modifiers.js +15 -0
- package/dist/ui/lib/viewer-selection.d.ts +132 -0
- package/dist/ui/lib/viewer-selection.d.ts.map +1 -0
- package/dist/ui/lib/viewer-selection.js +462 -0
- package/dist/ui/lib/zone-content.d.ts +6 -0
- package/dist/ui/lib/zone-content.d.ts.map +1 -0
- package/dist/ui/lib/zone-content.js +96 -0
- package/dist/ui/primitives/button.d.ts +11 -0
- package/dist/ui/primitives/button.d.ts.map +1 -0
- package/dist/ui/primitives/button.js +35 -0
- package/dist/ui/primitives/dropdown-menu.d.ts +26 -0
- package/dist/ui/primitives/dropdown-menu.d.ts.map +1 -0
- package/dist/ui/primitives/dropdown-menu.js +53 -0
- package/dist/ui/primitives/popover.d.ts +8 -0
- package/dist/ui/primitives/popover.d.ts.map +1 -0
- package/dist/ui/primitives/popover.js +17 -0
- package/dist/ui/primitives/switch.d.ts +5 -0
- package/dist/ui/primitives/switch.d.ts.map +1 -0
- package/dist/ui/primitives/switch.js +8 -0
- package/dist/ui/primitives/tooltip.d.ts +8 -0
- package/dist/ui/primitives/tooltip.d.ts.map +1 -0
- package/dist/ui/primitives/tooltip.js +17 -0
- package/dist/ui/store/camera-pose-store.d.ts +17 -0
- package/dist/ui/store/camera-pose-store.d.ts.map +1 -0
- package/dist/ui/store/camera-pose-store.js +15 -0
- package/dist/ui/store/navigation-sync-pose-store.d.ts +26 -0
- package/dist/ui/store/navigation-sync-pose-store.d.ts.map +1 -0
- package/dist/ui/store/navigation-sync-pose-store.js +16 -0
- package/dist/ui/store/use-follow-pascal.d.ts +30 -0
- package/dist/ui/store/use-follow-pascal.d.ts.map +1 -0
- package/dist/ui/store/use-follow-pascal.js +28 -0
- package/dist/ui/theme.css +339 -0
- package/package.json +34 -7
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type SoundName } from './sounds';
|
|
2
|
+
/** A host cue with filenames relative to the configured SFX base URL. */
|
|
3
|
+
export type SoundDefinition = {
|
|
4
|
+
src: string | string[];
|
|
5
|
+
rateRange?: [number, number];
|
|
6
|
+
volumeRange?: [number, number];
|
|
7
|
+
minIntervalMs?: number;
|
|
8
|
+
loop?: boolean;
|
|
9
|
+
volumeMultiplier?: number;
|
|
10
|
+
fadeInMs?: number;
|
|
11
|
+
fadeOutMs?: number;
|
|
12
|
+
};
|
|
13
|
+
/** Per-play gain, stereo position and local/remote repeat suppression. */
|
|
14
|
+
export type SoundPlaybackOptions = {
|
|
15
|
+
source?: 'local' | 'remote';
|
|
16
|
+
stereo?: number;
|
|
17
|
+
volumeMultiplier?: number;
|
|
18
|
+
};
|
|
19
|
+
/** Warm built-in cues and optional host cues without playing them. */
|
|
20
|
+
export declare function preloadSounds(extraSounds?: readonly SoundDefinition[]): void;
|
|
21
|
+
/** Unload the shared sound cache and detach its settings subscription. */
|
|
22
|
+
export declare function disposeSounds(): void;
|
|
23
|
+
/** Start a host-defined loop, fading out the previously active loop. */
|
|
24
|
+
export declare function startSoundLoop(name: SoundDefinition): void;
|
|
25
|
+
/** Fade out the active loop and cancel any pending loop playback. */
|
|
26
|
+
export declare function stopSoundLoop(): void;
|
|
27
|
+
/** Play a built-in cue or host definition using the shared audio settings. */
|
|
28
|
+
export declare function playSound(sound: SoundName | SoundDefinition, options?: SoundPlaybackOptions): void;
|
|
29
|
+
/** Apply current volume and mute settings to cached sounds and the active loop. */
|
|
30
|
+
export declare function updateSoundVolumes(): void;
|
|
31
|
+
//# sourceMappingURL=player.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../src/sfx/player.ts"],"names":[],"mappings":"AAGA,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,UAAU,CAAA;AAEjD,yEAAyE;AACzE,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACtB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,0EAA0E;AAC1E,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,CAAA;AA4ED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,WAAW,GAAE,SAAS,eAAe,EAAO,QA6BzE;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,SAK5B;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,IAAI,EAAE,eAAe,QA4CnD;AAED,qEAAqE;AACrE,wBAAgB,aAAa,SAK5B;AAED,8EAA8E;AAC9E,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,eAAe,EAAE,OAAO,GAAE,oBAAyB,QA2D/F;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,SAuBjC"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { Howl, Howler } from 'howler';
|
|
2
|
+
import { getViewerConfig } from '../lib/viewer-config';
|
|
3
|
+
import { useAudioSettings } from './audio-settings';
|
|
4
|
+
import { SOUNDS } from './sounds';
|
|
5
|
+
const DEFAULT_MIN_INTERVAL_MS = 30;
|
|
6
|
+
const SFX_FAILURE_BACKOFF_MS = 5_000;
|
|
7
|
+
const DEFAULT_LOOP_FADE_MS = 90;
|
|
8
|
+
function randomInRange([min, max]) {
|
|
9
|
+
return min + Math.random() * (max - min);
|
|
10
|
+
}
|
|
11
|
+
const sfxCache = new Map();
|
|
12
|
+
let cachedBaseUrl = null;
|
|
13
|
+
let unsubscribeAudio = null;
|
|
14
|
+
const definitions = new Set();
|
|
15
|
+
let sfxAudioContext = null;
|
|
16
|
+
let sfxRetryAfter = 0;
|
|
17
|
+
const lastPlayedAt = new Map();
|
|
18
|
+
const lastVariation = new Map();
|
|
19
|
+
let activeLoop = null;
|
|
20
|
+
let pendingLoop = null;
|
|
21
|
+
let requestedLoop = null;
|
|
22
|
+
function loopVolume(name) {
|
|
23
|
+
const { masterVolume, sfxVolume } = useAudioSettings.getState();
|
|
24
|
+
return (masterVolume / 100) * (sfxVolume / 100) * (name.volumeMultiplier ?? 1);
|
|
25
|
+
}
|
|
26
|
+
function stopActiveLoop(fadeMs) {
|
|
27
|
+
const active = activeLoop;
|
|
28
|
+
if (!active)
|
|
29
|
+
return;
|
|
30
|
+
activeLoop = null;
|
|
31
|
+
if (fadeMs <= 0) {
|
|
32
|
+
active.sound.stop(active.id);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
active.sound.once('fade', () => active.sound.stop(active.id), active.id);
|
|
36
|
+
active.sound.fade(active.volume, 0, fadeMs, active.id);
|
|
37
|
+
}
|
|
38
|
+
function unloadCachedSounds(resetPlaybackState) {
|
|
39
|
+
requestedLoop = null;
|
|
40
|
+
pendingLoop = null;
|
|
41
|
+
stopActiveLoop(0);
|
|
42
|
+
for (const sounds of sfxCache.values()) {
|
|
43
|
+
for (const sound of sounds) {
|
|
44
|
+
try {
|
|
45
|
+
sound.unload();
|
|
46
|
+
}
|
|
47
|
+
catch { }
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
sfxCache.clear();
|
|
51
|
+
sfxAudioContext = null;
|
|
52
|
+
if (resetPlaybackState) {
|
|
53
|
+
sfxRetryAfter = 0;
|
|
54
|
+
lastPlayedAt.clear();
|
|
55
|
+
lastVariation.clear();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function cacheNeedsRebuild() {
|
|
59
|
+
if (sfxCache.size !== definitions.size || sfxCache.size === 0)
|
|
60
|
+
return true;
|
|
61
|
+
if (cachedBaseUrl !== getViewerConfig().sfxBaseUrl)
|
|
62
|
+
return true;
|
|
63
|
+
if (sfxAudioContext !== Howler.ctx)
|
|
64
|
+
return true;
|
|
65
|
+
for (const sounds of sfxCache.values()) {
|
|
66
|
+
if (sounds.some((sound) => sound.state() === 'unloaded'))
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
/** Warm built-in cues and optional host cues without playing them. */
|
|
72
|
+
export function preloadSounds(extraSounds = []) {
|
|
73
|
+
for (const definition of [...Object.values(SOUNDS), ...extraSounds])
|
|
74
|
+
definitions.add(definition);
|
|
75
|
+
if (performance.now() < sfxRetryAfter)
|
|
76
|
+
return;
|
|
77
|
+
try {
|
|
78
|
+
if (!unsubscribeAudio)
|
|
79
|
+
unsubscribeAudio = useAudioSettings.subscribe(updateSoundVolumes);
|
|
80
|
+
if (!cacheNeedsRebuild())
|
|
81
|
+
return;
|
|
82
|
+
unloadCachedSounds(false);
|
|
83
|
+
const baseUrl = getViewerConfig().sfxBaseUrl.replace(/\/+$/, '');
|
|
84
|
+
cachedBaseUrl = getViewerConfig().sfxBaseUrl;
|
|
85
|
+
for (const config of definitions) {
|
|
86
|
+
const sources = Array.isArray(config.src) ? config.src : [config.src];
|
|
87
|
+
sfxCache.set(config, sources.map((src) => new Howl({
|
|
88
|
+
loop: config.loop ?? false,
|
|
89
|
+
src: [`${baseUrl}/${src}`],
|
|
90
|
+
preload: true,
|
|
91
|
+
volume: 0.5,
|
|
92
|
+
})));
|
|
93
|
+
}
|
|
94
|
+
sfxAudioContext = Howler.ctx ?? null;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
unloadCachedSounds(false);
|
|
98
|
+
sfxRetryAfter = performance.now() + SFX_FAILURE_BACKOFF_MS;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Unload the shared sound cache and detach its settings subscription. */
|
|
102
|
+
export function disposeSounds() {
|
|
103
|
+
unsubscribeAudio?.();
|
|
104
|
+
unsubscribeAudio = null;
|
|
105
|
+
unloadCachedSounds(true);
|
|
106
|
+
definitions.clear();
|
|
107
|
+
}
|
|
108
|
+
/** Start a host-defined loop, fading out the previously active loop. */
|
|
109
|
+
export function startSoundLoop(name) {
|
|
110
|
+
definitions.add(name);
|
|
111
|
+
const { muted } = useAudioSettings.getState();
|
|
112
|
+
if (muted) {
|
|
113
|
+
stopSoundLoop();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
requestedLoop = name;
|
|
117
|
+
const current = activeLoop;
|
|
118
|
+
if (current?.name === name && current.sound.playing(current.id))
|
|
119
|
+
return;
|
|
120
|
+
if (current)
|
|
121
|
+
stopActiveLoop(current.name.fadeOutMs ?? DEFAULT_LOOP_FADE_MS);
|
|
122
|
+
const now = performance.now();
|
|
123
|
+
if (now < sfxRetryAfter)
|
|
124
|
+
return;
|
|
125
|
+
try {
|
|
126
|
+
preloadSounds();
|
|
127
|
+
// A fresh Howler context rebuilds the cache and clears stale playback
|
|
128
|
+
// state. Restore this current press after that cleanup so a first-use loop
|
|
129
|
+
// can still begin when its asset finishes loading.
|
|
130
|
+
requestedLoop = name;
|
|
131
|
+
const sound = sfxCache.get(name)?.[0];
|
|
132
|
+
if (!sound)
|
|
133
|
+
return;
|
|
134
|
+
if (sound.state() !== 'loaded') {
|
|
135
|
+
if (pendingLoop?.name === name && pendingLoop.sound === sound)
|
|
136
|
+
return;
|
|
137
|
+
pendingLoop = { name, sound };
|
|
138
|
+
sound.once('load', () => {
|
|
139
|
+
if (pendingLoop?.sound === sound)
|
|
140
|
+
pendingLoop = null;
|
|
141
|
+
if (requestedLoop === name)
|
|
142
|
+
startSoundLoop(name);
|
|
143
|
+
});
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const config = name;
|
|
147
|
+
const volume = loopVolume(name);
|
|
148
|
+
const id = sound.play();
|
|
149
|
+
sound.volume(0, id);
|
|
150
|
+
activeLoop = { id, name, sound, volume };
|
|
151
|
+
sound.fade(0, volume, config.fadeInMs ?? DEFAULT_LOOP_FADE_MS, id);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
unloadCachedSounds(false);
|
|
155
|
+
sfxRetryAfter = now + SFX_FAILURE_BACKOFF_MS;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** Fade out the active loop and cancel any pending loop playback. */
|
|
159
|
+
export function stopSoundLoop() {
|
|
160
|
+
requestedLoop = null;
|
|
161
|
+
pendingLoop = null;
|
|
162
|
+
const fadeMs = activeLoop ? (activeLoop.name.fadeOutMs ?? DEFAULT_LOOP_FADE_MS) : 0;
|
|
163
|
+
stopActiveLoop(fadeMs);
|
|
164
|
+
}
|
|
165
|
+
/** Play a built-in cue or host definition using the shared audio settings. */
|
|
166
|
+
export function playSound(sound, options = {}) {
|
|
167
|
+
const name = typeof sound === 'string' ? SOUNDS[sound] : sound;
|
|
168
|
+
const config = name;
|
|
169
|
+
definitions.add(config);
|
|
170
|
+
const { masterVolume, sfxVolume, muted } = useAudioSettings.getState();
|
|
171
|
+
if (muted)
|
|
172
|
+
return;
|
|
173
|
+
// Drop rapid repeats — two plays of the same SFX within minIntervalMs just
|
|
174
|
+
// smear into noise, they don't add useful information.
|
|
175
|
+
const now = performance.now();
|
|
176
|
+
if (now < sfxRetryAfter)
|
|
177
|
+
return;
|
|
178
|
+
const minInterval = config.minIntervalMs ?? DEFAULT_MIN_INTERVAL_MS;
|
|
179
|
+
const source = options.source ?? 'local';
|
|
180
|
+
const times = lastPlayedAt.get(name) ?? {};
|
|
181
|
+
const last = times[source];
|
|
182
|
+
if (last !== undefined && now - last < minInterval)
|
|
183
|
+
return;
|
|
184
|
+
// Local feedback stays legible when a collaborator makes the same kind of
|
|
185
|
+
// change at nearly the same time; the quieter remote cue yields instead.
|
|
186
|
+
const lastLocal = times.local;
|
|
187
|
+
if (source === 'remote' && lastLocal !== undefined && now - lastLocal < 120)
|
|
188
|
+
return;
|
|
189
|
+
times[source] = now;
|
|
190
|
+
lastPlayedAt.set(name, times);
|
|
191
|
+
try {
|
|
192
|
+
preloadSounds();
|
|
193
|
+
const sounds = sfxCache.get(name);
|
|
194
|
+
if (!sounds || sounds.length === 0)
|
|
195
|
+
return;
|
|
196
|
+
// Pick a random variation, avoiding an immediate repeat of the last one so
|
|
197
|
+
// consecutive plays don't land on the same file.
|
|
198
|
+
let index = Math.floor(Math.random() * sounds.length);
|
|
199
|
+
if (sounds.length > 1 && index === lastVariation.get(name)) {
|
|
200
|
+
index = (index + 1) % sounds.length;
|
|
201
|
+
}
|
|
202
|
+
lastVariation.set(name, index);
|
|
203
|
+
const sound = sounds[index];
|
|
204
|
+
// Howler queues per-play mutations while a sound is loading. If its global
|
|
205
|
+
// AudioContext is replaced before that queue drains, stereo setup can try
|
|
206
|
+
// to connect nodes from different contexts and throw asynchronously.
|
|
207
|
+
if (sound.state() !== 'loaded')
|
|
208
|
+
return;
|
|
209
|
+
const baseVolume = (masterVolume / 100) * (sfxVolume / 100);
|
|
210
|
+
const volumeJitter = config.volumeRange ? randomInRange(config.volumeRange) : 1;
|
|
211
|
+
const volumeMultiplier = Number.isFinite(options.volumeMultiplier)
|
|
212
|
+
? Math.max(0, Math.min(2, options.volumeMultiplier))
|
|
213
|
+
: 1;
|
|
214
|
+
const rate = config.rateRange ? randomInRange(config.rateRange) : 1;
|
|
215
|
+
const id = sound.play();
|
|
216
|
+
sound.volume(baseVolume * volumeJitter * volumeMultiplier, id);
|
|
217
|
+
if (Number.isFinite(options.stereo)) {
|
|
218
|
+
sound.stereo(Math.max(-1, Math.min(1, options.stereo)), id);
|
|
219
|
+
}
|
|
220
|
+
if (rate !== 1)
|
|
221
|
+
sound.rate(rate, id);
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// Optional audio must never abort an input callback. Rebuild from
|
|
225
|
+
// the current Howler context after a backoff instead of retrying every pointer cue.
|
|
226
|
+
unloadCachedSounds(false);
|
|
227
|
+
sfxRetryAfter = now + SFX_FAILURE_BACKOFF_MS;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/** Apply current volume and mute settings to cached sounds and the active loop. */
|
|
231
|
+
export function updateSoundVolumes() {
|
|
232
|
+
const { masterVolume, muted, sfxVolume } = useAudioSettings.getState();
|
|
233
|
+
if (muted) {
|
|
234
|
+
stopSoundLoop();
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const finalVolume = (masterVolume / 100) * (sfxVolume / 100);
|
|
238
|
+
try {
|
|
239
|
+
if (performance.now() < sfxRetryAfter)
|
|
240
|
+
return;
|
|
241
|
+
sfxCache.forEach((sounds) => {
|
|
242
|
+
sounds.forEach((sound) => {
|
|
243
|
+
sound.volume(finalVolume);
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
if (activeLoop) {
|
|
247
|
+
activeLoop.volume = loopVolume(activeLoop.name);
|
|
248
|
+
activeLoop.sound.volume(activeLoop.volume, activeLoop.id);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
unloadCachedSounds(false);
|
|
253
|
+
sfxRetryAfter = performance.now() + SFX_FAILURE_BACKOFF_MS;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Built-in interaction and viewer UI cues, keyed by their public names. */
|
|
2
|
+
export declare const SOUNDS: {
|
|
3
|
+
menuHover: {
|
|
4
|
+
src: string;
|
|
5
|
+
rateRange: [number, number];
|
|
6
|
+
volumeRange: [number, number];
|
|
7
|
+
minIntervalMs: number;
|
|
8
|
+
};
|
|
9
|
+
menuClick: {
|
|
10
|
+
src: string;
|
|
11
|
+
rateRange: [number, number];
|
|
12
|
+
volumeRange: [number, number];
|
|
13
|
+
};
|
|
14
|
+
doorOpen: {
|
|
15
|
+
src: string;
|
|
16
|
+
rateRange: [number, number];
|
|
17
|
+
volumeRange: [number, number];
|
|
18
|
+
};
|
|
19
|
+
doorClose: {
|
|
20
|
+
src: string;
|
|
21
|
+
rateRange: [number, number];
|
|
22
|
+
volumeRange: [number, number];
|
|
23
|
+
};
|
|
24
|
+
doorSwing: {
|
|
25
|
+
src: string;
|
|
26
|
+
rateRange: [number, number];
|
|
27
|
+
};
|
|
28
|
+
garageDoor: {
|
|
29
|
+
src: string;
|
|
30
|
+
volumeRange: [number, number];
|
|
31
|
+
};
|
|
32
|
+
shuttersOpen: {
|
|
33
|
+
src: string;
|
|
34
|
+
rateRange: [number, number];
|
|
35
|
+
};
|
|
36
|
+
shuttersClose: {
|
|
37
|
+
src: string;
|
|
38
|
+
rateRange: [number, number];
|
|
39
|
+
};
|
|
40
|
+
switchOn: {
|
|
41
|
+
src: string;
|
|
42
|
+
};
|
|
43
|
+
switchOff: {
|
|
44
|
+
src: string;
|
|
45
|
+
};
|
|
46
|
+
viewerHover: {
|
|
47
|
+
src: string;
|
|
48
|
+
minIntervalMs: number;
|
|
49
|
+
};
|
|
50
|
+
viewerSelect: {
|
|
51
|
+
src: string;
|
|
52
|
+
minIntervalMs: number;
|
|
53
|
+
};
|
|
54
|
+
viewerDeselect: {
|
|
55
|
+
src: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
/** A built-in interaction or viewer UI cue name. */
|
|
59
|
+
export type SoundName = keyof typeof SOUNDS;
|
|
60
|
+
//# sourceMappingURL=sounds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sounds.d.ts","sourceRoot":"","sources":["../../src/sfx/sounds.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,eAAO,MAAM,MAAM;;QAEf,GAAG;QACH,SAAS;QACT,WAAW;QACX,aAAa;;;QAGb,GAAG;QACH,SAAS;QACT,WAAW;;;QAED,GAAG;QAAmB,SAAS;QAAgB,WAAW;;;QACzD,GAAG;QAAoB,SAAS;QAAgB,WAAW;;;QAC3D,GAAG;QAAoB,SAAS;;;QAC/B,GAAG;QAAqB,WAAW;;;QACjC,GAAG;QAAuB,SAAS;;;QAClC,GAAG;QAAwB,SAAS;;;QACzC,GAAG;;;QACF,GAAG;;;QACD,GAAG;QAAsB,aAAa;;;QACrC,GAAG;QAAuB,aAAa;;;QACrC,GAAG;;CACoB,CAAA;AAE3C,oDAAoD;AACpD,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,MAAM,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Built-in interaction and viewer UI cues, keyed by their public names. */
|
|
2
|
+
export const SOUNDS = {
|
|
3
|
+
menuHover: {
|
|
4
|
+
src: 'menu_hover.mp3',
|
|
5
|
+
rateRange: [0.98, 1.02],
|
|
6
|
+
volumeRange: [0.2, 0.3],
|
|
7
|
+
minIntervalMs: 0,
|
|
8
|
+
},
|
|
9
|
+
menuClick: {
|
|
10
|
+
src: 'menu_click.mp3',
|
|
11
|
+
rateRange: [0.98, 1.02],
|
|
12
|
+
volumeRange: [0.5, 0.6],
|
|
13
|
+
},
|
|
14
|
+
doorOpen: { src: 'door_open.mp3', rateRange: [0.96, 1.04], volumeRange: [0.9, 1] },
|
|
15
|
+
doorClose: { src: 'door_close.mp3', rateRange: [0.96, 1.04], volumeRange: [0.9, 1] },
|
|
16
|
+
doorSwing: { src: 'door_swing.mp3', rateRange: [0.97, 1.03] },
|
|
17
|
+
garageDoor: { src: 'garage_door.mp3', volumeRange: [0.9, 1] },
|
|
18
|
+
shuttersOpen: { src: 'shutters_open.mp3', rateRange: [0.96, 1.04] },
|
|
19
|
+
shuttersClose: { src: 'shutters_close.mp3', rateRange: [0.96, 1.04] },
|
|
20
|
+
switchOn: { src: 'switch_on.mp3' },
|
|
21
|
+
switchOff: { src: 'switch_off.mp3' },
|
|
22
|
+
viewerHover: { src: 'viewer_hover.mp3', minIntervalMs: 95 },
|
|
23
|
+
viewerSelect: { src: 'viewer_select.mp3', minIntervalMs: 90 },
|
|
24
|
+
viewerDeselect: { src: 'viewer_deselect.mp3' },
|
|
25
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type useViewer from '../store/use-viewer';
|
|
2
|
+
type Selection = ReturnType<typeof useViewer.getState>['selection'];
|
|
3
|
+
/** Which tick a selection change plays: anything newly picked selects, anything let go deselects. */
|
|
4
|
+
export declare function selectionCue(previous: Selection, next: Selection): 'viewerSelect' | 'viewerDeselect' | null;
|
|
5
|
+
/** Play selection and hover cues after user activation, except during walkthrough. */
|
|
6
|
+
export declare function useViewerUiSounds(): void;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=use-viewer-ui-sounds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-viewer-ui-sounds.d.ts","sourceRoot":"","sources":["../../src/sfx/use-viewer-ui-sounds.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,SAAS,MAAM,qBAAqB,CAAA;AAGhD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,CAAA;AAEnE,qGAAqG;AACrG,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,SAAS,EACnB,IAAI,EAAE,SAAS,GACd,cAAc,GAAG,gBAAgB,GAAG,IAAI,CAW1C;AAED,sFAAsF;AACtF,wBAAgB,iBAAiB,SAsBhC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { playSound, preloadSounds } from './player';
|
|
4
|
+
/** Which tick a selection change plays: anything newly picked selects, anything let go deselects. */
|
|
5
|
+
export function selectionCue(previous, next) {
|
|
6
|
+
const picked = (next.levelId && next.levelId !== previous.levelId) ||
|
|
7
|
+
(next.zoneId && next.zoneId !== previous.zoneId) ||
|
|
8
|
+
next.selectedIds.some((id) => !previous.selectedIds.includes(id));
|
|
9
|
+
if (picked)
|
|
10
|
+
return 'viewerSelect';
|
|
11
|
+
const released = (previous.levelId && !next.levelId) ||
|
|
12
|
+
(previous.zoneId && !next.zoneId) ||
|
|
13
|
+
previous.selectedIds.some((id) => !next.selectedIds.includes(id));
|
|
14
|
+
return released ? 'viewerDeselect' : null;
|
|
15
|
+
}
|
|
16
|
+
/** Play selection and hover cues after user activation, except during walkthrough. */
|
|
17
|
+
export function useViewerUiSounds() {
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
let disposed = false;
|
|
20
|
+
let unsubscribe;
|
|
21
|
+
preloadSounds();
|
|
22
|
+
void import('../store/use-viewer').then(({ default: viewer }) => {
|
|
23
|
+
if (disposed)
|
|
24
|
+
return;
|
|
25
|
+
unsubscribe = viewer.subscribe((state, previous) => {
|
|
26
|
+
if (state.walkthroughMode || !globalThis.navigator?.userActivation?.hasBeenActive)
|
|
27
|
+
return;
|
|
28
|
+
if (state.selection !== previous.selection) {
|
|
29
|
+
const cue = selectionCue(previous.selection, state.selection);
|
|
30
|
+
if (cue)
|
|
31
|
+
playSound(cue);
|
|
32
|
+
}
|
|
33
|
+
if (state.hoveredId && state.hoveredId !== previous.hoveredId && !state.cameraDragging)
|
|
34
|
+
playSound('viewerHover');
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
return () => {
|
|
38
|
+
disposed = true;
|
|
39
|
+
unsubscribe?.();
|
|
40
|
+
};
|
|
41
|
+
}, []);
|
|
42
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type WalkthroughInteract = {
|
|
2
|
+
label: string;
|
|
3
|
+
verb: string;
|
|
4
|
+
} | null;
|
|
5
|
+
export type FirstPersonHudState = {
|
|
6
|
+
floorLabel: string | null;
|
|
7
|
+
zoneLabel: string | null;
|
|
8
|
+
interact: WalkthroughInteract;
|
|
9
|
+
setHud: (hud: Partial<Pick<FirstPersonHudState, 'floorLabel' | 'zoneLabel' | 'interact'>>) => void;
|
|
10
|
+
reset: () => void;
|
|
11
|
+
};
|
|
12
|
+
export declare const useFirstPersonHud: import("zustand").UseBoundStore<import("zustand").StoreApi<FirstPersonHudState>>;
|
|
13
|
+
//# sourceMappingURL=use-first-person-hud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-first-person-hud.d.ts","sourceRoot":"","sources":["../../src/store/use-first-person-hud.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAA;AAExE,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,YAAY,GAAG,WAAW,GAAG,UAAU,CAAC,CAAC,KAAK,IAAI,CAAA;IAClG,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,CAAA;AAED,eAAO,MAAM,iBAAiB,kFA2B3B,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
export const useFirstPersonHud = create((set) => ({
|
|
3
|
+
floorLabel: null,
|
|
4
|
+
zoneLabel: null,
|
|
5
|
+
interact: null,
|
|
6
|
+
setHud: (hud) => set((state) => {
|
|
7
|
+
const floorLabel = hud.floorLabel === undefined ? state.floorLabel : hud.floorLabel;
|
|
8
|
+
const zoneLabel = hud.zoneLabel === undefined ? state.zoneLabel : hud.zoneLabel;
|
|
9
|
+
const interact = hud.interact === undefined ? state.interact : hud.interact;
|
|
10
|
+
if (floorLabel === state.floorLabel &&
|
|
11
|
+
zoneLabel === state.zoneLabel &&
|
|
12
|
+
interact?.label === state.interact?.label &&
|
|
13
|
+
interact?.verb === state.interact?.verb) {
|
|
14
|
+
return state;
|
|
15
|
+
}
|
|
16
|
+
return { floorLabel, zoneLabel, interact };
|
|
17
|
+
}),
|
|
18
|
+
reset: () => set((state) => state.floorLabel === null && state.zoneLabel === null && state.interact === null
|
|
19
|
+
? state
|
|
20
|
+
: { floorLabel: null, zoneLabel: null, interact: null }),
|
|
21
|
+
}));
|
|
@@ -296,67 +296,13 @@ declare const useViewer: import("zustand").UseBoundStore<Omit<import("zustand").
|
|
|
296
296
|
setState(partial: Partial<ViewerState> | ViewerState | ((state: ViewerState) => Partial<ViewerState> | ViewerState), replace?: false | undefined): unknown;
|
|
297
297
|
setState(state: ViewerState | ((state: ViewerState) => ViewerState), replace: true): unknown;
|
|
298
298
|
persist: {
|
|
299
|
-
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<ViewerState,
|
|
300
|
-
cameraMode: "orthographic" | "perspective";
|
|
301
|
-
sceneTheme: string;
|
|
302
|
-
shadingByContext: Partial<Record<RenderContext, RenderShading>>;
|
|
303
|
-
textures: boolean;
|
|
304
|
-
colorPreset: ColorPreset;
|
|
305
|
-
edges: EdgeMode;
|
|
306
|
-
shadows: boolean;
|
|
307
|
-
unit?: "imperial" | "metric" | undefined;
|
|
308
|
-
metricNotation: MetricNotation;
|
|
309
|
-
levelMode: "exploded" | "manual" | "solo" | "stacked";
|
|
310
|
-
wallMode: WallMode;
|
|
311
|
-
projectPreferences: {
|
|
312
|
-
[k: string]: {
|
|
313
|
-
look?: LocalLook;
|
|
314
|
-
showScans?: boolean;
|
|
315
|
-
showGuides?: boolean;
|
|
316
|
-
showGrid?: boolean;
|
|
317
|
-
showMeasurements?: boolean;
|
|
318
|
-
};
|
|
319
|
-
};
|
|
320
|
-
timeOfDay: "blue" | "golden" | "midday" | "night";
|
|
321
|
-
timeOfDayMinutes: number | null;
|
|
322
|
-
skyLive: boolean;
|
|
323
|
-
weather: "clear" | "cloudy" | "fair" | "overcast";
|
|
324
|
-
deviceLocation: LatLng | null;
|
|
325
|
-
renderQuality: RenderQualityChoice;
|
|
326
|
-
}, unknown>>) => void;
|
|
299
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<ViewerState, unknown, unknown>>) => void;
|
|
327
300
|
clearStorage: () => void;
|
|
328
301
|
rehydrate: () => Promise<void> | void;
|
|
329
302
|
hasHydrated: () => boolean;
|
|
330
303
|
onHydrate: (fn: (state: ViewerState) => void) => () => void;
|
|
331
304
|
onFinishHydration: (fn: (state: ViewerState) => void) => () => void;
|
|
332
|
-
getOptions: () => Partial<import("zustand/middleware").PersistOptions<ViewerState,
|
|
333
|
-
cameraMode: "orthographic" | "perspective";
|
|
334
|
-
sceneTheme: string;
|
|
335
|
-
shadingByContext: Partial<Record<RenderContext, RenderShading>>;
|
|
336
|
-
textures: boolean;
|
|
337
|
-
colorPreset: ColorPreset;
|
|
338
|
-
edges: EdgeMode;
|
|
339
|
-
shadows: boolean;
|
|
340
|
-
unit?: "imperial" | "metric" | undefined;
|
|
341
|
-
metricNotation: MetricNotation;
|
|
342
|
-
levelMode: "exploded" | "manual" | "solo" | "stacked";
|
|
343
|
-
wallMode: WallMode;
|
|
344
|
-
projectPreferences: {
|
|
345
|
-
[k: string]: {
|
|
346
|
-
look?: LocalLook;
|
|
347
|
-
showScans?: boolean;
|
|
348
|
-
showGuides?: boolean;
|
|
349
|
-
showGrid?: boolean;
|
|
350
|
-
showMeasurements?: boolean;
|
|
351
|
-
};
|
|
352
|
-
};
|
|
353
|
-
timeOfDay: "blue" | "golden" | "midday" | "night";
|
|
354
|
-
timeOfDayMinutes: number | null;
|
|
355
|
-
skyLive: boolean;
|
|
356
|
-
weather: "clear" | "cloudy" | "fair" | "overcast";
|
|
357
|
-
deviceLocation: LatLng | null;
|
|
358
|
-
renderQuality: RenderQualityChoice;
|
|
359
|
-
}, unknown>>;
|
|
305
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<ViewerState, unknown, unknown>>;
|
|
360
306
|
};
|
|
361
307
|
}>;
|
|
362
308
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,kBAAkB,EAClB,SAAS,EACT,gBAAgB,EAChB,QAAQ,EACR,QAAQ,EACT,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAIrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAClE,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"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"}
|
package/dist/store/use-viewer.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { create } from 'zustand';
|
|
3
|
-
import { persist } from 'zustand/middleware';
|
|
3
|
+
import { createJSONStorage, persist } from 'zustand/middleware';
|
|
4
4
|
import { getSceneTheme, projectSceneTheme, SCENE_THEME_IDS, } from '../lib/scene-themes';
|
|
5
|
+
import { viewerPreferenceStorage } from '../lib/viewer-preference-storage';
|
|
5
6
|
const TIMES_OF_DAY = ['golden', 'midday', 'blue', 'night'];
|
|
6
7
|
const WEATHERS = ['clear', 'fair', 'cloudy', 'overcast'];
|
|
7
8
|
const RENDER_QUALITY_CHOICES = ['auto', 'low', 'medium', 'high'];
|
|
@@ -481,6 +482,7 @@ const useViewer = create()(persist((set) => ({
|
|
|
481
482
|
setInputDragging: (dragging) => set({ inputDragging: dragging }),
|
|
482
483
|
}), {
|
|
483
484
|
name: 'viewer-preferences',
|
|
485
|
+
storage: createJSONStorage(() => viewerPreferenceStorage),
|
|
484
486
|
merge: (persistedState, currentState) => {
|
|
485
487
|
const persisted = normalizePersistedViewerState(persistedState);
|
|
486
488
|
const renderQualityChoice = persisted.renderQualityChoice ?? currentState.renderQualityChoice;
|
|
@@ -1,9 +1,23 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type AnyNodeId } from '@pascal-app/core';
|
|
2
|
+
import { type Object3D, Raycaster } from 'three';
|
|
3
|
+
type ElevatorButtonAction = 'open-door' | 'request-level';
|
|
4
|
+
type ElevatorButtonUserData = {
|
|
5
|
+
action: ElevatorButtonAction;
|
|
6
|
+
disabled: boolean;
|
|
7
|
+
elevatorId: AnyNodeId;
|
|
8
|
+
kind: 'cab' | 'landing';
|
|
9
|
+
levelId?: AnyNodeId;
|
|
10
|
+
};
|
|
2
11
|
/**
|
|
3
12
|
* The roots of every elevator button under `object`. Any button along the ray
|
|
4
13
|
* takes the click, so only they are raycast — never the rest of the scene,
|
|
5
14
|
* whose meshes this capture-phase listener must not trip over.
|
|
6
15
|
*/
|
|
7
16
|
export declare function collectElevatorButtons(object: Object3D, into?: Object3D[]): Object3D[];
|
|
8
|
-
|
|
17
|
+
/** Ignore malformed material groups during transient paint updates, rather than raycasting invalid faces. */
|
|
18
|
+
export declare function pickElevatorButton(scene: Object3D, raycaster: Raycaster): ElevatorButtonUserData | null;
|
|
19
|
+
export declare function ElevatorInteractionSystem({ enabled }: {
|
|
20
|
+
enabled?: boolean;
|
|
21
|
+
}): null;
|
|
22
|
+
export {};
|
|
9
23
|
//# sourceMappingURL=elevator-interaction-system.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elevator-interaction-system.d.ts","sourceRoot":"","sources":["../../../src/systems/elevator/elevator-interaction-system.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"elevator-interaction-system.d.ts","sourceRoot":"","sources":["../../../src/systems/elevator/elevator-interaction-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAMf,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAQ,KAAK,QAAQ,EAAE,SAAS,EAAW,MAAM,OAAO,CAAA;AAE/D,KAAK,oBAAoB,GAAG,WAAW,GAAG,eAAe,CAAA;AAEzD,KAAK,sBAAsB,GAAG;IAC5B,MAAM,EAAE,oBAAoB,CAAA;IAC5B,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,SAAS,CAAA;IACrB,IAAI,EAAE,KAAK,GAAG,SAAS,CAAA;IACvB,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB,CAAA;AAcD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAE,QAAQ,EAAO,GAAG,QAAQ,EAAE,CAQ1F;AAED,6GAA6G;AAC7G,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,QAAQ,EACf,SAAS,EAAE,SAAS,GACnB,sBAAsB,GAAG,IAAI,CAoC/B;AAED,wBAAgB,yBAAyB,CAAC,EAAE,OAAc,EAAE,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,QA0DlF"}
|