@limrun/ui 0.18.2 → 0.20.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/README.md CHANGED
@@ -16,6 +16,76 @@ logo is omitted. Pass your own images through the `assets` prop if you want fram
16
16
  `onConnectionStateChange` reports `connecting`, `connected`, `reconnecting`, `failed`, and
17
17
  `terminated` so a host can show status text without tracking the retry logic.
18
18
 
19
+ ## Playback buffering
20
+
21
+ `jitterBufferTargetMs` sets a preferred browser jitter buffer duration for incoming
22
+ audio and video on Android and iOS streams. It accepts finite numbers from 0 to
23
+ 4000 milliseconds. For example:
24
+
25
+ ```tsx
26
+ <RemoteControl url={instanceWebsocketUrl} token={instanceToken} jitterBufferTargetMs={50} />
27
+ ```
28
+
29
+ The default is the browser's automatic buffering. Changing the prop updates active
30
+ receivers without reconnecting and applies to new receivers after a reconnect.
31
+ Remove the prop or set it to `null` to restore automatic buffering. Browsers without
32
+ `RTCRtpReceiver.jitterBufferTarget` ignore the prop. Invalid values produce a console
33
+ warning and leave the receiver's previous target unchanged.
34
+
35
+ The target is a preference, not a maximum buffer size or an end-to-end latency
36
+ guarantee. A lower value can reduce playback delay but increase dropped frames,
37
+ freezes, or audio interruptions on unstable connections. The browser can use a
38
+ different duration and can adjust gradually. Compare first-frame latency after idle,
39
+ steady playback, and drops or freezes on your target browsers and networks before
40
+ choosing a value. The example's 50 ms is not a recommended default.
41
+
42
+ ## Playback measurements
43
+
44
+ Pass `onPlaybackStats` to receive browser measurements for incoming iOS and
45
+ Android streams, including phones, tablets, Apple Watch, and both Duo displays.
46
+ The callback and its types are available from `@limrun/ui` and `@limrun/ui/lite`.
47
+
48
+ ```tsx
49
+ import { useState } from 'react';
50
+ import { RemoteControl, type PlaybackStats } from '@limrun/ui';
51
+
52
+ function Player({ url, token }: { url: string; token: string }) {
53
+ const [stats, setStats] = useState<PlaybackStats | null>(null);
54
+ const primary = stats?.video.find((video) => video.display === 'primary');
55
+ return (
56
+ <>
57
+ <RemoteControl url={url} token={token} onPlaybackStats={setStats} />
58
+ <output>Buffer delay: {primary?.bufferDelayMs?.toFixed(1) ?? '—'} ms</output>
59
+ </>
60
+ );
61
+ }
62
+ ```
63
+
64
+ Collection uses the existing connection about every two seconds while the callback
65
+ is set and the tab is visible. Removing the callback stops collection. A disconnect,
66
+ hidden tab, or collection error emits `null` once after a measurement. Resuming or
67
+ reconnecting starts a fresh baseline. Changing the callback function does not reconnect
68
+ or restart collection. No stats requests run without a subscriber.
69
+
70
+ `PlaybackStats` contains `video` and `audio` arrays, a Unix-millisecond `timestamp`,
71
+ `requestedTargetMs`, and optional selected-connection `rttMs`. A `null` target means
72
+ automatic buffering. An invalid target prop leaves this field undefined. The requested
73
+ target does not confirm browser support or the duration actually used.
74
+
75
+ Each track has `id`, `trackId`, `timestamp`, and optional `intervalMs`,
76
+ `bufferDelayMs`, and `bitrateBps`. Video adds `display`, `fps`, `droppedFrames`, and
77
+ `freezes`. Duo's `primary` and `inner` displays stay separate. Audio is empty when
78
+ the connection has no incoming audio stream. Camera and microphone uploads are excluded.
79
+
80
+ Rates and counts describe the interval since that stream's previous sample.
81
+ Buffer delay divides the change in accumulated jitter-buffer delay by the change
82
+ in emitted frames or audio samples. FPS uses decoded frames; freezes count only
83
+ browser-reported freezes that have completed. Missing browser fields, the first
84
+ sample, and reset counters leave affected measurements undefined. A buffer with
85
+ no emitted frames has no delay measurement; it is not zero. Static screens may
86
+ have low FPS. These measurements do not include tap-to-screen latency or server
87
+ encoding time.
88
+
19
89
  ## Simulated cameras
20
90
 
21
91
  `RemoteControl` responds automatically when an app in the instance opens,
@@ -118,3 +188,106 @@ Hardware meshes under `stationary-half` must carry `extras.button` with
118
188
  `side`, `volumeUp`, or `volumeDown`. All three are required. This is a prepared Duo
119
189
  appearance contract, not a general-purpose GLB viewer. Serve the file on the same
120
190
  origin or with suitable CORS headers.
