@combos-fun/plugin-sound 0.0.45 → 0.0.47

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/agent-skill.md CHANGED
@@ -1,110 +1,60 @@
1
1
  # `@combos-fun/plugin-sound` — Agent notes
2
2
 
3
- Audio playback for Combos Fun. Web Audio internally (`AudioContext` + `AudioBufferSourceNode` + `GainNode`). Shared between 2D and 3D there is no spatial / 3D-positional audio in this package.
3
+ Web Audio playback for 2D and 3D games. This package does not provide spatial audio.
4
4
 
5
5
  ## When to read
6
6
 
7
- Read for any audio task: SFX, BGM, autoplay, loop, mute, volume, pause / resume integration with `Game.pause()` / `Game.resume()`, touch-to-unlock on mobile.
7
+ Read for SFX/BGM playback, looping, volume, mute, browser audio unlock, or game pause/resume behavior.
8
8
 
9
9
  ## Public API
10
10
 
11
11
  ```ts
12
12
  import { Sound, SoundSystem } from '@combos-fun/plugin-sound';
13
- import { resource, RESOURCE_TYPE } from '@combos-fun/engine';
14
13
  ```
15
14
 
16
- ### `Sound` Component params
15
+ `Sound` params: required `resource`; optional `autoplay`, `loop`, `muted`, `volume` (`0..1`), `seek`, `duration`, and `onEnd`. Its `play()`, `pause()`, and `stop()` methods return `void`; `muted`, `volume`, `loop`, `autoplay`, and `resource` are writable.
17
16
 
18
- | Field | Type | Notes |
19
- |-------|------|-------|
20
- | `resource` | `string` | Engine resource name registered with `RESOURCE_TYPE.AUDIO` |
21
- | `autoplay` / `loop` / `muted` | `boolean?` | |
22
- | `volume` | `number?` | `0` – `1` |
23
- | `seek` / `duration` | `number?` | |
24
- | `onEnd` | `() => void?` | Fires when playback ends naturally |
17
+ `SoundSystem` accepts optional `onError` and `autoPauseAndStart` (default `true`). It exposes `resumeAll()`, `pauseAll()`, `stopAll()`, global `muted` / `volume`, and `audioLocked`.
25
18
 
26
- Methods: `play()`, `pause()`, `stop()`. Read-only fields: `playing`, `state` (`'unloaded' | 'loading' | 'loaded'`), `muted`, `volume`.
19
+ Parameter interfaces are not exported from the package entry; pass object literals.
27
20
 
28
- ### `SoundSystemParams`
29
-
30
- | Field | Type | Notes |
31
- |-------|------|-------|
32
- | `onError` | `(error: unknown) => void?` | Optional. If omitted, load errors are swallowed |
33
- | `autoPauseAndStart` | `boolean?` | Pause / resume audio along with `Game` |
34
-
35
- System API: `resumeAll()`, `pauseAll()`, `stopAll()`, `muted`, `volume`, `audioLocked` (true until first user gesture). Decoded `AudioBuffer`s are cached per resource.
21
+ ## Required setup
36
22
 
37
- ### Audio resource registration
23
+ Register an `AUDIO` engine resource and `SoundSystem`. Pass `onError` to surface load/decode failures. Playback may remain locked until a user gesture.
38
24
 
39
25
  ```ts
40
- resource.addResource([
41
- { name: 'bgm', type: RESOURCE_TYPE.AUDIO, src: { audio: { type: 'audio', url: '/bgm.mp3' } }, preload: true },
42
- ]);
26
+ resource.addResource([{
27
+ name: 'tap',
28
+ type: RESOURCE_TYPE.AUDIO,
29
+ src: { audio: { type: 'audio', url: '/tap.mp3' } },
30
+ preload: true,
31
+ }]);
43
32
  ```
44
33
 
45
- The loader configures `mp3` / `wav` / `aac` / `ogg` as `arrayBuffer`. The audio buffer is decoded once and reused.
46
-
47
- ## Required setup
48
-
49
- - Register `SoundSystem` on `Game`. There is **no** renderer dependency —
50
- 2D and 3D projects both add it next to their existing systems.
51
- - Pass `onError` so load / decode failures are visible. It is optional in TypeScript.
52
- - Audio is locked until the first user gesture (browser autoplay policy).
53
- Either start audio inside an event-driven Component (e.g. on tap) or
54
- show a "tap to start" UI on first paint.
55
-
56
34
  ## Runtime behaviour
57
35
 
58
- - `Sound.play()` resolves to a fresh `AudioBufferSourceNode` per call;
59
- re-`play()` after `stop()` works.
60
- - `SoundSystem` listens to the unlock gesture once and sets
61
- `audioLocked = false`. Subsequent plays succeed without user gesture.
62
- - `autoPauseAndStart: true` calls `pauseAll()` on `Game.pause()` and
63
- `resumeAll()` on `Game.resume()`.
36
+ Decoded buffers are cached by resource. Each `play()` replaces the current `AudioBufferSourceNode`; `muted` and `volume` update gain immediately. With `autoPauseAndStart`, game pause/resume calls `pauseAll()` / `resumeAll()`.
64
37
 
65
38
  ## Common pitfalls
66
39
 
67
- | Symptom | Fix |
68
- |---------|-----|
69
- | Silent audio load failure | Pass `onError: (e) => console.warn(e)` — there is no default log |
70
- | No sound on page load | Browser autoplay policy — call `play()` from a user-gesture Component |
71
- | `state === 'unloaded'` | Resource not registered, or component `resource` name doesn't match |
72
- | `state === 'loading'` forever | Resource URL 404 or CORS — check network tab |
73
- | Stuck loud after pause | `volume` is per Sound; use `SoundSystem.volume` for global mute |
40
+ - Autoplay can be blocked; start from a touch/click path.
41
+ - A missing resource or failed request/decode leaves playback unavailable; inspect `onError`.
42
+ - Per-Sound volume does not set global volume; use `SoundSystem.volume`.
43
+ - Shared ECS lifecycle rules are documented by `@combos-fun/engine`.
74
44
 
75
45
  ## Minimal example
76
46
 
77
47
  ```ts
78
- import { Game, GameObject, resource, RESOURCE_TYPE } from '@combos-fun/engine';
79
- import { Sound, SoundSystem } from '@combos-fun/plugin-sound';
80
-
81
- resource.addResource([
82
- { name: 'tap-sfx', type: RESOURCE_TYPE.AUDIO, src: { audio: { type: 'audio', url: '/tap.mp3' } }, preload: true },
83
- ]);
84
-
85
- new Game({
86
- systems: [
87
- // existing project renderer / physics systems…
88
- new SoundSystem({ onError: (e) => console.warn(e) }),
89
- ],
90
- onSystemsBootstrapComplete: (game) => {
91
- const audio = new GameObject('tap-audio');
92
- audio.addComponent(new Sound({ resource: 'tap-sfx' }));
93
- game.scene.addChild(audio);
94
-
95
- // Trigger from a tap Component:
96
- // gameObject.getComponent(Sound)?.play()
97
- },
98
- });
48
+ const soundSystem = new SoundSystem({ onError: console.warn });
49
+ const sound = audioGo.addComponent(new Sound({
50
+ resource: 'tap',
51
+ volume: 0.8,
52
+ }));
53
+
54
+ // From a user-gesture Component:
55
+ sound.play();
99
56
  ```
100
57
 
101
- ## Video
102
-
103
- `RESOURCE_TYPE.VIDEO` is supported by `@combos-fun/engine`'s loader for `{ video: { type: 'mp4', url: '...' } }`, but on-canvas video playback is app- or plugin-specific. After `getResource(name)`, use the resolved `instance` in your video plugin or a DOM `<video>` element.
104
-
105
58
  ## Verification
106
59
 
107
- - `pnpm --filter @combos-fun/plugin-sound run build`
108
- - Run an example with audio on touch / click: verify autoplay-locked state
109
- unlocks after the first user gesture and the buffer is cached for
110
- subsequent plays.
60
+ Run `pnpm --filter @combos-fun/plugin-sound run build` and verify first-gesture unlock plus replay.
@@ -253,7 +253,7 @@ var SoundSystem = SoundSystem$1;
253
253
  /** Auto-generated by scripts/build-package.mjs — do not edit. */
254
254
  Object.assign(SoundSystem, {
255
255
  packageName: "@combos-fun/plugin-sound",
256
- packageVersion: "0.0.45",
256
+ packageVersion: "0.0.47",
257
257
  });
258
258
 
