@motionscript/browser 0.0.0-stage → 0.1.0-alpha.0
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/CHANGELOG.md +5 -0
- package/LICENSE +201 -0
- package/README.md +68 -3
- package/dist/asset-bytes.d.ts +50 -0
- package/dist/asset-bytes.d.ts.map +1 -0
- package/dist/asset-bytes.js +60 -0
- package/dist/asset-bytes.js.map +1 -0
- package/dist/audio/bus-graph.d.ts +43 -0
- package/dist/audio/bus-graph.d.ts.map +1 -0
- package/dist/audio/bus-graph.js +104 -0
- package/dist/audio/bus-graph.js.map +1 -0
- package/dist/audio/filter-graph.d.ts +58 -0
- package/dist/audio/filter-graph.d.ts.map +1 -0
- package/dist/audio/filter-graph.js +235 -0
- package/dist/audio/filter-graph.js.map +1 -0
- package/dist/audio/index.d.ts +5 -0
- package/dist/audio/index.d.ts.map +1 -0
- package/dist/audio/index.js +12 -0
- package/dist/audio/index.js.map +1 -0
- package/dist/audio/mixer.d.ts +59 -0
- package/dist/audio/mixer.d.ts.map +1 -0
- package/dist/audio/mixer.js +193 -0
- package/dist/audio/mixer.js.map +1 -0
- package/dist/audio/player.d.ts +49 -0
- package/dist/audio/player.d.ts.map +1 -0
- package/dist/audio/player.js +226 -0
- package/dist/audio/player.js.map +1 -0
- package/dist/browser/audio.js +2 -0
- package/dist/browser/audio.js.map +7 -0
- package/dist/browser/chunks/GLTFLoader-PGXD4V5B.js +2 -0
- package/dist/browser/chunks/GLTFLoader-PGXD4V5B.js.map +7 -0
- package/dist/browser/chunks/SkeletonUtils-XYDMTGTM.js +2 -0
- package/dist/browser/chunks/SkeletonUtils-XYDMTGTM.js.map +7 -0
- package/dist/browser/chunks/chunk-CTLBXZSU.js +4119 -0
- package/dist/browser/chunks/chunk-CTLBXZSU.js.map +7 -0
- package/dist/browser/chunks/chunk-FQ32PDIU.js +2 -0
- package/dist/browser/chunks/chunk-FQ32PDIU.js.map +7 -0
- package/dist/browser/chunks/chunk-FY3BTKY4.js +2 -0
- package/dist/browser/chunks/chunk-FY3BTKY4.js.map +7 -0
- package/dist/browser/chunks/chunk-NSFLRI4P.js +2 -0
- package/dist/browser/chunks/chunk-NSFLRI4P.js.map +7 -0
- package/dist/browser/chunks/three.module-Z4EOVUWF.js +2 -0
- package/dist/browser/chunks/three.module-Z4EOVUWF.js.map +7 -0
- package/dist/browser/esbuild.wasm +0 -0
- package/dist/browser/index.js +2172 -0
- package/dist/browser/index.js.map +7 -0
- package/dist/browser/manifest.json +15 -0
- package/dist/concat.d.ts +95 -0
- package/dist/concat.d.ts.map +1 -0
- package/dist/concat.js +174 -0
- package/dist/concat.js.map +1 -0
- package/dist/decode/image-levels.d.ts +137 -0
- package/dist/decode/image-levels.d.ts.map +1 -0
- package/dist/decode/image-levels.js +477 -0
- package/dist/decode/image-levels.js.map +1 -0
- package/dist/decode/levels.d.ts +37 -0
- package/dist/decode/levels.d.ts.map +1 -0
- package/dist/decode/levels.js +68 -0
- package/dist/decode/levels.js.map +1 -0
- package/dist/decode/video-levels.d.ts +37 -0
- package/dist/decode/video-levels.d.ts.map +1 -0
- package/dist/decode/video-levels.js +95 -0
- package/dist/decode/video-levels.js.map +1 -0
- package/dist/dynamic-nodes.d.ts +9 -0
- package/dist/dynamic-nodes.d.ts.map +1 -0
- package/dist/dynamic-nodes.js +56 -0
- package/dist/dynamic-nodes.js.map +1 -0
- package/dist/engine.d.ts +59 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +171 -0
- package/dist/engine.js.map +1 -0
- package/dist/exporter.d.ts +163 -0
- package/dist/exporter.d.ts.map +1 -0
- package/dist/exporter.js +263 -0
- package/dist/exporter.js.map +1 -0
- package/dist/getter.d.ts +10 -0
- package/dist/getter.d.ts.map +1 -0
- package/dist/getter.js +38 -0
- package/dist/getter.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/measure-context.d.ts +12 -0
- package/dist/measure-context.d.ts.map +1 -0
- package/dist/measure-context.js +12 -0
- package/dist/measure-context.js.map +1 -0
- package/dist/mix-timeline-audio.d.ts +42 -0
- package/dist/mix-timeline-audio.d.ts.map +1 -0
- package/dist/mix-timeline-audio.js +63 -0
- package/dist/mix-timeline-audio.js.map +1 -0
- package/dist/output.d.ts +7 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +6 -0
- package/dist/output.js.map +1 -0
- package/dist/render-context.d.ts +30 -0
- package/dist/render-context.d.ts.map +1 -0
- package/dist/render-context.js +55 -0
- package/dist/render-context.js.map +1 -0
- package/dist/screenshot.d.ts +45 -0
- package/dist/screenshot.d.ts.map +1 -0
- package/dist/screenshot.js +32 -0
- package/dist/screenshot.js.map +1 -0
- package/dist/still.d.ts +151 -0
- package/dist/still.d.ts.map +1 -0
- package/dist/still.js +222 -0
- package/dist/still.js.map +1 -0
- package/dist/storage-adapter.d.ts +367 -0
- package/dist/storage-adapter.d.ts.map +1 -0
- package/dist/storage-adapter.js +1278 -0
- package/dist/storage-adapter.js.map +1 -0
- package/dist/three/renderer.d.ts +48 -0
- package/dist/three/renderer.d.ts.map +1 -0
- package/dist/three/renderer.js +177 -0
- package/dist/three/renderer.js.map +1 -0
- package/dist/ticker.d.ts +42 -0
- package/dist/ticker.d.ts.map +1 -0
- package/dist/ticker.js +143 -0
- package/dist/ticker.js.map +1 -0
- package/package.json +74 -3
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { AudioSink, AudioRequest } from "@motionscript/core";
|
|
2
|
+
/**
|
|
3
|
+
* Web Audio implementation of {@link AudioSink} — decodes and caches source
|
|
4
|
+
* buffers, then schedules/plays {@link AudioRequest}s as `AudioBufferSourceNode`s
|
|
5
|
+
* through a shared master gain (global mute and volume). `schedule` registers the
|
|
6
|
+
* active set of requests for the current frame; `syncTo` then starts/stops
|
|
7
|
+
* sources to match `sceneTime`, so playback follows scrubbing and seeks.
|
|
8
|
+
*/
|
|
9
|
+
export declare class WebAudioSink extends AudioSink {
|
|
10
|
+
private context;
|
|
11
|
+
private ownsContext;
|
|
12
|
+
private bufferCache;
|
|
13
|
+
private decoding;
|
|
14
|
+
private active;
|
|
15
|
+
private scheduled;
|
|
16
|
+
private disposed;
|
|
17
|
+
private masterGain;
|
|
18
|
+
/** The live bus chains, shared across every clip that names one. */
|
|
19
|
+
private buses;
|
|
20
|
+
private muted;
|
|
21
|
+
private volume;
|
|
22
|
+
constructor(context?: AudioContext);
|
|
23
|
+
getContext(): AudioContext;
|
|
24
|
+
/**
|
|
25
|
+
* Resume the AudioContext. Must be called from within a user gesture
|
|
26
|
+
* (e.g. a click handler) the first time, or browsers keep the context
|
|
27
|
+
* suspended and no audio is heard.
|
|
28
|
+
*/
|
|
29
|
+
unlock(): void;
|
|
30
|
+
has(src: string): boolean;
|
|
31
|
+
append(src: string, data: ArrayBuffer): Promise<void>;
|
|
32
|
+
/** Drops cached buffers and stops active sources for srcs/requests no longer referenced — called when the asset set changes (e.g. seeking across scene boundaries). */
|
|
33
|
+
retain(keep: ReadonlySet<string>): void;
|
|
34
|
+
/** Replaces the active request set; stops any currently-playing source whose request is no longer scheduled. Actual start/stop-to-match-time happens in `syncTo`. */
|
|
35
|
+
schedule(requests: readonly AudioRequest[]): void;
|
|
36
|
+
/** Starts sources whose `[startAt, endAt)` window now contains `sceneTime` (computing the correct buffer offset for the seek point) and stops any that have fallen outside it. */
|
|
37
|
+
syncTo(sceneTime: number): void;
|
|
38
|
+
play(time: number, _speed: number, _reverse: boolean): Promise<void>;
|
|
39
|
+
stop(): void;
|
|
40
|
+
setMuted(muted: boolean): void;
|
|
41
|
+
setVolume(volume: number): void;
|
|
42
|
+
/** Mute and volume are held separately so unmuting restores the set level. */
|
|
43
|
+
private applyMasterGain;
|
|
44
|
+
/** Starts a buffer source mid-clip if `sceneTime` lands after the request's start — `audioOffset` accounts for the request's trim, the elapsed time since `startAt`, and any speed (playbackRate) change. */
|
|
45
|
+
private playBuffer;
|
|
46
|
+
private stopSource;
|
|
47
|
+
dispose(): void;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=player.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../src/audio/player.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAA4B,MAAM,oBAAoB,CAAC;AAcvF;;;;;;GAMG;AACH,qBAAa,YAAa,SAAQ,SAAS;IACvC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,UAAU,CAAW;IAC7B,oEAAoE;IACpE,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAK;gBAEP,OAAO,CAAC,EAAE,YAAY;IASlC,UAAU,IAAI,YAAY;IAI1B;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAMd,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAInB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB3D,uKAAuK;IACvK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI;IASvC,qKAAqK;IACrK,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI;IAQjD,kLAAkL;IAClL,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAqBzB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1E,IAAI,IAAI,IAAI;IAMZ,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAK9B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK/B,8EAA8E;IAC9E,OAAO,CAAC,eAAe;IAIvB,6MAA6M;IAC7M,OAAO,CAAC,UAAU;IAqElB,OAAO,CAAC,UAAU;IAclB,OAAO,IAAI,IAAI;CAiBlB"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { AudioSink, sourceTimeAtSceneElapsed } from "@motionscript/core";
|
|
2
|
+
import { AudioBusGraph } from "./bus-graph";
|
|
3
|
+
import { buildAudioFilterGraph, effectiveSpeed, speedCurveOf, applySpeedToPlaybackRate } from "./filter-graph";
|
|
4
|
+
/**
|
|
5
|
+
* Web Audio implementation of {@link AudioSink} — decodes and caches source
|
|
6
|
+
* buffers, then schedules/plays {@link AudioRequest}s as `AudioBufferSourceNode`s
|
|
7
|
+
* through a shared master gain (global mute and volume). `schedule` registers the
|
|
8
|
+
* active set of requests for the current frame; `syncTo` then starts/stops
|
|
9
|
+
* sources to match `sceneTime`, so playback follows scrubbing and seeks.
|
|
10
|
+
*/
|
|
11
|
+
export class WebAudioSink extends AudioSink {
|
|
12
|
+
context;
|
|
13
|
+
ownsContext;
|
|
14
|
+
bufferCache = new Map();
|
|
15
|
+
decoding = new Map();
|
|
16
|
+
active = new Map();
|
|
17
|
+
scheduled = [];
|
|
18
|
+
disposed = false;
|
|
19
|
+
masterGain;
|
|
20
|
+
/** The live bus chains, shared across every clip that names one. */
|
|
21
|
+
buses;
|
|
22
|
+
muted = false;
|
|
23
|
+
volume = 1;
|
|
24
|
+
constructor(context) {
|
|
25
|
+
super();
|
|
26
|
+
this.context = context ?? new AudioContext();
|
|
27
|
+
this.ownsContext = !context;
|
|
28
|
+
this.masterGain = this.context.createGain();
|
|
29
|
+
this.masterGain.connect(this.context.destination);
|
|
30
|
+
this.buses = new AudioBusGraph(this.context, this.masterGain);
|
|
31
|
+
}
|
|
32
|
+
getContext() {
|
|
33
|
+
return this.context;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resume the AudioContext. Must be called from within a user gesture
|
|
37
|
+
* (e.g. a click handler) the first time, or browsers keep the context
|
|
38
|
+
* suspended and no audio is heard.
|
|
39
|
+
*/
|
|
40
|
+
unlock() {
|
|
41
|
+
if (this.context.state === "suspended") {
|
|
42
|
+
this.context.resume();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
has(src) {
|
|
46
|
+
return this.bufferCache.has(src);
|
|
47
|
+
}
|
|
48
|
+
async append(src, data) {
|
|
49
|
+
if (this.bufferCache.has(src))
|
|
50
|
+
return;
|
|
51
|
+
const existing = this.decoding.get(src);
|
|
52
|
+
if (existing)
|
|
53
|
+
return existing;
|
|
54
|
+
// decodeAudioData detaches `data` — that's fine, the caller in
|
|
55
|
+
// AssetManager.fetchAudio discards its reference immediately after
|
|
56
|
+
// awaiting append. Skipping the defensive .slice(0) saves a multi-MB
|
|
57
|
+
// allocation per audio source.
|
|
58
|
+
const job = this.context.decodeAudioData(data).then((buffer) => {
|
|
59
|
+
this.bufferCache.set(src, buffer);
|
|
60
|
+
}).finally(() => {
|
|
61
|
+
this.decoding.delete(src);
|
|
62
|
+
});
|
|
63
|
+
this.decoding.set(src, job);
|
|
64
|
+
await job;
|
|
65
|
+
}
|
|
66
|
+
/** Drops cached buffers and stops active sources for srcs/requests no longer referenced — called when the asset set changes (e.g. seeking across scene boundaries). */
|
|
67
|
+
retain(keep) {
|
|
68
|
+
for (const src of [...this.bufferCache.keys()]) {
|
|
69
|
+
if (!keep.has(src))
|
|
70
|
+
this.bufferCache.delete(src);
|
|
71
|
+
}
|
|
72
|
+
for (const [id, active] of this.active) {
|
|
73
|
+
if (!keep.has(active.request.src))
|
|
74
|
+
this.stopSource(id, active);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** Replaces the active request set; stops any currently-playing source whose request is no longer scheduled. Actual start/stop-to-match-time happens in `syncTo`. */
|
|
78
|
+
schedule(requests) {
|
|
79
|
+
const next = new Set(requests.map(r => r.id));
|
|
80
|
+
for (const [id, active] of this.active) {
|
|
81
|
+
if (!next.has(id))
|
|
82
|
+
this.stopSource(id, active);
|
|
83
|
+
}
|
|
84
|
+
this.scheduled = requests.slice();
|
|
85
|
+
}
|
|
86
|
+
/** Starts sources whose `[startAt, endAt)` window now contains `sceneTime` (computing the correct buffer offset for the seek point) and stops any that have fallen outside it. */
|
|
87
|
+
syncTo(sceneTime) {
|
|
88
|
+
const liveIds = new Set();
|
|
89
|
+
for (const req of this.scheduled) {
|
|
90
|
+
// `endAt` is `Infinity` for an open clip, so the comparison needs no
|
|
91
|
+
// nullish fallback — see AudioRequest.endAt.
|
|
92
|
+
const isInWindow = sceneTime >= req.startAt && sceneTime < req.endAt;
|
|
93
|
+
if (!isInWindow)
|
|
94
|
+
continue;
|
|
95
|
+
liveIds.add(req.id);
|
|
96
|
+
if (!this.active.has(req.id)) {
|
|
97
|
+
const buffer = this.bufferCache.get(req.src);
|
|
98
|
+
if (buffer)
|
|
99
|
+
this.playBuffer(buffer, req, sceneTime);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
for (const [id, active] of this.active) {
|
|
103
|
+
if (!liveIds.has(id))
|
|
104
|
+
this.stopSource(id, active);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async play(time, _speed, _reverse) {
|
|
108
|
+
if (this.context.state === "suspended") {
|
|
109
|
+
await this.context.resume();
|
|
110
|
+
}
|
|
111
|
+
this.syncTo(time);
|
|
112
|
+
}
|
|
113
|
+
stop() {
|
|
114
|
+
for (const [id, active] of this.active) {
|
|
115
|
+
this.stopSource(id, active);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
setMuted(muted) {
|
|
119
|
+
this.muted = muted;
|
|
120
|
+
this.applyMasterGain();
|
|
121
|
+
}
|
|
122
|
+
setVolume(volume) {
|
|
123
|
+
this.volume = Math.max(0, volume);
|
|
124
|
+
this.applyMasterGain();
|
|
125
|
+
}
|
|
126
|
+
/** Mute and volume are held separately so unmuting restores the set level. */
|
|
127
|
+
applyMasterGain() {
|
|
128
|
+
this.masterGain.gain.value = this.muted ? 0 : this.volume;
|
|
129
|
+
}
|
|
130
|
+
/** Starts a buffer source mid-clip if `sceneTime` lands after the request's start — `audioOffset` accounts for the request's trim, the elapsed time since `startAt`, and any speed (playbackRate) change. */
|
|
131
|
+
playBuffer(buffer, req, sceneTime) {
|
|
132
|
+
const gainNode = this.context.createGain();
|
|
133
|
+
// Guard against a missing/NaN volume — a non-finite AudioParam value throws.
|
|
134
|
+
gainNode.gain.value = Number.isFinite(req.volume) ? req.volume : 1;
|
|
135
|
+
// Into this clip's bus chain, or straight to the master when it has none.
|
|
136
|
+
// The chain is shared: two clips on one bus reach the same nodes, which is
|
|
137
|
+
// what makes a bus effect one tail rather than one per clip.
|
|
138
|
+
gainNode.connect(this.buses.inputFor(req.bus, this.context.currentTime));
|
|
139
|
+
const source = this.context.createBufferSource();
|
|
140
|
+
source.buffer = buffer;
|
|
141
|
+
source.loop = req.loop;
|
|
142
|
+
const scalarSpeed = effectiveSpeed(req.filters);
|
|
143
|
+
const rate = Number.isFinite(scalarSpeed) && scalarSpeed > 0 ? scalarSpeed : 1;
|
|
144
|
+
const speedCurve = speedCurveOf(req.filters);
|
|
145
|
+
if (rate !== 1 && !speedCurve)
|
|
146
|
+
source.playbackRate.value = rate;
|
|
147
|
+
const elapsed = Math.max(0, sceneTime - req.startAt);
|
|
148
|
+
// Trimmed source length the filter curves / speed curve are authored over.
|
|
149
|
+
const sourceLength = Math.max(0, buffer.duration - req.trimStart);
|
|
150
|
+
// Scene-time length of the clip. Prefer the bounded [startAt, endAt) span; if
|
|
151
|
+
// endAt is unbounded (an open/looping clip reaching the device unresolved),
|
|
152
|
+
// fall back to the source length scaled by speed so curve params still resolve
|
|
153
|
+
// (a clipDuration of 0 would otherwise silently drop every fade/sweep).
|
|
154
|
+
const clipDuration = isFinite(req.endAt)
|
|
155
|
+
? Math.max(0, req.endAt - req.startAt)
|
|
156
|
+
: sourceLength / (rate || 1);
|
|
157
|
+
// Insert the filter chain between the source and the per-request gain. Pass
|
|
158
|
+
// the start time, clip duration, and elapsed so curve-valued params schedule
|
|
159
|
+
// and align to a mid-clip seek.
|
|
160
|
+
const startTime = this.context.currentTime;
|
|
161
|
+
const graph = buildAudioFilterGraph(this.context, source, req.filters ?? [], startTime, clipDuration, elapsed);
|
|
162
|
+
graph.output.connect(gainNode);
|
|
163
|
+
// Source-time offset for a mid-clip seek. Scalar speed scales linearly; a
|
|
164
|
+
// speed curve uses the integral inverse to find the true source position.
|
|
165
|
+
let audioOffset;
|
|
166
|
+
if (speedCurve) {
|
|
167
|
+
audioOffset = req.trimStart + sourceTimeAtSceneElapsed(speedCurve, sourceLength, elapsed);
|
|
168
|
+
// Schedule the time-varying playbackRate (folds in any scalar speed too).
|
|
169
|
+
applySpeedToPlaybackRate(source.playbackRate, speedCurve, sourceLength, clipDuration, rate, startTime, elapsed);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
audioOffset = req.trimStart + elapsed * rate;
|
|
173
|
+
}
|
|
174
|
+
source.start(startTime, audioOffset);
|
|
175
|
+
for (const osc of graph.oscillators)
|
|
176
|
+
osc.start(startTime);
|
|
177
|
+
source.onended = () => {
|
|
178
|
+
if (this.active.get(req.id)?.source === source) {
|
|
179
|
+
this.active.delete(req.id);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
this.active.set(req.id, {
|
|
183
|
+
source,
|
|
184
|
+
gainNode,
|
|
185
|
+
request: req,
|
|
186
|
+
filterNodes: graph.nodes,
|
|
187
|
+
oscillators: graph.oscillators,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
stopSource(id, active) {
|
|
191
|
+
try {
|
|
192
|
+
active.source.onended = null;
|
|
193
|
+
active.source.stop();
|
|
194
|
+
for (const osc of active.oscillators)
|
|
195
|
+
osc.stop();
|
|
196
|
+
active.source.disconnect();
|
|
197
|
+
for (const node of active.filterNodes)
|
|
198
|
+
node.disconnect();
|
|
199
|
+
active.gainNode.disconnect();
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
// already stopped
|
|
203
|
+
}
|
|
204
|
+
this.active.delete(id);
|
|
205
|
+
}
|
|
206
|
+
dispose() {
|
|
207
|
+
if (this.disposed)
|
|
208
|
+
return;
|
|
209
|
+
this.disposed = true;
|
|
210
|
+
super.dispose();
|
|
211
|
+
this.bufferCache.clear();
|
|
212
|
+
this.decoding.clear();
|
|
213
|
+
this.scheduled.length = 0;
|
|
214
|
+
this.buses.dispose();
|
|
215
|
+
try {
|
|
216
|
+
this.masterGain.disconnect();
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
// already disconnected
|
|
220
|
+
}
|
|
221
|
+
if (this.ownsContext && this.context.state !== "closed") {
|
|
222
|
+
this.context.close();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=player.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player.js","sourceRoot":"","sources":["../../src/audio/player.ts"],"names":[],"mappings":"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","sourcesContent":["import { AudioSink, AudioRequest, sourceTimeAtSceneElapsed } from \"@motionscript/core\";\nimport { AudioBusGraph } from \"./bus-graph\";\nimport { buildAudioFilterGraph, effectiveSpeed, speedCurveOf, applySpeedToPlaybackRate } from \"./filter-graph\";\n\ntype ActiveSource = {\n source: AudioBufferSourceNode;\n gainNode: GainNode;\n request: AudioRequest;\n /** Filter-graph nodes to disconnect on teardown. */\n filterNodes: AudioNode[];\n /** Tremolo LFOs to stop on teardown. */\n oscillators: OscillatorNode[];\n};\n\n/**\n * Web Audio implementation of {@link AudioSink} — decodes and caches source\n * buffers, then schedules/plays {@link AudioRequest}s as `AudioBufferSourceNode`s\n * through a shared master gain (global mute and volume). `schedule` registers the\n * active set of requests for the current frame; `syncTo` then starts/stops\n * sources to match `sceneTime`, so playback follows scrubbing and seeks.\n */\nexport class WebAudioSink extends AudioSink {\n private context: AudioContext;\n private ownsContext: boolean;\n private bufferCache = new Map<string, AudioBuffer>();\n private decoding = new Map<string, Promise<void>>();\n private active = new Map<string, ActiveSource>();\n private scheduled: AudioRequest[] = [];\n private disposed: boolean = false;\n private masterGain: GainNode;\n /** The live bus chains, shared across every clip that names one. */\n private buses: AudioBusGraph;\n private muted = false;\n private volume = 1;\n\n constructor(context?: AudioContext) {\n super();\n this.context = context ?? new AudioContext();\n this.ownsContext = !context;\n this.masterGain = this.context.createGain();\n this.masterGain.connect(this.context.destination);\n this.buses = new AudioBusGraph(this.context, this.masterGain);\n }\n\n getContext(): AudioContext {\n return this.context;\n }\n\n /**\n * Resume the AudioContext. Must be called from within a user gesture\n * (e.g. a click handler) the first time, or browsers keep the context\n * suspended and no audio is heard.\n */\n unlock(): void {\n if (this.context.state === \"suspended\") {\n this.context.resume();\n }\n }\n\n has(src: string): boolean {\n return this.bufferCache.has(src);\n }\n\n async append(src: string, data: ArrayBuffer): Promise<void> {\n if (this.bufferCache.has(src)) return;\n const existing = this.decoding.get(src);\n if (existing) return existing;\n\n // decodeAudioData detaches `data` — that's fine, the caller in\n // AssetManager.fetchAudio discards its reference immediately after\n // awaiting append. Skipping the defensive .slice(0) saves a multi-MB\n // allocation per audio source.\n const job = this.context.decodeAudioData(data).then((buffer) => {\n this.bufferCache.set(src, buffer);\n }).finally(() => {\n this.decoding.delete(src);\n });\n this.decoding.set(src, job);\n await job;\n }\n\n /** Drops cached buffers and stops active sources for srcs/requests no longer referenced — called when the asset set changes (e.g. seeking across scene boundaries). */\n retain(keep: ReadonlySet<string>): void {\n for (const src of [...this.bufferCache.keys()]) {\n if (!keep.has(src)) this.bufferCache.delete(src);\n }\n for (const [id, active] of this.active) {\n if (!keep.has(active.request.src)) this.stopSource(id, active);\n }\n }\n\n /** Replaces the active request set; stops any currently-playing source whose request is no longer scheduled. Actual start/stop-to-match-time happens in `syncTo`. */\n schedule(requests: readonly AudioRequest[]): void {\n const next = new Set(requests.map(r => r.id));\n for (const [id, active] of this.active) {\n if (!next.has(id)) this.stopSource(id, active);\n }\n this.scheduled = requests.slice();\n }\n\n /** Starts sources whose `[startAt, endAt)` window now contains `sceneTime` (computing the correct buffer offset for the seek point) and stops any that have fallen outside it. */\n syncTo(sceneTime: number): void {\n const liveIds = new Set<string>();\n\n for (const req of this.scheduled) {\n // `endAt` is `Infinity` for an open clip, so the comparison needs no\n // nullish fallback — see AudioRequest.endAt.\n const isInWindow = sceneTime >= req.startAt && sceneTime < req.endAt;\n if (!isInWindow) continue;\n\n liveIds.add(req.id);\n if (!this.active.has(req.id)) {\n const buffer = this.bufferCache.get(req.src);\n if (buffer) this.playBuffer(buffer, req, sceneTime);\n }\n }\n\n for (const [id, active] of this.active) {\n if (!liveIds.has(id)) this.stopSource(id, active);\n }\n }\n\n async play(time: number, _speed: number, _reverse: boolean): Promise<void> {\n if (this.context.state === \"suspended\") {\n await this.context.resume();\n }\n this.syncTo(time);\n }\n\n stop(): void {\n for (const [id, active] of this.active) {\n this.stopSource(id, active);\n }\n }\n\n setMuted(muted: boolean): void {\n this.muted = muted;\n this.applyMasterGain();\n }\n\n setVolume(volume: number): void {\n this.volume = Math.max(0, volume);\n this.applyMasterGain();\n }\n\n /** Mute and volume are held separately so unmuting restores the set level. */\n private applyMasterGain(): void {\n this.masterGain.gain.value = this.muted ? 0 : this.volume;\n }\n\n /** Starts a buffer source mid-clip if `sceneTime` lands after the request's start — `audioOffset` accounts for the request's trim, the elapsed time since `startAt`, and any speed (playbackRate) change. */\n private playBuffer(buffer: AudioBuffer, req: AudioRequest, sceneTime: number): void {\n const gainNode = this.context.createGain();\n // Guard against a missing/NaN volume — a non-finite AudioParam value throws.\n gainNode.gain.value = Number.isFinite(req.volume) ? req.volume : 1;\n // Into this clip's bus chain, or straight to the master when it has none.\n // The chain is shared: two clips on one bus reach the same nodes, which is\n // what makes a bus effect one tail rather than one per clip.\n gainNode.connect(this.buses.inputFor(req.bus, this.context.currentTime));\n\n const source = this.context.createBufferSource();\n source.buffer = buffer;\n source.loop = req.loop;\n\n const scalarSpeed = effectiveSpeed(req.filters);\n const rate = Number.isFinite(scalarSpeed) && scalarSpeed > 0 ? scalarSpeed : 1;\n const speedCurve = speedCurveOf(req.filters);\n if (rate !== 1 && !speedCurve) source.playbackRate.value = rate;\n\n const elapsed = Math.max(0, sceneTime - req.startAt);\n // Trimmed source length the filter curves / speed curve are authored over.\n const sourceLength = Math.max(0, buffer.duration - req.trimStart);\n // Scene-time length of the clip. Prefer the bounded [startAt, endAt) span; if\n // endAt is unbounded (an open/looping clip reaching the device unresolved),\n // fall back to the source length scaled by speed so curve params still resolve\n // (a clipDuration of 0 would otherwise silently drop every fade/sweep).\n const clipDuration = isFinite(req.endAt)\n ? Math.max(0, req.endAt - req.startAt)\n : sourceLength / (rate || 1);\n\n // Insert the filter chain between the source and the per-request gain. Pass\n // the start time, clip duration, and elapsed so curve-valued params schedule\n // and align to a mid-clip seek.\n const startTime = this.context.currentTime;\n const graph = buildAudioFilterGraph(\n this.context, source, req.filters ?? [], startTime, clipDuration, elapsed,\n );\n graph.output.connect(gainNode);\n\n // Source-time offset for a mid-clip seek. Scalar speed scales linearly; a\n // speed curve uses the integral inverse to find the true source position.\n let audioOffset: number;\n if (speedCurve) {\n audioOffset = req.trimStart + sourceTimeAtSceneElapsed(speedCurve, sourceLength, elapsed);\n // Schedule the time-varying playbackRate (folds in any scalar speed too).\n applySpeedToPlaybackRate(\n source.playbackRate, speedCurve, sourceLength, clipDuration, rate, startTime, elapsed,\n );\n } else {\n audioOffset = req.trimStart + elapsed * rate;\n }\n\n source.start(startTime, audioOffset);\n for (const osc of graph.oscillators) osc.start(startTime);\n\n source.onended = () => {\n if (this.active.get(req.id)?.source === source) {\n this.active.delete(req.id);\n }\n };\n\n this.active.set(req.id, {\n source,\n gainNode,\n request: req,\n filterNodes: graph.nodes,\n oscillators: graph.oscillators,\n });\n }\n\n private stopSource(id: string, active: ActiveSource): void {\n try {\n active.source.onended = null;\n active.source.stop();\n for (const osc of active.oscillators) osc.stop();\n active.source.disconnect();\n for (const node of active.filterNodes) node.disconnect();\n active.gainNode.disconnect();\n } catch {\n // already stopped\n }\n this.active.delete(id);\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n super.dispose();\n this.bufferCache.clear();\n this.decoding.clear();\n this.scheduled.length = 0;\n this.buses.dispose();\n try {\n this.masterGain.disconnect();\n } catch {\n // already disconnected\n }\n if (this.ownsContext && this.context.state !== \"closed\") {\n this.context.close();\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as e,b as i,c as r,d as A,e as d,f as o}from"./chunks/chunk-NSFLRI4P.js";import"./chunks/chunk-FY3BTKY4.js";export{e as AudioBusGraph,i as DEFAULT_SAMPLE_RATE,A as WebAudioMixer,o as WebAudioPlayer,o as WebAudioSink,d as encodeWav,r as mixAudio};
|
|
2
|
+
//# sourceMappingURL=audio.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{c as bt}from"./chunk-FQ32PDIU.js";import{$d as rt,$f as Rt,Ed as tt,Gd as G,Gf as de,If as he,Kb as Qe,Kf as pe,Lb as te,Lf as mt,Pf as gt,Qd as nt,Qf as me,Rd as ae,Sd as ce,Tb as $e,Td as ue,Ub as V,Ud as Y,Vb as F,Wf as Tt,Zd as P,_d as st,_f as At,ae as it,ag as yt,bc as k,bg as Et,cc as M,ce as ot,cg as _t,dd as et,de as le,ed as ne,ee as at,fd as se,gd as N,id as re,ig as B,je as ct,ke as ut,l as Xe,ld as ie,le as lt,me as ft,mg as xt,n as Ve,ne as dt,nf as fe,oa as j,oe as ht,of as S,pa as qe,qa as Ye,ra as $,sa as We,td as z,ua as Ze,wa as X,wd as oe,xa as Je,xd as q,yf as pt,yg as wt,za as ee,zd as O}from"./chunk-CTLBXZSU.js";import"./chunk-FY3BTKY4.js";function ge(f,t){if(t===$e)return console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles."),f;if(t===F||t===V){let e=f.getIndex();if(e===null){let i=[],a=f.getAttribute("position");if(a!==void 0){for(let o=0;o<a.count;o++)i.push(o);f.setIndex(i),e=f.getIndex()}else return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."),f}let s=e.count-2,n=[];if(t===F)for(let i=1;i<=s;i++)n.push(e.getX(0)),n.push(e.getX(i)),n.push(e.getX(i+1));else for(let i=0;i<s;i++)i%2===0?(n.push(e.getX(i)),n.push(e.getX(i+1)),n.push(e.getX(i+2))):(n.push(e.getX(i+2)),n.push(e.getX(i+1)),n.push(e.getX(i)));n.length/3!==s&&console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.");let r=f.clone();return r.setIndex(n),r.clearGroups(),r}else return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:",t),f}var St=class extends gt{constructor(t){super(t),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register(function(e){return new xe(e)}),this.register(function(e){return new we(e)}),this.register(function(e){return new ve(e)}),this.register(function(e){return new He(e)}),this.register(function(e){return new ke(e)}),this.register(function(e){return new Se(e)}),this.register(function(e){return new Me(e)}),this.register(function(e){return new Ie(e)}),this.register(function(e){return new Ne(e)}),this.register(function(e){return new _e(e)}),this.register(function(e){return new Le(e)}),this.register(function(e){return new be(e)}),this.register(function(e){return new Ce(e)}),this.register(function(e){return new Oe(e)}),this.register(function(e){return new ye(e)}),this.register(function(e){return new W(e,g.EXT_MESHOPT_COMPRESSION)}),this.register(function(e){return new W(e,g.KHR_MESHOPT_COMPRESSION)}),this.register(function(e){return new Pe(e)})}load(t,e,s,n){let r=this,i;if(this.resourcePath!=="")i=this.resourcePath;else if(this.path!==""){let c=B.extractUrlBase(t);i=B.resolveURL(c,this.path)}else i=B.extractUrlBase(t);this.manager.itemStart(t);let a=function(c){n?n(c):console.error(c),r.manager.itemError(t),r.manager.itemEnd(t)},o=new me(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(this.withCredentials),o.load(t,function(c){try{r.parse(c,i,function(u){e(u),r.manager.itemEnd(t)},a)}catch(u){a(u)}},s,a)}setDRACOLoader(t){return this.dracoLoader=t,this}setKTX2Loader(t){return this.ktx2Loader=t,this}setMeshoptDecoder(t){return this.meshoptDecoder=t,this}register(t){return this.pluginCallbacks.indexOf(t)===-1&&this.pluginCallbacks.push(t),this}unregister(t){return this.pluginCallbacks.indexOf(t)!==-1&&this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(t),1),this}parse(t,e,s,n){let r,i={},a={},o=new TextDecoder;if(typeof t=="string")r=JSON.parse(t);else if(t instanceof ArrayBuffer)if(o.decode(new Uint8Array(t,0,4))===Ot){try{i[g.KHR_BINARY_GLTF]=new Be(t)}catch(l){n&&n(l);return}r=JSON.parse(i[g.KHR_BINARY_GLTF].content)}else r=JSON.parse(o.decode(t));else r=t;if(r.asset===void 0||r.asset.version[0]<2){n&&n(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported."));return}let c=new je(r,{path:e||this.resourcePath||"",crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});c.fileLoader.setRequestHeader(this.requestHeader);for(let u=0;u<this.pluginCallbacks.length;u++){let l=this.pluginCallbacks[u](c);l.name||console.error("THREE.GLTFLoader: Invalid plugin found: missing name"),a[l.name]=l,i[l.name]=!0}if(r.extensionsUsed)for(let u=0;u<r.extensionsUsed.length;++u){let l=r.extensionsUsed[u],d=r.extensionsRequired||[];switch(l){case g.KHR_MATERIALS_UNLIT:i[l]=new Ee;break;case g.KHR_DRACO_MESH_COMPRESSION:i[l]=new De(r,this.dracoLoader);break;case g.KHR_TEXTURE_TRANSFORM:i[l]=new Ue;break;case g.KHR_MESH_QUANTIZATION:i[l]=new Fe;break;default:d.indexOf(l)>=0&&a[l]===void 0&&console.warn('THREE.GLTFLoader: Unknown extension "'+l+'".')}}c.setExtensions(i),c.setPlugins(a),c.parse(s,n)}parseAsync(t,e){let s=this;return new Promise(function(n,r){s.parse(t,e,n,r)})}};function Ct(){let f={};return{get:function(t){return f[t]},add:function(t,e){f[t]=e},remove:function(t){delete f[t]},removeAll:function(){f={}}}}function _(f,t,e){let s=f.json.materials[t];return s.extensions&&s.extensions[e]?s.extensions[e]:null}var g={KHR_BINARY_GLTF:"KHR_binary_glTF",KHR_DRACO_MESH_COMPRESSION:"KHR_draco_mesh_compression",KHR_LIGHTS_PUNCTUAL:"KHR_lights_punctual",KHR_MATERIALS_CLEARCOAT:"KHR_materials_clearcoat",KHR_MATERIALS_DISPERSION:"KHR_materials_dispersion",KHR_MATERIALS_IOR:"KHR_materials_ior",KHR_MATERIALS_SHEEN:"KHR_materials_sheen",KHR_MATERIALS_SPECULAR:"KHR_materials_specular",KHR_MATERIALS_TRANSMISSION:"KHR_materials_transmission",KHR_MATERIALS_IRIDESCENCE:"KHR_materials_iridescence",KHR_MATERIALS_ANISOTROPY:"KHR_materials_anisotropy",KHR_MATERIALS_UNLIT:"KHR_materials_unlit",KHR_MATERIALS_VOLUME:"KHR_materials_volume",KHR_TEXTURE_BASISU:"KHR_texture_basisu",KHR_TEXTURE_TRANSFORM:"KHR_texture_transform",KHR_MESH_QUANTIZATION:"KHR_mesh_quantization",KHR_MATERIALS_EMISSIVE_STRENGTH:"KHR_materials_emissive_strength",EXT_MATERIALS_BUMP:"EXT_materials_bump",EXT_TEXTURE_WEBP:"EXT_texture_webp",EXT_TEXTURE_AVIF:"EXT_texture_avif",EXT_MESHOPT_COMPRESSION:"EXT_meshopt_compression",KHR_MESHOPT_COMPRESSION:"KHR_meshopt_compression",EXT_MESH_GPU_INSTANCING:"EXT_mesh_gpu_instancing"},ye=class{constructor(t){this.parser=t,this.name=g.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){let t=this.parser,e=this.parser.json.nodes||[];for(let s=0,n=e.length;s<n;s++){let r=e[s];r.extensions&&r.extensions[this.name]&&r.extensions[this.name].light!==void 0&&t._addNodeRef(this.cache,r.extensions[this.name].light)}}_loadLight(t){let e=this.parser,s="light:"+t,n=e.cache.get(s);if(n)return n;let r=e.json,o=((r.extensions&&r.extensions[this.name]||{}).lights||[])[t],c,u=new O(16777215);o.color!==void 0&&u.setRGB(o.color[0],o.color[1],o.color[2],M);let l=o.range!==void 0?o.range:0;switch(o.type){case"directional":c=new _t(u),c.target.position.set(0,0,-1),c.add(c.target);break;case"point":c=new yt(u),c.distance=l;break;case"spot":c=new Rt(u),c.distance=l,o.spot=o.spot||{},o.spot.innerConeAngle=o.spot.innerConeAngle!==void 0?o.spot.innerConeAngle:0,o.spot.outerConeAngle=o.spot.outerConeAngle!==void 0?o.spot.outerConeAngle:Math.PI/4,c.angle=o.spot.outerConeAngle,c.penumbra=1-o.spot.innerConeAngle/o.spot.outerConeAngle,c.target.position.set(0,0,-1),c.add(c.target);break;default:throw new Error("THREE.GLTFLoader: Unexpected light type: "+o.type)}return c.position.set(0,0,0),I(c,o),o.intensity!==void 0&&(c.intensity=o.intensity),c.name=e.createUniqueName(o.name||"light_"+t),n=Promise.resolve(c),e.cache.add(s,n),n}getDependency(t,e){if(t==="light")return this._loadLight(e)}createNodeAttachment(t){let e=this,s=this.parser,r=s.json.nodes[t],a=(r.extensions&&r.extensions[this.name]||{}).light;return a===void 0?null:this._loadLight(a).then(function(o){return s._getNodeRef(e.cache,a,o)})}},Ee=class{constructor(){this.name=g.KHR_MATERIALS_UNLIT}getMaterialType(){return P}extendParams(t,e,s){let n=[];t.color=new O(1,1,1),t.opacity=1;let r=e.pbrMetallicRoughness;if(r){if(Array.isArray(r.baseColorFactor)){let i=r.baseColorFactor;t.color.setRGB(i[0],i[1],i[2],M),t.opacity=i[3]}r.baseColorTexture!==void 0&&n.push(s.assignTexture(t,"map",r.baseColorTexture,k))}return Promise.all(n)}},_e=class{constructor(t){this.parser=t,this.name=g.KHR_MATERIALS_EMISSIVE_STRENGTH}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);return s===null||s.emissiveStrength!==void 0&&(e.emissiveIntensity=s.emissiveStrength),Promise.resolve()}},xe=class{constructor(t){this.parser=t,this.name=g.KHR_MATERIALS_CLEARCOAT}getMaterialType(t){return _(this.parser,t,this.name)!==null?S:null}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);if(s===null)return Promise.resolve();let n=[];if(s.clearcoatFactor!==void 0&&(e.clearcoat=s.clearcoatFactor),s.clearcoatTexture!==void 0&&n.push(this.parser.assignTexture(e,"clearcoatMap",s.clearcoatTexture)),s.clearcoatRoughnessFactor!==void 0&&(e.clearcoatRoughness=s.clearcoatRoughnessFactor),s.clearcoatRoughnessTexture!==void 0&&n.push(this.parser.assignTexture(e,"clearcoatRoughnessMap",s.clearcoatRoughnessTexture)),s.clearcoatNormalTexture!==void 0&&(n.push(this.parser.assignTexture(e,"clearcoatNormalMap",s.clearcoatNormalTexture)),s.clearcoatNormalTexture.scale!==void 0)){let r=s.clearcoatNormalTexture.scale;e.clearcoatNormalScale=new ne(r,r)}return Promise.all(n)}},we=class{constructor(t){this.parser=t,this.name=g.KHR_MATERIALS_DISPERSION}getMaterialType(t){return _(this.parser,t,this.name)!==null?S:null}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);return s===null||(e.dispersion=s.dispersion!==void 0?s.dispersion:0),Promise.resolve()}},be=class{constructor(t){this.parser=t,this.name=g.KHR_MATERIALS_IRIDESCENCE}getMaterialType(t){return _(this.parser,t,this.name)!==null?S:null}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);if(s===null)return Promise.resolve();let n=[];return s.iridescenceFactor!==void 0&&(e.iridescence=s.iridescenceFactor),s.iridescenceTexture!==void 0&&n.push(this.parser.assignTexture(e,"iridescenceMap",s.iridescenceTexture)),s.iridescenceIor!==void 0&&(e.iridescenceIOR=s.iridescenceIor),e.iridescenceThicknessRange===void 0&&(e.iridescenceThicknessRange=[100,400]),s.iridescenceThicknessMinimum!==void 0&&(e.iridescenceThicknessRange[0]=s.iridescenceThicknessMinimum),s.iridescenceThicknessMaximum!==void 0&&(e.iridescenceThicknessRange[1]=s.iridescenceThicknessMaximum),s.iridescenceThicknessTexture!==void 0&&n.push(this.parser.assignTexture(e,"iridescenceThicknessMap",s.iridescenceThicknessTexture)),Promise.all(n)}},Se=class{constructor(t){this.parser=t,this.name=g.KHR_MATERIALS_SHEEN}getMaterialType(t){return _(this.parser,t,this.name)!==null?S:null}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);if(s===null)return Promise.resolve();let n=[];if(e.sheenColor=new O(0,0,0),e.sheenRoughness=0,e.sheen=1,s.sheenColorFactor!==void 0){let r=s.sheenColorFactor;e.sheenColor.setRGB(r[0],r[1],r[2],M)}return s.sheenRoughnessFactor!==void 0&&(e.sheenRoughness=s.sheenRoughnessFactor),s.sheenColorTexture!==void 0&&n.push(this.parser.assignTexture(e,"sheenColorMap",s.sheenColorTexture,k)),s.sheenRoughnessTexture!==void 0&&n.push(this.parser.assignTexture(e,"sheenRoughnessMap",s.sheenRoughnessTexture)),Promise.all(n)}},Me=class{constructor(t){this.parser=t,this.name=g.KHR_MATERIALS_TRANSMISSION}getMaterialType(t){return _(this.parser,t,this.name)!==null?S:null}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);if(s===null)return Promise.resolve();let n=[];return s.transmissionFactor!==void 0&&(e.transmission=s.transmissionFactor),s.transmissionTexture!==void 0&&n.push(this.parser.assignTexture(e,"transmissionMap",s.transmissionTexture)),Promise.all(n)}},Ie=class{constructor(t){this.parser=t,this.name=g.KHR_MATERIALS_VOLUME}getMaterialType(t){return _(this.parser,t,this.name)!==null?S:null}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);if(s===null)return Promise.resolve();let n=[];e.thickness=s.thicknessFactor!==void 0?s.thicknessFactor:0,s.thicknessTexture!==void 0&&n.push(this.parser.assignTexture(e,"thicknessMap",s.thicknessTexture)),e.attenuationDistance=s.attenuationDistance||1/0;let r=s.attenuationColor||[1,1,1];return e.attenuationColor=new O().setRGB(r[0],r[1],r[2],M),Promise.all(n)}},Ne=class{constructor(t){this.parser=t,this.name=g.KHR_MATERIALS_IOR}getMaterialType(t){return _(this.parser,t,this.name)!==null?S:null}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);return s===null||(e.ior=s.ior!==void 0?s.ior:1.5,e.ior===0&&(e.ior=1e3)),Promise.resolve()}},Le=class{constructor(t){this.parser=t,this.name=g.KHR_MATERIALS_SPECULAR}getMaterialType(t){return _(this.parser,t,this.name)!==null?S:null}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);if(s===null)return Promise.resolve();let n=[];e.specularIntensity=s.specularFactor!==void 0?s.specularFactor:1,s.specularTexture!==void 0&&n.push(this.parser.assignTexture(e,"specularIntensityMap",s.specularTexture));let r=s.specularColorFactor||[1,1,1];return e.specularColor=new O().setRGB(r[0],r[1],r[2],M),s.specularColorTexture!==void 0&&n.push(this.parser.assignTexture(e,"specularColorMap",s.specularColorTexture,k)),Promise.all(n)}},Oe=class{constructor(t){this.parser=t,this.name=g.EXT_MATERIALS_BUMP}getMaterialType(t){return _(this.parser,t,this.name)!==null?S:null}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);if(s===null)return Promise.resolve();let n=[];return e.bumpScale=s.bumpFactor!==void 0?s.bumpFactor:1,s.bumpTexture!==void 0&&n.push(this.parser.assignTexture(e,"bumpMap",s.bumpTexture)),Promise.all(n)}},Ce=class{constructor(t){this.parser=t,this.name=g.KHR_MATERIALS_ANISOTROPY}getMaterialType(t){return _(this.parser,t,this.name)!==null?S:null}extendMaterialParams(t,e){let s=_(this.parser,t,this.name);if(s===null)return Promise.resolve();let n=[];return s.anisotropyStrength!==void 0&&(e.anisotropy=s.anisotropyStrength),s.anisotropyRotation!==void 0&&(e.anisotropyRotation=s.anisotropyRotation),s.anisotropyTexture!==void 0&&n.push(this.parser.assignTexture(e,"anisotropyMap",s.anisotropyTexture)),Promise.all(n)}},ve=class{constructor(t){this.parser=t,this.name=g.KHR_TEXTURE_BASISU}loadTexture(t){let e=this.parser,s=e.json,n=s.textures[t];if(!n.extensions||!n.extensions[this.name])return null;let r=n.extensions[this.name],i=e.options.ktx2Loader;if(!i){if(s.extensionsRequired&&s.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures");return null}return e.loadTextureImage(t,r.source,i)}},He=class{constructor(t){this.parser=t,this.name=g.EXT_TEXTURE_WEBP}loadTexture(t){let e=this.name,s=this.parser,n=s.json,r=n.textures[t];if(!r.extensions||!r.extensions[e])return null;let i=r.extensions[e],a=n.images[i.source],o=s.textureLoader;if(a.uri){let c=s.options.manager.getHandler(a.uri);c!==null&&(o=c)}return s.loadTextureImage(t,i.source,o)}},ke=class{constructor(t){this.parser=t,this.name=g.EXT_TEXTURE_AVIF}loadTexture(t){let e=this.name,s=this.parser,n=s.json,r=n.textures[t];if(!r.extensions||!r.extensions[e])return null;let i=r.extensions[e],a=n.images[i.source],o=s.textureLoader;if(a.uri){let c=s.options.manager.getHandler(a.uri);c!==null&&(o=c)}return s.loadTextureImage(t,i.source,o)}},W=class{constructor(t,e){this.name=e,this.parser=t}loadBufferView(t){let e=this.parser.json,s=e.bufferViews[t];if(s.extensions&&s.extensions[this.name]){let n=s.extensions[this.name],r=this.parser.getDependency("buffer",n.buffer),i=this.parser.options.meshoptDecoder;if(!i||!i.supported){if(e.extensionsRequired&&e.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files");return null}return r.then(function(a){let o=n.byteOffset||0,c=n.byteLength||0,u=n.count,l=n.byteStride,d=new Uint8Array(a,o,c);return i.decodeGltfBufferAsync?i.decodeGltfBufferAsync(u,l,d,n.mode,n.filter).then(function(h){return h.buffer}):i.ready.then(function(){let h=new ArrayBuffer(u*l);return i.decodeGltfBuffer(new Uint8Array(h),u,l,d,n.mode,n.filter),h})})}else return null}},Pe=class{constructor(t){this.name=g.EXT_MESH_GPU_INSTANCING,this.parser=t}createNodeMesh(t){let e=this.parser.json,s=e.nodes[t];if(!s.extensions||!s.extensions[this.name]||s.mesh===void 0)return null;let n=e.meshes[s.mesh];for(let c of n.primitives)if(c.mode!==w.TRIANGLES&&c.mode!==w.TRIANGLE_STRIP&&c.mode!==w.TRIANGLE_FAN&&c.mode!==void 0)return null;let i=s.extensions[this.name].attributes,a=[],o={};for(let c in i)a.push(this.parser.getDependency("accessor",i[c]).then(u=>(o[c]=u,o[c])));return a.length<1?null:(a.push(this.parser.createNodeMesh(t)),Promise.all(a).then(c=>{let u=c.pop(),l=u.isGroup?u.children:[u],d=c[0].count,h=[];for(let p of l){let A=new z,m=new N,T=new se,E=new N(1,1,1),y=new at(p.geometry,p.material,d);for(let R=0;R<d;R++)o.TRANSLATION&&m.fromBufferAttribute(o.TRANSLATION,R),o.ROTATION&&T.fromBufferAttribute(o.ROTATION,R),o.SCALE&&E.fromBufferAttribute(o.SCALE,R),y.setMatrixAt(R,A.compose(m,T,E));for(let R in o)if(R==="_COLOR_0"){let x=o[R];y.instanceColor=new le(x.array,x.itemSize,x.normalized)}else R!=="TRANSLATION"&&R!=="ROTATION"&&R!=="SCALE"&&p.geometry.setAttribute(R,o[R]);oe.prototype.copy.call(y,p),this.parser.assignFinalMaterial(y),h.push(y)}return u.isGroup?(u.clear(),u.add(...h),u):h[0]}))}},Ot="glTF",K=12,Mt={JSON:1313821514,BIN:5130562},Be=class{constructor(t){this.name=g.KHR_BINARY_GLTF,this.content=null,this.body=null;let e=new DataView(t,0,K),s=new TextDecoder;if(this.header={magic:s.decode(new Uint8Array(t.slice(0,4))),version:e.getUint32(4,!0),length:e.getUint32(8,!0)},this.header.magic!==Ot)throw new Error("THREE.GLTFLoader: Unsupported glTF-Binary header.");if(this.header.version<2)throw new Error("THREE.GLTFLoader: Legacy binary file detected.");let n=this.header.length-K,r=new DataView(t,K),i=0;for(;i<n;){let a=r.getUint32(i,!0);i+=4;let o=r.getUint32(i,!0);if(i+=4,o===Mt.JSON){let c=new Uint8Array(t,K+i,a);this.content=s.decode(c)}else if(o===Mt.BIN){let c=K+i;this.body=t.slice(c,c+a)}i+=a}if(this.content===null)throw new Error("THREE.GLTFLoader: JSON content not found.")}},De=class{constructor(t,e){if(!e)throw new Error("THREE.GLTFLoader: No DRACOLoader instance provided.");this.name=g.KHR_DRACO_MESH_COMPRESSION,this.json=t,this.dracoLoader=e,this.dracoLoader.preload()}decodePrimitive(t,e){let s=this.json,n=this.dracoLoader,r=t.extensions[this.name].bufferView,i=t.extensions[this.name].attributes,a={},o={},c={};for(let u in i){let l=Ge[u]||u.toLowerCase();a[l]=i[u]}for(let u in t.attributes){let l=Ge[u]||u.toLowerCase();if(i[u]!==void 0){let d=s.accessors[t.attributes[u]],h=D[d.componentType];c[l]=h.name,o[l]=d.normalized===!0}}return e.getDependency("bufferView",r).then(function(u){return new Promise(function(l,d){n.decodeDracoFile(u,function(h){for(let p in h.attributes){let A=h.attributes[p],m=o[p];m!==void 0&&(A.normalized=m)}l(h)},a,c,M,d)})})}},Ue=class{constructor(){this.name=g.KHR_TEXTURE_TRANSFORM}extendTexture(t,e){return(e.texCoord===void 0||e.texCoord===t.channel)&&e.offset===void 0&&e.rotation===void 0&&e.scale===void 0||(t=t.clone(),e.texCoord!==void 0&&(t.channel=e.texCoord),e.offset!==void 0&&t.offset.fromArray(e.offset),e.rotation!==void 0&&(t.rotation=e.rotation),e.scale!==void 0&&t.repeat.fromArray(e.scale),t.needsUpdate=!0),t}},Fe=class{constructor(){this.name=g.KHR_MESH_QUANTIZATION}},Z=class extends pt{constructor(t,e,s,n){super(t,e,s,n)}copySampleValue_(t){let e=this.resultBuffer,s=this.sampleValues,n=this.valueSize,r=t*n*3+n;for(let i=0;i!==n;i++)e[i]=s[r+i];return e}interpolate_(t,e,s,n){let r=this.resultBuffer,i=this.sampleValues,a=this.valueSize,o=a*2,c=a*3,u=n-e,l=(s-e)/u,d=l*l,h=d*l,p=t*c,A=p-c,m=-2*h+3*d,T=h-d,E=1-m,y=T-d+l;for(let R=0;R!==a;R++){let x=i[A+R+a],L=i[A+R+o]*u,b=i[p+R+a],U=i[p+R]*u;r[R]=E*x+y*L+m*b+T*U}return r}},vt=new se,ze=class extends Z{interpolate_(t,e,s,n){let r=super.interpolate_(t,e,s,n);return vt.fromArray(r).normalize().toArray(r),r}},w={FLOAT:5126,FLOAT_MAT3:35675,FLOAT_MAT4:35676,FLOAT_VEC2:35664,FLOAT_VEC3:35665,FLOAT_VEC4:35666,LINEAR:9729,REPEAT:10497,SAMPLER_2D:35678,POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6,UNSIGNED_BYTE:5121,UNSIGNED_SHORT:5123},D={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array},It={9728:$,9729:X,9984:We,9985:Je,9986:Ze,9987:ee},Nt={33071:qe,33648:Ye,10497:j},Te={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16},Ge={POSITION:"position",NORMAL:"normal",TANGENT:"tangent",TEXCOORD_0:"uv",TEXCOORD_1:"uv1",TEXCOORD_2:"uv2",TEXCOORD_3:"uv3",COLOR_0:"color",WEIGHTS_0:"skinWeight",JOINTS_0:"skinIndex"},C={scale:"scale",translation:"position",rotation:"quaternion",weights:"morphTargetInfluences"},Ht={CUBICSPLINE:void 0,LINEAR:te,STEP:Qe},Ae={OPAQUE:"OPAQUE",MASK:"MASK",BLEND:"BLEND"};function kt(f){return f.DefaultMaterial===void 0&&(f.DefaultMaterial=new fe({color:16777215,emissive:0,metalness:1,roughness:1,transparent:!1,depthTest:!0,side:Xe})),f.DefaultMaterial}function v(f,t,e){for(let s in e.extensions)f[s]===void 0&&(t.userData.gltfExtensions=t.userData.gltfExtensions||{},t.userData.gltfExtensions[s]=e.extensions[s])}function I(f,t){t.extras!==void 0&&(typeof t.extras=="object"?Object.assign(f.userData,t.extras):console.warn("THREE.GLTFLoader: Ignoring primitive type .extras, "+t.extras))}function Pt(f,t,e){let s=!1,n=!1,r=!1;for(let c=0,u=t.length;c<u;c++){let l=t[c];if(l.POSITION!==void 0&&(s=!0),l.NORMAL!==void 0&&(n=!0),l.COLOR_0!==void 0&&(r=!0),s&&n&&r)break}if(!s&&!n&&!r)return Promise.resolve(f);let i=[],a=[],o=[];for(let c=0,u=t.length;c<u;c++){let l=t[c];if(s){let d=l.POSITION!==void 0?e.getDependency("accessor",l.POSITION):f.attributes.position;i.push(d)}if(n){let d=l.NORMAL!==void 0?e.getDependency("accessor",l.NORMAL):f.attributes.normal;a.push(d)}if(r){let d=l.COLOR_0!==void 0?e.getDependency("accessor",l.COLOR_0):f.attributes.color;o.push(d)}}return Promise.all([Promise.all(i),Promise.all(a),Promise.all(o)]).then(function(c){let u=c[0],l=c[1],d=c[2];return s&&(f.morphAttributes.position=u),n&&(f.morphAttributes.normal=l),r&&(f.morphAttributes.color=d),f.morphTargetsRelative=!0,f})}function Bt(f,t){if(f.updateMorphTargets(),t.weights!==void 0)for(let e=0,s=t.weights.length;e<s;e++)f.morphTargetInfluences[e]=t.weights[e];if(t.extras&&Array.isArray(t.extras.targetNames)){let e=t.extras.targetNames;if(f.morphTargetInfluences.length===e.length){f.morphTargetDictionary={};for(let s=0,n=e.length;s<n;s++)f.morphTargetDictionary[e[s]]=s}else console.warn("THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.")}}function Dt(f){let t,e=f.extensions&&f.extensions[g.KHR_DRACO_MESH_COMPRESSION];if(e?t="draco:"+e.bufferView+":"+e.indices+":"+Re(e.attributes):t=f.indices+":"+Re(f.attributes)+":"+f.mode,f.targets!==void 0)for(let s=0,n=f.targets.length;s<n;s++)t+=":"+Re(f.targets[s]);return t}function Re(f){let t="",e=Object.keys(f).sort();for(let s=0,n=e.length;s<n;s++)t+=e[s]+":"+f[e[s]]+";";return t}function Ke(f){switch(f){case Int8Array:return 1/127;case Uint8Array:return 1/255;case Int16Array:return 1/32767;case Uint16Array:return 1/65535;default:throw new Error("THREE.GLTFLoader: Unsupported normalized accessor component type.")}}function Ut(f){return f.search(/\.jpe?g($|\?)/i)>0||f.search(/^data\:image\/jpeg/)===0?"image/jpeg":f.search(/\.webp($|\?)/i)>0||f.search(/^data\:image\/webp/)===0?"image/webp":f.search(/\.ktx2($|\?)/i)>0||f.search(/^data\:image\/ktx2/)===0?"image/ktx2":"image/png"}var Ft=new z,je=class{constructor(t={},e={}){this.json=t,this.extensions={},this.plugins={},this.options=e,this.cache=new Ct,this.associations=new Map,this.primitiveCache={},this.nodeCache={},this.meshCache={refs:{},uses:{}},this.cameraCache={refs:{},uses:{}},this.lightCache={refs:{},uses:{}},this.sourceCache={},this.textureCache={},this.nodeNamesUsed={};let s=!1,n=-1,r=!1,i=-1;if(typeof navigator<"u"&&typeof navigator.userAgent<"u"){let a=navigator.userAgent;s=/^((?!chrome|android).)*safari/i.test(a)===!0;let o=a.match(/Version\/(\d+)/);n=s&&o?parseInt(o[1],10):-1,r=a.indexOf("Firefox")>-1,i=r?a.match(/Firefox\/([0-9]+)\./)[1]:-1}typeof createImageBitmap>"u"||s&&n<17||r&&i<98?this.textureLoader=new Tt(this.options.manager):this.textureLoader=new xt(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new me(this.options.manager),this.fileLoader.setResponseType("arraybuffer"),this.options.crossOrigin==="use-credentials"&&this.fileLoader.setWithCredentials(!0)}setExtensions(t){this.extensions=t}setPlugins(t){this.plugins=t}parse(t,e){let s=this,n=this.json,r=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll(function(i){return i._markDefs&&i._markDefs()}),Promise.all(this._invokeAll(function(i){return i.beforeRoot&&i.beforeRoot()})).then(function(){return Promise.all([s.getDependencies("scene"),s.getDependencies("animation"),s.getDependencies("camera")])}).then(function(i){let a={scene:i[0][n.scene||0],scenes:i[0],animations:i[1],cameras:i[2],asset:n.asset,parser:s,userData:{}};return v(r,a,n),I(a,n),Promise.all(s._invokeAll(function(o){return o.afterRoot&&o.afterRoot(a)})).then(function(){for(let o of a.scenes)o.updateMatrixWorld();t(a)})}).catch(e)}_markDefs(){let t=this.json.nodes||[],e=this.json.skins||[],s=this.json.meshes||[];for(let n=0,r=e.length;n<r;n++){let i=e[n].joints;for(let a=0,o=i.length;a<o;a++)t[i[a]].isBone=!0}for(let n=0,r=t.length;n<r;n++){let i=t[n];i.mesh!==void 0&&(this._addNodeRef(this.meshCache,i.mesh),i.skin!==void 0&&(s[i.mesh].isSkinnedMesh=!0)),i.camera!==void 0&&this._addNodeRef(this.cameraCache,i.camera)}}_addNodeRef(t,e){e!==void 0&&(t.refs[e]===void 0&&(t.refs[e]=t.uses[e]=0),t.refs[e]++)}_getNodeRef(t,e,s){if(t.refs[e]<=1)return s;let n=s.clone(),r=(i,a)=>{let o=this.associations.get(i);o!=null&&this.associations.set(a,o);for(let[c,u]of i.children.entries())r(u,a.children[c])};return r(s,n),n.name+="_instance_"+t.uses[e]++,n}_invokeOne(t){let e=Object.values(this.plugins);e.push(this);for(let s=0;s<e.length;s++){let n=t(e[s]);if(n)return n}return null}_invokeAll(t){let e=Object.values(this.plugins);e.unshift(this);let s=[];for(let n=0;n<e.length;n++){let r=t(e[n]);r&&s.push(r)}return s}getDependency(t,e){let s=t+":"+e,n=this.cache.get(s);if(!n){switch(t){case"scene":n=this.loadScene(e);break;case"node":n=this._invokeOne(function(r){return r.loadNode&&r.loadNode(e)});break;case"mesh":n=this._invokeOne(function(r){return r.loadMesh&&r.loadMesh(e)});break;case"accessor":n=this.loadAccessor(e);break;case"bufferView":n=this._invokeOne(function(r){return r.loadBufferView&&r.loadBufferView(e)});break;case"buffer":n=this.loadBuffer(e);break;case"material":n=this._invokeOne(function(r){return r.loadMaterial&&r.loadMaterial(e)});break;case"texture":n=this._invokeOne(function(r){return r.loadTexture&&r.loadTexture(e)});break;case"skin":n=this.loadSkin(e);break;case"animation":n=this._invokeOne(function(r){return r.loadAnimation&&r.loadAnimation(e)});break;case"camera":n=this.loadCamera(e);break;default:if(n=this._invokeOne(function(r){return r!=this&&r.getDependency&&r.getDependency(t,e)}),!n)throw new Error("Unknown type: "+t);break}this.cache.add(s,n)}return n}getDependencies(t){let e=this.cache.get(t);if(!e){let s=this,n=this.json[t+(t==="mesh"?"es":"s")]||[];e=Promise.all(n.map(function(r,i){return s.getDependency(t,i)})),this.cache.add(t,e)}return e}loadBuffer(t){let e=this.json.buffers[t],s=this.fileLoader;if(e.type&&e.type!=="arraybuffer")throw new Error("THREE.GLTFLoader: "+e.type+" buffer type is not supported.");if(e.uri===void 0&&t===0)return Promise.resolve(this.extensions[g.KHR_BINARY_GLTF].body);let n=this.options;return new Promise(function(r,i){s.load(B.resolveURL(e.uri,n.path),r,void 0,function(){i(new Error('THREE.GLTFLoader: Failed to load buffer "'+e.uri+'".'))})})}loadBufferView(t){let e=this.json.bufferViews[t];return this.getDependency("buffer",e.buffer).then(function(s){let n=e.byteLength||0,r=e.byteOffset||0;return s.slice(r,r+n)})}loadAccessor(t){let e=this,s=this.json,n=this.json.accessors[t];if(n.bufferView===void 0&&n.sparse===void 0){let i=Te[n.type],a=D[n.componentType],o=n.normalized===!0,c=new a(n.count*i);return Promise.resolve(new G(c,i,o))}let r=[];return n.bufferView!==void 0?r.push(this.getDependency("bufferView",n.bufferView)):r.push(null),n.sparse!==void 0&&(r.push(this.getDependency("bufferView",n.sparse.indices.bufferView)),r.push(this.getDependency("bufferView",n.sparse.values.bufferView))),Promise.all(r).then(function(i){let a=i[0],o=Te[n.type],c=D[n.componentType],u=c.BYTES_PER_ELEMENT,l=u*o,d=n.byteOffset||0,h=n.bufferView!==void 0?s.bufferViews[n.bufferView].byteStride:void 0,p=n.normalized===!0,A,m;if(h&&h!==l){let T=Math.floor(d/h),E="InterleavedBuffer:"+n.bufferView+":"+n.componentType+":"+T+":"+n.count,y=e.cache.get(E);y||(A=new c(a,T*h,n.count*h/u),y=new ce(A,h/u),e.cache.add(E,y)),m=new ue(y,o,d%h/u,p)}else a===null?A=new c(n.count*o):A=new c(a,d,n.count*o),m=new G(A,o,p);if(n.sparse!==void 0){let T=Te.SCALAR,E=D[n.sparse.indices.componentType],y=n.sparse.indices.byteOffset||0,R=n.sparse.values.byteOffset||0,x=new E(i[1],y,n.sparse.count*T),L=new c(i[2],R,n.sparse.count*o);a!==null&&(m=new G(m.array.slice(),m.itemSize,m.normalized)),m.normalized=!1;for(let b=0,U=x.length;b<U;b++){let H=x[b];if(m.setX(H,L[b*o]),o>=2&&m.setY(H,L[b*o+1]),o>=3&&m.setZ(H,L[b*o+2]),o>=4&&m.setW(H,L[b*o+3]),o>=5)throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.")}m.normalized=p}return m})}loadTexture(t){let e=this.json,s=this.options,r=e.textures[t].source,i=e.images[r],a=this.textureLoader;if(i.uri){let o=s.manager.getHandler(i.uri);o!==null&&(a=o)}return this.loadTextureImage(t,r,a)}loadTextureImage(t,e,s){let n=this,r=this.json,i=r.textures[t],a=r.images[e],o=(a.uri||a.bufferView)+":"+i.sampler;if(this.textureCache[o])return this.textureCache[o];let c=this.loadImageSource(e,s).then(function(u){u.flipY=!1,u.name=i.name||a.name||"",u.name===""&&typeof a.uri=="string"&&a.uri.startsWith("data:image/")===!1&&(u.name=a.uri);let d=(r.samplers||{})[i.sampler]||{};return u.magFilter=It[d.magFilter]||X,u.minFilter=It[d.minFilter]||ee,u.wrapS=Nt[d.wrapS]||j,u.wrapT=Nt[d.wrapT]||j,u.generateMipmaps=!u.isCompressedTexture&&u.minFilter!==$&&u.minFilter!==X,n.associations.set(u,{textures:t}),u}).catch(function(){return null});return this.textureCache[o]=c,c}loadImageSource(t,e){let s=this,n=this.json,r=this.options;if(this.sourceCache[t]!==void 0)return this.sourceCache[t].then(l=>l.clone());let i=n.images[t],a=self.URL||self.webkitURL,o=i.uri||"",c=!1;if(i.bufferView!==void 0)o=s.getDependency("bufferView",i.bufferView).then(function(l){c=!0;let d=new Blob([l],{type:i.mimeType});return o=a.createObjectURL(d),o});else if(i.uri===void 0)throw new Error("THREE.GLTFLoader: Image "+t+" is missing URI and bufferView");let u=Promise.resolve(o).then(function(l){return new Promise(function(d,h){let p=d;e.isImageBitmapLoader===!0&&(p=function(A){let m=new ie(A);m.needsUpdate=!0,d(m)}),e.load(B.resolveURL(l,r.path),p,void 0,h)})}).then(function(l){return c===!0&&a.revokeObjectURL(o),I(l,i),l.userData.mimeType=i.mimeType||Ut(i.uri),l}).catch(function(l){throw console.error("THREE.GLTFLoader: Couldn't load texture",o),l});return this.sourceCache[t]=u,u}assignTexture(t,e,s,n){let r=this;return this.getDependency("texture",s.index).then(function(i){if(!i)return null;if(s.texCoord!==void 0&&s.texCoord>0&&(i=i.clone(),i.channel=s.texCoord),r.extensions[g.KHR_TEXTURE_TRANSFORM]){let a=s.extensions!==void 0?s.extensions[g.KHR_TEXTURE_TRANSFORM]:void 0;if(a){let o=r.associations.get(i);i=r.extensions[g.KHR_TEXTURE_TRANSFORM].extendTexture(i,a),r.associations.set(i,o)}}return n!==void 0&&(i.colorSpace=n),t[e]=i,i})}assignFinalMaterial(t){let e=t.geometry,s=t.material,n=e.attributes.tangent===void 0,r=e.attributes.color!==void 0,i=e.attributes.normal===void 0;if(t.isPoints){let a="PointsMaterial:"+s.uuid,o=this.cache.get(a);o||(o=new dt,Y.prototype.copy.call(o,s),o.color.copy(s.color),o.map=s.map,o.sizeAttenuation=!1,this.cache.add(a,o)),s=o}else if(t.isLine){let a="LineBasicMaterial:"+s.uuid,o=this.cache.get(a);o||(o=new ct,Y.prototype.copy.call(o,s),o.color.copy(s.color),o.map=s.map,this.cache.add(a,o)),s=o}if(n||r||i){let a="ClonedMaterial:"+s.uuid+":";n&&(a+="derivative-tangents:"),r&&(a+="vertex-colors:"),i&&(a+="flat-shading:");let o=this.cache.get(a);o||(o=s.clone(),r&&(o.vertexColors=!0),i&&(o.flatShading=!0),n&&(o.normalScale&&(o.normalScale.y*=-1),o.clearcoatNormalScale&&(o.clearcoatNormalScale.y*=-1)),this.cache.add(a,o),this.associations.set(o,this.associations.get(s))),s=o}t.material=s}getMaterialType(){return fe}loadMaterial(t){let e=this,s=this.json,n=this.extensions,r=s.materials[t],i,a={},o=r.extensions||{},c=[];if(o[g.KHR_MATERIALS_UNLIT]){let l=n[g.KHR_MATERIALS_UNLIT];i=l.getMaterialType(),c.push(l.extendParams(a,r,e))}else{let l=r.pbrMetallicRoughness||{};if(a.color=new O(1,1,1),a.opacity=1,Array.isArray(l.baseColorFactor)){let d=l.baseColorFactor;a.color.setRGB(d[0],d[1],d[2],M),a.opacity=d[3]}l.baseColorTexture!==void 0&&c.push(e.assignTexture(a,"map",l.baseColorTexture,k)),a.metalness=l.metallicFactor!==void 0?l.metallicFactor:1,a.roughness=l.roughnessFactor!==void 0?l.roughnessFactor:1,l.metallicRoughnessTexture!==void 0&&(c.push(e.assignTexture(a,"metalnessMap",l.metallicRoughnessTexture)),c.push(e.assignTexture(a,"roughnessMap",l.metallicRoughnessTexture))),i=this._invokeOne(function(d){return d.getMaterialType&&d.getMaterialType(t)}),c.push(Promise.all(this._invokeAll(function(d){return d.extendMaterialParams&&d.extendMaterialParams(t,a)})))}r.doubleSided===!0&&(a.side=Ve);let u=r.alphaMode||Ae.OPAQUE;if(u===Ae.BLEND?(a.transparent=!0,a.depthWrite=!1):(a.transparent=!1,u===Ae.MASK&&(a.alphaTest=r.alphaCutoff!==void 0?r.alphaCutoff:.5)),r.normalTexture!==void 0&&i!==P&&(c.push(e.assignTexture(a,"normalMap",r.normalTexture)),a.normalScale=new ne(1,1),r.normalTexture.scale!==void 0)){let l=r.normalTexture.scale;a.normalScale.set(l,l)}if(r.occlusionTexture!==void 0&&i!==P&&(c.push(e.assignTexture(a,"aoMap",r.occlusionTexture)),r.occlusionTexture.strength!==void 0&&(a.aoMapIntensity=r.occlusionTexture.strength)),r.emissiveFactor!==void 0&&i!==P){let l=r.emissiveFactor;a.emissive=new O().setRGB(l[0],l[1],l[2],M)}return r.emissiveTexture!==void 0&&i!==P&&c.push(e.assignTexture(a,"emissiveMap",r.emissiveTexture,k)),Promise.all(c).then(function(){let l=new i(a);return r.name&&(l.name=r.name),I(l,r),e.associations.set(l,{materials:t}),r.extensions&&v(n,l,r),l})}createUniqueName(t){let e=wt.sanitizeNodeName(t||"");return e in this.nodeNamesUsed?e+"_"+ ++this.nodeNamesUsed[e]:(this.nodeNamesUsed[e]=0,e)}loadGeometries(t){let e=this,s=this.extensions,n=this.primitiveCache;function r(a){return s[g.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(a,e).then(function(o){return Lt(o,a,e)})}let i=[];for(let a=0,o=t.length;a<o;a++){let c=t[a],u=Dt(c),l=n[u];if(l)i.push(l.promise);else{let d;c.extensions&&c.extensions[g.KHR_DRACO_MESH_COMPRESSION]?d=r(c):d=Lt(new ae,c,e),n[u]={primitive:c,promise:d},i.push(d)}}return Promise.all(i)}loadMesh(t){let e=this,s=this.json,n=this.extensions,r=s.meshes[t],i=r.primitives,a=[];for(let o=0,c=i.length;o<c;o++){let u=i[o].material===void 0?kt(this.cache):this.getDependency("material",i[o].material);a.push(u)}return a.push(e.loadGeometries(i)),Promise.all(a).then(function(o){let c=o.slice(0,o.length-1),u=o[o.length-1],l=[];for(let h=0,p=u.length;h<p;h++){let A=u[h],m=i[h],T,E=c[h];if(m.mode===w.TRIANGLES||m.mode===w.TRIANGLE_STRIP||m.mode===w.TRIANGLE_FAN||m.mode===void 0)T=r.isSkinnedMesh===!0?new rt(A,E):new st(A,E),T.isSkinnedMesh===!0&&T.normalizeSkinWeights(),m.mode===w.TRIANGLE_STRIP?T.geometry=ge(T.geometry,V):m.mode===w.TRIANGLE_FAN&&(T.geometry=ge(T.geometry,F));else if(m.mode===w.LINES)T=new lt(A,E);else if(m.mode===w.LINE_STRIP)T=new ut(A,E);else if(m.mode===w.LINE_LOOP)T=new ft(A,E);else if(m.mode===w.POINTS)T=new ht(A,E);else throw new Error("THREE.GLTFLoader: Primitive mode unsupported: "+m.mode);Object.keys(T.geometry.morphAttributes).length>0&&Bt(T,r),T.name=e.createUniqueName(r.name||"mesh_"+t),I(T,r),m.extensions&&v(n,T,m),e.assignFinalMaterial(T),l.push(T)}for(let h=0,p=l.length;h<p;h++)e.associations.set(l[h],{meshes:t,primitives:h});if(l.length===1)return r.extensions&&v(n,l[0],r),l[0];let d=new q;r.extensions&&v(n,d,r),e.associations.set(d,{meshes:t});for(let h=0,p=l.length;h<p;h++)d.add(l[h]);return d})}loadCamera(t){let e,s=this.json.cameras[t],n=s[s.type];if(!n){console.warn("THREE.GLTFLoader: Missing camera parameters.");return}return s.type==="perspective"?e=new At(et.radToDeg(n.yfov),n.aspectRatio||1,n.znear||1,n.zfar||2e6):s.type==="orthographic"&&(e=new Et(-n.xmag,n.xmag,n.ymag,-n.ymag,n.znear,n.zfar)),s.name&&(e.name=this.createUniqueName(s.name)),I(e,s),Promise.resolve(e)}loadSkin(t){let e=this.json.skins[t],s=[];for(let n=0,r=e.joints.length;n<r;n++)s.push(this._loadNodeShallow(e.joints[n]));return e.inverseBindMatrices!==void 0?s.push(this.getDependency("accessor",e.inverseBindMatrices)):s.push(null),Promise.all(s).then(function(n){let r=n.pop(),i=n,a=[],o=[];for(let c=0,u=i.length;c<u;c++){let l=i[c];if(l){a.push(l);let d=new z;r!==null&&d.fromArray(r.array,c*16),o.push(d)}else console.warn('THREE.GLTFLoader: Joint "%s" could not be found.',e.joints[c])}return new ot(a,o)})}loadAnimation(t){let e=this.json,s=this,n=e.animations[t],r=n.name?n.name:"animation_"+t,i=[],a=[],o=[],c=[],u=[];for(let l=0,d=n.channels.length;l<d;l++){let h=n.channels[l],p=n.samplers[h.sampler],A=h.target,m=A.node,T=n.parameters!==void 0?n.parameters[p.input]:p.input,E=n.parameters!==void 0?n.parameters[p.output]:p.output;A.node!==void 0&&(i.push(this.getDependency("node",m)),a.push(this.getDependency("accessor",T)),o.push(this.getDependency("accessor",E)),c.push(p),u.push(A))}return Promise.all([Promise.all(i),Promise.all(a),Promise.all(o),Promise.all(c),Promise.all(u)]).then(function(l){let d=l[0],h=l[1],p=l[2],A=l[3],m=l[4],T=[];for(let y=0,R=d.length;y<R;y++){let x=d[y],L=h[y],b=p[y],U=A[y],H=m[y];if(x===void 0)continue;x.updateMatrix&&x.updateMatrix();let J=s._createAnimationTracks(x,L,b,U,H);if(J)for(let Q=0;Q<J.length;Q++)T.push(J[Q])}let E=new mt(r,void 0,T);return I(E,n),E})}createNodeMesh(t){let e=this.json,s=this,n=e.nodes[t];return n.mesh===void 0?null:s.getDependency("mesh",n.mesh).then(function(r){let i=s._getNodeRef(s.meshCache,n.mesh,r);return n.weights!==void 0&&i.traverse(function(a){if(a.isMesh)for(let o=0,c=n.weights.length;o<c;o++)a.morphTargetInfluences[o]=n.weights[o]}),i})}loadNode(t){let e=this.json,s=this,n=e.nodes[t],r=s._loadNodeShallow(t),i=[],a=n.children||[];for(let c=0,u=a.length;c<u;c++)i.push(s.getDependency("node",a[c]));let o=n.skin===void 0?Promise.resolve(null):s.getDependency("skin",n.skin);return Promise.all([r,Promise.all(i),o]).then(function(c){let u=c[0],l=c[1],d=c[2];d!==null&&u.traverse(function(h){h.isSkinnedMesh&&h.bind(d,Ft)});for(let h=0,p=l.length;h<p;h++)u.add(l[h]);if(u.userData.pivot!==void 0&&l.length>0){let h=u.userData.pivot,p=l[0];u.pivot=new N().fromArray(h),u.position.x-=h[0],u.position.y-=h[1],u.position.z-=h[2],p.position.set(0,0,0),delete u.userData.pivot}return u})}_loadNodeShallow(t){let e=this.json,s=this.extensions,n=this;if(this.nodeCache[t]!==void 0)return this.nodeCache[t];let r=e.nodes[t],i=r.name?n.createUniqueName(r.name):"",a=[],o=n._invokeOne(function(c){return c.createNodeMesh&&c.createNodeMesh(t)});return o&&a.push(o),r.camera!==void 0&&a.push(n.getDependency("camera",r.camera).then(function(c){return n._getNodeRef(n.cameraCache,r.camera,c)})),n._invokeAll(function(c){return c.createNodeAttachment&&c.createNodeAttachment(t)}).forEach(function(c){a.push(c)}),this.nodeCache[t]=Promise.all(a).then(function(c){let u;if(r.isBone===!0?u=new it:c.length>1?u=new q:c.length===1?u=c[0]:u=new oe,u!==c[0])for(let l=0,d=c.length;l<d;l++)u.add(c[l]);if(r.name&&(u.userData.name=r.name,u.name=i),I(u,r),r.extensions&&v(s,u,r),r.matrix!==void 0){let l=new z;l.fromArray(r.matrix),u.applyMatrix4(l)}else r.translation!==void 0&&u.position.fromArray(r.translation),r.rotation!==void 0&&u.quaternion.fromArray(r.rotation),r.scale!==void 0&&u.scale.fromArray(r.scale);if(!n.associations.has(u))n.associations.set(u,{});else if(r.mesh!==void 0&&n.meshCache.refs[r.mesh]>1){let l=n.associations.get(u);n.associations.set(u,{...l})}return n.associations.get(u).nodes=t,u}),this.nodeCache[t]}loadScene(t){let e=this.extensions,s=this.json.scenes[t],n=this,r=new q;s.name&&(r.name=n.createUniqueName(s.name)),I(r,s),s.extensions&&v(e,r,s);let i=s.nodes||[],a=[];for(let o=0,c=i.length;o<c;o++)a.push(n.getDependency("node",i[o]));return Promise.all(a).then(function(o){for(let u=0,l=o.length;u<l;u++){let d=o[u];d.parent!==null?r.add(bt(d)):r.add(d)}let c=u=>{let l=new Map;for(let[d,h]of n.associations)(d instanceof Y||d instanceof ie)&&l.set(d,h);return u.traverse(d=>{let h=n.associations.get(d);h!=null&&l.set(d,h)}),l};return n.associations=c(r),r})}_createAnimationTracks(t,e,s,n,r){let i=[],a=t.name?t.name:t.uuid,o=[];function c(h){h.morphTargetInfluences&&o.push(h.name?h.name:h.uuid)}C[r.path]===C.weights?(c(t),t.isGroup&&t.children.forEach(c)):o.push(a);let u;switch(C[r.path]){case C.weights:u=de;break;case C.rotation:u=he;break;case C.translation:case C.scale:u=pe;break;default:s.itemSize===1?u=de:u=pe;break}let l=n.interpolation!==void 0?Ht[n.interpolation]:te,d=this._getArrayFromAccessor(s);for(let h=0,p=o.length;h<p;h++){let A=new u(o[h]+"."+C[r.path],e.array,d,l);n.interpolation==="CUBICSPLINE"&&this._createCubicSplineTrackInterpolant(A),i.push(A)}return i}_getArrayFromAccessor(t){let e=t.array;if(t.normalized){let s=Ke(e.constructor),n=new Float32Array(e.length);for(let r=0,i=e.length;r<i;r++)n[r]=e[r]*s;e=n}return e}_createCubicSplineTrackInterpolant(t){t.createInterpolant=function(s){let n=this instanceof he?ze:Z;return new n(this.times,this.values,this.getValueSize()/3,s)},t.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline=!0}};function zt(f,t,e){let s=t.attributes,n=new tt;if(s.POSITION!==void 0){let a=e.json.accessors[s.POSITION],o=a.min,c=a.max;if(o!==void 0&&c!==void 0){if(n.set(new N(o[0],o[1],o[2]),new N(c[0],c[1],c[2])),a.normalized){let u=Ke(D[a.componentType]);n.min.multiplyScalar(u),n.max.multiplyScalar(u)}}else{console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.");return}}else return;let r=t.targets;if(r!==void 0){let a=new N,o=new N;for(let c=0,u=r.length;c<u;c++){let l=r[c];if(l.POSITION!==void 0){let d=e.json.accessors[l.POSITION],h=d.min,p=d.max;if(h!==void 0&&p!==void 0){if(o.setX(Math.max(Math.abs(h[0]),Math.abs(p[0]))),o.setY(Math.max(Math.abs(h[1]),Math.abs(p[1]))),o.setZ(Math.max(Math.abs(h[2]),Math.abs(p[2]))),d.normalized){let A=Ke(D[d.componentType]);o.multiplyScalar(A)}a.max(o)}else console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.")}}n.expandByVector(a)}f.boundingBox=n;let i=new nt;n.getCenter(i.center),i.radius=n.min.distanceTo(n.max)/2,f.boundingSphere=i}function Lt(f,t,e){let s=t.attributes,n=[];function r(i,a){return e.getDependency("accessor",i).then(function(o){f.setAttribute(a,o)})}for(let i in s){let a=Ge[i]||i.toLowerCase();a in f.attributes||n.push(r(s[i],a))}if(t.indices!==void 0&&!f.index){let i=e.getDependency("accessor",t.indices).then(function(a){f.setIndex(a)});n.push(i)}return re.workingColorSpace!==M&&"COLOR_0"in s&&console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${re.workingColorSpace}" not supported.`),I(f,t),zt(f,t,e),Promise.all(n).then(function(){return t.targets!==void 0?Pt(f,t.targets,e):f})}export{St as GLTFLoader};
|
|
2
|
+
//# sourceMappingURL=GLTFLoader-PGXD4V5B.js.map
|