@energy8platform/game-engine 0.34.2 → 0.34.3
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/dist/audio.cjs.js +114 -59
- package/dist/audio.cjs.js.map +1 -1
- package/dist/audio.d.ts +25 -0
- package/dist/audio.esm.js +114 -59
- package/dist/audio.esm.js.map +1 -1
- package/dist/core.cjs.js +114 -59
- package/dist/core.cjs.js.map +1 -1
- package/dist/core.d.ts +25 -0
- package/dist/core.esm.js +114 -59
- package/dist/core.esm.js.map +1 -1
- package/dist/host.cjs.js +114 -59
- package/dist/host.cjs.js.map +1 -1
- package/dist/host.d.ts +25 -0
- package/dist/host.esm.js +114 -59
- package/dist/host.esm.js.map +1 -1
- package/dist/index.cjs.js +114 -59
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +25 -0
- package/dist/index.esm.js +114 -59
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/audio/AudioManager.ts +111 -53
package/dist/audio.cjs.js
CHANGED
|
@@ -30,6 +30,12 @@ class AudioManager {
|
|
|
30
30
|
_categories;
|
|
31
31
|
_masterGain = 1.0;
|
|
32
32
|
_currentMusic = null;
|
|
33
|
+
/** Duck factor (0..1) from duckMusic/unduckMusic. A presentation state, not a player setting. */
|
|
34
|
+
_musicDuck = 1;
|
|
35
|
+
/** Crossfade ramp (0..1) for the track that is fading IN. 1 whenever no fade is running. */
|
|
36
|
+
_musicFade = 1;
|
|
37
|
+
/** Generation counter so a superseded crossfade ramp stops writing over the new track's. */
|
|
38
|
+
_musicFadeToken = 0;
|
|
33
39
|
_unlocked = false;
|
|
34
40
|
_unlockHandler = null;
|
|
35
41
|
constructor(config) {
|
|
@@ -88,7 +94,10 @@ class AudioManager {
|
|
|
88
94
|
if (this._globalMuted || this._categories[category].muted)
|
|
89
95
|
return;
|
|
90
96
|
const { sound } = this._soundModule;
|
|
91
|
-
|
|
97
|
+
// The master gain lives on the GLOBAL bus (`sound.volumeAll`, see applyVolumes) and @pixi/sound
|
|
98
|
+
// already multiplies it in — folding it in here as well squared it, so a master of 0.5 played
|
|
99
|
+
// sfx at 0.25.
|
|
100
|
+
const vol = (options?.volume ?? 1) * this._categories[category].volume;
|
|
92
101
|
try {
|
|
93
102
|
sound.play(alias, {
|
|
94
103
|
volume: vol,
|
|
@@ -110,52 +119,50 @@ class AudioManager {
|
|
|
110
119
|
if (!this._initialized || !this._soundModule)
|
|
111
120
|
return;
|
|
112
121
|
const { sound } = this._soundModule;
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
});
|
|
126
|
-
// Start new track at zero volume, fade in
|
|
127
|
-
try {
|
|
128
|
-
sound.play(alias, {
|
|
129
|
-
volume: 0,
|
|
130
|
-
loop: true,
|
|
122
|
+
const prevAlias = this._currentMusic;
|
|
123
|
+
const crossfade = !!prevAlias && prevAlias !== alias && fadeDuration > 0;
|
|
124
|
+
// Retire the outgoing track. Its own SOUND-level volume is the only thing still pointing at it,
|
|
125
|
+
// so fading that to 0 is safe — nothing else writes it once `_currentMusic` has moved on.
|
|
126
|
+
if (prevAlias) {
|
|
127
|
+
if (crossfade) {
|
|
128
|
+
const from = this.soundVolumeOf(prevAlias);
|
|
129
|
+
this.fadeVolume(prevAlias, from, 0, fadeDuration, () => {
|
|
130
|
+
try {
|
|
131
|
+
sound.stop(prevAlias);
|
|
132
|
+
}
|
|
133
|
+
catch { /* ignore */ }
|
|
131
134
|
});
|
|
132
|
-
this.fadeVolume(alias, 0, this._categories.music.volume * this._masterGain, fadeDuration);
|
|
133
135
|
}
|
|
134
|
-
|
|
135
|
-
console.warn(`[AudioManager] Failed to play music "${alias}":`, e);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
// No crossfade — instant switch
|
|
140
|
-
if (this._currentMusic) {
|
|
136
|
+
else {
|
|
141
137
|
try {
|
|
142
|
-
sound.stop(
|
|
138
|
+
sound.stop(prevAlias);
|
|
143
139
|
}
|
|
144
140
|
catch { /* ignore */ }
|
|
145
141
|
}
|
|
146
|
-
this._currentMusic = alias;
|
|
147
|
-
if (this._globalMuted || this._categories.music.muted)
|
|
148
|
-
return;
|
|
149
|
-
try {
|
|
150
|
-
sound.play(alias, {
|
|
151
|
-
volume: this._categories.music.volume * this._masterGain,
|
|
152
|
-
loop: true,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
catch (e) {
|
|
156
|
-
console.warn(`[AudioManager] Failed to play music "${alias}":`, e);
|
|
157
|
-
}
|
|
158
142
|
}
|
|
143
|
+
this._currentMusic = alias;
|
|
144
|
+
this._musicFadeToken++; // any ramp still running belongs to a track we just replaced
|
|
145
|
+
// Deliberately started even while muted. Global mute is the @pixi/sound CONTEXT mute and a
|
|
146
|
+
// muted music category is a 0 term in `musicGain()` — both already make this inaudible, and
|
|
147
|
+
// both undo themselves the moment the player flips them back. Returning early here instead
|
|
148
|
+
// meant a track begun while muted never existed, so unmuting restored silence until some
|
|
149
|
+
// later mode change happened to switch tracks.
|
|
150
|
+
// The incoming track plays at INSTANCE volume 1 and carries its whole gain on the SOUND layer
|
|
151
|
+
// (`musicGain()`), which is the layer the slider, the duck and this fade all write. Splitting
|
|
152
|
+
// them across layers is what silenced every crossfade: the track was started at instance volume
|
|
153
|
+
// 0 and the ramp then moved the sound layer, whose product with 0 is 0 for the track's life.
|
|
154
|
+
// The gain is written BEFORE play() so the first frame is never at full volume.
|
|
155
|
+
this._musicFade = crossfade ? 0 : 1;
|
|
156
|
+
this.applyMusicGain();
|
|
157
|
+
try {
|
|
158
|
+
sound.play(alias, { volume: 1, loop: true });
|
|
159
|
+
}
|
|
160
|
+
catch (e) {
|
|
161
|
+
console.warn(`[AudioManager] Failed to play music "${alias}":`, e);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (crossfade)
|
|
165
|
+
this.rampMusicFade(fadeDuration);
|
|
159
166
|
}
|
|
160
167
|
/**
|
|
161
168
|
* Stop current music.
|
|
@@ -171,6 +178,10 @@ class AudioManager {
|
|
|
171
178
|
// ignore
|
|
172
179
|
}
|
|
173
180
|
this._currentMusic = null;
|
|
181
|
+
// Retire any running ramp and clear the fade term, so the next track does not inherit a
|
|
182
|
+
// half-finished crossfade and start silent.
|
|
183
|
+
this._musicFadeToken++;
|
|
184
|
+
this._musicFade = 1;
|
|
174
185
|
}
|
|
175
186
|
/**
|
|
176
187
|
* Stop all sounds.
|
|
@@ -196,6 +207,9 @@ class AudioManager {
|
|
|
196
207
|
*/
|
|
197
208
|
setVolume(category, volume) {
|
|
198
209
|
this._categories[category].volume = Math.max(0, Math.min(1, volume));
|
|
210
|
+
// applyVolumes() re-pushes the music gain, so moving the Music slider is heard on the track
|
|
211
|
+
// that is ALREADY playing — it used to take effect only at the next playMusic (a mode change).
|
|
212
|
+
// SFX need no push: play() reads the category volume fresh on every call.
|
|
199
213
|
this.applyVolumes();
|
|
200
214
|
this.saveState();
|
|
201
215
|
}
|
|
@@ -268,30 +282,19 @@ class AudioManager {
|
|
|
268
282
|
* @param factor - Volume multiplier (0..1), e.g. 0.3 = 30% of normal
|
|
269
283
|
*/
|
|
270
284
|
duckMusic(factor) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
catch {
|
|
279
|
-
// ignore
|
|
280
|
-
}
|
|
285
|
+
// Held as a FACTOR rather than written as a finished volume: the duck used to write
|
|
286
|
+
// `category × factor` onto a track whose instance already carried the category volume, so it
|
|
287
|
+
// ducked to category², and unducking restored category² instead of category. Keeping it as one
|
|
288
|
+
// term of `musicGain()` also keeps the slider live while ducked.
|
|
289
|
+
this._musicDuck = Math.max(0, Math.min(1, factor));
|
|
290
|
+
this.applyMusicGain();
|
|
281
291
|
}
|
|
282
292
|
/**
|
|
283
293
|
* Restore music to normal volume after ducking.
|
|
284
294
|
*/
|
|
285
295
|
unduckMusic() {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const { sound } = this._soundModule;
|
|
289
|
-
try {
|
|
290
|
-
sound.volume(this._currentMusic, this._categories.music.volume);
|
|
291
|
-
}
|
|
292
|
-
catch {
|
|
293
|
-
// ignore
|
|
294
|
-
}
|
|
296
|
+
this._musicDuck = 1;
|
|
297
|
+
this.applyMusicGain();
|
|
295
298
|
}
|
|
296
299
|
/**
|
|
297
300
|
* Destroy the audio manager and free resources.
|
|
@@ -330,6 +333,57 @@ class AudioManager {
|
|
|
330
333
|
};
|
|
331
334
|
requestAnimationFrame(tick);
|
|
332
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* The SOUND-layer gain for the running music track.
|
|
338
|
+
*
|
|
339
|
+
* @pixi/sound resolves a playing instance as `instance × sound × global` (WebAudioInstance.
|
|
340
|
+
* refresh). Each of those three has exactly ONE owner here, which is what keeps the mixer honest:
|
|
341
|
+
* global — the master gain (`applyVolumes`)
|
|
342
|
+
* sound — music: this function. sfx: untouched, left at 1.
|
|
343
|
+
* instance — sfx: the per-call volume × the sfx category. music: always 1.
|
|
344
|
+
* Everything that can move music volume — the player's slider, the category mute, a big-win duck,
|
|
345
|
+
* a crossfade — is a term below, so they compose instead of overwriting each other.
|
|
346
|
+
*/
|
|
347
|
+
musicGain() {
|
|
348
|
+
const c = this._categories.music;
|
|
349
|
+
return (c.muted ? 0 : 1) * c.volume * this._musicDuck * this._musicFade;
|
|
350
|
+
}
|
|
351
|
+
/** Push `musicGain()` at the current track. Safe before it starts playing and with none playing. */
|
|
352
|
+
applyMusicGain() {
|
|
353
|
+
if (!this._soundModule || !this._currentMusic)
|
|
354
|
+
return;
|
|
355
|
+
try {
|
|
356
|
+
this._soundModule.sound.volume(this._currentMusic, this.musicGain());
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
// ignore — alias not registered yet
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/** Current SOUND-layer volume of `alias`, or 0 when it cannot be read. */
|
|
363
|
+
soundVolumeOf(alias) {
|
|
364
|
+
try {
|
|
365
|
+
return Number(this._soundModule.sound.volume(alias)) || 0;
|
|
366
|
+
}
|
|
367
|
+
catch {
|
|
368
|
+
return 0;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/** Ramp the crossfade term 0 → 1 over `durationMs`, recomposing the gain each frame so a slider
|
|
372
|
+
* drag or a duck landing mid-fade is honoured rather than overwritten when the fade ends. */
|
|
373
|
+
rampMusicFade(durationMs) {
|
|
374
|
+
const token = this._musicFadeToken;
|
|
375
|
+
const start = Date.now();
|
|
376
|
+
const tick = () => {
|
|
377
|
+
if (token !== this._musicFadeToken)
|
|
378
|
+
return; // a newer track owns the music now
|
|
379
|
+
const t = Math.min((Date.now() - start) / durationMs, 1);
|
|
380
|
+
this._musicFade = t;
|
|
381
|
+
this.applyMusicGain();
|
|
382
|
+
if (t < 1)
|
|
383
|
+
requestAnimationFrame(tick);
|
|
384
|
+
};
|
|
385
|
+
requestAnimationFrame(tick);
|
|
386
|
+
}
|
|
333
387
|
applyVolumes() {
|
|
334
388
|
if (!this._soundModule)
|
|
335
389
|
return;
|
|
@@ -337,6 +391,7 @@ class AudioManager {
|
|
|
337
391
|
// Global mute is owned by sound.muteAll()/unmuteAll() (context.muted),
|
|
338
392
|
// not by volumeAll — mixing both leaves mute un-undoable after reload.
|
|
339
393
|
sound.volumeAll = this._masterGain; // master multiplies the global bus
|
|
394
|
+
this.applyMusicGain(); // category volume/mute reach the RUNNING track
|
|
340
395
|
}
|
|
341
396
|
setupMobileUnlock() {
|
|
342
397
|
if (this._unlocked)
|
package/dist/audio.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio.cjs.js","sources":["../src/audio/AudioManager.ts"],"sourcesContent":[null],"names":[],"mappings":";;AASA;;;;;;;;;;;;;;;;;;;;AAoBG;MACU,YAAY,CAAA;IACf,YAAY,GAAQ,IAAI;IACxB,YAAY,GAAG,KAAK;IACpB,YAAY,GAAG,KAAK;AACpB,IAAA,QAAQ;AACR,IAAA,WAAW;AACX,IAAA,WAAW;IACX,WAAW,GAAG,GAAG;IACjB,aAAa,GAAkB,IAAI;
|
|
1
|
+
{"version":3,"file":"audio.cjs.js","sources":["../src/audio/AudioManager.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/dist/audio.d.ts
CHANGED
|
@@ -41,6 +41,12 @@ declare class AudioManager {
|
|
|
41
41
|
private _categories;
|
|
42
42
|
private _masterGain;
|
|
43
43
|
private _currentMusic;
|
|
44
|
+
/** Duck factor (0..1) from duckMusic/unduckMusic. A presentation state, not a player setting. */
|
|
45
|
+
private _musicDuck;
|
|
46
|
+
/** Crossfade ramp (0..1) for the track that is fading IN. 1 whenever no fade is running. */
|
|
47
|
+
private _musicFade;
|
|
48
|
+
/** Generation counter so a superseded crossfade ramp stops writing over the new track's. */
|
|
49
|
+
private _musicFadeToken;
|
|
44
50
|
private _unlocked;
|
|
45
51
|
private _unlockHandler;
|
|
46
52
|
constructor(config?: AudioConfig);
|
|
@@ -134,6 +140,25 @@ declare class AudioManager {
|
|
|
134
140
|
* Smoothly fade a sound's volume from `fromVol` to `toVol` over `durationMs`.
|
|
135
141
|
*/
|
|
136
142
|
private fadeVolume;
|
|
143
|
+
/**
|
|
144
|
+
* The SOUND-layer gain for the running music track.
|
|
145
|
+
*
|
|
146
|
+
* @pixi/sound resolves a playing instance as `instance × sound × global` (WebAudioInstance.
|
|
147
|
+
* refresh). Each of those three has exactly ONE owner here, which is what keeps the mixer honest:
|
|
148
|
+
* global — the master gain (`applyVolumes`)
|
|
149
|
+
* sound — music: this function. sfx: untouched, left at 1.
|
|
150
|
+
* instance — sfx: the per-call volume × the sfx category. music: always 1.
|
|
151
|
+
* Everything that can move music volume — the player's slider, the category mute, a big-win duck,
|
|
152
|
+
* a crossfade — is a term below, so they compose instead of overwriting each other.
|
|
153
|
+
*/
|
|
154
|
+
private musicGain;
|
|
155
|
+
/** Push `musicGain()` at the current track. Safe before it starts playing and with none playing. */
|
|
156
|
+
private applyMusicGain;
|
|
157
|
+
/** Current SOUND-layer volume of `alias`, or 0 when it cannot be read. */
|
|
158
|
+
private soundVolumeOf;
|
|
159
|
+
/** Ramp the crossfade term 0 → 1 over `durationMs`, recomposing the gain each frame so a slider
|
|
160
|
+
* drag or a duck landing mid-fade is honoured rather than overwritten when the fade ends. */
|
|
161
|
+
private rampMusicFade;
|
|
137
162
|
private applyVolumes;
|
|
138
163
|
private setupMobileUnlock;
|
|
139
164
|
private removeMobileUnlock;
|
package/dist/audio.esm.js
CHANGED
|
@@ -28,6 +28,12 @@ class AudioManager {
|
|
|
28
28
|
_categories;
|
|
29
29
|
_masterGain = 1.0;
|
|
30
30
|
_currentMusic = null;
|
|
31
|
+
/** Duck factor (0..1) from duckMusic/unduckMusic. A presentation state, not a player setting. */
|
|
32
|
+
_musicDuck = 1;
|
|
33
|
+
/** Crossfade ramp (0..1) for the track that is fading IN. 1 whenever no fade is running. */
|
|
34
|
+
_musicFade = 1;
|
|
35
|
+
/** Generation counter so a superseded crossfade ramp stops writing over the new track's. */
|
|
36
|
+
_musicFadeToken = 0;
|
|
31
37
|
_unlocked = false;
|
|
32
38
|
_unlockHandler = null;
|
|
33
39
|
constructor(config) {
|
|
@@ -86,7 +92,10 @@ class AudioManager {
|
|
|
86
92
|
if (this._globalMuted || this._categories[category].muted)
|
|
87
93
|
return;
|
|
88
94
|
const { sound } = this._soundModule;
|
|
89
|
-
|
|
95
|
+
// The master gain lives on the GLOBAL bus (`sound.volumeAll`, see applyVolumes) and @pixi/sound
|
|
96
|
+
// already multiplies it in — folding it in here as well squared it, so a master of 0.5 played
|
|
97
|
+
// sfx at 0.25.
|
|
98
|
+
const vol = (options?.volume ?? 1) * this._categories[category].volume;
|
|
90
99
|
try {
|
|
91
100
|
sound.play(alias, {
|
|
92
101
|
volume: vol,
|
|
@@ -108,52 +117,50 @@ class AudioManager {
|
|
|
108
117
|
if (!this._initialized || !this._soundModule)
|
|
109
118
|
return;
|
|
110
119
|
const { sound } = this._soundModule;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
});
|
|
124
|
-
// Start new track at zero volume, fade in
|
|
125
|
-
try {
|
|
126
|
-
sound.play(alias, {
|
|
127
|
-
volume: 0,
|
|
128
|
-
loop: true,
|
|
120
|
+
const prevAlias = this._currentMusic;
|
|
121
|
+
const crossfade = !!prevAlias && prevAlias !== alias && fadeDuration > 0;
|
|
122
|
+
// Retire the outgoing track. Its own SOUND-level volume is the only thing still pointing at it,
|
|
123
|
+
// so fading that to 0 is safe — nothing else writes it once `_currentMusic` has moved on.
|
|
124
|
+
if (prevAlias) {
|
|
125
|
+
if (crossfade) {
|
|
126
|
+
const from = this.soundVolumeOf(prevAlias);
|
|
127
|
+
this.fadeVolume(prevAlias, from, 0, fadeDuration, () => {
|
|
128
|
+
try {
|
|
129
|
+
sound.stop(prevAlias);
|
|
130
|
+
}
|
|
131
|
+
catch { /* ignore */ }
|
|
129
132
|
});
|
|
130
|
-
this.fadeVolume(alias, 0, this._categories.music.volume * this._masterGain, fadeDuration);
|
|
131
133
|
}
|
|
132
|
-
|
|
133
|
-
console.warn(`[AudioManager] Failed to play music "${alias}":`, e);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
// No crossfade — instant switch
|
|
138
|
-
if (this._currentMusic) {
|
|
134
|
+
else {
|
|
139
135
|
try {
|
|
140
|
-
sound.stop(
|
|
136
|
+
sound.stop(prevAlias);
|
|
141
137
|
}
|
|
142
138
|
catch { /* ignore */ }
|
|
143
139
|
}
|
|
144
|
-
this._currentMusic = alias;
|
|
145
|
-
if (this._globalMuted || this._categories.music.muted)
|
|
146
|
-
return;
|
|
147
|
-
try {
|
|
148
|
-
sound.play(alias, {
|
|
149
|
-
volume: this._categories.music.volume * this._masterGain,
|
|
150
|
-
loop: true,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
catch (e) {
|
|
154
|
-
console.warn(`[AudioManager] Failed to play music "${alias}":`, e);
|
|
155
|
-
}
|
|
156
140
|
}
|
|
141
|
+
this._currentMusic = alias;
|
|
142
|
+
this._musicFadeToken++; // any ramp still running belongs to a track we just replaced
|
|
143
|
+
// Deliberately started even while muted. Global mute is the @pixi/sound CONTEXT mute and a
|
|
144
|
+
// muted music category is a 0 term in `musicGain()` — both already make this inaudible, and
|
|
145
|
+
// both undo themselves the moment the player flips them back. Returning early here instead
|
|
146
|
+
// meant a track begun while muted never existed, so unmuting restored silence until some
|
|
147
|
+
// later mode change happened to switch tracks.
|
|
148
|
+
// The incoming track plays at INSTANCE volume 1 and carries its whole gain on the SOUND layer
|
|
149
|
+
// (`musicGain()`), which is the layer the slider, the duck and this fade all write. Splitting
|
|
150
|
+
// them across layers is what silenced every crossfade: the track was started at instance volume
|
|
151
|
+
// 0 and the ramp then moved the sound layer, whose product with 0 is 0 for the track's life.
|
|
152
|
+
// The gain is written BEFORE play() so the first frame is never at full volume.
|
|
153
|
+
this._musicFade = crossfade ? 0 : 1;
|
|
154
|
+
this.applyMusicGain();
|
|
155
|
+
try {
|
|
156
|
+
sound.play(alias, { volume: 1, loop: true });
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
console.warn(`[AudioManager] Failed to play music "${alias}":`, e);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (crossfade)
|
|
163
|
+
this.rampMusicFade(fadeDuration);
|
|
157
164
|
}
|
|
158
165
|
/**
|
|
159
166
|
* Stop current music.
|
|
@@ -169,6 +176,10 @@ class AudioManager {
|
|
|
169
176
|
// ignore
|
|
170
177
|
}
|
|
171
178
|
this._currentMusic = null;
|
|
179
|
+
// Retire any running ramp and clear the fade term, so the next track does not inherit a
|
|
180
|
+
// half-finished crossfade and start silent.
|
|
181
|
+
this._musicFadeToken++;
|
|
182
|
+
this._musicFade = 1;
|
|
172
183
|
}
|
|
173
184
|
/**
|
|
174
185
|
* Stop all sounds.
|
|
@@ -194,6 +205,9 @@ class AudioManager {
|
|
|
194
205
|
*/
|
|
195
206
|
setVolume(category, volume) {
|
|
196
207
|
this._categories[category].volume = Math.max(0, Math.min(1, volume));
|
|
208
|
+
// applyVolumes() re-pushes the music gain, so moving the Music slider is heard on the track
|
|
209
|
+
// that is ALREADY playing — it used to take effect only at the next playMusic (a mode change).
|
|
210
|
+
// SFX need no push: play() reads the category volume fresh on every call.
|
|
197
211
|
this.applyVolumes();
|
|
198
212
|
this.saveState();
|
|
199
213
|
}
|
|
@@ -266,30 +280,19 @@ class AudioManager {
|
|
|
266
280
|
* @param factor - Volume multiplier (0..1), e.g. 0.3 = 30% of normal
|
|
267
281
|
*/
|
|
268
282
|
duckMusic(factor) {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
catch {
|
|
277
|
-
// ignore
|
|
278
|
-
}
|
|
283
|
+
// Held as a FACTOR rather than written as a finished volume: the duck used to write
|
|
284
|
+
// `category × factor` onto a track whose instance already carried the category volume, so it
|
|
285
|
+
// ducked to category², and unducking restored category² instead of category. Keeping it as one
|
|
286
|
+
// term of `musicGain()` also keeps the slider live while ducked.
|
|
287
|
+
this._musicDuck = Math.max(0, Math.min(1, factor));
|
|
288
|
+
this.applyMusicGain();
|
|
279
289
|
}
|
|
280
290
|
/**
|
|
281
291
|
* Restore music to normal volume after ducking.
|
|
282
292
|
*/
|
|
283
293
|
unduckMusic() {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const { sound } = this._soundModule;
|
|
287
|
-
try {
|
|
288
|
-
sound.volume(this._currentMusic, this._categories.music.volume);
|
|
289
|
-
}
|
|
290
|
-
catch {
|
|
291
|
-
// ignore
|
|
292
|
-
}
|
|
294
|
+
this._musicDuck = 1;
|
|
295
|
+
this.applyMusicGain();
|
|
293
296
|
}
|
|
294
297
|
/**
|
|
295
298
|
* Destroy the audio manager and free resources.
|
|
@@ -328,6 +331,57 @@ class AudioManager {
|
|
|
328
331
|
};
|
|
329
332
|
requestAnimationFrame(tick);
|
|
330
333
|
}
|
|
334
|
+
/**
|
|
335
|
+
* The SOUND-layer gain for the running music track.
|
|
336
|
+
*
|
|
337
|
+
* @pixi/sound resolves a playing instance as `instance × sound × global` (WebAudioInstance.
|
|
338
|
+
* refresh). Each of those three has exactly ONE owner here, which is what keeps the mixer honest:
|
|
339
|
+
* global — the master gain (`applyVolumes`)
|
|
340
|
+
* sound — music: this function. sfx: untouched, left at 1.
|
|
341
|
+
* instance — sfx: the per-call volume × the sfx category. music: always 1.
|
|
342
|
+
* Everything that can move music volume — the player's slider, the category mute, a big-win duck,
|
|
343
|
+
* a crossfade — is a term below, so they compose instead of overwriting each other.
|
|
344
|
+
*/
|
|
345
|
+
musicGain() {
|
|
346
|
+
const c = this._categories.music;
|
|
347
|
+
return (c.muted ? 0 : 1) * c.volume * this._musicDuck * this._musicFade;
|
|
348
|
+
}
|
|
349
|
+
/** Push `musicGain()` at the current track. Safe before it starts playing and with none playing. */
|
|
350
|
+
applyMusicGain() {
|
|
351
|
+
if (!this._soundModule || !this._currentMusic)
|
|
352
|
+
return;
|
|
353
|
+
try {
|
|
354
|
+
this._soundModule.sound.volume(this._currentMusic, this.musicGain());
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
// ignore — alias not registered yet
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
/** Current SOUND-layer volume of `alias`, or 0 when it cannot be read. */
|
|
361
|
+
soundVolumeOf(alias) {
|
|
362
|
+
try {
|
|
363
|
+
return Number(this._soundModule.sound.volume(alias)) || 0;
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
return 0;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
/** Ramp the crossfade term 0 → 1 over `durationMs`, recomposing the gain each frame so a slider
|
|
370
|
+
* drag or a duck landing mid-fade is honoured rather than overwritten when the fade ends. */
|
|
371
|
+
rampMusicFade(durationMs) {
|
|
372
|
+
const token = this._musicFadeToken;
|
|
373
|
+
const start = Date.now();
|
|
374
|
+
const tick = () => {
|
|
375
|
+
if (token !== this._musicFadeToken)
|
|
376
|
+
return; // a newer track owns the music now
|
|
377
|
+
const t = Math.min((Date.now() - start) / durationMs, 1);
|
|
378
|
+
this._musicFade = t;
|
|
379
|
+
this.applyMusicGain();
|
|
380
|
+
if (t < 1)
|
|
381
|
+
requestAnimationFrame(tick);
|
|
382
|
+
};
|
|
383
|
+
requestAnimationFrame(tick);
|
|
384
|
+
}
|
|
331
385
|
applyVolumes() {
|
|
332
386
|
if (!this._soundModule)
|
|
333
387
|
return;
|
|
@@ -335,6 +389,7 @@ class AudioManager {
|
|
|
335
389
|
// Global mute is owned by sound.muteAll()/unmuteAll() (context.muted),
|
|
336
390
|
// not by volumeAll — mixing both leaves mute un-undoable after reload.
|
|
337
391
|
sound.volumeAll = this._masterGain; // master multiplies the global bus
|
|
392
|
+
this.applyMusicGain(); // category volume/mute reach the RUNNING track
|
|
338
393
|
}
|
|
339
394
|
setupMobileUnlock() {
|
|
340
395
|
if (this._unlocked)
|
package/dist/audio.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio.esm.js","sources":["../src/audio/AudioManager.ts"],"sourcesContent":[null],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;AAoBG;MACU,YAAY,CAAA;IACf,YAAY,GAAQ,IAAI;IACxB,YAAY,GAAG,KAAK;IACpB,YAAY,GAAG,KAAK;AACpB,IAAA,QAAQ;AACR,IAAA,WAAW;AACX,IAAA,WAAW;IACX,WAAW,GAAG,GAAG;IACjB,aAAa,GAAkB,IAAI;
|
|
1
|
+
{"version":3,"file":"audio.esm.js","sources":["../src/audio/AudioManager.ts"],"sourcesContent":[null],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;AAoBG;MACU,YAAY,CAAA;IACf,YAAY,GAAQ,IAAI;IACxB,YAAY,GAAG,KAAK;IACpB,YAAY,GAAG,KAAK;AACpB,IAAA,QAAQ;AACR,IAAA,WAAW;AACX,IAAA,WAAW;IACX,WAAW,GAAG,GAAG;IACjB,aAAa,GAAkB,IAAI;;IAEnC,UAAU,GAAG,CAAC;;IAEd,UAAU,GAAG,CAAC;;IAEd,eAAe,GAAG,CAAC;IACnB,SAAS,GAAG,KAAK;IACjB,cAAc,GAAwB,IAAI;AAElD,IAAA,WAAA,CAAY,MAAoB,EAAA;QAC9B,IAAI,CAAC,QAAQ,GAAG,MAAM,EAAE,OAAO,IAAI,IAAI;QACvC,IAAI,CAAC,WAAW,GAAG,MAAM,EAAE,UAAU,IAAI,UAAU;QAEnD,IAAI,CAAC,WAAW,GAAG;AACjB,YAAA,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE;AACrD,YAAA,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE;AACjD,YAAA,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE;AAC/C,YAAA,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,IAAI,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE;SAC1D;;AAGD,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;YACjB,IAAI,CAAC,YAAY,EAAE;QACrB;IACF;;AAGA,IAAA,IAAI,WAAW,GAAA;QACb,OAAO,IAAI,CAAC,YAAY;IAC1B;;AAGA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,YAAY;IAC1B;AAEA;;;AAGG;AACH,IAAA,MAAM,IAAI,GAAA;QACR,IAAI,IAAI,CAAC,YAAY;YAAE;AAEvB,QAAA,IAAI;YACF,IAAI,CAAC,YAAY,GAAG,MAAM,OAAO,aAAa,CAAC;AAC/C,YAAA,IAAI,CAAC,YAAY,GAAG,IAAI;YACxB,IAAI,CAAC,YAAY,EAAE;AACnB,YAAA,IAAI,IAAI,CAAC,YAAY,EAAE;AACrB,gBAAA,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,EAAE;YACnC;YACA,IAAI,CAAC,iBAAiB,EAAE;QAC1B;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,CAAC,IAAI,CACV,2DAA2D,CAC5D;AACD,YAAA,IAAI,CAAC,YAAY,GAAG,KAAK;QAC3B;IACF;AAEA;;;;;;AAMG;AACH,IAAA,IAAI,CACF,KAAa,EACb,QAAA,GAA8B,KAAK,EACnC,OAA6D,EAAA;QAE7D,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE;QAC9C,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK;YAAE;AAE3D,QAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,YAAY;;;;AAInC,QAAA,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM;AAEtE,QAAA,IAAI;AACF,YAAA,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE;AAChB,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,KAAK;AAC5B,gBAAA,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;AAC3B,aAAA,CAAC;QACJ;QAAE,OAAO,CAAC,EAAE;YACV,OAAO,CAAC,IAAI,CAAC,CAAA,+BAAA,EAAkC,KAAK,CAAA,EAAA,CAAI,EAAE,CAAC,CAAC;QAC9D;IACF;AAEA;;;;;AAKG;AACH,IAAA,SAAS,CAAC,KAAa,EAAE,YAAY,GAAG,GAAG,EAAA;QACzC,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE;AAE9C,QAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,YAAY;AACnC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa;AACpC,QAAA,MAAM,SAAS,GAAG,CAAC,CAAC,SAAS,IAAI,SAAS,KAAK,KAAK,IAAI,YAAY,GAAG,CAAC;;;QAIxE,IAAI,SAAS,EAAE;YACb,IAAI,SAAS,EAAE;gBACb,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;AAC1C,gBAAA,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,YAAY,EAAE,MAAK;AACrD,oBAAA,IAAI;AAAE,wBAAA,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;oBAAE;AAAE,oBAAA,MAAM,eAAe;AACtD,gBAAA,CAAC,CAAC;YACJ;iBAAO;AACL,gBAAA,IAAI;AAAE,oBAAA,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;gBAAE;AAAE,gBAAA,MAAM,eAAe;YACtD;QACF;AAEA,QAAA,IAAI,CAAC,aAAa,GAAG,KAAK;AAC1B,QAAA,IAAI,CAAC,eAAe,EAAE,CAAC;;;;;;;;;;;AAavB,QAAA,IAAI,CAAC,UAAU,GAAG,SAAS,GAAG,CAAC,GAAG,CAAC;QACnC,IAAI,CAAC,cAAc,EAAE;AACrB,QAAA,IAAI;AACF,YAAA,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC9C;QAAE,OAAO,CAAC,EAAE;YACV,OAAO,CAAC,IAAI,CAAC,CAAA,qCAAA,EAAwC,KAAK,CAAA,EAAA,CAAI,EAAE,CAAC,CAAC;YAClE;QACF;AACA,QAAA,IAAI,SAAS;AAAE,YAAA,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC;IACjD;AAEA;;AAEG;IACH,SAAS,GAAA;AACP,QAAA,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE;AACrE,QAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,YAAY;AACnC,QAAA,IAAI;AACF,YAAA,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;QAChC;AAAE,QAAA,MAAM;;QAER;AACA,QAAA,IAAI,CAAC,aAAa,GAAG,IAAI;;;QAGzB,IAAI,CAAC,eAAe,EAAE;AACtB,QAAA,IAAI,CAAC,UAAU,GAAG,CAAC;IACrB;AAEA;;AAEG;IACH,OAAO,GAAA;QACL,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE;AAC9C,QAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,YAAY;QACnC,KAAK,CAAC,OAAO,EAAE;AACf,QAAA,IAAI,CAAC,aAAa,GAAG,IAAI;IAC3B;AAEA;AACkF;AAClF,IAAA,eAAe,CAAC,MAAc,EAAA;AAC5B,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACnD,IAAI,CAAC,YAAY,EAAE;IACrB;IAEA,eAAe,GAAA;QACb,OAAO,IAAI,CAAC,WAAW;IACzB;AAEA;;AAEG;IACH,SAAS,CAAC,QAA2B,EAAE,MAAc,EAAA;QACnD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;;;;QAIpE,IAAI,CAAC,YAAY,EAAE;QACnB,IAAI,CAAC,SAAS,EAAE;IAClB;AAEA;;AAEG;AACH,IAAA,SAAS,CAAC,QAA2B,EAAA;QACnC,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM;IAC1C;AAEA;;AAEG;AACH,IAAA,YAAY,CAAC,QAA2B,EAAA;QACtC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK,GAAG,IAAI;QACvC,IAAI,CAAC,YAAY,EAAE;QACnB,IAAI,CAAC,SAAS,EAAE;IAClB;AAEA;;AAEG;AACH,IAAA,cAAc,CAAC,QAA2B,EAAA;QACxC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK,GAAG,KAAK;QACxC,IAAI,CAAC,YAAY,EAAE;QACnB,IAAI,CAAC,SAAS,EAAE;IAClB;AAEA;;AAEG;AACH,IAAA,cAAc,CAAC,QAA2B,EAAA;AACxC,QAAA,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK;QACpE,IAAI,CAAC,YAAY,EAAE;QACnB,IAAI,CAAC,SAAS,EAAE;QAChB,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK;IACzC;AAEA;;AAEG;IACH,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,YAAY,GAAG,IAAI;AACxB,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE;AACrB,YAAA,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,EAAE;QACnC;QACA,IAAI,CAAC,SAAS,EAAE;IAClB;AAEA;;AAEG;IACH,SAAS,GAAA;AACP,QAAA,IAAI,CAAC,YAAY,GAAG,KAAK;AACzB,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE;AACrB,YAAA,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE;QACrC;QACA,IAAI,CAAC,SAAS,EAAE;IAClB;AAEA;;AAEG;IACH,UAAU,GAAA;AACR,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE;YACrB,IAAI,CAAC,SAAS,EAAE;QAClB;aAAO;YACL,IAAI,CAAC,OAAO,EAAE;QAChB;QACA,OAAO,IAAI,CAAC,YAAY;IAC1B;AAEA;;;;AAIG;AACH,IAAA,SAAS,CAAC,MAAc,EAAA;;;;;AAKtB,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,CAAC,cAAc,EAAE;IACvB;AAEA;;AAEG;IACH,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,UAAU,GAAG,CAAC;QACnB,IAAI,CAAC,cAAc,EAAE;IACvB;AAEA;;AAEG;IACH,OAAO,GAAA;QACL,IAAI,CAAC,OAAO,EAAE;QACd,IAAI,CAAC,kBAAkB,EAAE;AACzB,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE;AACrB,YAAA,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE;QACrC;AACA,QAAA,IAAI,CAAC,YAAY,GAAG,KAAK;IAC3B;;AAIA;;AAEG;IACK,UAAU,CAChB,KAAa,EACb,OAAe,EACf,KAAa,EACb,UAAkB,EAClB,UAAuB,EAAA;QAEvB,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE;AACxB,QAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,YAAY;AACnC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE;QAE5B,MAAM,IAAI,GAAG,MAAK;YAChB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;AACtC,YAAA,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,UAAU,EAAE,CAAC,CAAC;YAC3C,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,KAAK,GAAG,OAAO,IAAI,CAAC;AAC3C,YAAA,IAAI;AAAE,gBAAA,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC;YAAE;AAAE,YAAA,MAAM,eAAe;AAEvD,YAAA,IAAI,CAAC,GAAG,CAAC,EAAE;gBACT,qBAAqB,CAAC,IAAI,CAAC;YAC7B;iBAAO;gBACL,UAAU,IAAI;YAChB;AACF,QAAA,CAAC;QACD,qBAAqB,CAAC,IAAI,CAAC;IAC7B;AAEA;;;;;;;;;;AAUG;IACK,SAAS,GAAA;AACf,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK;QAChC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU;IACzE;;IAGQ,cAAc,GAAA;QACpB,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE;AAC/C,QAAA,IAAI;AACF,YAAA,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;QACtE;AAAE,QAAA,MAAM;;QAER;IACF;;AAGQ,IAAA,aAAa,CAAC,KAAa,EAAA;AACjC,QAAA,IAAI;AACF,YAAA,OAAO,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;QAC3D;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,CAAC;QACV;IACF;AAEA;AAC8F;AACtF,IAAA,aAAa,CAAC,UAAkB,EAAA;AACtC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe;AAClC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE;QACxB,MAAM,IAAI,GAAG,MAAW;AACtB,YAAA,IAAI,KAAK,KAAK,IAAI,CAAC,eAAe;AAAE,gBAAA,OAAO;AAC3C,YAAA,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,UAAU,EAAE,CAAC,CAAC;AACxD,YAAA,IAAI,CAAC,UAAU,GAAG,CAAC;YACnB,IAAI,CAAC,cAAc,EAAE;YACrB,IAAI,CAAC,GAAG,CAAC;gBAAE,qBAAqB,CAAC,IAAI,CAAC;AACxC,QAAA,CAAC;QACD,qBAAqB,CAAC,IAAI,CAAC;IAC7B;IAEQ,YAAY,GAAA;QAClB,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE;AACxB,QAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,YAAY;;;QAGnC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC;AACnC,QAAA,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB;IAEQ,iBAAiB,GAAA;QACvB,IAAI,IAAI,CAAC,SAAS;YAAE;AAEpB,QAAA,IAAI,CAAC,cAAc,GAAG,MAAK;YACzB,IAAI,CAAC,IAAI,CAAC,YAAY;gBAAE;AACxB,YAAA,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,YAAY;;YAEnC,IAAI,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,KAAK,WAAW,EAAE;AACtD,gBAAA,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE;YACrC;AACA,YAAA,IAAI,CAAC,SAAS,GAAG,IAAI;YACrB,IAAI,CAAC,kBAAkB,EAAE;AAC3B,QAAA,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,CAAC;AACpE,QAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;AAC1B,YAAA,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACvE;IACF;IAEQ,kBAAkB,GAAA;QACxB,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE;QAC1B,MAAM,MAAM,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,CAAC;AACpE,QAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;YAC1B,QAAQ,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC;QAC1D;AACA,QAAA,IAAI,CAAC,cAAc,GAAG,IAAI;IAC5B;IAEQ,SAAS,GAAA;QACf,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE;AACpB,QAAA,IAAI;AACF,YAAA,MAAM,KAAK,GAAG;gBACZ,WAAW,EAAE,IAAI,CAAC,YAAY;gBAC9B,UAAU,EAAE,IAAI,CAAC,WAAW;aAC7B;AACD,YAAA,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC/D;AAAE,QAAA,MAAM;;QAER;IACF;IAEQ,YAAY,GAAA;AAClB,QAAA,IAAI;YACF,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;AAClD,YAAA,IAAI,CAAC,GAAG;gBAAE;YACV,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7B,YAAA,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,SAAS,EAAE;AAC1C,gBAAA,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,WAAW;YACvC;AACA,YAAA,IAAI,KAAK,CAAC,UAAU,EAAE;AACpB,gBAAA,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,CAAU,EAAE;AAC5D,oBAAA,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AACzB,wBAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG;AACtB,4BAAA,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM;4BACpE,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,KAAK;yBAC5C;oBACH;gBACF;YACF;QACF;AAAE,QAAA,MAAM;;QAER;IACF;AACD;;;;"}
|