191
+
192
+ ## Build a custom device viewer
193
+
194
+ Import `createDeviceStream` from `@limrun/ui/core` when you supply your own UI.
195
+ This browser entry has no React, CSS, or device-artwork imports. It uses the same
196
+ connection, input, playback, camera, microphone, and accessibility implementation
197
+ as `RemoteControl`. A browser WebView can use it too; it is not a Node.js WebRTC client.
198
+
199
+ Attach your video element before starting the session. Use the instance WebSocket
200
+ URL and instance token returned by the Limrun API, not your organization API key.
201
+
202
+ ```ts
203
+ import { createDeviceStream } from '@limrun/ui/core';
204
+
205
+ function mountDevice(video: HTMLVideoElement, url: string, token: string) {
206
+ video.autoplay = true;
207
+ video.playsInline = true;
208
+ video.muted = true;
209
+
210
+ const stream = createDeviceStream({
211
+ url,
212
+ token,
213
+ autoReconnect: true,
214
+ onStateChange: (state) => console.log(state.connection, state.controlReady),
215
+ onPlaybackStats: (stats) => console.log(stats),
216
+ });
217
+ stream.attachVideo(video);
218
+ stream.start();
219
+
220
+ return {
221
+ home: () => stream.pressButton('home'),
222
+ screenshot: () => stream.screenshot(),
223
+ unmount: () => stream.dispose(),
224
+ };
225
+ }
226
+ ```
227
+
228
+ For a canvas or texture renderer, replace `attachVideo` with `attachFrameSink`.
229
+ The core owns the video element and playback workaround, then delivers decoded
230
+ frames. The frame is borrowed: draw or copy it before `present` returns.
231
+
232
+ ```ts
233
+ stream.attachFrameSink({
234
+ present(source, width, height) {
235
+ if (canvas.width !== width) canvas.width = width;
236
+ if (canvas.height !== height) canvas.height = height;
237
+ canvas.getContext('2d')?.drawImage(source, 0, 0, width, height);
238
+ },
239
+ });
240
+ ```
241
+
242
+ Both attachment methods return a detach function. `stop()` closes the connection
243
+ and releases capture devices while retaining renderer attachments for `start()`.
244
+ `dispose()` also detaches every renderer and permanently closes the client.
245
+ Neither method terminates the Limrun instance.
246
+
247
+ Map your pointer events to frame pixels and call
248
+ `sendTouch(phase, x, y, width, height, pointerId)`. The phases are `begin`, `move`,
249
+ and `end`. Use `sendKeyEvent`, `sendText`, `pressButton`, and `rotate` for other
250
+ input. `sendControl` accepts messages built by the exported protocol helpers.
251
+
252
+ For Duo devices, attach a second renderer with display `'inner'`. The core
253
+ negotiates both tracks and reports the native display geometry through
254
+ `getState().duoState` and `onStateChange`. Use `sendDisplayTouch` with the native
255
+ `screenId` for panel input, or `sendDuoControl` for hinge and orientation commands.
256
+
257
+ Enable accessibility polling with `inspectMode: true`, receive snapshots with
258
+ `onAxSnapshotChange`, and request a fresh tree with `refreshAxTree()`. Camera and
259
+ microphone demand use the same browser permission prompts and callbacks as
260
+ `RemoteControl`. Your application remains responsible for instance creation and
261
+ termination, UI gestures, and any accessibility overlay.
262
+
263
+ ### Connect through your own proxy
264
+
265
+ Supply a transport when your backend authenticates the upstream WebSocket.
266
+ Return a fresh socket on each call, since reconnects call `connect()` again.
267
+ The client owns and closes that socket. Supply `platform` explicitly because a
268
+ proxy URL does not identify the device kind.
269
+
270
+ ```ts
271
+ const stream = createDeviceStream({
272
+ platform: 'ios',
273
+ autoReconnect: true,
274
+ transport: {
275
+ connect: () => new WebSocket(authenticatedProxyUrl),
276
+ },
277
+ });
278
+ ```
279
+
280
+ The proxy forwards Limrun's signaling messages unchanged. Video and control data
281
+ still travel over WebRTC. The core does not append a Limrun token to a custom
282
+ transport URL. You can fetch a fresh proxy ticket inside an asynchronous
283
+ `connect()` implementation.
284
+
285
+ If your backend can authoritatively report instance termination, implement
286
+ `transport.isTerminated(): Promise<boolean>`. Without it, proxy failures use the
287
+ normal retry policy. The core does not infer termination from a proxy's HTTP status.
288
+
289
+ Call `updateOptions` to change callbacks, accessibility polling, microphone
290
+ capture, reconnect policy, or the jitter buffer preference without replacing the
291
+ connection. A newly enabled `onTrace` callback takes effect on the next reconnect,
292
+ because tracing requires negotiation. Create a new client when changing the
293
+ instance, transport, platform, or session ID.
@@ -1,4 +1,4 @@
1
- import { L as Ae, a as G, F as he, M as w, V as fe, C as F, b, S as U, c as Le, P as Me, D as Se, d as K, e as C, I as ye, Q as de, f as we, O as pe, T as be, g as Ne, B as V, h as Ie, i as me, N as Oe, j as Ce, k as Fe, l as Q, m as ge, R as J, n as Pe, o as ke, p as He, q as z, r as De, s as Te, t as ve, u as v, v as Ge, w as Ue, x as Ke, y as Be, z as ee, A as je, E as Ve, G as ze, H as Xe, J as X, K as qe, U as We, W as Ye, X as Qe, Y as Je, Z as Ze, _ as $e, $ as Re, a0 as en, a1 as ne, a2 as te, a3 as se, a4 as ie, a5 as re, a6 as nn, a7 as tn, a8 as sn, a9 as rn, aa as on, ab as an } from "./duo-frame-B6jf62Rq.mjs";
1
+ import { L as Ae, a as G, F as he, M as w, V as fe, C as F, b, S as U, c as Le, P as Me, D as Se, d as K, e as C, I as ye, Q as de, f as we, O as pe, T as be, g as Ne, B as V, h as Ie, i as me, N as Oe, j as Ce, k as Fe, l as Q, m as ge, R as J, n as Pe, o as ke, p as He, q as z, r as De, s as Te, t as ve, u as v, v as Ge, w as Ue, x as Ke, y as Be, z as ee, A as je, E as Ve, G as ze, H as Xe, J as X, K as qe, U as We, W as Ye, X as Qe, Y as Je, Z as Ze, _ as $e, $ as Re, a0 as en, a1 as ne, a2 as te, a3 as se, a4 as ie, a5 as re, a6 as nn, a7 as tn, a8 as sn, a9 as rn, aa as on, ab as an } from "./duo-frame-CMiDITQA.mjs";
2
2
  function cn(f) {
3
3
  const n = /* @__PURE__ */ new Map(), e = /* @__PURE__ */ new Map(), t = f.clone();
4
4
  return Ee(f, t, function(s, i) {
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("./duo-frame-DAmRgZuT.js");function Q(d){const t=new Map,e=new Map,n=d.clone();return q(d,n,function(s,r){t.set(r,s),e.set(s,r)}),n.traverse(function(s){if(!s.isSkinnedMesh)return;const r=s,o=t.get(s),a=o.skeleton.bones;r.skeleton=o.skeleton.clone(),r.bindMatrix.copy(o.bindMatrix),r.skeleton.bones=a.map(function(i){return e.get(i)}),r.bind(r.skeleton,r.bindMatrix)}),n}function q(d,t,e){e(d,t);for(let n=0;n<d.children.length;n++)q(d.children[n],t.children[n],e)}class J extends h.Loader{constructor(t){super(t),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register(function(e){return new ne(e)}),this.register(function(e){return new se(e)}),this.register(function(e){return new fe(e)}),this.register(function(e){return new de(e)}),this.register(function(e){return new pe(e)}),this.register(function(e){return new ie(e)}),this.register(function(e){return new oe(e)}),this.register(function(e){return new ae(e)}),this.register(function(e){return new ce(e)}),this.register(function(e){return new te(e)}),this.register(function(e){return new le(e)}),this.register(function(e){return new re(e)}),this.register(function(e){return new he(e)}),this.register(function(e){return new ue(e)}),this.register(function(e){return new $(e)}),this.register(function(e){return new K(e,T.EXT_MESHOPT_COMPRESSION)}),this.register(function(e){return new K(e,T.KHR_MESHOPT_COMPRESSION)}),this.register(function(e){return new me(e)})}load(t,e,n,s){const r=this;let o;if(this.resourcePath!=="")o=this.resourcePath;else if(this.path!==""){const c=h.LoaderUtils.extractUrlBase(t);o=h.LoaderUtils.resolveURL(c,this.path)}else o=h.LoaderUtils.extractUrlBase(t);this.manager.itemStart(t);const a=function(c){s?s(c):console.error(c),r.manager.itemError(t),r.manager.itemEnd(t)},i=new h.FileLoader(this.manager);i.setPath(this.path),i.setResponseType("arraybuffer"),i.setRequestHeader(this.requestHeader),i.setWithCredentials(this.withCredentials),i.load(t,function(c){try{r.parse(c,o,function(u){e(u),r.manager.itemEnd(t)},a)}catch(u){a(u)}},n,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,n,s){let r;const o={},a={},i=new TextDecoder;if(typeof t=="string")r=JSON.parse(t);else if(t instanceof ArrayBuffer)if(i.decode(new Uint8Array(t,0,4))===W){try{o[T.KHR_BINARY_GLTF]=new ge(t)}catch(l){s&&s(l);return}r=JSON.parse(o[T.KHR_BINARY_GLTF].content)}else r=JSON.parse(i.decode(t));else r=t;if(r.asset===void 0||r.asset.version[0]<2){s&&s(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported."));return}const c=new Ne(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++){const l=this.pluginCallbacks[u](c);l.name||console.error("THREE.GLTFLoader: Invalid plugin found: missing name"),a[l.name]=l,o[l.name]=!0}if(r.extensionsUsed)for(let u=0;u<r.extensionsUsed.length;++u){const l=r.extensionsUsed[u],f=r.extensionsRequired||[];switch(l){case T.KHR_MATERIALS_UNLIT:o[l]=new ee;break;case T.KHR_DRACO_MESH_COMPRESSION:o[l]=new Te(r,this.dracoLoader);break;case T.KHR_TEXTURE_TRANSFORM:o[l]=new Re;break;case T.KHR_MESH_QUANTIZATION:o[l]=new Me;break;default:f.indexOf(l)>=0&&a[l]===void 0&&console.warn('THREE.GLTFLoader: Unknown extension "'+l+'".')}}c.setExtensions(o),c.setPlugins(a),c.parse(n,s)}parseAsync(t,e){const n=this;return new Promise(function(s,r){n.parse(t,e,s,r)})}}function Z(){let d={};return{get:function(t){return d[t]},add:function(t,e){d[t]=e},remove:function(t){delete d[t]},removeAll:function(){d={}}}}function _(d,t,e){const n=d.json.materials[t];return n.extensions&&n.extensions[e]?n.extensions[e]:null}const T={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"};class ${constructor(t){this.parser=t,this.name=T.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){const t=this.parser,e=this.parser.json.nodes||[];for(let n=0,s=e.length;n<s;n++){const r=e[n];r.extensions&&r.extensions[this.name]&&r.extensions[this.name].light!==void 0&&t._addNodeRef(this.cache,r.extensions[this.name].light)}}_loadLight(t){const e=this.parser,n="light:"+t;let s=e.cache.get(n);if(s)return s;const r=e.json,i=((r.extensions&&r.extensions[this.name]||{}).lights||[])[t];let c;const u=new h.Color(16777215);i.color!==void 0&&u.setRGB(i.color[0],i.color[1],i.color[2],h.LinearSRGBColorSpace);const l=i.range!==void 0?i.range:0;switch(i.type){case"directional":c=new h.DirectionalLight(u),c.target.position.set(0,0,-1),c.add(c.target);break;case"point":c=new h.PointLight(u),c.distance=l;break;case"spot":c=new h.SpotLight(u),c.distance=l,i.spot=i.spot||{},i.spot.innerConeAngle=i.spot.innerConeAngle!==void 0?i.spot.innerConeAngle:0,i.spot.outerConeAngle=i.spot.outerConeAngle!==void 0?i.spot.outerConeAngle:Math.PI/4,c.angle=i.spot.outerConeAngle,c.penumbra=1-i.spot.innerConeAngle/i.spot.outerConeAngle,c.target.position.set(0,0,-1),c.add(c.target);break;default:throw new Error("THREE.GLTFLoader: Unexpected light type: "+i.type)}return c.position.set(0,0,0),w(c,i),i.intensity!==void 0&&(c.intensity=i.intensity),c.name=e.createUniqueName(i.name||"light_"+t),s=Promise.resolve(c),e.cache.add(n,s),s}getDependency(t,e){if(t==="light")return this._loadLight(e)}createNodeAttachment(t){const e=this,n=this.parser,r=n.json.nodes[t],a=(r.extensions&&r.extensions[this.name]||{}).light;return a===void 0?null:this._loadLight(a).then(function(i){return n._getNodeRef(e.cache,a,i)})}}class ee{constructor(){this.name=T.KHR_MATERIALS_UNLIT}getMaterialType(){return h.MeshBasicMaterial}extendParams(t,e,n){const s=[];t.color=new h.Color(1,1,1),t.opacity=1;const r=e.pbrMetallicRoughness;if(r){if(Array.isArray(r.baseColorFactor)){const o=r.baseColorFactor;t.color.setRGB(o[0],o[1],o[2],h.LinearSRGBColorSpace),t.opacity=o[3]}r.baseColorTexture!==void 0&&s.push(n.assignTexture(t,"map",r.baseColorTexture,h.SRGBColorSpace))}return Promise.all(s)}}class te{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_EMISSIVE_STRENGTH}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);return n===null||n.emissiveStrength!==void 0&&(e.emissiveIntensity=n.emissiveStrength),Promise.resolve()}}class ne{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_CLEARCOAT}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];if(n.clearcoatFactor!==void 0&&(e.clearcoat=n.clearcoatFactor),n.clearcoatTexture!==void 0&&s.push(this.parser.assignTexture(e,"clearcoatMap",n.clearcoatTexture)),n.clearcoatRoughnessFactor!==void 0&&(e.clearcoatRoughness=n.clearcoatRoughnessFactor),n.clearcoatRoughnessTexture!==void 0&&s.push(this.parser.assignTexture(e,"clearcoatRoughnessMap",n.clearcoatRoughnessTexture)),n.clearcoatNormalTexture!==void 0&&(s.push(this.parser.assignTexture(e,"clearcoatNormalMap",n.clearcoatNormalTexture)),n.clearcoatNormalTexture.scale!==void 0)){const r=n.clearcoatNormalTexture.scale;e.clearcoatNormalScale=new h.Vector2(r,r)}return Promise.all(s)}}class se{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_DISPERSION}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);return n===null||(e.dispersion=n.dispersion!==void 0?n.dispersion:0),Promise.resolve()}}class re{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_IRIDESCENCE}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];return n.iridescenceFactor!==void 0&&(e.iridescence=n.iridescenceFactor),n.iridescenceTexture!==void 0&&s.push(this.parser.assignTexture(e,"iridescenceMap",n.iridescenceTexture)),n.iridescenceIor!==void 0&&(e.iridescenceIOR=n.iridescenceIor),e.iridescenceThicknessRange===void 0&&(e.iridescenceThicknessRange=[100,400]),n.iridescenceThicknessMinimum!==void 0&&(e.iridescenceThicknessRange[0]=n.iridescenceThicknessMinimum),n.iridescenceThicknessMaximum!==void 0&&(e.iridescenceThicknessRange[1]=n.iridescenceThicknessMaximum),n.iridescenceThicknessTexture!==void 0&&s.push(this.parser.assignTexture(e,"iridescenceThicknessMap",n.iridescenceThicknessTexture)),Promise.all(s)}}class ie{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_SHEEN}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];if(e.sheenColor=new h.Color(0,0,0),e.sheenRoughness=0,e.sheen=1,n.sheenColorFactor!==void 0){const r=n.sheenColorFactor;e.sheenColor.setRGB(r[0],r[1],r[2],h.LinearSRGBColorSpace)}return n.sheenRoughnessFactor!==void 0&&(e.sheenRoughness=n.sheenRoughnessFactor),n.sheenColorTexture!==void 0&&s.push(this.parser.assignTexture(e,"sheenColorMap",n.sheenColorTexture,h.SRGBColorSpace)),n.sheenRoughnessTexture!==void 0&&s.push(this.parser.assignTexture(e,"sheenRoughnessMap",n.sheenRoughnessTexture)),Promise.all(s)}}class oe{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_TRANSMISSION}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];return n.transmissionFactor!==void 0&&(e.transmission=n.transmissionFactor),n.transmissionTexture!==void 0&&s.push(this.parser.assignTexture(e,"transmissionMap",n.transmissionTexture)),Promise.all(s)}}class ae{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_VOLUME}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];e.thickness=n.thicknessFactor!==void 0?n.thicknessFactor:0,n.thicknessTexture!==void 0&&s.push(this.parser.assignTexture(e,"thicknessMap",n.thicknessTexture)),e.attenuationDistance=n.attenuationDistance||1/0;const r=n.attenuationColor||[1,1,1];return e.attenuationColor=new h.Color().setRGB(r[0],r[1],r[2],h.LinearSRGBColorSpace),Promise.all(s)}}class ce{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_IOR}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);return n===null||(e.ior=n.ior!==void 0?n.ior:1.5),Promise.resolve()}}class le{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_SPECULAR}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];e.specularIntensity=n.specularFactor!==void 0?n.specularFactor:1,n.specularTexture!==void 0&&s.push(this.parser.assignTexture(e,"specularIntensityMap",n.specularTexture));const r=n.specularColorFactor||[1,1,1];return e.specularColor=new h.Color().setRGB(r[0],r[1],r[2],h.LinearSRGBColorSpace),n.specularColorTexture!==void 0&&s.push(this.parser.assignTexture(e,"specularColorMap",n.specularColorTexture,h.SRGBColorSpace)),Promise.all(s)}}class ue{constructor(t){this.parser=t,this.name=T.EXT_MATERIALS_BUMP}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];return e.bumpScale=n.bumpFactor!==void 0?n.bumpFactor:1,n.bumpTexture!==void 0&&s.push(this.parser.assignTexture(e,"bumpMap",n.bumpTexture)),Promise.all(s)}}class he{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_ANISOTROPY}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];return n.anisotropyStrength!==void 0&&(e.anisotropy=n.anisotropyStrength),n.anisotropyRotation!==void 0&&(e.anisotropyRotation=n.anisotropyRotation),n.anisotropyTexture!==void 0&&s.push(this.parser.assignTexture(e,"anisotropyMap",n.anisotropyTexture)),Promise.all(s)}}class fe{constructor(t){this.parser=t,this.name=T.KHR_TEXTURE_BASISU}loadTexture(t){const e=this.parser,n=e.json,s=n.textures[t];if(!s.extensions||!s.extensions[this.name])return null;const r=s.extensions[this.name],o=e.options.ktx2Loader;if(!o){if(n.extensionsRequired&&n.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,o)}}class de{constructor(t){this.parser=t,this.name=T.EXT_TEXTURE_WEBP}loadTexture(t){const e=this.name,n=this.parser,s=n.json,r=s.textures[t];if(!r.extensions||!r.extensions[e])return null;const o=r.extensions[e],a=s.images[o.source];let i=n.textureLoader;if(a.uri){const c=n.options.manager.getHandler(a.uri);c!==null&&(i=c)}return n.loadTextureImage(t,o.source,i)}}class pe{constructor(t){this.parser=t,this.name=T.EXT_TEXTURE_AVIF}loadTexture(t){const e=this.name,n=this.parser,s=n.json,r=s.textures[t];if(!r.extensions||!r.extensions[e])return null;const o=r.extensions[e],a=s.images[o.source];let i=n.textureLoader;if(a.uri){const c=n.options.manager.getHandler(a.uri);c!==null&&(i=c)}return n.loadTextureImage(t,o.source,i)}}class K{constructor(t,e){this.name=e,this.parser=t}loadBufferView(t){const e=this.parser.json,n=e.bufferViews[t];if(n.extensions&&n.extensions[this.name]){const s=n.extensions[this.name],r=this.parser.getDependency("buffer",s.buffer),o=this.parser.options.meshoptDecoder;if(!o||!o.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){const i=s.byteOffset||0,c=s.byteLength||0,u=s.count,l=s.byteStride,f=new Uint8Array(a,i,c);return o.decodeGltfBufferAsync?o.decodeGltfBufferAsync(u,l,f,s.mode,s.filter).then(function(p){return p.buffer}):o.ready.then(function(){const p=new ArrayBuffer(u*l);return o.decodeGltfBuffer(new Uint8Array(p),u,l,f,s.mode,s.filter),p})})}else return null}}class me{constructor(t){this.name=T.EXT_MESH_GPU_INSTANCING,this.parser=t}createNodeMesh(t){const e=this.parser.json,n=e.nodes[t];if(!n.extensions||!n.extensions[this.name]||n.mesh===void 0)return null;const s=e.meshes[n.mesh];for(const c of s.primitives)if(c.mode!==S.TRIANGLES&&c.mode!==S.TRIANGLE_STRIP&&c.mode!==S.TRIANGLE_FAN&&c.mode!==void 0)return null;const o=n.extensions[this.name].attributes,a=[],i={};for(const c in o)a.push(this.parser.getDependency("accessor",o[c]).then(u=>(i[c]=u,i[c])));return a.length<1?null:(a.push(this.parser.createNodeMesh(t)),Promise.all(a).then(c=>{const u=c.pop(),l=u.isGroup?u.children:[u],f=c[0].count,p=[];for(const m of l){const M=new h.Matrix4,g=new h.Vector3,R=new h.Quaternion,A=new h.Vector3(1,1,1),x=new h.InstancedMesh(m.geometry,m.material,f);for(let E=0;E<f;E++)i.TRANSLATION&&g.fromBufferAttribute(i.TRANSLATION,E),i.ROTATION&&R.fromBufferAttribute(i.ROTATION,E),i.SCALE&&A.fromBufferAttribute(i.SCALE,E),x.setMatrixAt(E,M.compose(g,R,A));for(const E in i)if(E==="_COLOR_0"){const L=i[E];x.instanceColor=new h.InstancedBufferAttribute(L.array,L.itemSize,L.normalized)}else E!=="TRANSLATION"&&E!=="ROTATION"&&E!=="SCALE"&&m.geometry.setAttribute(E,i[E]);h.Object3D.prototype.copy.call(x,m),this.parser.assignFinalMaterial(x),p.push(x)}return u.isGroup?(u.clear(),u.add(...p),u):p[0]}))}}const W="glTF",F=12,j={JSON:1313821514,BIN:5130562};class ge{constructor(t){this.name=T.KHR_BINARY_GLTF,this.content=null,this.body=null;const e=new DataView(t,0,F),n=new TextDecoder;if(this.header={magic:n.decode(new Uint8Array(t.slice(0,4))),version:e.getUint32(4,!0),length:e.getUint32(8,!0)},this.header.magic!==W)throw new Error("THREE.GLTFLoader: Unsupported glTF-Binary header.");if(this.header.version<2)throw new Error("THREE.GLTFLoader: Legacy binary file detected.");const s=this.header.length-F,r=new DataView(t,F);let o=0;for(;o<s;){const a=r.getUint32(o,!0);o+=4;const i=r.getUint32(o,!0);if(o+=4,i===j.JSON){const c=new Uint8Array(t,F+o,a);this.content=n.decode(c)}else if(i===j.BIN){const c=F+o;this.body=t.slice(c,c+a)}o+=a}if(this.content===null)throw new Error("THREE.GLTFLoader: JSON content not found.")}}class Te{constructor(t,e){if(!e)throw new Error("THREE.GLTFLoader: No DRACOLoader instance provided.");this.name=T.KHR_DRACO_MESH_COMPRESSION,this.json=t,this.dracoLoader=e,this.dracoLoader.preload()}decodePrimitive(t,e){const n=this.json,s=this.dracoLoader,r=t.extensions[this.name].bufferView,o=t.extensions[this.name].attributes,a={},i={},c={};for(const u in o){const l=B[u]||u.toLowerCase();a[l]=o[u]}for(const u in t.attributes){const l=B[u]||u.toLowerCase();if(o[u]!==void 0){const f=n.accessors[t.attributes[u]],p=O[f.componentType];c[l]=p.name,i[l]=f.normalized===!0}}return e.getDependency("bufferView",r).then(function(u){return new Promise(function(l,f){s.decodeDracoFile(u,function(p){for(const m in p.attributes){const M=p.attributes[m],g=i[m];g!==void 0&&(M.normalized=g)}l(p)},a,c,h.LinearSRGBColorSpace,f)})})}}class Re{constructor(){this.name=T.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}}class Me{constructor(){this.name=T.KHR_MESH_QUANTIZATION}}class Y extends h.Interpolant{constructor(t,e,n,s){super(t,e,n,s)}copySampleValue_(t){const e=this.resultBuffer,n=this.sampleValues,s=this.valueSize,r=t*s*3+s;for(let o=0;o!==s;o++)e[o]=n[r+o];return e}interpolate_(t,e,n,s){const r=this.resultBuffer,o=this.sampleValues,a=this.valueSize,i=a*2,c=a*3,u=s-e,l=(n-e)/u,f=l*l,p=f*l,m=t*c,M=m-c,g=-2*p+3*f,R=p-f,A=1-g,x=R-f+l;for(let E=0;E!==a;E++){const L=o[M+E+a],b=o[M+E+i]*u,y=o[m+E+a],P=o[m+E]*u;r[E]=A*L+x*b+g*y+R*P}return r}}const Ee=new h.Quaternion;class xe extends Y{interpolate_(t,e,n,s){const r=super.interpolate_(t,e,n,s);return Ee.fromArray(r).normalize().toArray(r),r}}const S={POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6},O={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array},V={9728:h.NearestFilter,9729:h.LinearFilter,9984:h.NearestMipmapNearestFilter,9985:h.LinearMipmapNearestFilter,9986:h.NearestMipmapLinearFilter,9987:h.LinearMipmapLinearFilter},z={33071:h.ClampToEdgeWrapping,33648:h.MirroredRepeatWrapping,10497:h.RepeatWrapping},D={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16},B={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"},N={scale:"scale",translation:"position",rotation:"quaternion",weights:"morphTargetInfluences"},Ae={CUBICSPLINE:void 0,LINEAR:h.InterpolateLinear,STEP:h.InterpolateDiscrete},G={OPAQUE:"OPAQUE",MASK:"MASK",BLEND:"BLEND"};function _e(d){return d.DefaultMaterial===void 0&&(d.DefaultMaterial=new h.MeshStandardMaterial({color:16777215,emissive:0,metalness:1,roughness:1,transparent:!1,depthTest:!0,side:h.FrontSide})),d.DefaultMaterial}function I(d,t,e){for(const n in e.extensions)d[n]===void 0&&(t.userData.gltfExtensions=t.userData.gltfExtensions||{},t.userData.gltfExtensions[n]=e.extensions[n])}function w(d,t){t.extras!==void 0&&(typeof t.extras=="object"?Object.assign(d.userData,t.extras):console.warn("THREE.GLTFLoader: Ignoring primitive type .extras, "+t.extras))}function Le(d,t,e){let n=!1,s=!1,r=!1;for(let c=0,u=t.length;c<u;c++){const l=t[c];if(l.POSITION!==void 0&&(n=!0),l.NORMAL!==void 0&&(s=!0),l.COLOR_0!==void 0&&(r=!0),n&&s&&r)break}if(!n&&!s&&!r)return Promise.resolve(d);const o=[],a=[],i=[];for(let c=0,u=t.length;c<u;c++){const l=t[c];if(n){const f=l.POSITION!==void 0?e.getDependency("accessor",l.POSITION):d.attributes.position;o.push(f)}if(s){const f=l.NORMAL!==void 0?e.getDependency("accessor",l.NORMAL):d.attributes.normal;a.push(f)}if(r){const f=l.COLOR_0!==void 0?e.getDependency("accessor",l.COLOR_0):d.attributes.color;i.push(f)}}return Promise.all([Promise.all(o),Promise.all(a),Promise.all(i)]).then(function(c){const u=c[0],l=c[1],f=c[2];return n&&(d.morphAttributes.position=u),s&&(d.morphAttributes.normal=l),r&&(d.morphAttributes.color=f),d.morphTargetsRelative=!0,d})}function Se(d,t){if(d.updateMorphTargets(),t.weights!==void 0)for(let e=0,n=t.weights.length;e<n;e++)d.morphTargetInfluences[e]=t.weights[e];if(t.extras&&Array.isArray(t.extras.targetNames)){const e=t.extras.targetNames;if(d.morphTargetInfluences.length===e.length){d.morphTargetDictionary={};for(let n=0,s=e.length;n<s;n++)d.morphTargetDictionary[e[n]]=n}else console.warn("THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.")}}function ye(d){let t;const e=d.extensions&&d.extensions[T.KHR_DRACO_MESH_COMPRESSION];if(e?t="draco:"+e.bufferView+":"+e.indices+":"+v(e.attributes):t=d.indices+":"+v(d.attributes)+":"+d.mode,d.targets!==void 0)for(let n=0,s=d.targets.length;n<s;n++)t+=":"+v(d.targets[n]);return t}function v(d){let t="";const e=Object.keys(d).sort();for(let n=0,s=e.length;n<s;n++)t+=e[n]+":"+d[e[n]]+";";return t}function U(d){switch(d){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 we(d){return d.search(/\.jpe?g($|\?)/i)>0||d.search(/^data\:image\/jpeg/)===0?"image/jpeg":d.search(/\.webp($|\?)/i)>0||d.search(/^data\:image\/webp/)===0?"image/webp":d.search(/\.ktx2($|\?)/i)>0||d.search(/^data\:image\/ktx2/)===0?"image/ktx2":"image/png"}const be=new h.Matrix4;class Ne{constructor(t={},e={}){this.json=t,this.extensions={},this.plugins={},this.options=e,this.cache=new Z,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 n=!1,s=-1,r=!1,o=-1;if(typeof navigator<"u"&&typeof navigator.userAgent<"u"){const a=navigator.userAgent;n=/^((?!chrome|android).)*safari/i.test(a)===!0;const i=a.match(/Version\/(\d+)/);s=n&&i?parseInt(i[1],10):-1,r=a.indexOf("Firefox")>-1,o=r?a.match(/Firefox\/([0-9]+)\./)[1]:-1}typeof createImageBitmap>"u"||n&&s<17||r&&o<98?this.textureLoader=new h.TextureLoader(this.options.manager):this.textureLoader=new h.ImageBitmapLoader(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new h.FileLoader(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){const n=this,s=this.json,r=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll(function(o){return o._markDefs&&o._markDefs()}),Promise.all(this._invokeAll(function(o){return o.beforeRoot&&o.beforeRoot()})).then(function(){return Promise.all([n.getDependencies("scene"),n.getDependencies("animation"),n.getDependencies("camera")])}).then(function(o){const a={scene:o[0][s.scene||0],scenes:o[0],animations:o[1],cameras:o[2],asset:s.asset,parser:n,userData:{}};return I(r,a,s),w(a,s),Promise.all(n._invokeAll(function(i){return i.afterRoot&&i.afterRoot(a)})).then(function(){for(const i of a.scenes)i.updateMatrixWorld();t(a)})}).catch(e)}_markDefs(){const t=this.json.nodes||[],e=this.json.skins||[],n=this.json.meshes||[];for(let s=0,r=e.length;s<r;s++){const o=e[s].joints;for(let a=0,i=o.length;a<i;a++)t[o[a]].isBone=!0}for(let s=0,r=t.length;s<r;s++){const o=t[s];o.mesh!==void 0&&(this._addNodeRef(this.meshCache,o.mesh),o.skin!==void 0&&(n[o.mesh].isSkinnedMesh=!0)),o.camera!==void 0&&this._addNodeRef(this.cameraCache,o.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,n){if(t.refs[e]<=1)return n;const s=n.clone(),r=(o,a)=>{const i=this.associations.get(o);i!=null&&this.associations.set(a,i);for(const[c,u]of o.children.entries())r(u,a.children[c])};return r(n,s),s.name+="_instance_"+t.uses[e]++,s}_invokeOne(t){const e=Object.values(this.plugins);e.push(this);for(let n=0;n<e.length;n++){const s=t(e[n]);if(s)return s}return null}_invokeAll(t){const e=Object.values(this.plugins);e.unshift(this);const n=[];for(let s=0;s<e.length;s++){const r=t(e[s]);r&&n.push(r)}return n}getDependency(t,e){const n=t+":"+e;let s=this.cache.get(n);if(!s){switch(t){case"scene":s=this.loadScene(e);break;case"node":s=this._invokeOne(function(r){return r.loadNode&&r.loadNode(e)});break;case"mesh":s=this._invokeOne(function(r){return r.loadMesh&&r.loadMesh(e)});break;case"accessor":s=this.loadAccessor(e);break;case"bufferView":s=this._invokeOne(function(r){return r.loadBufferView&&r.loadBufferView(e)});break;case"buffer":s=this.loadBuffer(e);break;case"material":s=this._invokeOne(function(r){return r.loadMaterial&&r.loadMaterial(e)});break;case"texture":s=this._invokeOne(function(r){return r.loadTexture&&r.loadTexture(e)});break;case"skin":s=this.loadSkin(e);break;case"animation":s=this._invokeOne(function(r){return r.loadAnimation&&r.loadAnimation(e)});break;case"camera":s=this.loadCamera(e);break;default:if(s=this._invokeOne(function(r){return r!=this&&r.getDependency&&r.getDependency(t,e)}),!s)throw new Error("Unknown type: "+t);break}this.cache.add(n,s)}return s}getDependencies(t){let e=this.cache.get(t);if(!e){const n=this,s=this.json[t+(t==="mesh"?"es":"s")]||[];e=Promise.all(s.map(function(r,o){return n.getDependency(t,o)})),this.cache.add(t,e)}return e}loadBuffer(t){const e=this.json.buffers[t],n=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[T.KHR_BINARY_GLTF].body);const s=this.options;return new Promise(function(r,o){n.load(h.LoaderUtils.resolveURL(e.uri,s.path),r,void 0,function(){o(new Error('THREE.GLTFLoader: Failed to load buffer "'+e.uri+'".'))})})}loadBufferView(t){const e=this.json.bufferViews[t];return this.getDependency("buffer",e.buffer).then(function(n){const s=e.byteLength||0,r=e.byteOffset||0;return n.slice(r,r+s)})}loadAccessor(t){const e=this,n=this.json,s=this.json.accessors[t];if(s.bufferView===void 0&&s.sparse===void 0){const o=D[s.type],a=O[s.componentType],i=s.normalized===!0,c=new a(s.count*o);return Promise.resolve(new h.BufferAttribute(c,o,i))}const r=[];return s.bufferView!==void 0?r.push(this.getDependency("bufferView",s.bufferView)):r.push(null),s.sparse!==void 0&&(r.push(this.getDependency("bufferView",s.sparse.indices.bufferView)),r.push(this.getDependency("bufferView",s.sparse.values.bufferView))),Promise.all(r).then(function(o){const a=o[0],i=D[s.type],c=O[s.componentType],u=c.BYTES_PER_ELEMENT,l=u*i,f=s.byteOffset||0,p=s.bufferView!==void 0?n.bufferViews[s.bufferView].byteStride:void 0,m=s.normalized===!0;let M,g;if(p&&p!==l){const R=Math.floor(f/p),A="InterleavedBuffer:"+s.bufferView+":"+s.componentType+":"+R+":"+s.count;let x=e.cache.get(A);x||(M=new c(a,R*p,s.count*p/u),x=new h.InterleavedBuffer(M,p/u),e.cache.add(A,x)),g=new h.InterleavedBufferAttribute(x,i,f%p/u,m)}else a===null?M=new c(s.count*i):M=new c(a,f,s.count*i),g=new h.BufferAttribute(M,i,m);if(s.sparse!==void 0){const R=D.SCALAR,A=O[s.sparse.indices.componentType],x=s.sparse.indices.byteOffset||0,E=s.sparse.values.byteOffset||0,L=new A(o[1],x,s.sparse.count*R),b=new c(o[2],E,s.sparse.count*i);a!==null&&(g=new h.BufferAttribute(g.array.slice(),g.itemSize,g.normalized)),g.normalized=!1;for(let y=0,P=L.length;y<P;y++){const C=L[y];if(g.setX(C,b[y*i]),i>=2&&g.setY(C,b[y*i+1]),i>=3&&g.setZ(C,b[y*i+2]),i>=4&&g.setW(C,b[y*i+3]),i>=5)throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.")}g.normalized=m}return g})}loadTexture(t){const e=this.json,n=this.options,r=e.textures[t].source,o=e.images[r];let a=this.textureLoader;if(o.uri){const i=n.manager.getHandler(o.uri);i!==null&&(a=i)}return this.loadTextureImage(t,r,a)}loadTextureImage(t,e,n){const s=this,r=this.json,o=r.textures[t],a=r.images[e],i=(a.uri||a.bufferView)+":"+o.sampler;if(this.textureCache[i])return this.textureCache[i];const c=this.loadImageSource(e,n).then(function(u){u.flipY=!1,u.name=o.name||a.name||"",u.name===""&&typeof a.uri=="string"&&a.uri.startsWith("data:image/")===!1&&(u.name=a.uri);const f=(r.samplers||{})[o.sampler]||{};return u.magFilter=V[f.magFilter]||h.LinearFilter,u.minFilter=V[f.minFilter]||h.LinearMipmapLinearFilter,u.wrapS=z[f.wrapS]||h.RepeatWrapping,u.wrapT=z[f.wrapT]||h.RepeatWrapping,u.generateMipmaps=!u.isCompressedTexture&&u.minFilter!==h.NearestFilter&&u.minFilter!==h.LinearFilter,s.associations.set(u,{textures:t}),u}).catch(function(){return null});return this.textureCache[i]=c,c}loadImageSource(t,e){const n=this,s=this.json,r=this.options;if(this.sourceCache[t]!==void 0)return this.sourceCache[t].then(l=>l.clone());const o=s.images[t],a=self.URL||self.webkitURL;let i=o.uri||"",c=!1;if(o.bufferView!==void 0)i=n.getDependency("bufferView",o.bufferView).then(function(l){c=!0;const f=new Blob([l],{type:o.mimeType});return i=a.createObjectURL(f),i});else if(o.uri===void 0)throw new Error("THREE.GLTFLoader: Image "+t+" is missing URI and bufferView");const u=Promise.resolve(i).then(function(l){return new Promise(function(f,p){let m=f;e.isImageBitmapLoader===!0&&(m=function(M){const g=new h.Texture(M);g.needsUpdate=!0,f(g)}),e.load(h.LoaderUtils.resolveURL(l,r.path),m,void 0,p)})}).then(function(l){return c===!0&&a.revokeObjectURL(i),w(l,o),l.userData.mimeType=o.mimeType||we(o.uri),l}).catch(function(l){throw console.error("THREE.GLTFLoader: Couldn't load texture",i),l});return this.sourceCache[t]=u,u}assignTexture(t,e,n,s){const r=this;return this.getDependency("texture",n.index).then(function(o){if(!o)return null;if(n.texCoord!==void 0&&n.texCoord>0&&(o=o.clone(),o.channel=n.texCoord),r.extensions[T.KHR_TEXTURE_TRANSFORM]){const a=n.extensions!==void 0?n.extensions[T.KHR_TEXTURE_TRANSFORM]:void 0;if(a){const i=r.associations.get(o);o=r.extensions[T.KHR_TEXTURE_TRANSFORM].extendTexture(o,a),r.associations.set(o,i)}}return s!==void 0&&(o.colorSpace=s),t[e]=o,o})}assignFinalMaterial(t){const e=t.geometry;let n=t.material;const s=e.attributes.tangent===void 0,r=e.attributes.color!==void 0,o=e.attributes.normal===void 0;if(t.isPoints){const a="PointsMaterial:"+n.uuid;let i=this.cache.get(a);i||(i=new h.PointsMaterial,h.Material.prototype.copy.call(i,n),i.color.copy(n.color),i.map=n.map,i.sizeAttenuation=!1,this.cache.add(a,i)),n=i}else if(t.isLine){const a="LineBasicMaterial:"+n.uuid;let i=this.cache.get(a);i||(i=new h.LineBasicMaterial,h.Material.prototype.copy.call(i,n),i.color.copy(n.color),i.map=n.map,this.cache.add(a,i)),n=i}if(s||r||o){let a="ClonedMaterial:"+n.uuid+":";s&&(a+="derivative-tangents:"),r&&(a+="vertex-colors:"),o&&(a+="flat-shading:");let i=this.cache.get(a);i||(i=n.clone(),r&&(i.vertexColors=!0),o&&(i.flatShading=!0),s&&(i.normalScale&&(i.normalScale.y*=-1),i.clearcoatNormalScale&&(i.clearcoatNormalScale.y*=-1)),this.cache.add(a,i),this.associations.set(i,this.associations.get(n))),n=i}t.material=n}getMaterialType(){return h.MeshStandardMaterial}loadMaterial(t){const e=this,n=this.json,s=this.extensions,r=n.materials[t];let o;const a={},i=r.extensions||{},c=[];if(i[T.KHR_MATERIALS_UNLIT]){const l=s[T.KHR_MATERIALS_UNLIT];o=l.getMaterialType(),c.push(l.extendParams(a,r,e))}else{const l=r.pbrMetallicRoughness||{};if(a.color=new h.Color(1,1,1),a.opacity=1,Array.isArray(l.baseColorFactor)){const f=l.baseColorFactor;a.color.setRGB(f[0],f[1],f[2],h.LinearSRGBColorSpace),a.opacity=f[3]}l.baseColorTexture!==void 0&&c.push(e.assignTexture(a,"map",l.baseColorTexture,h.SRGBColorSpace)),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))),o=this._invokeOne(function(f){return f.getMaterialType&&f.getMaterialType(t)}),c.push(Promise.all(this._invokeAll(function(f){return f.extendMaterialParams&&f.extendMaterialParams(t,a)})))}r.doubleSided===!0&&(a.side=h.DoubleSide);const u=r.alphaMode||G.OPAQUE;if(u===G.BLEND?(a.transparent=!0,a.depthWrite=!1):(a.transparent=!1,u===G.MASK&&(a.alphaTest=r.alphaCutoff!==void 0?r.alphaCutoff:.5)),r.normalTexture!==void 0&&o!==h.MeshBasicMaterial&&(c.push(e.assignTexture(a,"normalMap",r.normalTexture)),a.normalScale=new h.Vector2(1,1),r.normalTexture.scale!==void 0)){const l=r.normalTexture.scale;a.normalScale.set(l,l)}if(r.occlusionTexture!==void 0&&o!==h.MeshBasicMaterial&&(c.push(e.assignTexture(a,"aoMap",r.occlusionTexture)),r.occlusionTexture.strength!==void 0&&(a.aoMapIntensity=r.occlusionTexture.strength)),r.emissiveFactor!==void 0&&o!==h.MeshBasicMaterial){const l=r.emissiveFactor;a.emissive=new h.Color().setRGB(l[0],l[1],l[2],h.LinearSRGBColorSpace)}return r.emissiveTexture!==void 0&&o!==h.MeshBasicMaterial&&c.push(e.assignTexture(a,"emissiveMap",r.emissiveTexture,h.SRGBColorSpace)),Promise.all(c).then(function(){const l=new o(a);return r.name&&(l.name=r.name),w(l,r),e.associations.set(l,{materials:t}),r.extensions&&I(s,l,r),l})}createUniqueName(t){const e=h.PropertyBinding.sanitizeNodeName(t||"");return e in this.nodeNamesUsed?e+"_"+ ++this.nodeNamesUsed[e]:(this.nodeNamesUsed[e]=0,e)}loadGeometries(t){const e=this,n=this.extensions,s=this.primitiveCache;function r(a){return n[T.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(a,e).then(function(i){return X(i,a,e)})}const o=[];for(let a=0,i=t.length;a<i;a++){const c=t[a],u=ye(c),l=s[u];if(l)o.push(l.promise);else{let f;c.extensions&&c.extensions[T.KHR_DRACO_MESH_COMPRESSION]?f=r(c):f=X(new h.BufferGeometry,c,e),s[u]={primitive:c,promise:f},o.push(f)}}return Promise.all(o)}loadMesh(t){const e=this,n=this.json,s=this.extensions,r=n.meshes[t],o=r.primitives,a=[];for(let i=0,c=o.length;i<c;i++){const u=o[i].material===void 0?_e(this.cache):this.getDependency("material",o[i].material);a.push(u)}return a.push(e.loadGeometries(o)),Promise.all(a).then(function(i){const c=i.slice(0,i.length-1),u=i[i.length-1],l=[];for(let p=0,m=u.length;p<m;p++){const M=u[p],g=o[p];let R;const A=c[p];if(g.mode===S.TRIANGLES||g.mode===S.TRIANGLE_STRIP||g.mode===S.TRIANGLE_FAN||g.mode===void 0)R=r.isSkinnedMesh===!0?new h.SkinnedMesh(M,A):new h.Mesh(M,A),R.isSkinnedMesh===!0&&R.normalizeSkinWeights(),g.mode===S.TRIANGLE_STRIP?R.geometry=h.toTrianglesDrawMode(R.geometry,h.TriangleStripDrawMode):g.mode===S.TRIANGLE_FAN&&(R.geometry=h.toTrianglesDrawMode(R.geometry,h.TriangleFanDrawMode));else if(g.mode===S.LINES)R=new h.LineSegments(M,A);else if(g.mode===S.LINE_STRIP)R=new h.Line(M,A);else if(g.mode===S.LINE_LOOP)R=new h.LineLoop(M,A);else if(g.mode===S.POINTS)R=new h.Points(M,A);else throw new Error("THREE.GLTFLoader: Primitive mode unsupported: "+g.mode);Object.keys(R.geometry.morphAttributes).length>0&&Se(R,r),R.name=e.createUniqueName(r.name||"mesh_"+t),w(R,r),g.extensions&&I(s,R,g),e.assignFinalMaterial(R),l.push(R)}for(let p=0,m=l.length;p<m;p++)e.associations.set(l[p],{meshes:t,primitives:p});if(l.length===1)return r.extensions&&I(s,l[0],r),l[0];const f=new h.Group;r.extensions&&I(s,f,r),e.associations.set(f,{meshes:t});for(let p=0,m=l.length;p<m;p++)f.add(l[p]);return f})}loadCamera(t){let e;const n=this.json.cameras[t],s=n[n.type];if(!s){console.warn("THREE.GLTFLoader: Missing camera parameters.");return}return n.type==="perspective"?e=new h.PerspectiveCamera(h.MathUtils.radToDeg(s.yfov),s.aspectRatio||1,s.znear||1,s.zfar||2e6):n.type==="orthographic"&&(e=new h.OrthographicCamera(-s.xmag,s.xmag,s.ymag,-s.ymag,s.znear,s.zfar)),n.name&&(e.name=this.createUniqueName(n.name)),w(e,n),Promise.resolve(e)}loadSkin(t){const e=this.json.skins[t],n=[];for(let s=0,r=e.joints.length;s<r;s++)n.push(this._loadNodeShallow(e.joints[s]));return e.inverseBindMatrices!==void 0?n.push(this.getDependency("accessor",e.inverseBindMatrices)):n.push(null),Promise.all(n).then(function(s){const r=s.pop(),o=s,a=[],i=[];for(let c=0,u=o.length;c<u;c++){const l=o[c];if(l){a.push(l);const f=new h.Matrix4;r!==null&&f.fromArray(r.array,c*16),i.push(f)}else console.warn('THREE.GLTFLoader: Joint "%s" could not be found.',e.joints[c])}return new h.Skeleton(a,i)})}loadAnimation(t){const e=this.json,n=this,s=e.animations[t],r=s.name?s.name:"animation_"+t,o=[],a=[],i=[],c=[],u=[];for(let l=0,f=s.channels.length;l<f;l++){const p=s.channels[l],m=s.samplers[p.sampler],M=p.target,g=M.node,R=s.parameters!==void 0?s.parameters[m.input]:m.input,A=s.parameters!==void 0?s.parameters[m.output]:m.output;M.node!==void 0&&(o.push(this.getDependency("node",g)),a.push(this.getDependency("accessor",R)),i.push(this.getDependency("accessor",A)),c.push(m),u.push(M))}return Promise.all([Promise.all(o),Promise.all(a),Promise.all(i),Promise.all(c),Promise.all(u)]).then(function(l){const f=l[0],p=l[1],m=l[2],M=l[3],g=l[4],R=[];for(let x=0,E=f.length;x<E;x++){const L=f[x],b=p[x],y=m[x],P=M[x],C=g[x];if(L===void 0)continue;L.updateMatrix&&L.updateMatrix();const k=n._createAnimationTracks(L,b,y,P,C);if(k)for(let H=0;H<k.length;H++)R.push(k[H])}const A=new h.AnimationClip(r,void 0,R);return w(A,s),A})}createNodeMesh(t){const e=this.json,n=this,s=e.nodes[t];return s.mesh===void 0?null:n.getDependency("mesh",s.mesh).then(function(r){const o=n._getNodeRef(n.meshCache,s.mesh,r);return s.weights!==void 0&&o.traverse(function(a){if(a.isMesh)for(let i=0,c=s.weights.length;i<c;i++)a.morphTargetInfluences[i]=s.weights[i]}),o})}loadNode(t){const e=this.json,n=this,s=e.nodes[t],r=n._loadNodeShallow(t),o=[],a=s.children||[];for(let c=0,u=a.length;c<u;c++)o.push(n.getDependency("node",a[c]));const i=s.skin===void 0?Promise.resolve(null):n.getDependency("skin",s.skin);return Promise.all([r,Promise.all(o),i]).then(function(c){const u=c[0],l=c[1],f=c[2];f!==null&&u.traverse(function(p){p.isSkinnedMesh&&p.bind(f,be)});for(let p=0,m=l.length;p<m;p++)u.add(l[p]);if(u.userData.pivot!==void 0&&l.length>0){const p=u.userData.pivot,m=l[0];u.pivot=new h.Vector3().fromArray(p),u.position.x-=p[0],u.position.y-=p[1],u.position.z-=p[2],m.position.set(0,0,0),delete u.userData.pivot}return u})}_loadNodeShallow(t){const e=this.json,n=this.extensions,s=this;if(this.nodeCache[t]!==void 0)return this.nodeCache[t];const r=e.nodes[t],o=r.name?s.createUniqueName(r.name):"",a=[],i=s._invokeOne(function(c){return c.createNodeMesh&&c.createNodeMesh(t)});return i&&a.push(i),r.camera!==void 0&&a.push(s.getDependency("camera",r.camera).then(function(c){return s._getNodeRef(s.cameraCache,r.camera,c)})),s._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 h.Bone:c.length>1?u=new h.Group:c.length===1?u=c[0]:u=new h.Object3D,u!==c[0])for(let l=0,f=c.length;l<f;l++)u.add(c[l]);if(r.name&&(u.userData.name=r.name,u.name=o),w(u,r),r.extensions&&I(n,u,r),r.matrix!==void 0){const l=new h.Matrix4;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(!s.associations.has(u))s.associations.set(u,{});else if(r.mesh!==void 0&&s.meshCache.refs[r.mesh]>1){const l=s.associations.get(u);s.associations.set(u,{...l})}return s.associations.get(u).nodes=t,u}),this.nodeCache[t]}loadScene(t){const e=this.extensions,n=this.json.scenes[t],s=this,r=new h.Group;n.name&&(r.name=s.createUniqueName(n.name)),w(r,n),n.extensions&&I(e,r,n);const o=n.nodes||[],a=[];for(let i=0,c=o.length;i<c;i++)a.push(s.getDependency("node",o[i]));return Promise.all(a).then(function(i){for(let u=0,l=i.length;u<l;u++){const f=i[u];f.parent!==null?r.add(Q(f)):r.add(f)}const c=u=>{const l=new Map;for(const[f,p]of s.associations)(f instanceof h.Material||f instanceof h.Texture)&&l.set(f,p);return u.traverse(f=>{const p=s.associations.get(f);p!=null&&l.set(f,p)}),l};return s.associations=c(r),r})}_createAnimationTracks(t,e,n,s,r){const o=[],a=t.name?t.name:t.uuid,i=[];N[r.path]===N.weights?t.traverse(function(f){f.morphTargetInfluences&&i.push(f.name?f.name:f.uuid)}):i.push(a);let c;switch(N[r.path]){case N.weights:c=h.NumberKeyframeTrack;break;case N.rotation:c=h.QuaternionKeyframeTrack;break;case N.translation:case N.scale:c=h.VectorKeyframeTrack;break;default:n.itemSize===1?c=h.NumberKeyframeTrack:c=h.VectorKeyframeTrack;break}const u=s.interpolation!==void 0?Ae[s.interpolation]:h.InterpolateLinear,l=this._getArrayFromAccessor(n);for(let f=0,p=i.length;f<p;f++){const m=new c(i[f]+"."+N[r.path],e.array,l,u);s.interpolation==="CUBICSPLINE"&&this._createCubicSplineTrackInterpolant(m),o.push(m)}return o}_getArrayFromAccessor(t){let e=t.array;if(t.normalized){const n=U(e.constructor),s=new Float32Array(e.length);for(let r=0,o=e.length;r<o;r++)s[r]=e[r]*n;e=s}return e}_createCubicSplineTrackInterpolant(t){t.createInterpolant=function(n){const s=this instanceof h.QuaternionKeyframeTrack?xe:Y;return new s(this.times,this.values,this.getValueSize()/3,n)},t.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline=!0}}function Ie(d,t,e){const n=t.attributes,s=new h.Box3;if(n.POSITION!==void 0){const a=e.json.accessors[n.POSITION],i=a.min,c=a.max;if(i!==void 0&&c!==void 0){if(s.set(new h.Vector3(i[0],i[1],i[2]),new h.Vector3(c[0],c[1],c[2])),a.normalized){const u=U(O[a.componentType]);s.min.multiplyScalar(u),s.max.multiplyScalar(u)}}else{console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.");return}}else return;const r=t.targets;if(r!==void 0){const a=new h.Vector3,i=new h.Vector3;for(let c=0,u=r.length;c<u;c++){const l=r[c];if(l.POSITION!==void 0){const f=e.json.accessors[l.POSITION],p=f.min,m=f.max;if(p!==void 0&&m!==void 0){if(i.setX(Math.max(Math.abs(p[0]),Math.abs(m[0]))),i.setY(Math.max(Math.abs(p[1]),Math.abs(m[1]))),i.setZ(Math.max(Math.abs(p[2]),Math.abs(m[2]))),f.normalized){const M=U(O[f.componentType]);i.multiplyScalar(M)}a.max(i)}else console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.")}}s.expandByVector(a)}d.boundingBox=s;const o=new h.Sphere;s.getCenter(o.center),o.radius=s.min.distanceTo(s.max)/2,d.boundingSphere=o}function X(d,t,e){const n=t.attributes,s=[];function r(o,a){return e.getDependency("accessor",o).then(function(i){d.setAttribute(a,i)})}for(const o in n){const a=B[o]||o.toLowerCase();a in d.attributes||s.push(r(n[o],a))}if(t.indices!==void 0&&!d.index){const o=e.getDependency("accessor",t.indices).then(function(a){d.setIndex(a)});s.push(o)}return h.ColorManagement.workingColorSpace!==h.LinearSRGBColorSpace&&"COLOR_0"in n&&console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${h.ColorManagement.workingColorSpace}" not supported.`),w(d,t),Ie(d,t,e),Promise.all(s).then(function(){return t.targets!==void 0?Le(d,t.targets,e):d})}exports.GLTFLoader=J;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("./duo-frame-D9832t6H.js");function Q(d){const t=new Map,e=new Map,n=d.clone();return q(d,n,function(s,r){t.set(r,s),e.set(s,r)}),n.traverse(function(s){if(!s.isSkinnedMesh)return;const r=s,o=t.get(s),a=o.skeleton.bones;r.skeleton=o.skeleton.clone(),r.bindMatrix.copy(o.bindMatrix),r.skeleton.bones=a.map(function(i){return e.get(i)}),r.bind(r.skeleton,r.bindMatrix)}),n}function q(d,t,e){e(d,t);for(let n=0;n<d.children.length;n++)q(d.children[n],t.children[n],e)}class J extends h.Loader{constructor(t){super(t),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register(function(e){return new ne(e)}),this.register(function(e){return new se(e)}),this.register(function(e){return new fe(e)}),this.register(function(e){return new de(e)}),this.register(function(e){return new pe(e)}),this.register(function(e){return new ie(e)}),this.register(function(e){return new oe(e)}),this.register(function(e){return new ae(e)}),this.register(function(e){return new ce(e)}),this.register(function(e){return new te(e)}),this.register(function(e){return new le(e)}),this.register(function(e){return new re(e)}),this.register(function(e){return new he(e)}),this.register(function(e){return new ue(e)}),this.register(function(e){return new $(e)}),this.register(function(e){return new K(e,T.EXT_MESHOPT_COMPRESSION)}),this.register(function(e){return new K(e,T.KHR_MESHOPT_COMPRESSION)}),this.register(function(e){return new me(e)})}load(t,e,n,s){const r=this;let o;if(this.resourcePath!=="")o=this.resourcePath;else if(this.path!==""){const c=h.LoaderUtils.extractUrlBase(t);o=h.LoaderUtils.resolveURL(c,this.path)}else o=h.LoaderUtils.extractUrlBase(t);this.manager.itemStart(t);const a=function(c){s?s(c):console.error(c),r.manager.itemError(t),r.manager.itemEnd(t)},i=new h.FileLoader(this.manager);i.setPath(this.path),i.setResponseType("arraybuffer"),i.setRequestHeader(this.requestHeader),i.setWithCredentials(this.withCredentials),i.load(t,function(c){try{r.parse(c,o,function(u){e(u),r.manager.itemEnd(t)},a)}catch(u){a(u)}},n,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,n,s){let r;const o={},a={},i=new TextDecoder;if(typeof t=="string")r=JSON.parse(t);else if(t instanceof ArrayBuffer)if(i.decode(new Uint8Array(t,0,4))===W){try{o[T.KHR_BINARY_GLTF]=new ge(t)}catch(l){s&&s(l);return}r=JSON.parse(o[T.KHR_BINARY_GLTF].content)}else r=JSON.parse(i.decode(t));else r=t;if(r.asset===void 0||r.asset.version[0]<2){s&&s(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported."));return}const c=new Ne(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++){const l=this.pluginCallbacks[u](c);l.name||console.error("THREE.GLTFLoader: Invalid plugin found: missing name"),a[l.name]=l,o[l.name]=!0}if(r.extensionsUsed)for(let u=0;u<r.extensionsUsed.length;++u){const l=r.extensionsUsed[u],f=r.extensionsRequired||[];switch(l){case T.KHR_MATERIALS_UNLIT:o[l]=new ee;break;case T.KHR_DRACO_MESH_COMPRESSION:o[l]=new Te(r,this.dracoLoader);break;case T.KHR_TEXTURE_TRANSFORM:o[l]=new Re;break;case T.KHR_MESH_QUANTIZATION:o[l]=new Me;break;default:f.indexOf(l)>=0&&a[l]===void 0&&console.warn('THREE.GLTFLoader: Unknown extension "'+l+'".')}}c.setExtensions(o),c.setPlugins(a),c.parse(n,s)}parseAsync(t,e){const n=this;return new Promise(function(s,r){n.parse(t,e,s,r)})}}function Z(){let d={};return{get:function(t){return d[t]},add:function(t,e){d[t]=e},remove:function(t){delete d[t]},removeAll:function(){d={}}}}function _(d,t,e){const n=d.json.materials[t];return n.extensions&&n.extensions[e]?n.extensions[e]:null}const T={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"};class ${constructor(t){this.parser=t,this.name=T.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){const t=this.parser,e=this.parser.json.nodes||[];for(let n=0,s=e.length;n<s;n++){const r=e[n];r.extensions&&r.extensions[this.name]&&r.extensions[this.name].light!==void 0&&t._addNodeRef(this.cache,r.extensions[this.name].light)}}_loadLight(t){const e=this.parser,n="light:"+t;let s=e.cache.get(n);if(s)return s;const r=e.json,i=((r.extensions&&r.extensions[this.name]||{}).lights||[])[t];let c;const u=new h.Color(16777215);i.color!==void 0&&u.setRGB(i.color[0],i.color[1],i.color[2],h.LinearSRGBColorSpace);const l=i.range!==void 0?i.range:0;switch(i.type){case"directional":c=new h.DirectionalLight(u),c.target.position.set(0,0,-1),c.add(c.target);break;case"point":c=new h.PointLight(u),c.distance=l;break;case"spot":c=new h.SpotLight(u),c.distance=l,i.spot=i.spot||{},i.spot.innerConeAngle=i.spot.innerConeAngle!==void 0?i.spot.innerConeAngle:0,i.spot.outerConeAngle=i.spot.outerConeAngle!==void 0?i.spot.outerConeAngle:Math.PI/4,c.angle=i.spot.outerConeAngle,c.penumbra=1-i.spot.innerConeAngle/i.spot.outerConeAngle,c.target.position.set(0,0,-1),c.add(c.target);break;default:throw new Error("THREE.GLTFLoader: Unexpected light type: "+i.type)}return c.position.set(0,0,0),w(c,i),i.intensity!==void 0&&(c.intensity=i.intensity),c.name=e.createUniqueName(i.name||"light_"+t),s=Promise.resolve(c),e.cache.add(n,s),s}getDependency(t,e){if(t==="light")return this._loadLight(e)}createNodeAttachment(t){const e=this,n=this.parser,r=n.json.nodes[t],a=(r.extensions&&r.extensions[this.name]||{}).light;return a===void 0?null:this._loadLight(a).then(function(i){return n._getNodeRef(e.cache,a,i)})}}class ee{constructor(){this.name=T.KHR_MATERIALS_UNLIT}getMaterialType(){return h.MeshBasicMaterial}extendParams(t,e,n){const s=[];t.color=new h.Color(1,1,1),t.opacity=1;const r=e.pbrMetallicRoughness;if(r){if(Array.isArray(r.baseColorFactor)){const o=r.baseColorFactor;t.color.setRGB(o[0],o[1],o[2],h.LinearSRGBColorSpace),t.opacity=o[3]}r.baseColorTexture!==void 0&&s.push(n.assignTexture(t,"map",r.baseColorTexture,h.SRGBColorSpace))}return Promise.all(s)}}class te{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_EMISSIVE_STRENGTH}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);return n===null||n.emissiveStrength!==void 0&&(e.emissiveIntensity=n.emissiveStrength),Promise.resolve()}}class ne{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_CLEARCOAT}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];if(n.clearcoatFactor!==void 0&&(e.clearcoat=n.clearcoatFactor),n.clearcoatTexture!==void 0&&s.push(this.parser.assignTexture(e,"clearcoatMap",n.clearcoatTexture)),n.clearcoatRoughnessFactor!==void 0&&(e.clearcoatRoughness=n.clearcoatRoughnessFactor),n.clearcoatRoughnessTexture!==void 0&&s.push(this.parser.assignTexture(e,"clearcoatRoughnessMap",n.clearcoatRoughnessTexture)),n.clearcoatNormalTexture!==void 0&&(s.push(this.parser.assignTexture(e,"clearcoatNormalMap",n.clearcoatNormalTexture)),n.clearcoatNormalTexture.scale!==void 0)){const r=n.clearcoatNormalTexture.scale;e.clearcoatNormalScale=new h.Vector2(r,r)}return Promise.all(s)}}class se{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_DISPERSION}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);return n===null||(e.dispersion=n.dispersion!==void 0?n.dispersion:0),Promise.resolve()}}class re{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_IRIDESCENCE}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];return n.iridescenceFactor!==void 0&&(e.iridescence=n.iridescenceFactor),n.iridescenceTexture!==void 0&&s.push(this.parser.assignTexture(e,"iridescenceMap",n.iridescenceTexture)),n.iridescenceIor!==void 0&&(e.iridescenceIOR=n.iridescenceIor),e.iridescenceThicknessRange===void 0&&(e.iridescenceThicknessRange=[100,400]),n.iridescenceThicknessMinimum!==void 0&&(e.iridescenceThicknessRange[0]=n.iridescenceThicknessMinimum),n.iridescenceThicknessMaximum!==void 0&&(e.iridescenceThicknessRange[1]=n.iridescenceThicknessMaximum),n.iridescenceThicknessTexture!==void 0&&s.push(this.parser.assignTexture(e,"iridescenceThicknessMap",n.iridescenceThicknessTexture)),Promise.all(s)}}class ie{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_SHEEN}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];if(e.sheenColor=new h.Color(0,0,0),e.sheenRoughness=0,e.sheen=1,n.sheenColorFactor!==void 0){const r=n.sheenColorFactor;e.sheenColor.setRGB(r[0],r[1],r[2],h.LinearSRGBColorSpace)}return n.sheenRoughnessFactor!==void 0&&(e.sheenRoughness=n.sheenRoughnessFactor),n.sheenColorTexture!==void 0&&s.push(this.parser.assignTexture(e,"sheenColorMap",n.sheenColorTexture,h.SRGBColorSpace)),n.sheenRoughnessTexture!==void 0&&s.push(this.parser.assignTexture(e,"sheenRoughnessMap",n.sheenRoughnessTexture)),Promise.all(s)}}class oe{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_TRANSMISSION}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];return n.transmissionFactor!==void 0&&(e.transmission=n.transmissionFactor),n.transmissionTexture!==void 0&&s.push(this.parser.assignTexture(e,"transmissionMap",n.transmissionTexture)),Promise.all(s)}}class ae{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_VOLUME}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];e.thickness=n.thicknessFactor!==void 0?n.thicknessFactor:0,n.thicknessTexture!==void 0&&s.push(this.parser.assignTexture(e,"thicknessMap",n.thicknessTexture)),e.attenuationDistance=n.attenuationDistance||1/0;const r=n.attenuationColor||[1,1,1];return e.attenuationColor=new h.Color().setRGB(r[0],r[1],r[2],h.LinearSRGBColorSpace),Promise.all(s)}}class ce{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_IOR}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);return n===null||(e.ior=n.ior!==void 0?n.ior:1.5),Promise.resolve()}}class le{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_SPECULAR}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];e.specularIntensity=n.specularFactor!==void 0?n.specularFactor:1,n.specularTexture!==void 0&&s.push(this.parser.assignTexture(e,"specularIntensityMap",n.specularTexture));const r=n.specularColorFactor||[1,1,1];return e.specularColor=new h.Color().setRGB(r[0],r[1],r[2],h.LinearSRGBColorSpace),n.specularColorTexture!==void 0&&s.push(this.parser.assignTexture(e,"specularColorMap",n.specularColorTexture,h.SRGBColorSpace)),Promise.all(s)}}class ue{constructor(t){this.parser=t,this.name=T.EXT_MATERIALS_BUMP}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];return e.bumpScale=n.bumpFactor!==void 0?n.bumpFactor:1,n.bumpTexture!==void 0&&s.push(this.parser.assignTexture(e,"bumpMap",n.bumpTexture)),Promise.all(s)}}class he{constructor(t){this.parser=t,this.name=T.KHR_MATERIALS_ANISOTROPY}getMaterialType(t){return _(this.parser,t,this.name)!==null?h.MeshPhysicalMaterial:null}extendMaterialParams(t,e){const n=_(this.parser,t,this.name);if(n===null)return Promise.resolve();const s=[];return n.anisotropyStrength!==void 0&&(e.anisotropy=n.anisotropyStrength),n.anisotropyRotation!==void 0&&(e.anisotropyRotation=n.anisotropyRotation),n.anisotropyTexture!==void 0&&s.push(this.parser.assignTexture(e,"anisotropyMap",n.anisotropyTexture)),Promise.all(s)}}class fe{constructor(t){this.parser=t,this.name=T.KHR_TEXTURE_BASISU}loadTexture(t){const e=this.parser,n=e.json,s=n.textures[t];if(!s.extensions||!s.extensions[this.name])return null;const r=s.extensions[this.name],o=e.options.ktx2Loader;if(!o){if(n.extensionsRequired&&n.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,o)}}class de{constructor(t){this.parser=t,this.name=T.EXT_TEXTURE_WEBP}loadTexture(t){const e=this.name,n=this.parser,s=n.json,r=s.textures[t];if(!r.extensions||!r.extensions[e])return null;const o=r.extensions[e],a=s.images[o.source];let i=n.textureLoader;if(a.uri){const c=n.options.manager.getHandler(a.uri);c!==null&&(i=c)}return n.loadTextureImage(t,o.source,i)}}class pe{constructor(t){this.parser=t,this.name=T.EXT_TEXTURE_AVIF}loadTexture(t){const e=this.name,n=this.parser,s=n.json,r=s.textures[t];if(!r.extensions||!r.extensions[e])return null;const o=r.extensions[e],a=s.images[o.source];let i=n.textureLoader;if(a.uri){const c=n.options.manager.getHandler(a.uri);c!==null&&(i=c)}return n.loadTextureImage(t,o.source,i)}}class K{constructor(t,e){this.name=e,this.parser=t}loadBufferView(t){const e=this.parser.json,n=e.bufferViews[t];if(n.extensions&&n.extensions[this.name]){const s=n.extensions[this.name],r=this.parser.getDependency("buffer",s.buffer),o=this.parser.options.meshoptDecoder;if(!o||!o.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){const i=s.byteOffset||0,c=s.byteLength||0,u=s.count,l=s.byteStride,f=new Uint8Array(a,i,c);return o.decodeGltfBufferAsync?o.decodeGltfBufferAsync(u,l,f,s.mode,s.filter).then(function(p){return p.buffer}):o.ready.then(function(){const p=new ArrayBuffer(u*l);return o.decodeGltfBuffer(new Uint8Array(p),u,l,f,s.mode,s.filter),p})})}else return null}}class me{constructor(t){this.name=T.EXT_MESH_GPU_INSTANCING,this.parser=t}createNodeMesh(t){const e=this.parser.json,n=e.nodes[t];if(!n.extensions||!n.extensions[this.name]||n.mesh===void 0)return null;const s=e.meshes[n.mesh];for(const c of s.primitives)if(c.mode!==S.TRIANGLES&&c.mode!==S.TRIANGLE_STRIP&&c.mode!==S.TRIANGLE_FAN&&c.mode!==void 0)return null;const o=n.extensions[this.name].attributes,a=[],i={};for(const c in o)a.push(this.parser.getDependency("accessor",o[c]).then(u=>(i[c]=u,i[c])));return a.length<1?null:(a.push(this.parser.createNodeMesh(t)),Promise.all(a).then(c=>{const u=c.pop(),l=u.isGroup?u.children:[u],f=c[0].count,p=[];for(const m of l){const M=new h.Matrix4,g=new h.Vector3,R=new h.Quaternion,A=new h.Vector3(1,1,1),x=new h.InstancedMesh(m.geometry,m.material,f);for(let E=0;E<f;E++)i.TRANSLATION&&g.fromBufferAttribute(i.TRANSLATION,E),i.ROTATION&&R.fromBufferAttribute(i.ROTATION,E),i.SCALE&&A.fromBufferAttribute(i.SCALE,E),x.setMatrixAt(E,M.compose(g,R,A));for(const E in i)if(E==="_COLOR_0"){const L=i[E];x.instanceColor=new h.InstancedBufferAttribute(L.array,L.itemSize,L.normalized)}else E!=="TRANSLATION"&&E!=="ROTATION"&&E!=="SCALE"&&m.geometry.setAttribute(E,i[E]);h.Object3D.prototype.copy.call(x,m),this.parser.assignFinalMaterial(x),p.push(x)}return u.isGroup?(u.clear(),u.add(...p),u):p[0]}))}}const W="glTF",F=12,j={JSON:1313821514,BIN:5130562};class ge{constructor(t){this.name=T.KHR_BINARY_GLTF,this.content=null,this.body=null;const e=new DataView(t,0,F),n=new TextDecoder;if(this.header={magic:n.decode(new Uint8Array(t.slice(0,4))),version:e.getUint32(4,!0),length:e.getUint32(8,!0)},this.header.magic!==W)throw new Error("THREE.GLTFLoader: Unsupported glTF-Binary header.");if(this.header.version<2)throw new Error("THREE.GLTFLoader: Legacy binary file detected.");const s=this.header.length-F,r=new DataView(t,F);let o=0;for(;o<s;){const a=r.getUint32(o,!0);o+=4;const i=r.getUint32(o,!0);if(o+=4,i===j.JSON){const c=new Uint8Array(t,F+o,a);this.content=n.decode(c)}else if(i===j.BIN){const c=F+o;this.body=t.slice(c,c+a)}o+=a}if(this.content===null)throw new Error("THREE.GLTFLoader: JSON content not found.")}}class Te{constructor(t,e){if(!e)throw new Error("THREE.GLTFLoader: No DRACOLoader instance provided.");this.name=T.KHR_DRACO_MESH_COMPRESSION,this.json=t,this.dracoLoader=e,this.dracoLoader.preload()}decodePrimitive(t,e){const n=this.json,s=this.dracoLoader,r=t.extensions[this.name].bufferView,o=t.extensions[this.name].attributes,a={},i={},c={};for(const u in o){const l=B[u]||u.toLowerCase();a[l]=o[u]}for(const u in t.attributes){const l=B[u]||u.toLowerCase();if(o[u]!==void 0){const f=n.accessors[t.attributes[u]],p=O[f.componentType];c[l]=p.name,i[l]=f.normalized===!0}}return e.getDependency("bufferView",r).then(function(u){return new Promise(function(l,f){s.decodeDracoFile(u,function(p){for(const m in p.attributes){const M=p.attributes[m],g=i[m];g!==void 0&&(M.normalized=g)}l(p)},a,c,h.LinearSRGBColorSpace,f)})})}}class Re{constructor(){this.name=T.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}}class Me{constructor(){this.name=T.KHR_MESH_QUANTIZATION}}class Y extends h.Interpolant{constructor(t,e,n,s){super(t,e,n,s)}copySampleValue_(t){const e=this.resultBuffer,n=this.sampleValues,s=this.valueSize,r=t*s*3+s;for(let o=0;o!==s;o++)e[o]=n[r+o];return e}interpolate_(t,e,n,s){const r=this.resultBuffer,o=this.sampleValues,a=this.valueSize,i=a*2,c=a*3,u=s-e,l=(n-e)/u,f=l*l,p=f*l,m=t*c,M=m-c,g=-2*p+3*f,R=p-f,A=1-g,x=R-f+l;for(let E=0;E!==a;E++){const L=o[M+E+a],b=o[M+E+i]*u,y=o[m+E+a],P=o[m+E]*u;r[E]=A*L+x*b+g*y+R*P}return r}}const Ee=new h.Quaternion;class xe extends Y{interpolate_(t,e,n,s){const r=super.interpolate_(t,e,n,s);return Ee.fromArray(r).normalize().toArray(r),r}}const S={POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6},O={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array},V={9728:h.NearestFilter,9729:h.LinearFilter,9984:h.NearestMipmapNearestFilter,9985:h.LinearMipmapNearestFilter,9986:h.NearestMipmapLinearFilter,9987:h.LinearMipmapLinearFilter},z={33071:h.ClampToEdgeWrapping,33648:h.MirroredRepeatWrapping,10497:h.RepeatWrapping},D={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16},B={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"},N={scale:"scale",translation:"position",rotation:"quaternion",weights:"morphTargetInfluences"},Ae={CUBICSPLINE:void 0,LINEAR:h.InterpolateLinear,STEP:h.InterpolateDiscrete},G={OPAQUE:"OPAQUE",MASK:"MASK",BLEND:"BLEND"};function _e(d){return d.DefaultMaterial===void 0&&(d.DefaultMaterial=new h.MeshStandardMaterial({color:16777215,emissive:0,metalness:1,roughness:1,transparent:!1,depthTest:!0,side:h.FrontSide})),d.DefaultMaterial}function I(d,t,e){for(const n in e.extensions)d[n]===void 0&&(t.userData.gltfExtensions=t.userData.gltfExtensions||{},t.userData.gltfExtensions[n]=e.extensions[n])}function w(d,t){t.extras!==void 0&&(typeof t.extras=="object"?Object.assign(d.userData,t.extras):console.warn("THREE.GLTFLoader: Ignoring primitive type .extras, "+t.extras))}function Le(d,t,e){let n=!1,s=!1,r=!1;for(let c=0,u=t.length;c<u;c++){const l=t[c];if(l.POSITION!==void 0&&(n=!0),l.NORMAL!==void 0&&(s=!0),l.COLOR_0!==void 0&&(r=!0),n&&s&&r)break}if(!n&&!s&&!r)return Promise.resolve(d);const o=[],a=[],i=[];for(let c=0,u=t.length;c<u;c++){const l=t[c];if(n){const f=l.POSITION!==void 0?e.getDependency("accessor",l.POSITION):d.attributes.position;o.push(f)}if(s){const f=l.NORMAL!==void 0?e.getDependency("accessor",l.NORMAL):d.attributes.normal;a.push(f)}if(r){const f=l.COLOR_0!==void 0?e.getDependency("accessor",l.COLOR_0):d.attributes.color;i.push(f)}}return Promise.all([Promise.all(o),Promise.all(a),Promise.all(i)]).then(function(c){const u=c[0],l=c[1],f=c[2];return n&&(d.morphAttributes.position=u),s&&(d.morphAttributes.normal=l),r&&(d.morphAttributes.color=f),d.morphTargetsRelative=!0,d})}function Se(d,t){if(d.updateMorphTargets(),t.weights!==void 0)for(let e=0,n=t.weights.length;e<n;e++)d.morphTargetInfluences[e]=t.weights[e];if(t.extras&&Array.isArray(t.extras.targetNames)){const e=t.extras.targetNames;if(d.morphTargetInfluences.length===e.length){d.morphTargetDictionary={};for(let n=0,s=e.length;n<s;n++)d.morphTargetDictionary[e[n]]=n}else console.warn("THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.")}}function ye(d){let t;const e=d.extensions&&d.extensions[T.KHR_DRACO_MESH_COMPRESSION];if(e?t="draco:"+e.bufferView+":"+e.indices+":"+v(e.attributes):t=d.indices+":"+v(d.attributes)+":"+d.mode,d.targets!==void 0)for(let n=0,s=d.targets.length;n<s;n++)t+=":"+v(d.targets[n]);return t}function v(d){let t="";const e=Object.keys(d).sort();for(let n=0,s=e.length;n<s;n++)t+=e[n]+":"+d[e[n]]+";";return t}function U(d){switch(d){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 we(d){return d.search(/\.jpe?g($|\?)/i)>0||d.search(/^data\:image\/jpeg/)===0?"image/jpeg":d.search(/\.webp($|\?)/i)>0||d.search(/^data\:image\/webp/)===0?"image/webp":d.search(/\.ktx2($|\?)/i)>0||d.search(/^data\:image\/ktx2/)===0?"image/ktx2":"image/png"}const be=new h.Matrix4;class Ne{constructor(t={},e={}){this.json=t,this.extensions={},this.plugins={},this.options=e,this.cache=new Z,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 n=!1,s=-1,r=!1,o=-1;if(typeof navigator<"u"&&typeof navigator.userAgent<"u"){const a=navigator.userAgent;n=/^((?!chrome|android).)*safari/i.test(a)===!0;const i=a.match(/Version\/(\d+)/);s=n&&i?parseInt(i[1],10):-1,r=a.indexOf("Firefox")>-1,o=r?a.match(/Firefox\/([0-9]+)\./)[1]:-1}typeof createImageBitmap>"u"||n&&s<17||r&&o<98?this.textureLoader=new h.TextureLoader(this.options.manager):this.textureLoader=new h.ImageBitmapLoader(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new h.FileLoader(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){const n=this,s=this.json,r=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll(function(o){return o._markDefs&&o._markDefs()}),Promise.all(this._invokeAll(function(o){return o.beforeRoot&&o.beforeRoot()})).then(function(){return Promise.all([n.getDependencies("scene"),n.getDependencies("animation"),n.getDependencies("camera")])}).then(function(o){const a={scene:o[0][s.scene||0],scenes:o[0],animations:o[1],cameras:o[2],asset:s.asset,parser:n,userData:{}};return I(r,a,s),w(a,s),Promise.all(n._invokeAll(function(i){return i.afterRoot&&i.afterRoot(a)})).then(function(){for(const i of a.scenes)i.updateMatrixWorld();t(a)})}).catch(e)}_markDefs(){const t=this.json.nodes||[],e=this.json.skins||[],n=this.json.meshes||[];for(let s=0,r=e.length;s<r;s++){const o=e[s].joints;for(let a=0,i=o.length;a<i;a++)t[o[a]].isBone=!0}for(let s=0,r=t.length;s<r;s++){const o=t[s];o.mesh!==void 0&&(this._addNodeRef(this.meshCache,o.mesh),o.skin!==void 0&&(n[o.mesh].isSkinnedMesh=!0)),o.camera!==void 0&&this._addNodeRef(this.cameraCache,o.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,n){if(t.refs[e]<=1)return n;const s=n.clone(),r=(o,a)=>{const i=this.associations.get(o);i!=null&&this.associations.set(a,i);for(const[c,u]of o.children.entries())r(u,a.children[c])};return r(n,s),s.name+="_instance_"+t.uses[e]++,s}_invokeOne(t){const e=Object.values(this.plugins);e.push(this);for(let n=0;n<e.length;n++){const s=t(e[n]);if(s)return s}return null}_invokeAll(t){const e=Object.values(this.plugins);e.unshift(this);const n=[];for(let s=0;s<e.length;s++){const r=t(e[s]);r&&n.push(r)}return n}getDependency(t,e){const n=t+":"+e;let s=this.cache.get(n);if(!s){switch(t){case"scene":s=this.loadScene(e);break;case"node":s=this._invokeOne(function(r){return r.loadNode&&r.loadNode(e)});break;case"mesh":s=this._invokeOne(function(r){return r.loadMesh&&r.loadMesh(e)});break;case"accessor":s=this.loadAccessor(e);break;case"bufferView":s=this._invokeOne(function(r){return r.loadBufferView&&r.loadBufferView(e)});break;case"buffer":s=this.loadBuffer(e);break;case"material":s=this._invokeOne(function(r){return r.loadMaterial&&r.loadMaterial(e)});break;case"texture":s=this._invokeOne(function(r){return r.loadTexture&&r.loadTexture(e)});break;case"skin":s=this.loadSkin(e);break;case"animation":s=this._invokeOne(function(r){return r.loadAnimation&&r.loadAnimation(e)});break;case"camera":s=this.loadCamera(e);break;default:if(s=this._invokeOne(function(r){return r!=this&&r.getDependency&&r.getDependency(t,e)}),!s)throw new Error("Unknown type: "+t);break}this.cache.add(n,s)}return s}getDependencies(t){let e=this.cache.get(t);if(!e){const n=this,s=this.json[t+(t==="mesh"?"es":"s")]||[];e=Promise.all(s.map(function(r,o){return n.getDependency(t,o)})),this.cache.add(t,e)}return e}loadBuffer(t){const e=this.json.buffers[t],n=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[T.KHR_BINARY_GLTF].body);const s=this.options;return new Promise(function(r,o){n.load(h.LoaderUtils.resolveURL(e.uri,s.path),r,void 0,function(){o(new Error('THREE.GLTFLoader: Failed to load buffer "'+e.uri+'".'))})})}loadBufferView(t){const e=this.json.bufferViews[t];return this.getDependency("buffer",e.buffer).then(function(n){const s=e.byteLength||0,r=e.byteOffset||0;return n.slice(r,r+s)})}loadAccessor(t){const e=this,n=this.json,s=this.json.accessors[t];if(s.bufferView===void 0&&s.sparse===void 0){const o=D[s.type],a=O[s.componentType],i=s.normalized===!0,c=new a(s.count*o);return Promise.resolve(new h.BufferAttribute(c,o,i))}const r=[];return s.bufferView!==void 0?r.push(this.getDependency("bufferView",s.bufferView)):r.push(null),s.sparse!==void 0&&(r.push(this.getDependency("bufferView",s.sparse.indices.bufferView)),r.push(this.getDependency("bufferView",s.sparse.values.bufferView))),Promise.all(r).then(function(o){const a=o[0],i=D[s.type],c=O[s.componentType],u=c.BYTES_PER_ELEMENT,l=u*i,f=s.byteOffset||0,p=s.bufferView!==void 0?n.bufferViews[s.bufferView].byteStride:void 0,m=s.normalized===!0;let M,g;if(p&&p!==l){const R=Math.floor(f/p),A="InterleavedBuffer:"+s.bufferView+":"+s.componentType+":"+R+":"+s.count;let x=e.cache.get(A);x||(M=new c(a,R*p,s.count*p/u),x=new h.InterleavedBuffer(M,p/u),e.cache.add(A,x)),g=new h.InterleavedBufferAttribute(x,i,f%p/u,m)}else a===null?M=new c(s.count*i):M=new c(a,f,s.count*i),g=new h.BufferAttribute(M,i,m);if(s.sparse!==void 0){const R=D.SCALAR,A=O[s.sparse.indices.componentType],x=s.sparse.indices.byteOffset||0,E=s.sparse.values.byteOffset||0,L=new A(o[1],x,s.sparse.count*R),b=new c(o[2],E,s.sparse.count*i);a!==null&&(g=new h.BufferAttribute(g.array.slice(),g.itemSize,g.normalized)),g.normalized=!1;for(let y=0,P=L.length;y<P;y++){const C=L[y];if(g.setX(C,b[y*i]),i>=2&&g.setY(C,b[y*i+1]),i>=3&&g.setZ(C,b[y*i+2]),i>=4&&g.setW(C,b[y*i+3]),i>=5)throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.")}g.normalized=m}return g})}loadTexture(t){const e=this.json,n=this.options,r=e.textures[t].source,o=e.images[r];let a=this.textureLoader;if(o.uri){const i=n.manager.getHandler(o.uri);i!==null&&(a=i)}return this.loadTextureImage(t,r,a)}loadTextureImage(t,e,n){const s=this,r=this.json,o=r.textures[t],a=r.images[e],i=(a.uri||a.bufferView)+":"+o.sampler;if(this.textureCache[i])return this.textureCache[i];const c=this.loadImageSource(e,n).then(function(u){u.flipY=!1,u.name=o.name||a.name||"",u.name===""&&typeof a.uri=="string"&&a.uri.startsWith("data:image/")===!1&&(u.name=a.uri);const f=(r.samplers||{})[o.sampler]||{};return u.magFilter=V[f.magFilter]||h.LinearFilter,u.minFilter=V[f.minFilter]||h.LinearMipmapLinearFilter,u.wrapS=z[f.wrapS]||h.RepeatWrapping,u.wrapT=z[f.wrapT]||h.RepeatWrapping,u.generateMipmaps=!u.isCompressedTexture&&u.minFilter!==h.NearestFilter&&u.minFilter!==h.LinearFilter,s.associations.set(u,{textures:t}),u}).catch(function(){return null});return this.textureCache[i]=c,c}loadImageSource(t,e){const n=this,s=this.json,r=this.options;if(this.sourceCache[t]!==void 0)return this.sourceCache[t].then(l=>l.clone());const o=s.images[t],a=self.URL||self.webkitURL;let i=o.uri||"",c=!1;if(o.bufferView!==void 0)i=n.getDependency("bufferView",o.bufferView).then(function(l){c=!0;const f=new Blob([l],{type:o.mimeType});return i=a.createObjectURL(f),i});else if(o.uri===void 0)throw new Error("THREE.GLTFLoader: Image "+t+" is missing URI and bufferView");const u=Promise.resolve(i).then(function(l){return new Promise(function(f,p){let m=f;e.isImageBitmapLoader===!0&&(m=function(M){const g=new h.Texture(M);g.needsUpdate=!0,f(g)}),e.load(h.LoaderUtils.resolveURL(l,r.path),m,void 0,p)})}).then(function(l){return c===!0&&a.revokeObjectURL(i),w(l,o),l.userData.mimeType=o.mimeType||we(o.uri),l}).catch(function(l){throw console.error("THREE.GLTFLoader: Couldn't load texture",i),l});return this.sourceCache[t]=u,u}assignTexture(t,e,n,s){const r=this;return this.getDependency("texture",n.index).then(function(o){if(!o)return null;if(n.texCoord!==void 0&&n.texCoord>0&&(o=o.clone(),o.channel=n.texCoord),r.extensions[T.KHR_TEXTURE_TRANSFORM]){const a=n.extensions!==void 0?n.extensions[T.KHR_TEXTURE_TRANSFORM]:void 0;if(a){const i=r.associations.get(o);o=r.extensions[T.KHR_TEXTURE_TRANSFORM].extendTexture(o,a),r.associations.set(o,i)}}return s!==void 0&&(o.colorSpace=s),t[e]=o,o})}assignFinalMaterial(t){const e=t.geometry;let n=t.material;const s=e.attributes.tangent===void 0,r=e.attributes.color!==void 0,o=e.attributes.normal===void 0;if(t.isPoints){const a="PointsMaterial:"+n.uuid;let i=this.cache.get(a);i||(i=new h.PointsMaterial,h.Material.prototype.copy.call(i,n),i.color.copy(n.color),i.map=n.map,i.sizeAttenuation=!1,this.cache.add(a,i)),n=i}else if(t.isLine){const a="LineBasicMaterial:"+n.uuid;let i=this.cache.get(a);i||(i=new h.LineBasicMaterial,h.Material.prototype.copy.call(i,n),i.color.copy(n.color),i.map=n.map,this.cache.add(a,i)),n=i}if(s||r||o){let a="ClonedMaterial:"+n.uuid+":";s&&(a+="derivative-tangents:"),r&&(a+="vertex-colors:"),o&&(a+="flat-shading:");let i=this.cache.get(a);i||(i=n.clone(),r&&(i.vertexColors=!0),o&&(i.flatShading=!0),s&&(i.normalScale&&(i.normalScale.y*=-1),i.clearcoatNormalScale&&(i.clearcoatNormalScale.y*=-1)),this.cache.add(a,i),this.associations.set(i,this.associations.get(n))),n=i}t.material=n}getMaterialType(){return h.MeshStandardMaterial}loadMaterial(t){const e=this,n=this.json,s=this.extensions,r=n.materials[t];let o;const a={},i=r.extensions||{},c=[];if(i[T.KHR_MATERIALS_UNLIT]){const l=s[T.KHR_MATERIALS_UNLIT];o=l.getMaterialType(),c.push(l.extendParams(a,r,e))}else{const l=r.pbrMetallicRoughness||{};if(a.color=new h.Color(1,1,1),a.opacity=1,Array.isArray(l.baseColorFactor)){const f=l.baseColorFactor;a.color.setRGB(f[0],f[1],f[2],h.LinearSRGBColorSpace),a.opacity=f[3]}l.baseColorTexture!==void 0&&c.push(e.assignTexture(a,"map",l.baseColorTexture,h.SRGBColorSpace)),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))),o=this._invokeOne(function(f){return f.getMaterialType&&f.getMaterialType(t)}),c.push(Promise.all(this._invokeAll(function(f){return f.extendMaterialParams&&f.extendMaterialParams(t,a)})))}r.doubleSided===!0&&(a.side=h.DoubleSide);const u=r.alphaMode||G.OPAQUE;if(u===G.BLEND?(a.transparent=!0,a.depthWrite=!1):(a.transparent=!1,u===G.MASK&&(a.alphaTest=r.alphaCutoff!==void 0?r.alphaCutoff:.5)),r.normalTexture!==void 0&&o!==h.MeshBasicMaterial&&(c.push(e.assignTexture(a,"normalMap",r.normalTexture)),a.normalScale=new h.Vector2(1,1),r.normalTexture.scale!==void 0)){const l=r.normalTexture.scale;a.normalScale.set(l,l)}if(r.occlusionTexture!==void 0&&o!==h.MeshBasicMaterial&&(c.push(e.assignTexture(a,"aoMap",r.occlusionTexture)),r.occlusionTexture.strength!==void 0&&(a.aoMapIntensity=r.occlusionTexture.strength)),r.emissiveFactor!==void 0&&o!==h.MeshBasicMaterial){const l=r.emissiveFactor;a.emissive=new h.Color().setRGB(l[0],l[1],l[2],h.LinearSRGBColorSpace)}return r.emissiveTexture!==void 0&&o!==h.MeshBasicMaterial&&c.push(e.assignTexture(a,"emissiveMap",r.emissiveTexture,h.SRGBColorSpace)),Promise.all(c).then(function(){const l=new o(a);return r.name&&(l.name=r.name),w(l,r),e.associations.set(l,{materials:t}),r.extensions&&I(s,l,r),l})}createUniqueName(t){const e=h.PropertyBinding.sanitizeNodeName(t||"");return e in this.nodeNamesUsed?e+"_"+ ++this.nodeNamesUsed[e]:(this.nodeNamesUsed[e]=0,e)}loadGeometries(t){const e=this,n=this.extensions,s=this.primitiveCache;function r(a){return n[T.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(a,e).then(function(i){return X(i,a,e)})}const o=[];for(let a=0,i=t.length;a<i;a++){const c=t[a],u=ye(c),l=s[u];if(l)o.push(l.promise);else{let f;c.extensions&&c.extensions[T.KHR_DRACO_MESH_COMPRESSION]?f=r(c):f=X(new h.BufferGeometry,c,e),s[u]={primitive:c,promise:f},o.push(f)}}return Promise.all(o)}loadMesh(t){const e=this,n=this.json,s=this.extensions,r=n.meshes[t],o=r.primitives,a=[];for(let i=0,c=o.length;i<c;i++){const u=o[i].material===void 0?_e(this.cache):this.getDependency("material",o[i].material);a.push(u)}return a.push(e.loadGeometries(o)),Promise.all(a).then(function(i){const c=i.slice(0,i.length-1),u=i[i.length-1],l=[];for(let p=0,m=u.length;p<m;p++){const M=u[p],g=o[p];let R;const A=c[p];if(g.mode===S.TRIANGLES||g.mode===S.TRIANGLE_STRIP||g.mode===S.TRIANGLE_FAN||g.mode===void 0)R=r.isSkinnedMesh===!0?new h.SkinnedMesh(M,A):new h.Mesh(M,A),R.isSkinnedMesh===!0&&R.normalizeSkinWeights(),g.mode===S.TRIANGLE_STRIP?R.geometry=h.toTrianglesDrawMode(R.geometry,h.TriangleStripDrawMode):g.mode===S.TRIANGLE_FAN&&(R.geometry=h.toTrianglesDrawMode(R.geometry,h.TriangleFanDrawMode));else if(g.mode===S.LINES)R=new h.LineSegments(M,A);else if(g.mode===S.LINE_STRIP)R=new h.Line(M,A);else if(g.mode===S.LINE_LOOP)R=new h.LineLoop(M,A);else if(g.mode===S.POINTS)R=new h.Points(M,A);else throw new Error("THREE.GLTFLoader: Primitive mode unsupported: "+g.mode);Object.keys(R.geometry.morphAttributes).length>0&&Se(R,r),R.name=e.createUniqueName(r.name||"mesh_"+t),w(R,r),g.extensions&&I(s,R,g),e.assignFinalMaterial(R),l.push(R)}for(let p=0,m=l.length;p<m;p++)e.associations.set(l[p],{meshes:t,primitives:p});if(l.length===1)return r.extensions&&I(s,l[0],r),l[0];const f=new h.Group;r.extensions&&I(s,f,r),e.associations.set(f,{meshes:t});for(let p=0,m=l.length;p<m;p++)f.add(l[p]);return f})}loadCamera(t){let e;const n=this.json.cameras[t],s=n[n.type];if(!s){console.warn("THREE.GLTFLoader: Missing camera parameters.");return}return n.type==="perspective"?e=new h.PerspectiveCamera(h.MathUtils.radToDeg(s.yfov),s.aspectRatio||1,s.znear||1,s.zfar||2e6):n.type==="orthographic"&&(e=new h.OrthographicCamera(-s.xmag,s.xmag,s.ymag,-s.ymag,s.znear,s.zfar)),n.name&&(e.name=this.createUniqueName(n.name)),w(e,n),Promise.resolve(e)}loadSkin(t){const e=this.json.skins[t],n=[];for(let s=0,r=e.joints.length;s<r;s++)n.push(this._loadNodeShallow(e.joints[s]));return e.inverseBindMatrices!==void 0?n.push(this.getDependency("accessor",e.inverseBindMatrices)):n.push(null),Promise.all(n).then(function(s){const r=s.pop(),o=s,a=[],i=[];for(let c=0,u=o.length;c<u;c++){const l=o[c];if(l){a.push(l);const f=new h.Matrix4;r!==null&&f.fromArray(r.array,c*16),i.push(f)}else console.warn('THREE.GLTFLoader: Joint "%s" could not be found.',e.joints[c])}return new h.Skeleton(a,i)})}loadAnimation(t){const e=this.json,n=this,s=e.animations[t],r=s.name?s.name:"animation_"+t,o=[],a=[],i=[],c=[],u=[];for(let l=0,f=s.channels.length;l<f;l++){const p=s.channels[l],m=s.samplers[p.sampler],M=p.target,g=M.node,R=s.parameters!==void 0?s.parameters[m.input]:m.input,A=s.parameters!==void 0?s.parameters[m.output]:m.output;M.node!==void 0&&(o.push(this.getDependency("node",g)),a.push(this.getDependency("accessor",R)),i.push(this.getDependency("accessor",A)),c.push(m),u.push(M))}return Promise.all([Promise.all(o),Promise.all(a),Promise.all(i),Promise.all(c),Promise.all(u)]).then(function(l){const f=l[0],p=l[1],m=l[2],M=l[3],g=l[4],R=[];for(let x=0,E=f.length;x<E;x++){const L=f[x],b=p[x],y=m[x],P=M[x],C=g[x];if(L===void 0)continue;L.updateMatrix&&L.updateMatrix();const k=n._createAnimationTracks(L,b,y,P,C);if(k)for(let H=0;H<k.length;H++)R.push(k[H])}const A=new h.AnimationClip(r,void 0,R);return w(A,s),A})}createNodeMesh(t){const e=this.json,n=this,s=e.nodes[t];return s.mesh===void 0?null:n.getDependency("mesh",s.mesh).then(function(r){const o=n._getNodeRef(n.meshCache,s.mesh,r);return s.weights!==void 0&&o.traverse(function(a){if(a.isMesh)for(let i=0,c=s.weights.length;i<c;i++)a.morphTargetInfluences[i]=s.weights[i]}),o})}loadNode(t){const e=this.json,n=this,s=e.nodes[t],r=n._loadNodeShallow(t),o=[],a=s.children||[];for(let c=0,u=a.length;c<u;c++)o.push(n.getDependency("node",a[c]));const i=s.skin===void 0?Promise.resolve(null):n.getDependency("skin",s.skin);return Promise.all([r,Promise.all(o),i]).then(function(c){const u=c[0],l=c[1],f=c[2];f!==null&&u.traverse(function(p){p.isSkinnedMesh&&p.bind(f,be)});for(let p=0,m=l.length;p<m;p++)u.add(l[p]);if(u.userData.pivot!==void 0&&l.length>0){const p=u.userData.pivot,m=l[0];u.pivot=new h.Vector3().fromArray(p),u.position.x-=p[0],u.position.y-=p[1],u.position.z-=p[2],m.position.set(0,0,0),delete u.userData.pivot}return u})}_loadNodeShallow(t){const e=this.json,n=this.extensions,s=this;if(this.nodeCache[t]!==void 0)return this.nodeCache[t];const r=e.nodes[t],o=r.name?s.createUniqueName(r.name):"",a=[],i=s._invokeOne(function(c){return c.createNodeMesh&&c.createNodeMesh(t)});return i&&a.push(i),r.camera!==void 0&&a.push(s.getDependency("camera",r.camera).then(function(c){return s._getNodeRef(s.cameraCache,r.camera,c)})),s._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 h.Bone:c.length>1?u=new h.Group:c.length===1?u=c[0]:u=new h.Object3D,u!==c[0])for(let l=0,f=c.length;l<f;l++)u.add(c[l]);if(r.name&&(u.userData.name=r.name,u.name=o),w(u,r),r.extensions&&I(n,u,r),r.matrix!==void 0){const l=new h.Matrix4;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(!s.associations.has(u))s.associations.set(u,{});else if(r.mesh!==void 0&&s.meshCache.refs[r.mesh]>1){const l=s.associations.get(u);s.associations.set(u,{...l})}return s.associations.get(u).nodes=t,u}),this.nodeCache[t]}loadScene(t){const e=this.extensions,n=this.json.scenes[t],s=this,r=new h.Group;n.name&&(r.name=s.createUniqueName(n.name)),w(r,n),n.extensions&&I(e,r,n);const o=n.nodes||[],a=[];for(let i=0,c=o.length;i<c;i++)a.push(s.getDependency("node",o[i]));return Promise.all(a).then(function(i){for(let u=0,l=i.length;u<l;u++){const f=i[u];f.parent!==null?r.add(Q(f)):r.add(f)}const c=u=>{const l=new Map;for(const[f,p]of s.associations)(f instanceof h.Material||f instanceof h.Texture)&&l.set(f,p);return u.traverse(f=>{const p=s.associations.get(f);p!=null&&l.set(f,p)}),l};return s.associations=c(r),r})}_createAnimationTracks(t,e,n,s,r){const o=[],a=t.name?t.name:t.uuid,i=[];N[r.path]===N.weights?t.traverse(function(f){f.morphTargetInfluences&&i.push(f.name?f.name:f.uuid)}):i.push(a);let c;switch(N[r.path]){case N.weights:c=h.NumberKeyframeTrack;break;case N.rotation:c=h.QuaternionKeyframeTrack;break;case N.translation:case N.scale:c=h.VectorKeyframeTrack;break;default:n.itemSize===1?c=h.NumberKeyframeTrack:c=h.VectorKeyframeTrack;break}const u=s.interpolation!==void 0?Ae[s.interpolation]:h.InterpolateLinear,l=this._getArrayFromAccessor(n);for(let f=0,p=i.length;f<p;f++){const m=new c(i[f]+"."+N[r.path],e.array,l,u);s.interpolation==="CUBICSPLINE"&&this._createCubicSplineTrackInterpolant(m),o.push(m)}return o}_getArrayFromAccessor(t){let e=t.array;if(t.normalized){const n=U(e.constructor),s=new Float32Array(e.length);for(let r=0,o=e.length;r<o;r++)s[r]=e[r]*n;e=s}return e}_createCubicSplineTrackInterpolant(t){t.createInterpolant=function(n){const s=this instanceof h.QuaternionKeyframeTrack?xe:Y;return new s(this.times,this.values,this.getValueSize()/3,n)},t.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline=!0}}function Ie(d,t,e){const n=t.attributes,s=new h.Box3;if(n.POSITION!==void 0){const a=e.json.accessors[n.POSITION],i=a.min,c=a.max;if(i!==void 0&&c!==void 0){if(s.set(new h.Vector3(i[0],i[1],i[2]),new h.Vector3(c[0],c[1],c[2])),a.normalized){const u=U(O[a.componentType]);s.min.multiplyScalar(u),s.max.multiplyScalar(u)}}else{console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.");return}}else return;const r=t.targets;if(r!==void 0){const a=new h.Vector3,i=new h.Vector3;for(let c=0,u=r.length;c<u;c++){const l=r[c];if(l.POSITION!==void 0){const f=e.json.accessors[l.POSITION],p=f.min,m=f.max;if(p!==void 0&&m!==void 0){if(i.setX(Math.max(Math.abs(p[0]),Math.abs(m[0]))),i.setY(Math.max(Math.abs(p[1]),Math.abs(m[1]))),i.setZ(Math.max(Math.abs(p[2]),Math.abs(m[2]))),f.normalized){const M=U(O[f.componentType]);i.multiplyScalar(M)}a.max(i)}else console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.")}}s.expandByVector(a)}d.boundingBox=s;const o=new h.Sphere;s.getCenter(o.center),o.radius=s.min.distanceTo(s.max)/2,d.boundingSphere=o}function X(d,t,e){const n=t.attributes,s=[];function r(o,a){return e.getDependency("accessor",o).then(function(i){d.setAttribute(a,i)})}for(const o in n){const a=B[o]||o.toLowerCase();a in d.attributes||s.push(r(n[o],a))}if(t.indices!==void 0&&!d.index){const o=e.getDependency("accessor",t.indices).then(function(a){d.setIndex(a)});s.push(o)}return h.ColorManagement.workingColorSpace!==h.LinearSRGBColorSpace&&"COLOR_0"in n&&console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${h.ColorManagement.workingColorSpace}" not supported.`),w(d,t),Ie(d,t,e),Promise.all(s).then(function(){return t.targets!==void 0?Le(d,t.targets,e):d})}exports.GLTFLoader=J;
@@ -1,7 +1,12 @@
1
+ import { DevicePlatform } from '../core/stream-utils';
2
+ import { ScreenshotData, ImperativeKeyboardEvent, RemoteControlConnectionState, MicrophoneState, CameraStreamStats } from '../core/stream-types';
1
3
  import { default as React } from 'react';
4
+ import { PlaybackStats } from '../core/playback-stats';
2
5
  import { AxStatus, AndroidElementTreeOptions } from '../core/ax-fetcher';
3
6
  import { AxElement, AxSnapshot } from '../core/ax-tree';
4
7
  import { CameraCaptureInfo } from '../core/camera';
8
+ export type { RemoteControlConnectionState, MicrophoneState, CameraStreamStats } from '../core/stream-types';
9
+ export { withAuthenticationToken } from '../core/stream-utils';
5
10
  export type { CameraCaptureInfo, CameraFacingMode, CameraRequest, CameraResult } from '../core/camera';
6
11
  declare global {
7
12
  interface Window {
@@ -22,6 +27,23 @@ export interface RemoteControlProps {
22
27
  /** Optional prepared Duo GLB, supplied and licensed by the host application. */
23
28
  duoModelUrl?: string;
24
29
  autoReconnect?: boolean;
30
+ /**
31
+ * Preferred playback jitter buffer duration in milliseconds (0–4000), for
32
+ * incoming audio and video. Lower values can reduce latency but increase
33
+ * dropped frames or freezes. This is a preference, not a latency limit.
34
+ * Updates apply without reconnecting. Omit or pass null to use the browser
35
+ * default. Unsupported browsers ignore this prop. Invalid values are ignored
36
+ * with a console warning, leaving the previous target unchanged.
37
+ */
38
+ jitterBufferTargetMs?: number | null;
39
+ /**
40
+ * Incoming playback stats, sampled every two seconds while subscribed,
41
+ * connected, and visible. Works with iOS and Android, including Duo displays.
42
+ * Missing measurements stay undefined; the first sample establishes a baseline.
43
+ * Emits null when collection pauses, disconnects, or fails after a sample.
44
+ * Buffer delay measures receiving-side buffering, not tap-to-screen latency.
45
+ */
46
+ onPlaybackStats?: (stats: PlaybackStats | null) => void;
25
47
  /**
26
48
  * Fires once when the component concludes the instance is permanently
27
49
  * gone rather than suffering a recoverable connection blip.
@@ -185,71 +207,6 @@ export interface RemoteControlProps {
185
207
  */
186
208
  onMicrophoneStateChange?: (state: MicrophoneState) => void;
187
209
  }
188
- /**
189
- * Snapshot of the live-microphone pipeline, reported through
190
- * `onMicrophoneStateChange`.
191
- */
192
- export interface MicrophoneState {
193
- /** True while the browser mic is captured and streaming to the sim. */
194
- active: boolean;
195
- /**
196
- * Human-readable failure from the last attempt, if any (permission
197
- * denied, no device, host rejection, ...).
198
- */
199
- error?: string;
200
- /** Device label of the captured microphone, when available. */
201
- label?: string;
202
- }
203
- /**
204
- * Live outbound-camera quality snapshot. Derived from
205
- * `RTCPeerConnection.getStats()` and rate-derived deltas, sampled
206
- * once per second while the camera is sending. All fields optional:
207
- * some browsers omit fields (Safari rarely reports
208
- * `encoderImplementation`), and the first sample after camera start
209
- * has no delta-derived numbers yet.
210
- */
211
- export interface CameraStreamStats {
212
- /** "H264", "HEVC"/"H265", "VP9", "VP8", "AV1", etc. (uppercased). */
213
- codec?: string;
214
- /** e.g. "VideoToolbox" (hw), "OpenH264" (sw), "ExternalEncoder". */
215
- encoderImplementation?: string;
216
- /**
217
- * Browser-reported hardware-acceleration hint. Some Chromium
218
- * versions expose this via `powerEfficientEncoder`; we mirror it
219
- * here so consumers don't have to know the spec quirk.
220
- */
221
- hardwareAccelerated?: boolean;
222
- /** Outbound encoded fps over the last sample window. */
223
- framesPerSecond?: number;
224
- /** Cumulative encoded frame count. */
225
- framesEncoded?: number;
226
- /** Outbound encoded bitrate (bits/s) over the last window. */
227
- bitrateBps?: number;
228
- /** Width/height the encoder is currently producing. */
229
- width?: number;
230
- height?: number;
231
- /**
232
- * One of `'none' | 'cpu' | 'bandwidth' | 'other'`. Mirrors
233
- * Meet/Zoom's "limited by …" banners. Anything other than
234
- * `'none'` means the encoder dropped resolution to keep up.
235
- */
236
- qualityLimitationReason?: string;
237
- /** Round-trip time in milliseconds, from the matching RTCP. */
238
- rttMs?: number;
239
- /** Packet-loss percentage over the last sample window (0..100). */
240
- packetsLostPct?: number;
241
- }
242
- interface ScreenshotData {
243
- dataUri: string;
244
- }
245
- export interface ImperativeKeyboardEvent {
246
- type: 'keydown' | 'keyup';
247
- code: string;
248
- shiftKey?: boolean;
249
- altKey?: boolean;
250
- ctrlKey?: boolean;
251
- metaKey?: boolean;
252
- }
253
210
  export interface RemoteControlHandle {
254
211
  openUrl: (url: string) => void;
255
212
  sendKeyEvent: (event: ImperativeKeyboardEvent) => void;
@@ -262,9 +219,6 @@ export interface RemoteControlHandle {
262
219
  setInspectSelection: (element: AxElement | null) => void;
263
220
  getAxStatus: () => AxStatus;
264
221
  }
265
- type DevicePlatform = 'ios' | 'android';
266
- export declare const withAuthenticationToken: (url: string, token: string) => string;
267
- export type RemoteControlConnectionState = 'connecting' | 'connected' | 'reconnecting' | 'failed' | 'terminated';
268
222
  export type RemoteControlPlatformAssets = {
269
223
  frame?: string;
270
224
  frameLandscape?: string;
@@ -0,0 +1,30 @@
1
+ import { AxSnapshot } from './ax-tree';
2
+ import { ScreenshotData, ImperativeKeyboardEvent } from './stream-types';
3
+ import { DeviceStreamOptions, DeviceStreamLiveOptions, DeviceStreamState, StreamDisplay, DeviceFrameSink } from './stream-options';
4
+ /** A browser session shared by RemoteControl and custom renderers. No React or CSS required. */
5
+ export declare function createDeviceStream(initialOptions: DeviceStreamOptions): {
6
+ start: () => void;
7
+ stop: () => void;
8
+ attachVideo: (video: HTMLVideoElement, display?: StreamDisplay) => () => void;
9
+ attachFrameSink: (sink: DeviceFrameSink, display?: StreamDisplay) => () => void;
10
+ dispose: () => void;
11
+ getState: () => DeviceStreamState;
12
+ updateOptions: (patch: Partial<DeviceStreamLiveOptions>) => void;
13
+ sendControl: (data: ArrayBuffer) => void;
14
+ sendTouch: (phase: "begin" | "move" | "end", x: number, y: number, width: number, height: number, pointerId?: number) => void;
15
+ sendText: (text: string) => void;
16
+ sendDisplayTouch: (action: number, display: number, x: number, y: number) => void;
17
+ sendDuoControl: (type: string, parameters: object) => Promise<void>;
18
+ pressButton: (button: "home" | "back" | "recents" | "power") => void;
19
+ rotate: () => void;
20
+ bumpActivity: () => void | undefined;
21
+ getAxStatus: () => import('./ax-fetcher').AxStatus;
22
+ openUrl: (newUrl: string) => void;
23
+ sendKeyEvent: (event: ImperativeKeyboardEvent) => void;
24
+ screenshot: (display?: "outer" | "inner") => Promise<ScreenshotData>;
25
+ terminateApp: (bundleId: string) => Promise<void>;
26
+ reconnect: () => void;
27
+ refreshAxTree: () => Promise<AxSnapshot>;
28
+ getAxSnapshot: () => AxSnapshot | null;
29
+ };
30
+ export type DeviceStream = ReturnType<typeof createDeviceStream>;
@@ -0,0 +1,2 @@
1
+ /** Set a playback preference without letting browser support interrupt the stream. */
2
+ export declare function applyJitterBufferTarget(receiver: RTCRtpReceiver, targetMs: number | null | undefined): void;
@@ -0,0 +1,48 @@
1
+ /** Measurements for one incoming RTP stream. Missing browser fields stay undefined. */
2
+ export interface PlaybackTrackStats {
3
+ /** Browser stats identity. Changes when the RTP stream is replaced. */
4
+ id: string;
5
+ trackId: string;
6
+ /** Browser collection time in Unix milliseconds. */
7
+ timestamp: number;
8
+ /** Time between this stream's samples. Absent on the first sample. */
9
+ intervalMs?: number;
10
+ /** Average receiving-side buffer delay over the interval, not end-to-end latency. */
11
+ bufferDelayMs?: number;
12
+ /** Received media bitrate over the interval, in bits per second. */
13
+ bitrateBps?: number;
14
+ }
15
+ export interface PlaybackVideoStats extends PlaybackTrackStats {
16
+ /** The main display, or the independently streamed inner display on iPhone Duo. */
17
+ display: 'primary' | 'inner';
18
+ /** Decoded frames per second over the interval. Static screens may send few frames. */
19
+ fps?: number;
20
+ /** Frames dropped during the interval, as reported by the browser. */
21
+ droppedFrames?: number;
22
+ /** Browser-reported freezes completed during the interval. */
23
+ freezes?: number;
24
+ }
25
+ export type PlaybackAudioStats = PlaybackTrackStats;
26
+ export interface PlaybackStats {
27
+ /** Latest incoming-stream collection time in Unix milliseconds. */
28
+ timestamp: number;
29
+ /** Configured preference; null means automatic. Absent when the prop is invalid. */
30
+ requestedTargetMs?: number | null;
31
+ /** Current round-trip time of the selected ICE pair, when reported by the browser. */
32
+ rttMs?: number;
33
+ /** Separate measurements for each incoming display; never sum their frame rates. */
34
+ video: PlaybackVideoStats[];
35
+ audio: PlaybackAudioStats[];
36
+ }
37
+ export interface PlaybackReceiver {
38
+ trackId: string;
39
+ kind: string;
40
+ mid: string | null;
41
+ display?: PlaybackVideoStats['display'];
42
+ }
43
+ /** Keep baselines per stream so reconnects and Duo displays cannot contaminate each other. */
44
+ export declare class PlaybackStatsReader {
45
+ private previous;
46
+ reset(): void;
47
+ read(report: RTCStatsReport, receivers: PlaybackReceiver[], target: number | null | undefined): PlaybackStats | null;
48
+ }
@@ -0,0 +1,7 @@
1
+ import { PlaybackStats, PlaybackVideoStats } from './playback-stats';
2
+ export interface PlaybackConnection {
3
+ peer: RTCPeerConnection;
4
+ displays: Map<RTCRtpReceiver, PlaybackVideoStats['display']>;
5
+ }
6
+ /** Poll only visible, connected subscribers and discard stale asynchronous results. */
7
+ export declare function subscribePlaybackStats(connection: PlaybackConnection, callback: () => ((stats: PlaybackStats | null) => void) | undefined, target: () => number | null | undefined): () => void;