259
259
  class Sound extends engine.Component {
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-sound.cjs.js","sources":["../lib/SoundSystem.ts","../lib/__combosPackageMeta.gen.ts","../lib/Sound.ts"],"sourcesContent":["import { System, decorators, ComponentChanged, OBSERVER_TYPE, resource } from '@combos-fun/engine';\nimport SoundComponent from './Sound';\n\ninterface SoundSystemParams {\n autoPauseAndStart?: boolean;\n onError?: (error: any) => void;\n}\n\n@decorators.componentObserver({\n Sound: [],\n})\nclass SoundSystem extends System {\n static systemName = 'SoundSystem';\n\n private ctx: AudioContext;\n\n private gainNode: GainNode;\n\n /** Whether to pause/resume in sync with the game. */\n private autoPauseAndStart = true;\n\n private onError: (error: any) => void;\n\n private components: SoundComponent[] = [];\n\n private pausedComponents: SoundComponent[] = [];\n\n private audioBufferCache = {};\n\n private decodeAudioPromiseMap = {};\n\n /** Desired mute/volume are the source of truth; the gain node is derived. */\n private _muted = false;\n\n private _volume = 1;\n\n get muted(): boolean {\n return this._muted;\n }\n\n set muted(v: boolean) {\n this._muted = v;\n this.applyGain();\n }\n\n get volume(): number {\n return this._volume;\n }\n\n set volume(v: number) {\n if (typeof v !== 'number' || v < 0 || v > 1) {\n return;\n }\n this._volume = v;\n this.applyGain();\n }\n\n /**\n * Apply the effective gain (`muted ? 0 : volume`) to the gain node.\n *\n * Assigns `gain.value` directly rather than `setValueAtTime`: `.value` updates\n * the AudioParam's intrinsic value synchronously, so the `muted` / `volume`\n * getters reflect the change immediately. `setValueAtTime` only schedules an\n * event on the automation timeline and leaves `.value` stale until the next\n * render quantum, which made `muted` report the pre-change value.\n */\n private applyGain() {\n if (!this.gainNode) {\n return;\n }\n this.gainNode.gain.value = this._muted ? 0 : this._volume;\n }\n\n get audioLocked(): boolean {\n if (!this.ctx) {\n return true;\n }\n return this.ctx.state !== 'running';\n }\n\n constructor(obj?: SoundSystemParams) {\n super();\n Object.assign(this, obj);\n }\n\n /**\n * Resume playback of all paused audio.\n */\n resumeAll() {\n const handleResume = () => {\n this.pausedComponents.forEach(component => {\n component.play();\n });\n // Clear the previously cached paused list.\n this.pausedComponents = [];\n };\n this.ctx.resume().then(handleResume, handleResume);\n }\n\n /**\n * Pause all currently playing audio.\n */\n pauseAll() {\n this.components.forEach(component => {\n if (component.playing) {\n this.pausedComponents.push(component);\n component.pause();\n }\n });\n this.ctx.suspend().then();\n }\n\n /**\n * Stop all currently playing audio.\n */\n stopAll() {\n this.components.forEach(component => {\n if (component.playing) {\n component.stop();\n }\n });\n // Clear the previously cached paused list.\n this.pausedComponents = [];\n this.ctx.suspend().then();\n }\n\n /**\n * System init: configure params before the game starts.\n */\n init() {\n this.setupAudioContext();\n }\n\n update() {\n const changes = this.componentObserver.clear();\n for (const changed of changes) {\n this.componentChanged(changed);\n }\n }\n\n /**\n * Called when the game starts or resumes playing after a pause.\n */\n onResume() {\n if (!this.autoPauseAndStart) {\n return;\n }\n this.resumeAll();\n }\n\n /**\n * Called when the game is paused.\n */\n onPause() {\n if (!this.autoPauseAndStart) {\n return;\n }\n this.pauseAll();\n }\n\n /**\n * Called when the system is destroyed.\n */\n onDestroy() {\n this.components.forEach(component => {\n component.onDestroy();\n });\n this.components = [];\n if (this.ctx) {\n this.gainNode.disconnect();\n this.gainNode = null;\n this.ctx.close();\n this.ctx = null;\n }\n }\n\n async componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Sound') return;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.add(changed);\n }\n }\n\n private setupAudioContext() {\n try {\n const AudioContext = window.AudioContext || (window as any).webkitAudioContext;\n this.ctx = new AudioContext();\n } catch (error) {\n console.error(error);\n if (this.onError) {\n this.onError(error);\n }\n }\n\n if (!this.ctx) {\n return;\n }\n this.gainNode =\n typeof this.ctx.createGain === 'undefined' ? (this.ctx as any).createGainNode() : this.ctx.createGain();\n this.applyGain();\n this.gainNode.connect(this.ctx.destination);\n this.unlockAudio();\n }\n\n private unlockAudio() {\n if (!this.ctx || !this.audioLocked) {\n return;\n }\n\n const unlock = () => {\n if (this.ctx) {\n const removeListenerFn = () => {\n document.body.removeEventListener('touchstart', unlock);\n document.body.removeEventListener('touchend', unlock);\n document.body.removeEventListener('click', unlock);\n };\n this.ctx.resume().then(removeListenerFn, removeListenerFn);\n }\n };\n document.body.addEventListener('touchstart', unlock);\n document.body.addEventListener('touchend', unlock);\n document.body.addEventListener('click', unlock);\n }\n\n private async add(changed: ComponentChanged) {\n const component = changed.component as SoundComponent;\n this.components.push(component);\n try {\n const { config } = component;\n component.state = 'loading';\n\n const audio = await resource.getResource(config.resource);\n if (!this.audioBufferCache[audio.name] && audio?.data?.audio) {\n this.audioBufferCache[audio.name] = await this.decodeAudioData(audio.data.audio, audio.name);\n }\n if (this.audioBufferCache[audio.name]) {\n component.systemContext = this.ctx;\n component.systemDestination = this.gainNode;\n component.onload(this.audioBufferCache[audio.name]);\n }\n } catch (error) {\n if (this.onError) {\n this.onError(error);\n }\n }\n }\n\n private decodeAudioData(arraybuffer: ArrayBuffer, name: string) {\n if (this.decodeAudioPromiseMap[name]) {\n return this.decodeAudioPromiseMap[name];\n }\n\n const promise = new Promise<AudioBuffer>((resolve, reject) => {\n if (!this.ctx) {\n reject(new Error('No audio support'));\n }\n\n const success = (decodedData: AudioBuffer) => {\n if (this.decodeAudioPromiseMap[name]) {\n delete this.decodeAudioPromiseMap[name];\n }\n if (decodedData) {\n resolve(decodedData);\n } else {\n reject(new Error(`Error decoding audio ${name}`));\n }\n };\n\n const error = (err: DOMException) => {\n if (this.decodeAudioPromiseMap[name]) {\n delete this.decodeAudioPromiseMap[name];\n }\n reject(new Error(`${err}. arrayBuffer byteLength: ${arraybuffer ? arraybuffer.byteLength : 0}`));\n };\n\n const promise = this.ctx.decodeAudioData(arraybuffer, success, error)\n if (promise instanceof Promise) {\n promise.catch((err) => {\n reject(new Error(`catch ${err}, arrayBuffer byteLength: ${arraybuffer ? arraybuffer.byteLength : 0}`));\n });\n }\n });\n\n this.decodeAudioPromiseMap[name] = promise;\n return promise;\n }\n}\n\nexport default SoundSystem;\n","/** Auto-generated by scripts/build-package.mjs — do not edit. */\n\nimport SoundSystem from './SoundSystem';\n\nObject.assign(SoundSystem, {\n packageName: \"@combos-fun/plugin-sound\",\n packageVersion: \"0.0.45\",\n});\n","import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\n\nexport interface SoundParams {\n resource: string;\n autoplay?: boolean;\n muted?: boolean;\n volume?: number;\n loop?: boolean;\n seek?: number;\n duration?: number;\n onEnd?: () => void;\n}\n\nclass Sound extends Component<SoundParams> {\n static componentName = 'Sound';\n\n systemContext: AudioContext;\n\n systemDestination: GainNode;\n\n playing: boolean;\n\n state: 'unloaded' | 'loading' | 'loaded' = 'unloaded';\n\n config: SoundParams = {\n resource: '',\n autoplay: false,\n muted: false,\n volume: 1,\n loop: false,\n seek: 0,\n };\n\n private buffer: AudioBuffer;\n\n private sourceNode: AudioBufferSourceNode;\n\n private gainNode: GainNode;\n\n private paused: boolean;\n\n private playTime: number = 0;\n\n private startTime: number = 0;\n\n private duration: number = 0;\n\n private actionQueue: (() => void)[] = [];\n\n private endedListener: () => void;\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Muted',\n description: 'Silence this sound without changing its volume setting.',\n editor: 'toggle',\n })\n get muted(): boolean {\n return this.config.muted ?? false;\n }\n\n set muted(v: boolean) {\n this.config.muted = v;\n this.applyGain();\n }\n\n @Field({\n type: 'number',\n min: 0,\n max: 1,\n step: 0.01,\n group: 'Sound',\n label: 'Volume',\n description: 'Loudness of this sound from 0 (silent) to 1 (full).',\n editor: 'volume-slider',\n })\n get volume(): number {\n return this.config.volume ?? 1;\n }\n\n set volume(v: number) {\n if (typeof v !== 'number' || v < 0 || v > 1) {\n return;\n }\n this.config.volume = v;\n this.applyGain();\n }\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Loop',\n description: 'Replay the sound continuously when it reaches the end.',\n editor: 'toggle',\n })\n get loop(): boolean {\n return this.config.loop ?? false;\n }\n\n set loop(v: boolean) {\n this.config.loop = v;\n if (this.sourceNode) {\n this.sourceNode.loop = v;\n }\n }\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Autoplay',\n description: 'Start playing automatically once the audio has loaded.',\n editor: 'toggle',\n })\n get autoplay(): boolean {\n return this.config.autoplay ?? false;\n }\n\n set autoplay(v: boolean) {\n this.config.autoplay = v;\n }\n\n @Field({\n type: 'string',\n group: 'Sound',\n label: 'Resource',\n description: 'Audio resource id used by the sound system.',\n editor: 'text',\n })\n get resource(): string {\n return this.config.resource ?? '';\n }\n\n set resource(v: string) {\n this.config.resource = v;\n }\n\n /**\n * Apply the effective gain (`muted ? 0 : volume`) to the gain node.\n *\n * `config` is the source of truth and the gain is assigned via `gain.value`\n * (updates the AudioParam intrinsic value synchronously) so the `muted` /\n * `volume` getters — and anything reading them back, e.g. the scene-edit\n * volume slider — reflect the change immediately. `setValueAtTime` only\n * schedules on the automation timeline and leaves `.value` stale.\n */\n private applyGain() {\n if (!this.gainNode) {\n return;\n }\n this.gainNode.gain.value = this.config.muted ? 0 : (this.config.volume ?? 1);\n }\n\n init(obj?: SoundParams) {\n if (!obj) {\n return;\n }\n\n Object.assign(this.config, obj);\n if (this.config.autoplay) {\n this.actionQueue.push(this.play.bind(this));\n }\n }\n\n play() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.play.bind(this));\n }\n this.destroySource();\n this.createSource();\n\n if (!this.sourceNode) {\n return;\n }\n const when = this.systemContext.currentTime;\n const offset = this.config.seek;\n const duration = this.config.duration;\n\n this.sourceNode.start(0, offset, duration);\n\n this.startTime = when;\n this.playTime = when - offset;\n this.paused = false;\n this.playing = true;\n this.resetConfig();\n this.endedListener = () => {\n if (!this.sourceNode) {\n return;\n }\n if (this.config.onEnd) {\n this.config.onEnd();\n }\n // Release resources once non-interactive playback finishes.\n if (this.playing) {\n this.destroySource();\n }\n };\n this.sourceNode.addEventListener('ended', this.endedListener);\n }\n\n pause() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.pause.bind(this));\n }\n if (this.paused || !this.playing) {\n return;\n }\n this.paused = true;\n this.playing = false;\n this.config.seek = this.getCurrentTime();\n this.destroySource();\n }\n\n stop() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.stop.bind(this));\n }\n if (!this.paused && !this.playing) {\n return;\n }\n this.playing = false;\n this.paused = false;\n this.destroySource();\n this.resetConfig();\n }\n\n onload(buffer: AudioBuffer) {\n this.state = 'loaded';\n this.buffer = buffer;\n this.duration = this.buffer.duration;\n this.actionQueue.forEach(action => action());\n this.actionQueue.length = 0;\n }\n\n onDestroy() {\n this.actionQueue.length = 0;\n this.destroySource();\n }\n\n private resetConfig() {\n this.config.seek = 0;\n }\n\n private getCurrentTime() {\n if (this.config.loop && this.duration > 0) {\n return (this.systemContext.currentTime - this.playTime) % this.duration;\n }\n\n return this.systemContext.currentTime - this.playTime;\n }\n\n private createSource() {\n if (!this.systemContext || this.state !== 'loaded') {\n return;\n }\n this.sourceNode = this.systemContext.createBufferSource();\n this.sourceNode.buffer = this.buffer;\n this.sourceNode.loop = this.config.loop;\n\n if (!this.gainNode) {\n this.gainNode = this.systemContext.createGain();\n this.gainNode.connect(this.systemDestination);\n Object.assign(this, this.config);\n }\n this.sourceNode.connect(this.gainNode);\n }\n\n private destroySource() {\n if (!this.sourceNode) return;\n this.sourceNode.removeEventListener('ended', this.endedListener);\n this.sourceNode.stop();\n this.sourceNode.disconnect();\n this.sourceNode = null;\n\n this.startTime = 0;\n this.playTime = 0;\n this.playing = false;\n }\n}\n\nexport default Sound;\n"],"names":["SoundSystem","System","OBSERVER_TYPE","resource","__decorate","decorators","Component","Field"],"mappings":"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"}
1
+ {"version":3,"file":"plugin-sound.cjs.js","sources":["../lib/SoundSystem.ts","../lib/__combosPackageMeta.gen.ts","../lib/Sound.ts"],"sourcesContent":["import { System, decorators, ComponentChanged, OBSERVER_TYPE, resource } from '@combos-fun/engine';\nimport SoundComponent from './Sound';\n\ninterface SoundSystemParams {\n autoPauseAndStart?: boolean;\n onError?: (error: any) => void;\n}\n\n@decorators.componentObserver({\n Sound: [],\n})\nclass SoundSystem extends System {\n static systemName = 'SoundSystem';\n\n private ctx: AudioContext;\n\n private gainNode: GainNode;\n\n /** Whether to pause/resume in sync with the game. */\n private autoPauseAndStart = true;\n\n private onError: (error: any) => void;\n\n private components: SoundComponent[] = [];\n\n private pausedComponents: SoundComponent[] = [];\n\n private audioBufferCache = {};\n\n private decodeAudioPromiseMap = {};\n\n /** Desired mute/volume are the source of truth; the gain node is derived. */\n private _muted = false;\n\n private _volume = 1;\n\n get muted(): boolean {\n return this._muted;\n }\n\n set muted(v: boolean) {\n this._muted = v;\n this.applyGain();\n }\n\n get volume(): number {\n return this._volume;\n }\n\n set volume(v: number) {\n if (typeof v !== 'number' || v < 0 || v > 1) {\n return;\n }\n this._volume = v;\n this.applyGain();\n }\n\n /**\n * Apply the effective gain (`muted ? 0 : volume`) to the gain node.\n *\n * Assigns `gain.value` directly rather than `setValueAtTime`: `.value` updates\n * the AudioParam's intrinsic value synchronously, so the `muted` / `volume`\n * getters reflect the change immediately. `setValueAtTime` only schedules an\n * event on the automation timeline and leaves `.value` stale until the next\n * render quantum, which made `muted` report the pre-change value.\n */\n private applyGain() {\n if (!this.gainNode) {\n return;\n }\n this.gainNode.gain.value = this._muted ? 0 : this._volume;\n }\n\n get audioLocked(): boolean {\n if (!this.ctx) {\n return true;\n }\n return this.ctx.state !== 'running';\n }\n\n constructor(obj?: SoundSystemParams) {\n super();\n Object.assign(this, obj);\n }\n\n /**\n * Resume playback of all paused audio.\n */\n resumeAll() {\n const handleResume = () => {\n this.pausedComponents.forEach(component => {\n component.play();\n });\n // Clear the previously cached paused list.\n this.pausedComponents = [];\n };\n this.ctx.resume().then(handleResume, handleResume);\n }\n\n /**\n * Pause all currently playing audio.\n */\n pauseAll() {\n this.components.forEach(component => {\n if (component.playing) {\n this.pausedComponents.push(component);\n component.pause();\n }\n });\n this.ctx.suspend().then();\n }\n\n /**\n * Stop all currently playing audio.\n */\n stopAll() {\n this.components.forEach(component => {\n if (component.playing) {\n component.stop();\n }\n });\n // Clear the previously cached paused list.\n this.pausedComponents = [];\n this.ctx.suspend().then();\n }\n\n /**\n * System init: configure params before the game starts.\n */\n init() {\n this.setupAudioContext();\n }\n\n update() {\n const changes = this.componentObserver.clear();\n for (const changed of changes) {\n this.componentChanged(changed);\n }\n }\n\n /**\n * Called when the game starts or resumes playing after a pause.\n */\n onResume() {\n if (!this.autoPauseAndStart) {\n return;\n }\n this.resumeAll();\n }\n\n /**\n * Called when the game is paused.\n */\n onPause() {\n if (!this.autoPauseAndStart) {\n return;\n }\n this.pauseAll();\n }\n\n /**\n * Called when the system is destroyed.\n */\n onDestroy() {\n this.components.forEach(component => {\n component.onDestroy();\n });\n this.components = [];\n if (this.ctx) {\n this.gainNode.disconnect();\n this.gainNode = null;\n this.ctx.close();\n this.ctx = null;\n }\n }\n\n async componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Sound') return;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.add(changed);\n }\n }\n\n private setupAudioContext() {\n try {\n const AudioContext = window.AudioContext || (window as any).webkitAudioContext;\n this.ctx = new AudioContext();\n } catch (error) {\n console.error(error);\n if (this.onError) {\n this.onError(error);\n }\n }\n\n if (!this.ctx) {\n return;\n }\n this.gainNode =\n typeof this.ctx.createGain === 'undefined' ? (this.ctx as any).createGainNode() : this.ctx.createGain();\n this.applyGain();\n this.gainNode.connect(this.ctx.destination);\n this.unlockAudio();\n }\n\n private unlockAudio() {\n if (!this.ctx || !this.audioLocked) {\n return;\n }\n\n const unlock = () => {\n if (this.ctx) {\n const removeListenerFn = () => {\n document.body.removeEventListener('touchstart', unlock);\n document.body.removeEventListener('touchend', unlock);\n document.body.removeEventListener('click', unlock);\n };\n this.ctx.resume().then(removeListenerFn, removeListenerFn);\n }\n };\n document.body.addEventListener('touchstart', unlock);\n document.body.addEventListener('touchend', unlock);\n document.body.addEventListener('click', unlock);\n }\n\n private async add(changed: ComponentChanged) {\n const component = changed.component as SoundComponent;\n this.components.push(component);\n try {\n const { config } = component;\n component.state = 'loading';\n\n const audio = await resource.getResource(config.resource);\n if (!this.audioBufferCache[audio.name] && audio?.data?.audio) {\n this.audioBufferCache[audio.name] = await this.decodeAudioData(audio.data.audio, audio.name);\n }\n if (this.audioBufferCache[audio.name]) {\n component.systemContext = this.ctx;\n component.systemDestination = this.gainNode;\n component.onload(this.audioBufferCache[audio.name]);\n }\n } catch (error) {\n if (this.onError) {\n this.onError(error);\n }\n }\n }\n\n private decodeAudioData(arraybuffer: ArrayBuffer, name: string) {\n if (this.decodeAudioPromiseMap[name]) {\n return this.decodeAudioPromiseMap[name];\n }\n\n const promise = new Promise<AudioBuffer>((resolve, reject) => {\n if (!this.ctx) {\n reject(new Error('No audio support'));\n }\n\n const success = (decodedData: AudioBuffer) => {\n if (this.decodeAudioPromiseMap[name]) {\n delete this.decodeAudioPromiseMap[name];\n }\n if (decodedData) {\n resolve(decodedData);\n } else {\n reject(new Error(`Error decoding audio ${name}`));\n }\n };\n\n const error = (err: DOMException) => {\n if (this.decodeAudioPromiseMap[name]) {\n delete this.decodeAudioPromiseMap[name];\n }\n reject(new Error(`${err}. arrayBuffer byteLength: ${arraybuffer ? arraybuffer.byteLength : 0}`));\n };\n\n const promise = this.ctx.decodeAudioData(arraybuffer, success, error)\n if (promise instanceof Promise) {\n promise.catch((err) => {\n reject(new Error(`catch ${err}, arrayBuffer byteLength: ${arraybuffer ? arraybuffer.byteLength : 0}`));\n });\n }\n });\n\n this.decodeAudioPromiseMap[name] = promise;\n return promise;\n }\n}\n\nexport default SoundSystem;\n","/** Auto-generated by scripts/build-package.mjs — do not edit. */\n\nimport SoundSystem from './SoundSystem';\n\nObject.assign(SoundSystem, {\n packageName: \"@combos-fun/plugin-sound\",\n packageVersion: \"0.0.47\",\n});\n","import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\n\nexport interface SoundParams {\n resource: string;\n autoplay?: boolean;\n muted?: boolean;\n volume?: number;\n loop?: boolean;\n seek?: number;\n duration?: number;\n onEnd?: () => void;\n}\n\nclass Sound extends Component<SoundParams> {\n static componentName = 'Sound';\n\n systemContext: AudioContext;\n\n systemDestination: GainNode;\n\n playing: boolean;\n\n state: 'unloaded' | 'loading' | 'loaded' = 'unloaded';\n\n config: SoundParams = {\n resource: '',\n autoplay: false,\n muted: false,\n volume: 1,\n loop: false,\n seek: 0,\n };\n\n private buffer: AudioBuffer;\n\n private sourceNode: AudioBufferSourceNode;\n\n private gainNode: GainNode;\n\n private paused: boolean;\n\n private playTime: number = 0;\n\n private startTime: number = 0;\n\n private duration: number = 0;\n\n private actionQueue: (() => void)[] = [];\n\n private endedListener: () => void;\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Muted',\n description: 'Silence this sound without changing its volume setting.',\n editor: 'toggle',\n })\n get muted(): boolean {\n return this.config.muted ?? false;\n }\n\n set muted(v: boolean) {\n this.config.muted = v;\n this.applyGain();\n }\n\n @Field({\n type: 'number',\n min: 0,\n max: 1,\n step: 0.01,\n group: 'Sound',\n label: 'Volume',\n description: 'Loudness of this sound from 0 (silent) to 1 (full).',\n editor: 'volume-slider',\n })\n get volume(): number {\n return this.config.volume ?? 1;\n }\n\n set volume(v: number) {\n if (typeof v !== 'number' || v < 0 || v > 1) {\n return;\n }\n this.config.volume = v;\n this.applyGain();\n }\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Loop',\n description: 'Replay the sound continuously when it reaches the end.',\n editor: 'toggle',\n })\n get loop(): boolean {\n return this.config.loop ?? false;\n }\n\n set loop(v: boolean) {\n this.config.loop = v;\n if (this.sourceNode) {\n this.sourceNode.loop = v;\n }\n }\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Autoplay',\n description: 'Start playing automatically once the audio has loaded.',\n editor: 'toggle',\n })\n get autoplay(): boolean {\n return this.config.autoplay ?? false;\n }\n\n set autoplay(v: boolean) {\n this.config.autoplay = v;\n }\n\n @Field({\n type: 'string',\n group: 'Sound',\n label: 'Resource',\n description: 'Audio resource id used by the sound system.',\n editor: 'text',\n })\n get resource(): string {\n return this.config.resource ?? '';\n }\n\n set resource(v: string) {\n this.config.resource = v;\n }\n\n /**\n * Apply the effective gain (`muted ? 0 : volume`) to the gain node.\n *\n * `config` is the source of truth and the gain is assigned via `gain.value`\n * (updates the AudioParam intrinsic value synchronously) so the `muted` /\n * `volume` getters — and anything reading them back, e.g. the scene-edit\n * volume slider — reflect the change immediately. `setValueAtTime` only\n * schedules on the automation timeline and leaves `.value` stale.\n */\n private applyGain() {\n if (!this.gainNode) {\n return;\n }\n this.gainNode.gain.value = this.config.muted ? 0 : (this.config.volume ?? 1);\n }\n\n init(obj?: SoundParams) {\n if (!obj) {\n return;\n }\n\n Object.assign(this.config, obj);\n if (this.config.autoplay) {\n this.actionQueue.push(this.play.bind(this));\n }\n }\n\n play() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.play.bind(this));\n }\n this.destroySource();\n this.createSource();\n\n if (!this.sourceNode) {\n return;\n }\n const when = this.systemContext.currentTime;\n const offset = this.config.seek;\n const duration = this.config.duration;\n\n this.sourceNode.start(0, offset, duration);\n\n this.startTime = when;\n this.playTime = when - offset;\n this.paused = false;\n this.playing = true;\n this.resetConfig();\n this.endedListener = () => {\n if (!this.sourceNode) {\n return;\n }\n if (this.config.onEnd) {\n this.config.onEnd();\n }\n // Release resources once non-interactive playback finishes.\n if (this.playing) {\n this.destroySource();\n }\n };\n this.sourceNode.addEventListener('ended', this.endedListener);\n }\n\n pause() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.pause.bind(this));\n }\n if (this.paused || !this.playing) {\n return;\n }\n this.paused = true;\n this.playing = false;\n this.config.seek = this.getCurrentTime();\n this.destroySource();\n }\n\n stop() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.stop.bind(this));\n }\n if (!this.paused && !this.playing) {\n return;\n }\n this.playing = false;\n this.paused = false;\n this.destroySource();\n this.resetConfig();\n }\n\n onload(buffer: AudioBuffer) {\n this.state = 'loaded';\n this.buffer = buffer;\n this.duration = this.buffer.duration;\n this.actionQueue.forEach(action => action());\n this.actionQueue.length = 0;\n }\n\n onDestroy() {\n this.actionQueue.length = 0;\n this.destroySource();\n }\n\n private resetConfig() {\n this.config.seek = 0;\n }\n\n private getCurrentTime() {\n if (this.config.loop && this.duration > 0) {\n return (this.systemContext.currentTime - this.playTime) % this.duration;\n }\n\n return this.systemContext.currentTime - this.playTime;\n }\n\n private createSource() {\n if (!this.systemContext || this.state !== 'loaded') {\n return;\n }\n this.sourceNode = this.systemContext.createBufferSource();\n this.sourceNode.buffer = this.buffer;\n this.sourceNode.loop = this.config.loop;\n\n if (!this.gainNode) {\n this.gainNode = this.systemContext.createGain();\n this.gainNode.connect(this.systemDestination);\n Object.assign(this, this.config);\n }\n this.sourceNode.connect(this.gainNode);\n }\n\n private destroySource() {\n if (!this.sourceNode) return;\n this.sourceNode.removeEventListener('ended', this.endedListener);\n this.sourceNode.stop();\n this.sourceNode.disconnect();\n this.sourceNode = null;\n\n this.startTime = 0;\n this.playTime = 0;\n this.playing = false;\n }\n}\n\nexport default Sound;\n"],"names":["SoundSystem","System","OBSERVER_TYPE","resource","__decorate","decorators","Component","Field"],"mappings":";;;;;;AAWA,IAAMA,aAAW,GAAjB,MAAM,WAAY,SAAQC,aAAM,CAAA;aACvB,IAAA,CAAA,UAAU,GAAG,aAAH,CAAiB;AAwBlC,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;IAEA,IAAI,KAAK,CAAC,CAAU,EAAA;AAClB,QAAA,IAAI,CAAC,MAAM,GAAG,CAAC;QACf,IAAI,CAAC,SAAS,EAAE;IAClB;AAEA,IAAA,IAAI,MAAM,GAAA;QACR,OAAO,IAAI,CAAC,OAAO;IACrB;IAEA,IAAI,MAAM,CAAC,CAAS,EAAA;AAClB,QAAA,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAC3C;QACF;AACA,QAAA,IAAI,CAAC,OAAO,GAAG,CAAC;QAChB,IAAI,CAAC,SAAS,EAAE;IAClB;AAEA;;;;;;;;AAQG;IACK,SAAS,GAAA;AACf,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB;QACF;QACA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO;IAC3D;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;AACb,YAAA,OAAO,IAAI;QACb;AACA,QAAA,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS;IACrC;AAEA,IAAA,WAAA,CAAY,GAAuB,EAAA;AACjC,QAAA,KAAK,EAAE;;QA9DD,IAAA,CAAA,iBAAiB,GAAG,IAAI;QAIxB,IAAA,CAAA,UAAU,GAAqB,EAAE;QAEjC,IAAA,CAAA,gBAAgB,GAAqB,EAAE;QAEvC,IAAA,CAAA,gBAAgB,GAAG,EAAE;QAErB,IAAA,CAAA,qBAAqB,GAAG,EAAE;;QAG1B,IAAA,CAAA,MAAM,GAAG,KAAK;QAEd,IAAA,CAAA,OAAO,GAAG,CAAC;AAgDjB,QAAA,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC;IAC1B;AAEA;;AAEG;IACH,SAAS,GAAA;QACP,MAAM,YAAY,GAAG,MAAK;AACxB,YAAA,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,SAAS,IAAG;gBACxC,SAAS,CAAC,IAAI,EAAE;AAClB,YAAA,CAAC,CAAC;;AAEF,YAAA,IAAI,CAAC,gBAAgB,GAAG,EAAE;AAC5B,QAAA,CAAC;AACD,QAAA,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC;IACpD;AAEA;;AAEG;IACH,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,IAAG;AAClC,YAAA,IAAI,SAAS,CAAC,OAAO,EAAE;AACrB,gBAAA,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC;gBACrC,SAAS,CAAC,KAAK,EAAE;YACnB;AACF,QAAA,CAAC,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE;IAC3B;AAEA;;AAEG;IACH,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,IAAG;AAClC,YAAA,IAAI,SAAS,CAAC,OAAO,EAAE;gBACrB,SAAS,CAAC,IAAI,EAAE;YAClB;AACF,QAAA,CAAC,CAAC;;AAEF,QAAA,IAAI,CAAC,gBAAgB,GAAG,EAAE;QAC1B,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE;IAC3B;AAEA;;AAEG;IACH,IAAI,GAAA;QACF,IAAI,CAAC,iBAAiB,EAAE;IAC1B;IAEA,MAAM,GAAA;QACJ,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE;AAC9C,QAAA,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE;AAC7B,YAAA,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;QAChC;IACF;AAEA;;AAEG;IACH,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;YAC3B;QACF;QACA,IAAI,CAAC,SAAS,EAAE;IAClB;AAEA;;AAEG;IACH,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;YAC3B;QACF;QACA,IAAI,CAAC,QAAQ,EAAE;IACjB;AAEA;;AAEG;IACH,SAAS,GAAA;AACP,QAAA,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,IAAG;YAClC,SAAS,CAAC,SAAS,EAAE;AACvB,QAAA,CAAC,CAAC;AACF,QAAA,IAAI,CAAC,UAAU,GAAG,EAAE;AACpB,QAAA,IAAI,IAAI,CAAC,GAAG,EAAE;AACZ,YAAA,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE;AAC1B,YAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;AACpB,YAAA,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE;AAChB,YAAA,IAAI,CAAC,GAAG,GAAG,IAAI;QACjB;IACF;IAEA,MAAM,gBAAgB,CAAC,OAAyB,EAAA;AAC9C,QAAA,IAAI,OAAO,CAAC,aAAa,KAAK,OAAO;YAAE;QAEvC,IAAI,OAAO,CAAC,IAAI,KAAKC,oBAAa,CAAC,GAAG,EAAE;AACtC,YAAA,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;QACnB;IACF;IAEQ,iBAAiB,GAAA;AACvB,QAAA,IAAI;YACF,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAK,MAAc,CAAC,kBAAkB;AAC9E,YAAA,IAAI,CAAC,GAAG,GAAG,IAAI,YAAY,EAAE;QAC/B;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;AACpB,YAAA,IAAI,IAAI,CAAC,OAAO,EAAE;AAChB,gBAAA,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACrB;QACF;AAEA,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACb;QACF;AACA,QAAA,IAAI,CAAC,QAAQ;YACX,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,WAAW,GAAI,IAAI,CAAC,GAAW,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE;QACzG,IAAI,CAAC,SAAS,EAAE;QAChB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;QAC3C,IAAI,CAAC,WAAW,EAAE;IACpB;IAEQ,WAAW,GAAA;QACjB,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;YAClC;QACF;QAEA,MAAM,MAAM,GAAG,MAAK;AAClB,YAAA,IAAI,IAAI,CAAC,GAAG,EAAE;gBACZ,MAAM,gBAAgB,GAAG,MAAK;oBAC5B,QAAQ,CAAC,IAAI,CAAC,mBAAmB,CAAC,YAAY,EAAE,MAAM,CAAC;oBACvD,QAAQ,CAAC,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC;oBACrD,QAAQ,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC;AACpD,gBAAA,CAAC;AACD,gBAAA,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;YAC5D;AACF,QAAA,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,MAAM,CAAC;QACpD,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC;QAClD,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC;IACjD;IAEQ,MAAM,GAAG,CAAC,OAAyB,EAAA;AACzC,QAAA,MAAM,SAAS,GAAG,OAAO,CAAC,SAA2B;AACrD,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;AAC/B,QAAA,IAAI;AACF,YAAA,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS;AAC5B,YAAA,SAAS,CAAC,KAAK,GAAG,SAAS;YAE3B,MAAM,KAAK,GAAG,MAAMC,eAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC;AACzD,YAAA,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE;gBAC5D,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC;YAC9F;YACA,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;AACrC,gBAAA,SAAS,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG;AAClC,gBAAA,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,QAAQ;AAC3C,gBAAA,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACrD;QACF;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,IAAI,IAAI,CAAC,OAAO,EAAE;AAChB,gBAAA,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACrB;QACF;IACF;IAEQ,eAAe,CAAC,WAAwB,EAAE,IAAY,EAAA;AAC5D,QAAA,IAAI,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE;AACpC,YAAA,OAAO,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC;QACzC;QAEA,MAAM,OAAO,GAAG,IAAI,OAAO,CAAc,CAAC,OAAO,EAAE,MAAM,KAAI;AAC3D,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;AACb,gBAAA,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;YACvC;AAEA,YAAA,MAAM,OAAO,GAAG,CAAC,WAAwB,KAAI;AAC3C,gBAAA,IAAI,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE;AACpC,oBAAA,OAAO,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC;gBACzC;gBACA,IAAI,WAAW,EAAE;oBACf,OAAO,CAAC,WAAW,CAAC;gBACtB;qBAAO;oBACL,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAA,CAAE,CAAC,CAAC;gBACnD;AACF,YAAA,CAAC;AAED,YAAA,MAAM,KAAK,GAAG,CAAC,GAAiB,KAAI;AAClC,gBAAA,IAAI,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE;AACpC,oBAAA,OAAO,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC;gBACzC;gBACA,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,CAAA,0BAAA,EAA6B,WAAW,GAAG,WAAW,CAAC,UAAU,GAAG,CAAC,CAAA,CAAE,CAAC,CAAC;AAClG,YAAA,CAAC;AAED,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC;AACrE,YAAA,IAAI,OAAO,YAAY,OAAO,EAAE;AAC9B,gBAAA,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,KAAI;oBACpB,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,GAAG,CAAA,0BAAA,EAA6B,WAAW,GAAG,WAAW,CAAC,UAAU,GAAG,CAAC,CAAA,CAAE,CAAC,CAAC;AACxG,gBAAA,CAAC,CAAC;YACJ;AACF,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,GAAG,OAAO;AAC1C,QAAA,OAAO,OAAO;IAChB;;AAnRIH,aAAW,GAAAI,gBAAA,CAAA;IAHhBC,iBAAU,CAAC,iBAAiB,CAAC;AAC5B,QAAA,KAAK,EAAE,EAAE;KACV;AACK,CAAA,EAAAL,aAAW,CAoRhB;AAED,kBAAeA,aAAW;;ACjS1B;AAIA,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE;AACzB,IAAA,WAAW,EAAE,0BAA0B;AACvC,IAAA,cAAc,EAAE,QAAQ;AACzB,CAAA,CAAC;;ACOF,MAAM,KAAM,SAAQM,gBAAsB,CAAA;AAA1C,IAAA,WAAA,GAAA;;QASE,IAAA,CAAA,KAAK,GAAsC,UAAU;AAErD,QAAA,IAAA,CAAA,MAAM,GAAgB;AACpB,YAAA,QAAQ,EAAE,EAAE;AACZ,YAAA,QAAQ,EAAE,KAAK;AACf,YAAA,KAAK,EAAE,KAAK;AACZ,YAAA,MAAM,EAAE,CAAC;AACT,YAAA,IAAI,EAAE,KAAK;AACX,YAAA,IAAI,EAAE,CAAC;SACR;QAUO,IAAA,CAAA,QAAQ,GAAW,CAAC;QAEpB,IAAA,CAAA,SAAS,GAAW,CAAC;QAErB,IAAA,CAAA,QAAQ,GAAW,CAAC;QAEpB,IAAA,CAAA,WAAW,GAAmB,EAAE;IAuO1C;aAxQS,IAAA,CAAA,aAAa,GAAG,OAAH,CAAW;AA4C/B,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK;IACnC;IAEA,IAAI,KAAK,CAAC,CAAU,EAAA;AAClB,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC;QACrB,IAAI,CAAC,SAAS,EAAE;IAClB;AAYA,IAAA,IAAI,MAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC;IAChC;IAEA,IAAI,MAAM,CAAC,CAAS,EAAA;AAClB,QAAA,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAC3C;QACF;AACA,QAAA,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QACtB,IAAI,CAAC,SAAS,EAAE;IAClB;AASA,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,KAAK;IAClC;IAEA,IAAI,IAAI,CAAC,CAAU,EAAA;AACjB,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;AACpB,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACnB,YAAA,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC;QAC1B;IACF;AASA,IAAA,IAAI,QAAQ,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,KAAK;IACtC;IAEA,IAAI,QAAQ,CAAC,CAAU,EAAA;AACrB,QAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC;IAC1B;AASA,IAAA,IAAI,QAAQ,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE;IACnC;IAEA,IAAI,QAAQ,CAAC,CAAS,EAAA;AACpB,QAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC;IAC1B;AAEA;;;;;;;;AAQG;IACK,SAAS,GAAA;AACf,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB;QACF;AACA,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IAC9E;AAEA,IAAA,IAAI,CAAC,GAAiB,EAAA;QACpB,IAAI,CAAC,GAAG,EAAE;YACR;QACF;QAEA,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC;AAC/B,QAAA,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;AACxB,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C;IACF;IAEA,IAAI,GAAA;AACF,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE;AAC3B,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C;QACA,IAAI,CAAC,aAAa,EAAE;QACpB,IAAI,CAAC,YAAY,EAAE;AAEnB,QAAA,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YACpB;QACF;AACA,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW;AAC3C,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI;AAC/B,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ;QAErC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC;AAE1C,QAAA,IAAI,CAAC,SAAS,GAAG,IAAI;AACrB,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,MAAM;AAC7B,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK;AACnB,QAAA,IAAI,CAAC,OAAO,GAAG,IAAI;QACnB,IAAI,CAAC,WAAW,EAAE;AAClB,QAAA,IAAI,CAAC,aAAa,GAAG,MAAK;AACxB,YAAA,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;gBACpB;YACF;AACA,YAAA,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;AACrB,gBAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;YACrB;;AAEA,YAAA,IAAI,IAAI,CAAC,OAAO,EAAE;gBAChB,IAAI,CAAC,aAAa,EAAE;YACtB;AACF,QAAA,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC;IAC/D;IAEA,KAAK,GAAA;AACH,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE;AAC3B,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C;QACA,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YAChC;QACF;AACA,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI;AAClB,QAAA,IAAI,CAAC,OAAO,GAAG,KAAK;QACpB,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE;QACxC,IAAI,CAAC,aAAa,EAAE;IACtB;IAEA,IAAI,GAAA;AACF,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE;AAC3B,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C;QACA,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACjC;QACF;AACA,QAAA,IAAI,CAAC,OAAO,GAAG,KAAK;AACpB,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK;QACnB,IAAI,CAAC,aAAa,EAAE;QACpB,IAAI,CAAC,WAAW,EAAE;IACpB;AAEA,IAAA,MAAM,CAAC,MAAmB,EAAA;AACxB,QAAA,IAAI,CAAC,KAAK,GAAG,QAAQ;AACrB,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;QACpB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ;AACpC,QAAA,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;AAC5C,QAAA,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;IAC7B;IAEA,SAAS,GAAA;AACP,QAAA,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QAC3B,IAAI,CAAC,aAAa,EAAE;IACtB;IAEQ,WAAW,GAAA;AACjB,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;IACtB;IAEQ,cAAc,GAAA;AACpB,QAAA,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAE;AACzC,YAAA,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ;QACzE;QAEA,OAAO,IAAI,CAAC,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ;IACvD;IAEQ,YAAY,GAAA;QAClB,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE;YAClD;QACF;QACA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,kBAAkB,EAAE;QACzD,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM;QACpC,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI;AAEvC,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE;YAC/C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;QAClC;QACA,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;IACxC;IAEQ,aAAa,GAAA;QACnB,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE;QACtB,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC;AAChE,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;AACtB,QAAA,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE;AAC5B,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI;AAEtB,QAAA,IAAI,CAAC,SAAS,GAAG,CAAC;AAClB,QAAA,IAAI,CAAC,QAAQ,GAAG,CAAC;AACjB,QAAA,IAAI,CAAC,OAAO,GAAG,KAAK;IACtB;;AA3NAF,gBAAA,CAAA;AAPC,IAAAG,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,WAAW,EAAE,yDAAyD;AACtE,QAAA,MAAM,EAAE,QAAQ;KACjB;AAGA,CAAA,EAAA,KAAA,CAAA,SAAA,EAAA,OAAA,EAAA,IAAA,CAAA;AAiBDH,gBAAA,CAAA;AAVC,IAAAG,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,GAAG,EAAE,CAAC;AACN,QAAA,GAAG,EAAE,CAAC;AACN,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,KAAK,EAAE,QAAQ;AACf,QAAA,WAAW,EAAE,qDAAqD;AAClE,QAAA,MAAM,EAAE,eAAe;KACxB;AAGA,CAAA,EAAA,KAAA,CAAA,SAAA,EAAA,QAAA,EAAA,IAAA,CAAA;AAiBDH,gBAAA,CAAA;AAPC,IAAAG,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,KAAK,EAAE,MAAM;AACb,QAAA,WAAW,EAAE,wDAAwD;AACrE,QAAA,MAAM,EAAE,QAAQ;KACjB;AAGA,CAAA,EAAA,KAAA,CAAA,SAAA,EAAA,MAAA,EAAA,IAAA,CAAA;AAgBDH,gBAAA,CAAA;AAPC,IAAAG,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,KAAK,EAAE,UAAU;AACjB,QAAA,WAAW,EAAE,wDAAwD;AACrE,QAAA,MAAM,EAAE,QAAQ;KACjB;AAGA,CAAA,EAAA,KAAA,CAAA,SAAA,EAAA,UAAA,EAAA,IAAA,CAAA;AAaDH,gBAAA,CAAA;AAPC,IAAAG,wBAAK,CAAC;AACL,QAAA,IAAI,EAAE,QAAQ;AACd,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,KAAK,EAAE,UAAU;AACjB,QAAA,WAAW,EAAE,6CAA6C;AAC1D,QAAA,MAAM,EAAE,MAAM;KACf;AAGA,CAAA,EAAA,KAAA,CAAA,SAAA,EAAA,UAAA,EAAA,IAAA,CAAA;;;;;"}
@@ -1 +1 @@
1
- "use strict";var t=require("tslib"),e=require("@combos-fun/engine"),o=require("@combos-fun/inspector-decorator");let s=class extends e.System{static{this.systemName="SoundSystem"}get muted(){return this._muted}set muted(t){this._muted=t,this.applyGain()}get volume(){return this._volume}set volume(t){"number"!=typeof t||t<0||t>1||(this._volume=t,this.applyGain())}applyGain(){this.gainNode&&(this.gainNode.gain.value=this._muted?0:this._volume)}get audioLocked(){return!this.ctx||"running"!==this.ctx.state}constructor(t){super(),this.autoPauseAndStart=!0,this.components=[],this.pausedComponents=[],this.audioBufferCache={},this.decodeAudioPromiseMap={},this._muted=!1,this._volume=1,Object.assign(this,t)}resumeAll(){const t=()=>{this.pausedComponents.forEach(t=>{t.play()}),this.pausedComponents=[]};this.ctx.resume().then(t,t)}pauseAll(){this.components.forEach(t=>{t.playing&&(this.pausedComponents.push(t),t.pause())}),this.ctx.suspend().then()}stopAll(){this.components.forEach(t=>{t.playing&&t.stop()}),this.pausedComponents=[],this.ctx.suspend().then()}init(){this.setupAudioContext()}update(){const t=this.componentObserver.clear();for(const e of t)this.componentChanged(e)}onResume(){this.autoPauseAndStart&&this.resumeAll()}onPause(){this.autoPauseAndStart&&this.pauseAll()}onDestroy(){this.components.forEach(t=>{t.onDestroy()}),this.components=[],this.ctx&&(this.gainNode.disconnect(),this.gainNode=null,this.ctx.close(),this.ctx=null)}async componentChanged(t){"Sound"===t.componentName&&t.type===e.OBSERVER_TYPE.ADD&&this.add(t)}setupAudioContext(){try{const t=window.AudioContext||window.webkitAudioContext;this.ctx=new t}catch(t){console.error(t),this.onError&&this.onError(t)}this.ctx&&(this.gainNode=void 0===this.ctx.createGain?this.ctx.createGainNode():this.ctx.createGain(),this.applyGain(),this.gainNode.connect(this.ctx.destination),this.unlockAudio())}unlockAudio(){if(!this.ctx||!this.audioLocked)return;const t=()=>{if(this.ctx){const e=()=>{document.body.removeEventListener("touchstart",t),document.body.removeEventListener("touchend",t),document.body.removeEventListener("click",t)};this.ctx.resume().then(e,e)}};document.body.addEventListener("touchstart",t),document.body.addEventListener("touchend",t),document.body.addEventListener("click",t)}async add(t){const o=t.component;this.components.push(o);try{const{config:t}=o;o.state="loading";const s=await e.resource.getResource(t.resource);!this.audioBufferCache[s.name]&&s?.data?.audio&&(this.audioBufferCache[s.name]=await this.decodeAudioData(s.data.audio,s.name)),this.audioBufferCache[s.name]&&(o.systemContext=this.ctx,o.systemDestination=this.gainNode,o.onload(this.audioBufferCache[s.name]))}catch(t){this.onError&&this.onError(t)}}decodeAudioData(t,e){if(this.decodeAudioPromiseMap[e])return this.decodeAudioPromiseMap[e];const o=new Promise((o,s)=>{this.ctx||s(new Error("No audio support"));const i=this.ctx.decodeAudioData(t,t=>{this.decodeAudioPromiseMap[e]&&delete this.decodeAudioPromiseMap[e],t?o(t):s(new Error(`Error decoding audio ${e}`))},o=>{this.decodeAudioPromiseMap[e]&&delete this.decodeAudioPromiseMap[e],s(new Error(`${o}. arrayBuffer byteLength: ${t?t.byteLength:0}`))});i instanceof Promise&&i.catch(e=>{s(new Error(`catch ${e}, arrayBuffer byteLength: ${t?t.byteLength:0}`))})});return this.decodeAudioPromiseMap[e]=o,o}};s=t.__decorate([e.decorators.componentObserver({Sound:[]})],s);var i=s;Object.assign(i,{packageName:"@combos-fun/plugin-sound",packageVersion:"0.0.45"});class n extends e.Component{constructor(){super(...arguments),this.state="unloaded",this.config={resource:"",autoplay:!1,muted:!1,volume:1,loop:!1,seek:0},this.playTime=0,this.startTime=0,this.duration=0,this.actionQueue=[]}static{this.componentName="Sound"}get muted(){return this.config.muted??!1}set muted(t){this.config.muted=t,this.applyGain()}get volume(){return this.config.volume??1}set volume(t){"number"!=typeof t||t<0||t>1||(this.config.volume=t,this.applyGain())}get loop(){return this.config.loop??!1}set loop(t){this.config.loop=t,this.sourceNode&&(this.sourceNode.loop=t)}get autoplay(){return this.config.autoplay??!1}set autoplay(t){this.config.autoplay=t}get resource(){return this.config.resource??""}set resource(t){this.config.resource=t}applyGain(){this.gainNode&&(this.gainNode.gain.value=this.config.muted?0:this.config.volume??1)}init(t){t&&(Object.assign(this.config,t),this.config.autoplay&&this.actionQueue.push(this.play.bind(this)))}play(){if("loaded"!==this.state&&this.actionQueue.push(this.play.bind(this)),this.destroySource(),this.createSource(),!this.sourceNode)return;const t=this.systemContext.currentTime,e=this.config.seek,o=this.config.duration;this.sourceNode.start(0,e,o),this.startTime=t,this.playTime=t-e,this.paused=!1,this.playing=!0,this.resetConfig(),this.endedListener=()=>{this.sourceNode&&(this.config.onEnd&&this.config.onEnd(),this.playing&&this.destroySource())},this.sourceNode.addEventListener("ended",this.endedListener)}pause(){"loaded"!==this.state&&this.actionQueue.push(this.pause.bind(this)),!this.paused&&this.playing&&(this.paused=!0,this.playing=!1,this.config.seek=this.getCurrentTime(),this.destroySource())}stop(){"loaded"!==this.state&&this.actionQueue.push(this.stop.bind(this)),(this.paused||this.playing)&&(this.playing=!1,this.paused=!1,this.destroySource(),this.resetConfig())}onload(t){this.state="loaded",this.buffer=t,this.duration=this.buffer.duration,this.actionQueue.forEach(t=>t()),this.actionQueue.length=0}onDestroy(){this.actionQueue.length=0,this.destroySource()}resetConfig(){this.config.seek=0}getCurrentTime(){return this.config.loop&&this.duration>0?(this.systemContext.currentTime-this.playTime)%this.duration:this.systemContext.currentTime-this.playTime}createSource(){this.systemContext&&"loaded"===this.state&&(this.sourceNode=this.systemContext.createBufferSource(),this.sourceNode.buffer=this.buffer,this.sourceNode.loop=this.config.loop,this.gainNode||(this.gainNode=this.systemContext.createGain(),this.gainNode.connect(this.systemDestination),Object.assign(this,this.config)),this.sourceNode.connect(this.gainNode))}destroySource(){this.sourceNode&&(this.sourceNode.removeEventListener("ended",this.endedListener),this.sourceNode.stop(),this.sourceNode.disconnect(),this.sourceNode=null,this.startTime=0,this.playTime=0,this.playing=!1)}}t.__decorate([o.Field({type:"boolean",group:"Sound",label:"Muted",description:"Silence this sound without changing its volume setting.",editor:"toggle"})],n.prototype,"muted",null),t.__decorate([o.Field({type:"number",min:0,max:1,step:.01,group:"Sound",label:"Volume",description:"Loudness of this sound from 0 (silent) to 1 (full).",editor:"volume-slider"})],n.prototype,"volume",null),t.__decorate([o.Field({type:"boolean",group:"Sound",label:"Loop",description:"Replay the sound continuously when it reaches the end.",editor:"toggle"})],n.prototype,"loop",null),t.__decorate([o.Field({type:"boolean",group:"Sound",label:"Autoplay",description:"Start playing automatically once the audio has loaded.",editor:"toggle"})],n.prototype,"autoplay",null),t.__decorate([o.Field({type:"string",group:"Sound",label:"Resource",description:"Audio resource id used by the sound system.",editor:"text"})],n.prototype,"resource",null),exports.Sound=n,exports.SoundSystem=i;
1
+ "use strict";var t=require("tslib"),e=require("@combos-fun/engine"),o=require("@combos-fun/inspector-decorator");let s=class extends e.System{static{this.systemName="SoundSystem"}get muted(){return this._muted}set muted(t){this._muted=t,this.applyGain()}get volume(){return this._volume}set volume(t){"number"!=typeof t||t<0||t>1||(this._volume=t,this.applyGain())}applyGain(){this.gainNode&&(this.gainNode.gain.value=this._muted?0:this._volume)}get audioLocked(){return!this.ctx||"running"!==this.ctx.state}constructor(t){super(),this.autoPauseAndStart=!0,this.components=[],this.pausedComponents=[],this.audioBufferCache={},this.decodeAudioPromiseMap={},this._muted=!1,this._volume=1,Object.assign(this,t)}resumeAll(){const t=()=>{this.pausedComponents.forEach(t=>{t.play()}),this.pausedComponents=[]};this.ctx.resume().then(t,t)}pauseAll(){this.components.forEach(t=>{t.playing&&(this.pausedComponents.push(t),t.pause())}),this.ctx.suspend().then()}stopAll(){this.components.forEach(t=>{t.playing&&t.stop()}),this.pausedComponents=[],this.ctx.suspend().then()}init(){this.setupAudioContext()}update(){const t=this.componentObserver.clear();for(const e of t)this.componentChanged(e)}onResume(){this.autoPauseAndStart&&this.resumeAll()}onPause(){this.autoPauseAndStart&&this.pauseAll()}onDestroy(){this.components.forEach(t=>{t.onDestroy()}),this.components=[],this.ctx&&(this.gainNode.disconnect(),this.gainNode=null,this.ctx.close(),this.ctx=null)}async componentChanged(t){"Sound"===t.componentName&&t.type===e.OBSERVER_TYPE.ADD&&this.add(t)}setupAudioContext(){try{const t=window.AudioContext||window.webkitAudioContext;this.ctx=new t}catch(t){console.error(t),this.onError&&this.onError(t)}this.ctx&&(this.gainNode=void 0===this.ctx.createGain?this.ctx.createGainNode():this.ctx.createGain(),this.applyGain(),this.gainNode.connect(this.ctx.destination),this.unlockAudio())}unlockAudio(){if(!this.ctx||!this.audioLocked)return;const t=()=>{if(this.ctx){const e=()=>{document.body.removeEventListener("touchstart",t),document.body.removeEventListener("touchend",t),document.body.removeEventListener("click",t)};this.ctx.resume().then(e,e)}};document.body.addEventListener("touchstart",t),document.body.addEventListener("touchend",t),document.body.addEventListener("click",t)}async add(t){const o=t.component;this.components.push(o);try{const{config:t}=o;o.state="loading";const s=await e.resource.getResource(t.resource);!this.audioBufferCache[s.name]&&s?.data?.audio&&(this.audioBufferCache[s.name]=await this.decodeAudioData(s.data.audio,s.name)),this.audioBufferCache[s.name]&&(o.systemContext=this.ctx,o.systemDestination=this.gainNode,o.onload(this.audioBufferCache[s.name]))}catch(t){this.onError&&this.onError(t)}}decodeAudioData(t,e){if(this.decodeAudioPromiseMap[e])return this.decodeAudioPromiseMap[e];const o=new Promise((o,s)=>{this.ctx||s(new Error("No audio support"));const i=this.ctx.decodeAudioData(t,t=>{this.decodeAudioPromiseMap[e]&&delete this.decodeAudioPromiseMap[e],t?o(t):s(new Error(`Error decoding audio ${e}`))},o=>{this.decodeAudioPromiseMap[e]&&delete this.decodeAudioPromiseMap[e],s(new Error(`${o}. arrayBuffer byteLength: ${t?t.byteLength:0}`))});i instanceof Promise&&i.catch(e=>{s(new Error(`catch ${e}, arrayBuffer byteLength: ${t?t.byteLength:0}`))})});return this.decodeAudioPromiseMap[e]=o,o}};s=t.__decorate([e.decorators.componentObserver({Sound:[]})],s);var i=s;Object.assign(i,{packageName:"@combos-fun/plugin-sound",packageVersion:"0.0.47"});class n extends e.Component{constructor(){super(...arguments),this.state="unloaded",this.config={resource:"",autoplay:!1,muted:!1,volume:1,loop:!1,seek:0},this.playTime=0,this.startTime=0,this.duration=0,this.actionQueue=[]}static{this.componentName="Sound"}get muted(){return this.config.muted??!1}set muted(t){this.config.muted=t,this.applyGain()}get volume(){return this.config.volume??1}set volume(t){"number"!=typeof t||t<0||t>1||(this.config.volume=t,this.applyGain())}get loop(){return this.config.loop??!1}set loop(t){this.config.loop=t,this.sourceNode&&(this.sourceNode.loop=t)}get autoplay(){return this.config.autoplay??!1}set autoplay(t){this.config.autoplay=t}get resource(){return this.config.resource??""}set resource(t){this.config.resource=t}applyGain(){this.gainNode&&(this.gainNode.gain.value=this.config.muted?0:this.config.volume??1)}init(t){t&&(Object.assign(this.config,t),this.config.autoplay&&this.actionQueue.push(this.play.bind(this)))}play(){if("loaded"!==this.state&&this.actionQueue.push(this.play.bind(this)),this.destroySource(),this.createSource(),!this.sourceNode)return;const t=this.systemContext.currentTime,e=this.config.seek,o=this.config.duration;this.sourceNode.start(0,e,o),this.startTime=t,this.playTime=t-e,this.paused=!1,this.playing=!0,this.resetConfig(),this.endedListener=()=>{this.sourceNode&&(this.config.onEnd&&this.config.onEnd(),this.playing&&this.destroySource())},this.sourceNode.addEventListener("ended",this.endedListener)}pause(){"loaded"!==this.state&&this.actionQueue.push(this.pause.bind(this)),!this.paused&&this.playing&&(this.paused=!0,this.playing=!1,this.config.seek=this.getCurrentTime(),this.destroySource())}stop(){"loaded"!==this.state&&this.actionQueue.push(this.stop.bind(this)),(this.paused||this.playing)&&(this.playing=!1,this.paused=!1,this.destroySource(),this.resetConfig())}onload(t){this.state="loaded",this.buffer=t,this.duration=this.buffer.duration,this.actionQueue.forEach(t=>t()),this.actionQueue.length=0}onDestroy(){this.actionQueue.length=0,this.destroySource()}resetConfig(){this.config.seek=0}getCurrentTime(){return this.config.loop&&this.duration>0?(this.systemContext.currentTime-this.playTime)%this.duration:this.systemContext.currentTime-this.playTime}createSource(){this.systemContext&&"loaded"===this.state&&(this.sourceNode=this.systemContext.createBufferSource(),this.sourceNode.buffer=this.buffer,this.sourceNode.loop=this.config.loop,this.gainNode||(this.gainNode=this.systemContext.createGain(),this.gainNode.connect(this.systemDestination),Object.assign(this,this.config)),this.sourceNode.connect(this.gainNode))}destroySource(){this.sourceNode&&(this.sourceNode.removeEventListener("ended",this.endedListener),this.sourceNode.stop(),this.sourceNode.disconnect(),this.sourceNode=null,this.startTime=0,this.playTime=0,this.playing=!1)}}t.__decorate([o.Field({type:"boolean",group:"Sound",label:"Muted",description:"Silence this sound without changing its volume setting.",editor:"toggle"})],n.prototype,"muted",null),t.__decorate([o.Field({type:"number",min:0,max:1,step:.01,group:"Sound",label:"Volume",description:"Loudness of this sound from 0 (silent) to 1 (full).",editor:"volume-slider"})],n.prototype,"volume",null),t.__decorate([o.Field({type:"boolean",group:"Sound",label:"Loop",description:"Replay the sound continuously when it reaches the end.",editor:"toggle"})],n.prototype,"loop",null),t.__decorate([o.Field({type:"boolean",group:"Sound",label:"Autoplay",description:"Start playing automatically once the audio has loaded.",editor:"toggle"})],n.prototype,"autoplay",null),t.__decorate([o.Field({type:"string",group:"Sound",label:"Resource",description:"Audio resource id used by the sound system.",editor:"text"})],n.prototype,"resource",null),exports.Sound=n,exports.SoundSystem=i;
@@ -251,7 +251,7 @@ var SoundSystem$1 = SoundSystem;
251
251
  /** Auto-generated by scripts/build-package.mjs — do not edit. */
252
252
  Object.assign(SoundSystem$1, {
253
253
  packageName: "@combos-fun/plugin-sound",
254
- packageVersion: "0.0.45",
254
+ packageVersion: "0.0.47",
255
255
  });
256
256
 
257
257
  class Sound extends Component {
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-sound.esm.js","sources":["../lib/SoundSystem.ts","../lib/__combosPackageMeta.gen.ts","../lib/Sound.ts"],"sourcesContent":["import { System, decorators, ComponentChanged, OBSERVER_TYPE, resource } from '@combos-fun/engine';\nimport SoundComponent from './Sound';\n\ninterface SoundSystemParams {\n autoPauseAndStart?: boolean;\n onError?: (error: any) => void;\n}\n\n@decorators.componentObserver({\n Sound: [],\n})\nclass SoundSystem extends System {\n static systemName = 'SoundSystem';\n\n private ctx: AudioContext;\n\n private gainNode: GainNode;\n\n /** Whether to pause/resume in sync with the game. */\n private autoPauseAndStart = true;\n\n private onError: (error: any) => void;\n\n private components: SoundComponent[] = [];\n\n private pausedComponents: SoundComponent[] = [];\n\n private audioBufferCache = {};\n\n private decodeAudioPromiseMap = {};\n\n /** Desired mute/volume are the source of truth; the gain node is derived. */\n private _muted = false;\n\n private _volume = 1;\n\n get muted(): boolean {\n return this._muted;\n }\n\n set muted(v: boolean) {\n this._muted = v;\n this.applyGain();\n }\n\n get volume(): number {\n return this._volume;\n }\n\n set volume(v: number) {\n if (typeof v !== 'number' || v < 0 || v > 1) {\n return;\n }\n this._volume = v;\n this.applyGain();\n }\n\n /**\n * Apply the effective gain (`muted ? 0 : volume`) to the gain node.\n *\n * Assigns `gain.value` directly rather than `setValueAtTime`: `.value` updates\n * the AudioParam's intrinsic value synchronously, so the `muted` / `volume`\n * getters reflect the change immediately. `setValueAtTime` only schedules an\n * event on the automation timeline and leaves `.value` stale until the next\n * render quantum, which made `muted` report the pre-change value.\n */\n private applyGain() {\n if (!this.gainNode) {\n return;\n }\n this.gainNode.gain.value = this._muted ? 0 : this._volume;\n }\n\n get audioLocked(): boolean {\n if (!this.ctx) {\n return true;\n }\n return this.ctx.state !== 'running';\n }\n\n constructor(obj?: SoundSystemParams) {\n super();\n Object.assign(this, obj);\n }\n\n /**\n * Resume playback of all paused audio.\n */\n resumeAll() {\n const handleResume = () => {\n this.pausedComponents.forEach(component => {\n component.play();\n });\n // Clear the previously cached paused list.\n this.pausedComponents = [];\n };\n this.ctx.resume().then(handleResume, handleResume);\n }\n\n /**\n * Pause all currently playing audio.\n */\n pauseAll() {\n this.components.forEach(component => {\n if (component.playing) {\n this.pausedComponents.push(component);\n component.pause();\n }\n });\n this.ctx.suspend().then();\n }\n\n /**\n * Stop all currently playing audio.\n */\n stopAll() {\n this.components.forEach(component => {\n if (component.playing) {\n component.stop();\n }\n });\n // Clear the previously cached paused list.\n this.pausedComponents = [];\n this.ctx.suspend().then();\n }\n\n /**\n * System init: configure params before the game starts.\n */\n init() {\n this.setupAudioContext();\n }\n\n update() {\n const changes = this.componentObserver.clear();\n for (const changed of changes) {\n this.componentChanged(changed);\n }\n }\n\n /**\n * Called when the game starts or resumes playing after a pause.\n */\n onResume() {\n if (!this.autoPauseAndStart) {\n return;\n }\n this.resumeAll();\n }\n\n /**\n * Called when the game is paused.\n */\n onPause() {\n if (!this.autoPauseAndStart) {\n return;\n }\n this.pauseAll();\n }\n\n /**\n * Called when the system is destroyed.\n */\n onDestroy() {\n this.components.forEach(component => {\n component.onDestroy();\n });\n this.components = [];\n if (this.ctx) {\n this.gainNode.disconnect();\n this.gainNode = null;\n this.ctx.close();\n this.ctx = null;\n }\n }\n\n async componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Sound') return;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.add(changed);\n }\n }\n\n private setupAudioContext() {\n try {\n const AudioContext = window.AudioContext || (window as any).webkitAudioContext;\n this.ctx = new AudioContext();\n } catch (error) {\n console.error(error);\n if (this.onError) {\n this.onError(error);\n }\n }\n\n if (!this.ctx) {\n return;\n }\n this.gainNode =\n typeof this.ctx.createGain === 'undefined' ? (this.ctx as any).createGainNode() : this.ctx.createGain();\n this.applyGain();\n this.gainNode.connect(this.ctx.destination);\n this.unlockAudio();\n }\n\n private unlockAudio() {\n if (!this.ctx || !this.audioLocked) {\n return;\n }\n\n const unlock = () => {\n if (this.ctx) {\n const removeListenerFn = () => {\n document.body.removeEventListener('touchstart', unlock);\n document.body.removeEventListener('touchend', unlock);\n document.body.removeEventListener('click', unlock);\n };\n this.ctx.resume().then(removeListenerFn, removeListenerFn);\n }\n };\n document.body.addEventListener('touchstart', unlock);\n document.body.addEventListener('touchend', unlock);\n document.body.addEventListener('click', unlock);\n }\n\n private async add(changed: ComponentChanged) {\n const component = changed.component as SoundComponent;\n this.components.push(component);\n try {\n const { config } = component;\n component.state = 'loading';\n\n const audio = await resource.getResource(config.resource);\n if (!this.audioBufferCache[audio.name] && audio?.data?.audio) {\n this.audioBufferCache[audio.name] = await this.decodeAudioData(audio.data.audio, audio.name);\n }\n if (this.audioBufferCache[audio.name]) {\n component.systemContext = this.ctx;\n component.systemDestination = this.gainNode;\n component.onload(this.audioBufferCache[audio.name]);\n }\n } catch (error) {\n if (this.onError) {\n this.onError(error);\n }\n }\n }\n\n private decodeAudioData(arraybuffer: ArrayBuffer, name: string) {\n if (this.decodeAudioPromiseMap[name]) {\n return this.decodeAudioPromiseMap[name];\n }\n\n const promise = new Promise<AudioBuffer>((resolve, reject) => {\n if (!this.ctx) {\n reject(new Error('No audio support'));\n }\n\n const success = (decodedData: AudioBuffer) => {\n if (this.decodeAudioPromiseMap[name]) {\n delete this.decodeAudioPromiseMap[name];\n }\n if (decodedData) {\n resolve(decodedData);\n } else {\n reject(new Error(`Error decoding audio ${name}`));\n }\n };\n\n const error = (err: DOMException) => {\n if (this.decodeAudioPromiseMap[name]) {\n delete this.decodeAudioPromiseMap[name];\n }\n reject(new Error(`${err}. arrayBuffer byteLength: ${arraybuffer ? arraybuffer.byteLength : 0}`));\n };\n\n const promise = this.ctx.decodeAudioData(arraybuffer, success, error)\n if (promise instanceof Promise) {\n promise.catch((err) => {\n reject(new Error(`catch ${err}, arrayBuffer byteLength: ${arraybuffer ? arraybuffer.byteLength : 0}`));\n });\n }\n });\n\n this.decodeAudioPromiseMap[name] = promise;\n return promise;\n }\n}\n\nexport default SoundSystem;\n","/** Auto-generated by scripts/build-package.mjs — do not edit. */\n\nimport SoundSystem from './SoundSystem';\n\nObject.assign(SoundSystem, {\n packageName: \"@combos-fun/plugin-sound\",\n packageVersion: \"0.0.45\",\n});\n","import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\n\nexport interface SoundParams {\n resource: string;\n autoplay?: boolean;\n muted?: boolean;\n volume?: number;\n loop?: boolean;\n seek?: number;\n duration?: number;\n onEnd?: () => void;\n}\n\nclass Sound extends Component<SoundParams> {\n static componentName = 'Sound';\n\n systemContext: AudioContext;\n\n systemDestination: GainNode;\n\n playing: boolean;\n\n state: 'unloaded' | 'loading' | 'loaded' = 'unloaded';\n\n config: SoundParams = {\n resource: '',\n autoplay: false,\n muted: false,\n volume: 1,\n loop: false,\n seek: 0,\n };\n\n private buffer: AudioBuffer;\n\n private sourceNode: AudioBufferSourceNode;\n\n private gainNode: GainNode;\n\n private paused: boolean;\n\n private playTime: number = 0;\n\n private startTime: number = 0;\n\n private duration: number = 0;\n\n private actionQueue: (() => void)[] = [];\n\n private endedListener: () => void;\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Muted',\n description: 'Silence this sound without changing its volume setting.',\n editor: 'toggle',\n })\n get muted(): boolean {\n return this.config.muted ?? false;\n }\n\n set muted(v: boolean) {\n this.config.muted = v;\n this.applyGain();\n }\n\n @Field({\n type: 'number',\n min: 0,\n max: 1,\n step: 0.01,\n group: 'Sound',\n label: 'Volume',\n description: 'Loudness of this sound from 0 (silent) to 1 (full).',\n editor: 'volume-slider',\n })\n get volume(): number {\n return this.config.volume ?? 1;\n }\n\n set volume(v: number) {\n if (typeof v !== 'number' || v < 0 || v > 1) {\n return;\n }\n this.config.volume = v;\n this.applyGain();\n }\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Loop',\n description: 'Replay the sound continuously when it reaches the end.',\n editor: 'toggle',\n })\n get loop(): boolean {\n return this.config.loop ?? false;\n }\n\n set loop(v: boolean) {\n this.config.loop = v;\n if (this.sourceNode) {\n this.sourceNode.loop = v;\n }\n }\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Autoplay',\n description: 'Start playing automatically once the audio has loaded.',\n editor: 'toggle',\n })\n get autoplay(): boolean {\n return this.config.autoplay ?? false;\n }\n\n set autoplay(v: boolean) {\n this.config.autoplay = v;\n }\n\n @Field({\n type: 'string',\n group: 'Sound',\n label: 'Resource',\n description: 'Audio resource id used by the sound system.',\n editor: 'text',\n })\n get resource(): string {\n return this.config.resource ?? '';\n }\n\n set resource(v: string) {\n this.config.resource = v;\n }\n\n /**\n * Apply the effective gain (`muted ? 0 : volume`) to the gain node.\n *\n * `config` is the source of truth and the gain is assigned via `gain.value`\n * (updates the AudioParam intrinsic value synchronously) so the `muted` /\n * `volume` getters — and anything reading them back, e.g. the scene-edit\n * volume slider — reflect the change immediately. `setValueAtTime` only\n * schedules on the automation timeline and leaves `.value` stale.\n */\n private applyGain() {\n if (!this.gainNode) {\n return;\n }\n this.gainNode.gain.value = this.config.muted ? 0 : (this.config.volume ?? 1);\n }\n\n init(obj?: SoundParams) {\n if (!obj) {\n return;\n }\n\n Object.assign(this.config, obj);\n if (this.config.autoplay) {\n this.actionQueue.push(this.play.bind(this));\n }\n }\n\n play() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.play.bind(this));\n }\n this.destroySource();\n this.createSource();\n\n if (!this.sourceNode) {\n return;\n }\n const when = this.systemContext.currentTime;\n const offset = this.config.seek;\n const duration = this.config.duration;\n\n this.sourceNode.start(0, offset, duration);\n\n this.startTime = when;\n this.playTime = when - offset;\n this.paused = false;\n this.playing = true;\n this.resetConfig();\n this.endedListener = () => {\n if (!this.sourceNode) {\n return;\n }\n if (this.config.onEnd) {\n this.config.onEnd();\n }\n // Release resources once non-interactive playback finishes.\n if (this.playing) {\n this.destroySource();\n }\n };\n this.sourceNode.addEventListener('ended', this.endedListener);\n }\n\n pause() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.pause.bind(this));\n }\n if (this.paused || !this.playing) {\n return;\n }\n this.paused = true;\n this.playing = false;\n this.config.seek = this.getCurrentTime();\n this.destroySource();\n }\n\n stop() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.stop.bind(this));\n }\n if (!this.paused && !this.playing) {\n return;\n }\n this.playing = false;\n this.paused = false;\n this.destroySource();\n this.resetConfig();\n }\n\n onload(buffer: AudioBuffer) {\n this.state = 'loaded';\n this.buffer = buffer;\n this.duration = this.buffer.duration;\n this.actionQueue.forEach(action => action());\n this.actionQueue.length = 0;\n }\n\n onDestroy() {\n this.actionQueue.length = 0;\n this.destroySource();\n }\n\n private resetConfig() {\n this.config.seek = 0;\n }\n\n private getCurrentTime() {\n if (this.config.loop && this.duration > 0) {\n return (this.systemContext.currentTime - this.playTime) % this.duration;\n }\n\n return this.systemContext.currentTime - this.playTime;\n }\n\n private createSource() {\n if (!this.systemContext || this.state !== 'loaded') {\n return;\n }\n this.sourceNode = this.systemContext.createBufferSource();\n this.sourceNode.buffer = this.buffer;\n this.sourceNode.loop = this.config.loop;\n\n if (!this.gainNode) {\n this.gainNode = this.systemContext.createGain();\n this.gainNode.connect(this.systemDestination);\n Object.assign(this, this.config);\n }\n this.sourceNode.connect(this.gainNode);\n }\n\n private destroySource() {\n if (!this.sourceNode) return;\n this.sourceNode.removeEventListener('ended', this.endedListener);\n this.sourceNode.stop();\n this.sourceNode.disconnect();\n this.sourceNode = null;\n\n this.startTime = 0;\n this.playTime = 0;\n this.playing = false;\n }\n}\n\nexport default Sound;\n"],"names":["SoundSystem"],"mappings":"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"}
1
+ {"version":3,"file":"plugin-sound.esm.js","sources":["../lib/SoundSystem.ts","../lib/__combosPackageMeta.gen.ts","../lib/Sound.ts"],"sourcesContent":["import { System, decorators, ComponentChanged, OBSERVER_TYPE, resource } from '@combos-fun/engine';\nimport SoundComponent from './Sound';\n\ninterface SoundSystemParams {\n autoPauseAndStart?: boolean;\n onError?: (error: any) => void;\n}\n\n@decorators.componentObserver({\n Sound: [],\n})\nclass SoundSystem extends System {\n static systemName = 'SoundSystem';\n\n private ctx: AudioContext;\n\n private gainNode: GainNode;\n\n /** Whether to pause/resume in sync with the game. */\n private autoPauseAndStart = true;\n\n private onError: (error: any) => void;\n\n private components: SoundComponent[] = [];\n\n private pausedComponents: SoundComponent[] = [];\n\n private audioBufferCache = {};\n\n private decodeAudioPromiseMap = {};\n\n /** Desired mute/volume are the source of truth; the gain node is derived. */\n private _muted = false;\n\n private _volume = 1;\n\n get muted(): boolean {\n return this._muted;\n }\n\n set muted(v: boolean) {\n this._muted = v;\n this.applyGain();\n }\n\n get volume(): number {\n return this._volume;\n }\n\n set volume(v: number) {\n if (typeof v !== 'number' || v < 0 || v > 1) {\n return;\n }\n this._volume = v;\n this.applyGain();\n }\n\n /**\n * Apply the effective gain (`muted ? 0 : volume`) to the gain node.\n *\n * Assigns `gain.value` directly rather than `setValueAtTime`: `.value` updates\n * the AudioParam's intrinsic value synchronously, so the `muted` / `volume`\n * getters reflect the change immediately. `setValueAtTime` only schedules an\n * event on the automation timeline and leaves `.value` stale until the next\n * render quantum, which made `muted` report the pre-change value.\n */\n private applyGain() {\n if (!this.gainNode) {\n return;\n }\n this.gainNode.gain.value = this._muted ? 0 : this._volume;\n }\n\n get audioLocked(): boolean {\n if (!this.ctx) {\n return true;\n }\n return this.ctx.state !== 'running';\n }\n\n constructor(obj?: SoundSystemParams) {\n super();\n Object.assign(this, obj);\n }\n\n /**\n * Resume playback of all paused audio.\n */\n resumeAll() {\n const handleResume = () => {\n this.pausedComponents.forEach(component => {\n component.play();\n });\n // Clear the previously cached paused list.\n this.pausedComponents = [];\n };\n this.ctx.resume().then(handleResume, handleResume);\n }\n\n /**\n * Pause all currently playing audio.\n */\n pauseAll() {\n this.components.forEach(component => {\n if (component.playing) {\n this.pausedComponents.push(component);\n component.pause();\n }\n });\n this.ctx.suspend().then();\n }\n\n /**\n * Stop all currently playing audio.\n */\n stopAll() {\n this.components.forEach(component => {\n if (component.playing) {\n component.stop();\n }\n });\n // Clear the previously cached paused list.\n this.pausedComponents = [];\n this.ctx.suspend().then();\n }\n\n /**\n * System init: configure params before the game starts.\n */\n init() {\n this.setupAudioContext();\n }\n\n update() {\n const changes = this.componentObserver.clear();\n for (const changed of changes) {\n this.componentChanged(changed);\n }\n }\n\n /**\n * Called when the game starts or resumes playing after a pause.\n */\n onResume() {\n if (!this.autoPauseAndStart) {\n return;\n }\n this.resumeAll();\n }\n\n /**\n * Called when the game is paused.\n */\n onPause() {\n if (!this.autoPauseAndStart) {\n return;\n }\n this.pauseAll();\n }\n\n /**\n * Called when the system is destroyed.\n */\n onDestroy() {\n this.components.forEach(component => {\n component.onDestroy();\n });\n this.components = [];\n if (this.ctx) {\n this.gainNode.disconnect();\n this.gainNode = null;\n this.ctx.close();\n this.ctx = null;\n }\n }\n\n async componentChanged(changed: ComponentChanged) {\n if (changed.componentName !== 'Sound') return;\n\n if (changed.type === OBSERVER_TYPE.ADD) {\n this.add(changed);\n }\n }\n\n private setupAudioContext() {\n try {\n const AudioContext = window.AudioContext || (window as any).webkitAudioContext;\n this.ctx = new AudioContext();\n } catch (error) {\n console.error(error);\n if (this.onError) {\n this.onError(error);\n }\n }\n\n if (!this.ctx) {\n return;\n }\n this.gainNode =\n typeof this.ctx.createGain === 'undefined' ? (this.ctx as any).createGainNode() : this.ctx.createGain();\n this.applyGain();\n this.gainNode.connect(this.ctx.destination);\n this.unlockAudio();\n }\n\n private unlockAudio() {\n if (!this.ctx || !this.audioLocked) {\n return;\n }\n\n const unlock = () => {\n if (this.ctx) {\n const removeListenerFn = () => {\n document.body.removeEventListener('touchstart', unlock);\n document.body.removeEventListener('touchend', unlock);\n document.body.removeEventListener('click', unlock);\n };\n this.ctx.resume().then(removeListenerFn, removeListenerFn);\n }\n };\n document.body.addEventListener('touchstart', unlock);\n document.body.addEventListener('touchend', unlock);\n document.body.addEventListener('click', unlock);\n }\n\n private async add(changed: ComponentChanged) {\n const component = changed.component as SoundComponent;\n this.components.push(component);\n try {\n const { config } = component;\n component.state = 'loading';\n\n const audio = await resource.getResource(config.resource);\n if (!this.audioBufferCache[audio.name] && audio?.data?.audio) {\n this.audioBufferCache[audio.name] = await this.decodeAudioData(audio.data.audio, audio.name);\n }\n if (this.audioBufferCache[audio.name]) {\n component.systemContext = this.ctx;\n component.systemDestination = this.gainNode;\n component.onload(this.audioBufferCache[audio.name]);\n }\n } catch (error) {\n if (this.onError) {\n this.onError(error);\n }\n }\n }\n\n private decodeAudioData(arraybuffer: ArrayBuffer, name: string) {\n if (this.decodeAudioPromiseMap[name]) {\n return this.decodeAudioPromiseMap[name];\n }\n\n const promise = new Promise<AudioBuffer>((resolve, reject) => {\n if (!this.ctx) {\n reject(new Error('No audio support'));\n }\n\n const success = (decodedData: AudioBuffer) => {\n if (this.decodeAudioPromiseMap[name]) {\n delete this.decodeAudioPromiseMap[name];\n }\n if (decodedData) {\n resolve(decodedData);\n } else {\n reject(new Error(`Error decoding audio ${name}`));\n }\n };\n\n const error = (err: DOMException) => {\n if (this.decodeAudioPromiseMap[name]) {\n delete this.decodeAudioPromiseMap[name];\n }\n reject(new Error(`${err}. arrayBuffer byteLength: ${arraybuffer ? arraybuffer.byteLength : 0}`));\n };\n\n const promise = this.ctx.decodeAudioData(arraybuffer, success, error)\n if (promise instanceof Promise) {\n promise.catch((err) => {\n reject(new Error(`catch ${err}, arrayBuffer byteLength: ${arraybuffer ? arraybuffer.byteLength : 0}`));\n });\n }\n });\n\n this.decodeAudioPromiseMap[name] = promise;\n return promise;\n }\n}\n\nexport default SoundSystem;\n","/** Auto-generated by scripts/build-package.mjs — do not edit. */\n\nimport SoundSystem from './SoundSystem';\n\nObject.assign(SoundSystem, {\n packageName: \"@combos-fun/plugin-sound\",\n packageVersion: \"0.0.47\",\n});\n","import { Component } from '@combos-fun/engine';\nimport { Field } from '@combos-fun/inspector-decorator';\n\nexport interface SoundParams {\n resource: string;\n autoplay?: boolean;\n muted?: boolean;\n volume?: number;\n loop?: boolean;\n seek?: number;\n duration?: number;\n onEnd?: () => void;\n}\n\nclass Sound extends Component<SoundParams> {\n static componentName = 'Sound';\n\n systemContext: AudioContext;\n\n systemDestination: GainNode;\n\n playing: boolean;\n\n state: 'unloaded' | 'loading' | 'loaded' = 'unloaded';\n\n config: SoundParams = {\n resource: '',\n autoplay: false,\n muted: false,\n volume: 1,\n loop: false,\n seek: 0,\n };\n\n private buffer: AudioBuffer;\n\n private sourceNode: AudioBufferSourceNode;\n\n private gainNode: GainNode;\n\n private paused: boolean;\n\n private playTime: number = 0;\n\n private startTime: number = 0;\n\n private duration: number = 0;\n\n private actionQueue: (() => void)[] = [];\n\n private endedListener: () => void;\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Muted',\n description: 'Silence this sound without changing its volume setting.',\n editor: 'toggle',\n })\n get muted(): boolean {\n return this.config.muted ?? false;\n }\n\n set muted(v: boolean) {\n this.config.muted = v;\n this.applyGain();\n }\n\n @Field({\n type: 'number',\n min: 0,\n max: 1,\n step: 0.01,\n group: 'Sound',\n label: 'Volume',\n description: 'Loudness of this sound from 0 (silent) to 1 (full).',\n editor: 'volume-slider',\n })\n get volume(): number {\n return this.config.volume ?? 1;\n }\n\n set volume(v: number) {\n if (typeof v !== 'number' || v < 0 || v > 1) {\n return;\n }\n this.config.volume = v;\n this.applyGain();\n }\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Loop',\n description: 'Replay the sound continuously when it reaches the end.',\n editor: 'toggle',\n })\n get loop(): boolean {\n return this.config.loop ?? false;\n }\n\n set loop(v: boolean) {\n this.config.loop = v;\n if (this.sourceNode) {\n this.sourceNode.loop = v;\n }\n }\n\n @Field({\n type: 'boolean',\n group: 'Sound',\n label: 'Autoplay',\n description: 'Start playing automatically once the audio has loaded.',\n editor: 'toggle',\n })\n get autoplay(): boolean {\n return this.config.autoplay ?? false;\n }\n\n set autoplay(v: boolean) {\n this.config.autoplay = v;\n }\n\n @Field({\n type: 'string',\n group: 'Sound',\n label: 'Resource',\n description: 'Audio resource id used by the sound system.',\n editor: 'text',\n })\n get resource(): string {\n return this.config.resource ?? '';\n }\n\n set resource(v: string) {\n this.config.resource = v;\n }\n\n /**\n * Apply the effective gain (`muted ? 0 : volume`) to the gain node.\n *\n * `config` is the source of truth and the gain is assigned via `gain.value`\n * (updates the AudioParam intrinsic value synchronously) so the `muted` /\n * `volume` getters — and anything reading them back, e.g. the scene-edit\n * volume slider — reflect the change immediately. `setValueAtTime` only\n * schedules on the automation timeline and leaves `.value` stale.\n */\n private applyGain() {\n if (!this.gainNode) {\n return;\n }\n this.gainNode.gain.value = this.config.muted ? 0 : (this.config.volume ?? 1);\n }\n\n init(obj?: SoundParams) {\n if (!obj) {\n return;\n }\n\n Object.assign(this.config, obj);\n if (this.config.autoplay) {\n this.actionQueue.push(this.play.bind(this));\n }\n }\n\n play() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.play.bind(this));\n }\n this.destroySource();\n this.createSource();\n\n if (!this.sourceNode) {\n return;\n }\n const when = this.systemContext.currentTime;\n const offset = this.config.seek;\n const duration = this.config.duration;\n\n this.sourceNode.start(0, offset, duration);\n\n this.startTime = when;\n this.playTime = when - offset;\n this.paused = false;\n this.playing = true;\n this.resetConfig();\n this.endedListener = () => {\n if (!this.sourceNode) {\n return;\n }\n if (this.config.onEnd) {\n this.config.onEnd();\n }\n // Release resources once non-interactive playback finishes.\n if (this.playing) {\n this.destroySource();\n }\n };\n this.sourceNode.addEventListener('ended', this.endedListener);\n }\n\n pause() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.pause.bind(this));\n }\n if (this.paused || !this.playing) {\n return;\n }\n this.paused = true;\n this.playing = false;\n this.config.seek = this.getCurrentTime();\n this.destroySource();\n }\n\n stop() {\n if (this.state !== 'loaded') {\n this.actionQueue.push(this.stop.bind(this));\n }\n if (!this.paused && !this.playing) {\n return;\n }\n this.playing = false;\n this.paused = false;\n this.destroySource();\n this.resetConfig();\n }\n\n onload(buffer: AudioBuffer) {\n this.state = 'loaded';\n this.buffer = buffer;\n this.duration = this.buffer.duration;\n this.actionQueue.forEach(action => action());\n this.actionQueue.length = 0;\n }\n\n onDestroy() {\n this.actionQueue.length = 0;\n this.destroySource();\n }\n\n private resetConfig() {\n this.config.seek = 0;\n }\n\n private getCurrentTime() {\n if (this.config.loop && this.duration > 0) {\n return (this.systemContext.currentTime - this.playTime) % this.duration;\n }\n\n return this.systemContext.currentTime - this.playTime;\n }\n\n private createSource() {\n if (!this.systemContext || this.state !== 'loaded') {\n return;\n }\n this.sourceNode = this.systemContext.createBufferSource();\n this.sourceNode.buffer = this.buffer;\n this.sourceNode.loop = this.config.loop;\n\n if (!this.gainNode) {\n this.gainNode = this.systemContext.createGain();\n this.gainNode.connect(this.systemDestination);\n Object.assign(this, this.config);\n }\n this.sourceNode.connect(this.gainNode);\n }\n\n private destroySource() {\n if (!this.sourceNode) return;\n this.sourceNode.removeEventListener('ended', this.endedListener);\n this.sourceNode.stop();\n this.sourceNode.disconnect();\n this.sourceNode = null;\n\n this.startTime = 0;\n this.playTime = 0;\n this.playing = false;\n }\n}\n\nexport default Sound;\n"],"names":["SoundSystem"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@combos-fun/plugin-sound",
3
- "version": "0.0.45",
3
+ "version": "0.0.47",
4
4
  "description": "Audio playback",
5
5
  "main": "index.js",
6
6
  "module": "dist/plugin-sound.esm.js",
@@ -38,8 +38,8 @@
38
38
  "author": "sun668 <q947692259@gmail.com>",
39
39
  "dependencies": {
40
40
  "eventemitter3": "^5.0.4",
41
- "@combos-fun/inspector-decorator": "0.0.45",
42
- "@combos-fun/engine": "0.0.45"
41
+ "@combos-fun/engine": "0.0.47",
42
+ "@combos-fun/inspector-decorator": "0.0.47"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "node ../../scripts/build-package.mjs"