u-space 0.0.30 → 0.0.32

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.
Files changed (37) hide show
  1. package/dist/getTransferables-C97JPUVf.cjs +1 -0
  2. package/dist/getTransferables-DrzSmiCR.js +43 -0
  3. package/dist/index.cjs +3 -3
  4. package/dist/index.js +1549 -1026
  5. package/dist/modelDecodeProtocol-D1Apm9iG.cjs +1 -0
  6. package/dist/modelDecodeProtocol-wDB7ksYw.js +56 -0
  7. package/dist/plugins/u-manager/index.cjs +1 -1
  8. package/dist/plugins/u-manager/index.js +73 -53
  9. package/dist/src/loaders/ModelDecodeWorkerClient.d.ts +31 -0
  10. package/dist/src/loaders/ModelLoaderManager.d.ts +15 -2
  11. package/dist/src/loaders/buildDecodedGltfModel.d.ts +4 -0
  12. package/dist/src/loaders/index.d.ts +1 -0
  13. package/dist/src/objects/Model.d.ts +1 -0
  14. package/dist/src/worker/decodeGltfModel.d.ts +10 -0
  15. package/dist/src/worker/getTransferables.d.ts +1 -0
  16. package/dist/src/worker/index.d.ts +1 -0
  17. package/dist/src/worker/installWorkerImageLoader.d.ts +3 -0
  18. package/dist/src/worker/model-decoder.d.ts +13 -0
  19. package/dist/src/worker/modelDecodeProtocol.d.ts +205 -0
  20. package/dist/src/worker/workerImageUtils.d.ts +8 -0
  21. package/dist/worker/index.cjs +1 -1
  22. package/dist/worker/index.js +8 -6
  23. package/dist/worker/model-decoder.cjs +1 -0
  24. package/dist/worker/model-decoder.js +339 -0
  25. package/dist/worker/runtime.cjs +1 -1
  26. package/dist/worker/runtime.js +202 -208
  27. package/dist/workerImageUtils-lmOMyTQN.cjs +1 -0
  28. package/dist/workerImageUtils-mQD3TQ1N.js +105 -0
  29. package/docs/api-effects.md +66 -2
  30. package/docs/api-viewer.md +45 -1
  31. package/docs/changelog.md +26 -0
  32. package/docs/examples-guide.md +31 -11
  33. package/docs/getting-started.md +97 -93
  34. package/docs/index.md +2 -2
  35. package/docs/mcp.md +16 -3
  36. package/docs/release.md +5 -3
  37. package/package.json +9 -1
@@ -0,0 +1,205 @@
1
+ export declare const MODEL_DECODE_PROTOCOL_VERSION: 3;
2
+ export interface SerializedModelDecodeError {
3
+ message: string;
4
+ name?: string;
5
+ stack?: string;
6
+ }
7
+ export interface ModelDecodeRequestOptions {
8
+ persistent?: boolean;
9
+ headers?: Record<string, string>;
10
+ credentials?: RequestCredentials;
11
+ /** Original absolute model URL used to resolve relative glTF dependencies. */
12
+ resourceBaseUrl?: string;
13
+ }
14
+ export interface GltfBufferDefinition {
15
+ byteLength: number;
16
+ uri?: string;
17
+ name?: string;
18
+ }
19
+ export interface GltfBufferViewDefinition {
20
+ buffer: number;
21
+ byteOffset?: number;
22
+ byteLength: number;
23
+ byteStride?: number;
24
+ target?: number;
25
+ name?: string;
26
+ extensions?: Record<string, unknown>;
27
+ }
28
+ export interface GltfAccessorDefinition {
29
+ bufferView?: number;
30
+ byteOffset?: number;
31
+ componentType: number;
32
+ normalized?: boolean;
33
+ count: number;
34
+ type: string;
35
+ min?: number[];
36
+ max?: number[];
37
+ sparse?: unknown;
38
+ name?: string;
39
+ }
40
+ export interface GltfTextureInfo {
41
+ index: number;
42
+ texCoord?: number;
43
+ scale?: number;
44
+ strength?: number;
45
+ extensions?: Record<string, unknown>;
46
+ }
47
+ export interface GltfMaterialDefinition {
48
+ name?: string;
49
+ pbrMetallicRoughness?: {
50
+ baseColorFactor?: number[];
51
+ baseColorTexture?: GltfTextureInfo;
52
+ metallicFactor?: number;
53
+ roughnessFactor?: number;
54
+ metallicRoughnessTexture?: GltfTextureInfo;
55
+ };
56
+ normalTexture?: GltfTextureInfo;
57
+ occlusionTexture?: GltfTextureInfo;
58
+ emissiveTexture?: GltfTextureInfo;
59
+ emissiveFactor?: number[];
60
+ alphaMode?: 'OPAQUE' | 'MASK' | 'BLEND';
61
+ alphaCutoff?: number;
62
+ doubleSided?: boolean;
63
+ extras?: unknown;
64
+ extensions?: Record<string, unknown>;
65
+ }
66
+ export interface GltfPrimitiveDefinition {
67
+ attributes: Record<string, number>;
68
+ indices?: number;
69
+ material?: number;
70
+ mode?: number;
71
+ targets?: unknown[];
72
+ extensions?: Record<string, unknown>;
73
+ }
74
+ export interface GltfMeshDefinition {
75
+ name?: string;
76
+ primitives: GltfPrimitiveDefinition[];
77
+ extras?: unknown;
78
+ }
79
+ export interface GltfNodeDefinition {
80
+ name?: string;
81
+ mesh?: number;
82
+ camera?: number;
83
+ children?: number[];
84
+ matrix?: number[];
85
+ translation?: number[];
86
+ rotation?: number[];
87
+ scale?: number[];
88
+ weights?: number[];
89
+ skin?: number;
90
+ extras?: unknown;
91
+ extensions?: Record<string, unknown>;
92
+ }
93
+ export interface GltfSceneDefinition {
94
+ name?: string;
95
+ nodes?: number[];
96
+ extras?: unknown;
97
+ }
98
+ export interface GltfImageDefinition {
99
+ name?: string;
100
+ uri?: string;
101
+ mimeType?: string;
102
+ bufferView?: number;
103
+ }
104
+ export interface GltfSamplerDefinition {
105
+ name?: string;
106
+ magFilter?: number;
107
+ minFilter?: number;
108
+ wrapS?: number;
109
+ wrapT?: number;
110
+ }
111
+ export interface GltfTextureDefinition {
112
+ name?: string;
113
+ sampler?: number;
114
+ source?: number;
115
+ extensions?: Record<string, unknown>;
116
+ }
117
+ export interface GltfDocument {
118
+ asset: {
119
+ version: string;
120
+ generator?: string;
121
+ };
122
+ scene?: number;
123
+ scenes?: GltfSceneDefinition[];
124
+ nodes?: GltfNodeDefinition[];
125
+ meshes?: GltfMeshDefinition[];
126
+ accessors?: GltfAccessorDefinition[];
127
+ bufferViews?: GltfBufferViewDefinition[];
128
+ buffers?: GltfBufferDefinition[];
129
+ materials?: GltfMaterialDefinition[];
130
+ textures?: GltfTextureDefinition[];
131
+ samplers?: GltfSamplerDefinition[];
132
+ images?: GltfImageDefinition[];
133
+ animations?: unknown[];
134
+ skins?: unknown[];
135
+ cameras?: unknown[];
136
+ extensionsUsed?: string[];
137
+ extensionsRequired?: string[];
138
+ extensions?: Record<string, unknown>;
139
+ }
140
+ export interface DecodedGltfModelPacket {
141
+ protocolVersion: typeof MODEL_DECODE_PROTOCOL_VERSION;
142
+ kind: 'gltf-static';
143
+ url: string;
144
+ document: GltfDocument;
145
+ buffers: ArrayBuffer[];
146
+ images: ImageBitmap[];
147
+ /** Stable content identities used to preserve material batching across models. */
148
+ imageKeys: string[];
149
+ }
150
+ /**
151
+ * Validates the parts of the glTF node graph that would otherwise make
152
+ * recursive Object3D reconstruction unsafe. glTF nodes form a forest: a node
153
+ * cannot be repeated under one parent, have multiple parents, or form cycles.
154
+ */
155
+ export declare function validateDecodedGltfNodeGraph(document: GltfDocument): void;
156
+ export type ModelDecodeWorkerRequest = {
157
+ type: 'decode';
158
+ id: number;
159
+ url: string;
160
+ options: ModelDecodeRequestOptions;
161
+ } | {
162
+ type: 'cancel';
163
+ id: number;
164
+ } | {
165
+ type: 'ack';
166
+ id: number;
167
+ } | {
168
+ type: 'resource-resolved';
169
+ id: number;
170
+ resourceId: number;
171
+ url?: string;
172
+ error?: SerializedModelDecodeError;
173
+ } | {
174
+ type: 'dispose';
175
+ };
176
+ export type ModelDecodeWorkerResponse = {
177
+ type: 'decoded';
178
+ id: number;
179
+ packet: DecodedGltfModelPacket;
180
+ } | {
181
+ type: 'unsupported';
182
+ id: number;
183
+ reason: string;
184
+ } | {
185
+ type: 'error';
186
+ id: number;
187
+ error: SerializedModelDecodeError;
188
+ } | {
189
+ type: 'resolve-resource';
190
+ id: number;
191
+ resourceId: number;
192
+ url: string;
193
+ } | {
194
+ type: 'resource-complete';
195
+ id: number;
196
+ resourceId: number;
197
+ ok: boolean;
198
+ error?: SerializedModelDecodeError;
199
+ } | {
200
+ type: 'disposed';
201
+ };
202
+ export declare class UnsupportedModelDecodeError extends Error {
203
+ name: string;
204
+ constructor(message: string);
205
+ }
@@ -0,0 +1,8 @@
1
+ interface ImageDimensions {
2
+ width: number;
3
+ height: number;
4
+ }
5
+ export declare const MAX_WORKER_TEXTURE_DIMENSION_2D = 8192;
6
+ export declare function clampWorkerImageDimensions(width: number, height: number, maxDimension?: number): ImageDimensions | null;
7
+ export declare function createWorkerImageBitmap(blob: Blob, options?: ImageBitmapOptions): Promise<ImageBitmap>;
8
+ export {};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("../protocol-IUAzx0lk.cjs"),n=["click","dblclick","contextmenu","pointerdown","pointerup","pointermove","pointercancel","wheel"];function a(i){const e=i,t=i,s=i;return{type:i.type,pointerId:t.pointerId,pointerType:t.pointerType,button:e.button,buttons:e.buttons,altKey:e.altKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey,shiftKey:e.shiftKey,movementX:e.movementX,movementY:e.movementY,clientX:e.clientX,clientY:e.clientY,offsetX:e.offsetX,offsetY:e.offsetY,pageX:e.pageX,pageY:e.pageY,screenX:e.screenX,screenY:e.screenY,deltaX:s.deltaX,deltaY:s.deltaY,deltaZ:s.deltaZ,deltaMode:s.deltaMode}}function o(i){const e=new Error(i.message);return e.name=i.name??"WorkerError",i.stack&&(e.stack=i.stack),e}class r extends EventTarget{el;worker;canvas;#u;#f;#r=null;#i=new Map;#b=0;#t=!1;#e=!1;#n=null;#o=null;#a=null;#h=new Map;#s=0;#p=0;constructor(e){super(),this.el=e.el,this.worker=e.worker,this.canvas=e.canvas??document.createElement("canvas"),this.#u=e.pixelRatio,this.#f=e.terminateWorkerOnDispose??!0,this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.display="block",this.canvas.style.touchAction="none",this.canvas.parentElement||this.el.appendChild(this.canvas)}static isSupported(){return typeof Worker<"u"&&typeof OffscreenCanvas<"u"&&typeof HTMLCanvasElement<"u"&&"transferControlToOffscreen"in HTMLCanvasElement.prototype}init(){if(this.#n)return this.#n;if(this.#e)return Promise.reject(new Error("OffscreenViewerHost has been disposed."));if(!r.isSupported())return Promise.reject(new Error("This browser does not support transferring a canvas to a Worker."));this.#n=new Promise((e,t)=>{this.#o=e,this.#a=t}),this.worker.addEventListener("message",this.#y),this.worker.addEventListener("error",this.#k),this.#z(),this.#C();try{const e=this.canvas.transferControlToOffscreen(),t={type:"init",canvas:e,size:this.#v()};this.worker.postMessage(t,[e])}catch(e){const t=e instanceof Error?e:new Error(String(e));this.#d(t),this.#l()}return this.#n}request(e,t){if(this.#e)return Promise.reject(new Error("OffscreenViewerHost has been disposed."));if(!this.#t)return Promise.reject(new Error("The Worker viewer has not initialized yet."));const s=++this.#b,h={type:"request",id:s,command:e,payload:t};return this.worker.postMessage(h),new Promise((c,l)=>{this.#i.set(s,{resolve:d=>c(d),reject:l})})}dispose(){const e=new Error("OffscreenViewerHost has been disposed.");if(!this.#d(e))return;const t={type:"dispose"};this.worker.postMessage(t),this.#p=window.setTimeout(this.#l,1e3)}#z(){for(const e of n)this.canvas.addEventListener(e,this.#m,{passive:e!=="wheel"&&e!=="contextmenu"})}#M(){for(const e of n)this.canvas.removeEventListener(e,this.#m)}#C(){this.#r=new ResizeObserver(this.#c),this.#r.observe(this.el),window.addEventListener("resize",this.#c)}#v(){const e=this.canvas.getBoundingClientRect();return{width:Math.max(1,e.width||this.el.clientWidth),height:Math.max(1,e.height||this.el.clientHeight),top:e.top,left:e.left,pixelRatio:this.#u??Math.min(window.devicePixelRatio,1.5)}}#c=()=>{if(!this.#t||this.#e)return;const e={type:"resize",size:this.#v()};this.worker.postMessage(e)};#m=e=>{(e.type==="wheel"||e.type==="contextmenu")&&e.preventDefault();const t=e;if(e.type==="pointerdown")try{this.canvas.setPointerCapture(t.pointerId)}catch{}if(e.type==="pointerup"||e.type==="pointercancel"){this.#w();try{this.canvas.hasPointerCapture(t.pointerId)&&this.canvas.releasePointerCapture(t.pointerId)}catch{}}const s=a(e);if(e.type==="pointermove"){this.#h.set(s.pointerId??-1,s),this.#s||(this.#s=requestAnimationFrame(this.#w));return}this.#E(s)};#w=()=>{this.#s=0;for(const e of this.#h.values())this.#E(e);this.#h.clear()};#E(e){if(!this.#t||this.#e)return;const t={type:"dom-event",event:e};this.worker.postMessage(t)}#y=e=>{const t=e.data;if(!(this.#e&&t.type!=="error"&&t.type!=="disposed"))switch(t.type){case"initialized":if(this.#e)break;this.#t=!0,this.#o?.(),this.#o=null,this.#a=null,this.#c(),this.dispatchEvent(new Event("initialized"));break;case"ready":this.dispatchEvent(new CustomEvent("ready",{detail:t.detail}));break;case"status":this.dispatchEvent(new CustomEvent("status",{detail:t.message}));break;case"stats":this.dispatchEvent(new CustomEvent("stats",{detail:t.stats}));break;case"event":this.dispatchEvent(new CustomEvent(t.eventType,{detail:t.detail}));break;case"response":{const s=this.#i.get(t.id);if(!s)break;this.#i.delete(t.id),t.error?s.reject(o(t.error)):s.resolve(t.result);break}case"error":{const s=o(t.error);this.#t||this.#g(s),this.dispatchEvent(new CustomEvent("error",{detail:s}));break}case"disposed":this.#d(new Error("The Worker viewer has been disposed.")),this.dispatchEvent(new Event("disposed")),this.#l();break}};#k=e=>{const t=e.error instanceof Error?e.error:new Error(e.message);this.#d(t),this.dispatchEvent(new CustomEvent("error",{detail:t})),this.#l()};#l=()=>{window.clearTimeout(this.#p),this.#p=0,this.worker.removeEventListener("message",this.#y),this.worker.removeEventListener("error",this.#k),this.#f&&this.worker.terminate()};#d(e){if(this.#e)return!1;this.#e=!0,this.#s&&cancelAnimationFrame(this.#s),this.#s=0,this.#h.clear(),this.#r?.disconnect(),this.#r=null,window.removeEventListener("resize",this.#c),this.#M(),this.#t||this.#g(e);for(const t of this.#i.values())t.reject(e);return this.#i.clear(),this.canvas.remove(),!0}#g(e){this.#a?.(e),this.#o=null,this.#a=null}}exports.serializeError=p.serializeError;exports.OffscreenViewerHost=r;exports.serializeDomEvent=a;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("../protocol-IUAzx0lk.cjs"),u=require("../getTransferables-C97JPUVf.cjs"),n=["click","dblclick","contextmenu","pointerdown","pointerup","pointermove","pointercancel","wheel"];function a(i){const e=i,t=i,s=i;return{type:i.type,pointerId:t.pointerId,pointerType:t.pointerType,button:e.button,buttons:e.buttons,altKey:e.altKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey,shiftKey:e.shiftKey,movementX:e.movementX,movementY:e.movementY,clientX:e.clientX,clientY:e.clientY,offsetX:e.offsetX,offsetY:e.offsetY,pageX:e.pageX,pageY:e.pageY,screenX:e.screenX,screenY:e.screenY,deltaX:s.deltaX,deltaY:s.deltaY,deltaZ:s.deltaZ,deltaMode:s.deltaMode}}function o(i){const e=new Error(i.message);return e.name=i.name??"WorkerError",i.stack&&(e.stack=i.stack),e}class r extends EventTarget{el;worker;canvas;#u;#f;#r=null;#i=new Map;#b=0;#t=!1;#e=!1;#n=null;#o=null;#a=null;#h=new Map;#s=0;#p=0;constructor(e){super(),this.el=e.el,this.worker=e.worker,this.canvas=e.canvas??document.createElement("canvas"),this.#u=e.pixelRatio,this.#f=e.terminateWorkerOnDispose??!0,this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.display="block",this.canvas.style.touchAction="none",this.canvas.parentElement||this.el.appendChild(this.canvas)}static isSupported(){return typeof Worker<"u"&&typeof OffscreenCanvas<"u"&&typeof HTMLCanvasElement<"u"&&"transferControlToOffscreen"in HTMLCanvasElement.prototype}init(){if(this.#n)return this.#n;if(this.#e)return Promise.reject(new Error("OffscreenViewerHost has been disposed."));if(!r.isSupported())return Promise.reject(new Error("This browser does not support transferring a canvas to a Worker."));this.#n=new Promise((e,t)=>{this.#o=e,this.#a=t}),this.worker.addEventListener("message",this.#y),this.worker.addEventListener("error",this.#g),this.#z(),this.#T();try{const e=this.canvas.transferControlToOffscreen(),t={type:"init",canvas:e,size:this.#v()};this.worker.postMessage(t,[e])}catch(e){const t=e instanceof Error?e:new Error(String(e));this.#d(t),this.#l()}return this.#n}request(e,t){if(this.#e)return Promise.reject(new Error("OffscreenViewerHost has been disposed."));if(!this.#t)return Promise.reject(new Error("The Worker viewer has not initialized yet."));const s=++this.#b,h={type:"request",id:s,command:e,payload:t};return this.worker.postMessage(h),new Promise((c,l)=>{this.#i.set(s,{resolve:d=>c(d),reject:l})})}dispose(){const e=new Error("OffscreenViewerHost has been disposed.");if(!this.#d(e))return;const t={type:"dispose"};this.worker.postMessage(t),this.#p=window.setTimeout(this.#l,1e3)}#z(){for(const e of n)this.canvas.addEventListener(e,this.#m,{passive:e!=="wheel"&&e!=="contextmenu"})}#M(){for(const e of n)this.canvas.removeEventListener(e,this.#m)}#T(){this.#r=new ResizeObserver(this.#c),this.#r.observe(this.el),window.addEventListener("resize",this.#c)}#v(){const e=this.canvas.getBoundingClientRect();return{width:Math.max(1,e.width||this.el.clientWidth),height:Math.max(1,e.height||this.el.clientHeight),top:e.top,left:e.left,pixelRatio:this.#u??Math.min(window.devicePixelRatio,1.5)}}#c=()=>{if(!this.#t||this.#e)return;const e={type:"resize",size:this.#v()};this.worker.postMessage(e)};#m=e=>{(e.type==="wheel"||e.type==="contextmenu")&&e.preventDefault();const t=e;if(e.type==="pointerdown")try{this.canvas.setPointerCapture(t.pointerId)}catch{}if(e.type==="pointerup"||e.type==="pointercancel"){this.#w();try{this.canvas.hasPointerCapture(t.pointerId)&&this.canvas.releasePointerCapture(t.pointerId)}catch{}}const s=a(e);if(e.type==="pointermove"){this.#h.set(s.pointerId??-1,s),this.#s||(this.#s=requestAnimationFrame(this.#w));return}this.#E(s)};#w=()=>{this.#s=0;for(const e of this.#h.values())this.#E(e);this.#h.clear()};#E(e){if(!this.#t||this.#e)return;const t={type:"dom-event",event:e};this.worker.postMessage(t)}#y=e=>{const t=e.data;if(!(this.#e&&t.type!=="error"&&t.type!=="disposed"))switch(t.type){case"initialized":if(this.#e)break;this.#t=!0,this.#o?.(),this.#o=null,this.#a=null,this.#c(),this.dispatchEvent(new Event("initialized"));break;case"ready":this.dispatchEvent(new CustomEvent("ready",{detail:t.detail}));break;case"status":this.dispatchEvent(new CustomEvent("status",{detail:t.message}));break;case"stats":this.dispatchEvent(new CustomEvent("stats",{detail:t.stats}));break;case"event":this.dispatchEvent(new CustomEvent(t.eventType,{detail:t.detail}));break;case"response":{const s=this.#i.get(t.id);if(!s)break;this.#i.delete(t.id),t.error?s.reject(o(t.error)):s.resolve(t.result);break}case"error":{const s=o(t.error);this.#t||this.#k(s),this.dispatchEvent(new CustomEvent("error",{detail:s}));break}case"disposed":this.#d(new Error("The Worker viewer has been disposed.")),this.dispatchEvent(new Event("disposed")),this.#l();break}};#g=e=>{const t=e.error instanceof Error?e.error:new Error(e.message);this.#d(t),this.dispatchEvent(new CustomEvent("error",{detail:t})),this.#l()};#l=()=>{window.clearTimeout(this.#p),this.#p=0,this.worker.removeEventListener("message",this.#y),this.worker.removeEventListener("error",this.#g),this.#f&&this.worker.terminate()};#d(e){if(this.#e)return!1;this.#e=!0,this.#s&&cancelAnimationFrame(this.#s),this.#s=0,this.#h.clear(),this.#r?.disconnect(),this.#r=null,window.removeEventListener("resize",this.#c),this.#M(),this.#t||this.#k(e);for(const t of this.#i.values())t.reject(e);return this.#i.clear(),this.canvas.remove(),!0}#k(e){this.#a?.(e),this.#o=null,this.#a=null}}exports.serializeError=p.serializeError;exports.getTransferables=u.getTransferables;exports.OffscreenViewerHost=r;exports.serializeDomEvent=a;
@@ -1,4 +1,5 @@
1
- import { s as f } from "../protocol-C-OMPz15.js";
1
+ import { s as u } from "../protocol-C-OMPz15.js";
2
+ import { g as m } from "../getTransferables-DrzSmiCR.js";
2
3
  const r = [
3
4
  "click",
4
5
  "dblclick",
@@ -45,8 +46,8 @@ class o extends EventTarget {
45
46
  el;
46
47
  worker;
47
48
  canvas;
48
- #u;
49
49
  #f;
50
+ #u;
50
51
  #r = null;
51
52
  #i = /* @__PURE__ */ new Map();
52
53
  #b = 0;
@@ -59,7 +60,7 @@ class o extends EventTarget {
59
60
  #s = 0;
60
61
  #p = 0;
61
62
  constructor(e) {
62
- super(), this.el = e.el, this.worker = e.worker, this.canvas = e.canvas ?? document.createElement("canvas"), this.#u = e.pixelRatio, this.#f = e.terminateWorkerOnDispose ?? !0, this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.display = "block", this.canvas.style.touchAction = "none", this.canvas.parentElement || this.el.appendChild(this.canvas);
63
+ super(), this.el = e.el, this.worker = e.worker, this.canvas = e.canvas ?? document.createElement("canvas"), this.#f = e.pixelRatio, this.#u = e.terminateWorkerOnDispose ?? !0, this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.display = "block", this.canvas.style.touchAction = "none", this.canvas.parentElement || this.el.appendChild(this.canvas);
63
64
  }
64
65
  static isSupported() {
65
66
  return typeof Worker < "u" && typeof OffscreenCanvas < "u" && typeof HTMLCanvasElement < "u" && "transferControlToOffscreen" in HTMLCanvasElement.prototype;
@@ -124,7 +125,7 @@ class o extends EventTarget {
124
125
  height: Math.max(1, e.height || this.el.clientHeight),
125
126
  top: e.top,
126
127
  left: e.left,
127
- pixelRatio: this.#u ?? Math.min(window.devicePixelRatio, 1.5)
128
+ pixelRatio: this.#f ?? Math.min(window.devicePixelRatio, 1.5)
128
129
  };
129
130
  }
130
131
  #c = () => {
@@ -205,7 +206,7 @@ class o extends EventTarget {
205
206
  this.#d(t), this.dispatchEvent(new CustomEvent("error", { detail: t })), this.#l();
206
207
  };
207
208
  #l = () => {
208
- window.clearTimeout(this.#p), this.#p = 0, this.worker.removeEventListener("message", this.#y), this.worker.removeEventListener("error", this.#k), this.#f && this.worker.terminate();
209
+ window.clearTimeout(this.#p), this.#p = 0, this.worker.removeEventListener("message", this.#y), this.worker.removeEventListener("error", this.#k), this.#u && this.worker.terminate();
209
210
  };
210
211
  #d(e) {
211
212
  if (this.#e) return !1;
@@ -219,6 +220,7 @@ class o extends EventTarget {
219
220
  }
220
221
  export {
221
222
  o as OffscreenViewerHost,
223
+ m as getTransferables,
222
224
  d as serializeDomEvent,
223
- f as serializeError
225
+ u as serializeError
224
226
  };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("../getTransferables-C97JPUVf.cjs"),A=require("../workerImageUtils-lmOMyTQN.cjs"),w=require("../modelDecodeProtocol-D1Apm9iG.cjs"),D="u-space-model-loader-cache",S="SBMG----",F=1179937895,C=1313821514,U=5130562,k=new TextDecoder;function g(e){throw new w.UnsupportedModelDecodeError(e)}async function v(e,r,s,o=e,i=!1){const n=e.startsWith("data:")||e.startsWith("blob:");let l=!i;if(i&&!n)try{const u=new URL(e),c=new URL(o);l=(u.protocol==="http:"||u.protocol==="https:")&&u.origin===c.origin}catch{l=!1}const h=await fetch(e,n?{signal:s}:{signal:s,headers:l?r.headers:void 0,credentials:l?r.credentials:"omit"});if(!h.ok)throw new Error(`Failed to load model resource ${e}: ${h.status} ${h.statusText}`);return h}async function M(e,r,s,o,i,n,l){const h=$(e,r),u=n?await n.resolve(h,i):{url:h,complete(){}};try{const c=await v(u.url,o,i,s,!0),t=await l(c);return u.complete(),t}catch(c){throw u.complete(c),c}}async function B(e,r,s){if(r.persistent!==!1&&typeof caches<"u"){let o;try{o=await caches.open(D);const n=await o.match(e);if(n)return n.arrayBuffer()}catch(n){if(s.aborted)throw n;console.warn(`[ModelDecodeWorker] Failed to read Cache Storage for ${e}:`,n)}const i=await v(e,r,s);if(o)try{await o.put(e,i.clone())}catch(n){if(s.aborted)throw n;console.warn(`[ModelDecodeWorker] Failed to write Cache Storage for ${e}:`,n)}return i.arrayBuffer()}return(await v(e,r,s)).arrayBuffer()}function R(e){if(e.byteLength<8||k.decode(new Uint8Array(e,0,8))!==S)return e;const s=new Uint8Array(e.byteLength-8),o=new Uint8Array(e,8);for(let i=0;i<o.length;i++){const n=o[i];s[i]=n>>4&15|n<<4&240}return s.buffer}function G(e){const r=new DataView(e);if(e.byteLength>=12&&r.getUint32(0,!0)===F){const s=r.getUint32(8,!0);if(s>e.byteLength)throw new Error(`Invalid GLB length: expected ${s}, received ${e.byteLength}.`);let o=12,i;const n=[];for(;o+8<=s;){const l=r.getUint32(o,!0),h=r.getUint32(o+4,!0);if(o+=8,o+l>s)throw new Error("Invalid GLB chunk length.");const u=e.slice(o,o+l);h===C?i=JSON.parse(k.decode(u).replace(/\u0000+$/u,"")):h===U&&n.push(u),o+=l}if(!i)throw new Error("GLB does not contain a JSON chunk.");return{document:i,binaryChunks:n}}return{document:JSON.parse(k.decode(e).replace(/^\uFEFF/u,"")),binaryChunks:[]}}function V(e){e.asset?.version?.startsWith("2")||g("Only glTF 2.x static models are supported by the decode worker."),(e.extensionsRequired?.length||e.extensionsUsed?.length)&&g("glTF extensions are not supported by the decode worker."),e.animations?.length&&g("Animated glTF models must use the regular loader."),e.skins?.length&&g("Skinned glTF models must use the regular loader."),e.cameras?.length&&g("glTF cameras must use the regular loader."),w.validateDecodedGltfNodeGraph(e);for(const r of e.accessors??[])r.sparse&&g("Sparse glTF accessors must use the regular loader."),r.bufferView===void 0&&g("Accessors without a bufferView must use the regular loader."),["SCALAR","VEC2","VEC3","VEC4"].includes(r.type)||g(`Accessor type ${r.type} must use the regular loader.`),[5120,5121,5122,5123,5125,5126].includes(r.componentType)||g(`Accessor component type ${r.componentType} must use the regular loader.`);for(const r of e.bufferViews??[])r.extensions&&Object.keys(r.extensions).length>0&&g("Compressed glTF buffer views must use the regular loader.");for(const r of e.nodes??[])(r.skin!==void 0||r.weights?.length||r.camera!==void 0)&&g("Skinned, morphed, or camera glTF nodes must use the regular loader."),r.extensions&&Object.keys(r.extensions).length>0&&g("Extended glTF nodes must use the regular loader.");for(const r of e.meshes??[])for(const s of r.primitives)(s.mode??4)!==4&&g("Only triangle glTF primitives are supported."),s.targets?.length&&g("Morph targets must use the regular loader."),s.extensions&&Object.keys(s.extensions).length>0&&g("Extended glTF primitives must use the regular loader.");for(const r of e.materials??[])r.extensions&&Object.keys(r.extensions).length>0&&g("Extended glTF materials must use the regular loader.");for(const r of e.textures??[])r.extensions&&Object.keys(r.extensions).length>0&&g("Extended glTF textures must use the regular loader.")}function $(e,r){return e.startsWith("data:")||e.startsWith("blob:")?e:new URL(e,r).href}async function _(e,r,s,o,i,n,l){const h=[...r],u=[];for(const c of e.buffers??[]){let t;if(c.uri)t=await M(c.uri,s,o,i,n,l,a=>a.arrayBuffer());else{const a=h.shift();if(!a)throw new Error("glTF buffer is missing its GLB binary chunk.");t=a}if(t.byteLength<c.byteLength)throw new Error(`glTF buffer is truncated: expected ${c.byteLength}, received ${t.byteLength}.`);u.push(t),Reflect.deleteProperty(c,"uri")}return u}function I(e,r,s,o){const i=e.bufferViews?.[s];if(!i)throw new Error(`glTF image references missing bufferView ${s}.`);const n=r[i.buffer];if(!n)throw new Error(`glTF image references missing buffer ${i.buffer}.`);const l=i.byteOffset??0;return new Blob([new Uint8Array(n,l,i.byteLength)],{type:o??"application/octet-stream"})}async function N(e,r,s,o,i,n,l){const h=[],u=[];try{for(const c of e.images??[]){let t;if(c.uri)t=await M(c.uri,s,o,i,n,l,f=>f.blob());else if(c.bufferView!==void 0)t=I(e,r,c.bufferView,c.mimeType);else throw new Error("glTF image is missing both uri and bufferView.");if(n.aborted)throw n.reason??new DOMException("Aborted","AbortError");const a=await globalThis.crypto.subtle.digest("SHA-256",await t.arrayBuffer());if(n.aborted)throw n.reason??new DOMException("Aborted","AbortError");const d=Array.from(new Uint8Array(a),f=>f.toString(16).padStart(2,"0")).join("");u.push(`${t.type}:${t.size}:${d}`),h.push(await A.createWorkerImageBitmap(t,{imageOrientation:"flipY"})),Reflect.deleteProperty(c,"uri")}return{images:h,imageKeys:u}}catch(c){throw h.forEach(t=>t.close()),c}}async function P(e,r,s={},o=new AbortController().signal,i){const n=R(r),{document:l,binaryChunks:h}=G(n);V(l);const u=s.resourceBaseUrl??e,c=await _(l,h,u,e,s,o,i),{images:t,imageKeys:a}=await N(l,c,u,e,s,o,i);return{protocolVersion:w.MODEL_DECODE_PROTOCOL_VERSION,kind:"gltf-static",url:e,document:l,buffers:c,images:t,imageKeys:a}}async function W(e,r={},s=new AbortController().signal,o){const i=await B(e,r,s);return P(e,i,r,s,o)}function L(e){return e instanceof Error?{message:e.message,name:e.name,stack:e.stack}:{message:String(e)}}function j(e=globalThis){const r=[],s=new Set;let o=null,i=!1,n=!1;const l=t=>new Promise(a=>{t.acknowledge=a}),h=(t,a)=>{for(const d of t.resources.values())d.cleanup(),d.reject(a);t.resources.clear()},u=t=>({async resolve(a,d){if(d.aborted)throw d.reason??new DOMException("Aborted","AbortError");const f=t.nextResourceId++,m=await new Promise((y,E)=>{const x=()=>{t.resources.delete(f),E(d.reason??new DOMException("Aborted","AbortError"))},b=()=>d.removeEventListener("abort",x);t.resources.set(f,{resolve(p){b(),t.resources.delete(f),y(p)},reject(p){b(),t.resources.delete(f),E(p)},cleanup:b}),d.addEventListener("abort",x,{once:!0});try{e.postMessage({type:"resolve-resource",id:t.id,resourceId:f,url:a})}catch(p){b(),t.resources.delete(f),E(p instanceof Error?p:new Error(String(p)))}});let O=!1;return{url:m,complete(y){O||(O=!0,e.postMessage({type:"resource-complete",id:t.id,resourceId:f,ok:y===void 0,error:y===void 0?void 0:L(y)}))}}}}),c=async()=>{if(!(i||n)){i=!0;try{for(;!n&&r.length>0;){const t=r.shift();if(s.delete(t.id))continue;const a={id:t.id,controller:new AbortController,nextResourceId:1,resources:new Map};o=a;try{const d=await W(t.url,t.options,a.controller.signal,u(a));if(s.delete(t.id)||n){d.images.forEach(f=>f.close());continue}try{e.postMessage({type:"decoded",id:t.id,packet:d},T.getTransferables(d))}catch(f){throw d.images.forEach(m=>m.close()),f}await l(a)}catch(d){const f=s.delete(t.id);if(a.controller.signal.aborted||f||n)continue;d instanceof w.UnsupportedModelDecodeError?e.postMessage({type:"unsupported",id:t.id,reason:d.message}):e.postMessage({type:"error",id:t.id,error:L(d)})}finally{h(a,new DOMException("Model decode request ended.","AbortError")),s.delete(t.id),o===a&&(o=null)}}}finally{i=!1,!n&&r.length>0&&c()}}};e.addEventListener("message",t=>{const a=t.data;if(a.type==="decode"){if(n)return;r.push(a),c();return}if(a.type==="cancel"){s.add(a.id),o?.id===a.id&&(o.controller.abort(),o.acknowledge?.());return}if(a.type==="ack"){o?.id===a.id&&o.acknowledge?.();return}if(a.type==="resource-resolved"){if(o?.id!==a.id)return;const d=o.resources.get(a.resourceId);if(!d)return;if(a.url!==void 0)d.resolve(a.url);else{const f=new Error(a.error?.message??"Failed to resolve model resource URL.");f.name=a.error?.name??"Error",f.stack=a.error?.stack,d.reject(f)}return}a.type==="dispose"&&(n=!0,r.length=0,o?.controller.abort(),o?.acknowledge?.(),e.postMessage({type:"disposed"}),e.close())})}exports.MODEL_DECODE_PROTOCOL_VERSION=w.MODEL_DECODE_PROTOCOL_VERSION;exports.UnsupportedModelDecodeError=w.UnsupportedModelDecodeError;exports.validateDecodedGltfNodeGraph=w.validateDecodedGltfNodeGraph;exports.installModelDecodeWorker=j;
@@ -0,0 +1,339 @@
1
+ import { g as F } from "../getTransferables-DrzSmiCR.js";
2
+ import { c as M } from "../workerImageUtils-mQD3TQ1N.js";
3
+ import { M as O, v as S, U as L } from "../modelDecodeProtocol-wDB7ksYw.js";
4
+ const B = "u-space-model-loader-cache", U = "SBMG----", C = 1179937895, R = 1313821514, D = 5130562, E = new TextDecoder();
5
+ function g(e) {
6
+ throw new L(e);
7
+ }
8
+ async function k(e, t, s, o = e, i = !1) {
9
+ const n = e.startsWith("data:") || e.startsWith("blob:");
10
+ let l = !i;
11
+ if (i && !n)
12
+ try {
13
+ const f = new URL(e), c = new URL(o);
14
+ l = (f.protocol === "http:" || f.protocol === "https:") && f.origin === c.origin;
15
+ } catch {
16
+ l = !1;
17
+ }
18
+ const h = await fetch(e, n ? { signal: s } : {
19
+ signal: s,
20
+ headers: l ? t.headers : void 0,
21
+ credentials: l ? t.credentials : "omit"
22
+ });
23
+ if (!h.ok)
24
+ throw new Error(`Failed to load model resource ${e}: ${h.status} ${h.statusText}`);
25
+ return h;
26
+ }
27
+ async function T(e, t, s, o, i, n, l) {
28
+ const h = N(e, t), f = n ? await n.resolve(h, i) : { url: h, complete() {
29
+ } };
30
+ try {
31
+ const c = await k(f.url, o, i, s, !0), r = await l(c);
32
+ return f.complete(), r;
33
+ } catch (c) {
34
+ throw f.complete(c), c;
35
+ }
36
+ }
37
+ async function $(e, t, s) {
38
+ if (t.persistent !== !1 && typeof caches < "u") {
39
+ let o;
40
+ try {
41
+ o = await caches.open(B);
42
+ const n = await o.match(e);
43
+ if (n) return n.arrayBuffer();
44
+ } catch (n) {
45
+ if (s.aborted) throw n;
46
+ console.warn(`[ModelDecodeWorker] Failed to read Cache Storage for ${e}:`, n);
47
+ }
48
+ const i = await k(e, t, s);
49
+ if (o)
50
+ try {
51
+ await o.put(e, i.clone());
52
+ } catch (n) {
53
+ if (s.aborted) throw n;
54
+ console.warn(`[ModelDecodeWorker] Failed to write Cache Storage for ${e}:`, n);
55
+ }
56
+ return i.arrayBuffer();
57
+ }
58
+ return (await k(e, t, s)).arrayBuffer();
59
+ }
60
+ function V(e) {
61
+ if (e.byteLength < 8 || E.decode(new Uint8Array(e, 0, 8)) !== U) return e;
62
+ const s = new Uint8Array(e.byteLength - 8), o = new Uint8Array(e, 8);
63
+ for (let i = 0; i < o.length; i++) {
64
+ const n = o[i];
65
+ s[i] = n >> 4 & 15 | n << 4 & 240;
66
+ }
67
+ return s.buffer;
68
+ }
69
+ function G(e) {
70
+ const t = new DataView(e);
71
+ if (e.byteLength >= 12 && t.getUint32(0, !0) === C) {
72
+ const s = t.getUint32(8, !0);
73
+ if (s > e.byteLength)
74
+ throw new Error(`Invalid GLB length: expected ${s}, received ${e.byteLength}.`);
75
+ let o = 12, i;
76
+ const n = [];
77
+ for (; o + 8 <= s; ) {
78
+ const l = t.getUint32(o, !0), h = t.getUint32(o + 4, !0);
79
+ if (o += 8, o + l > s) throw new Error("Invalid GLB chunk length.");
80
+ const f = e.slice(o, o + l);
81
+ h === R ? i = JSON.parse(E.decode(f).replace(/\u0000+$/u, "")) : h === D && n.push(f), o += l;
82
+ }
83
+ if (!i) throw new Error("GLB does not contain a JSON chunk.");
84
+ return { document: i, binaryChunks: n };
85
+ }
86
+ return {
87
+ document: JSON.parse(E.decode(e).replace(/^\uFEFF/u, "")),
88
+ binaryChunks: []
89
+ };
90
+ }
91
+ function I(e) {
92
+ e.asset?.version?.startsWith("2") || g("Only glTF 2.x static models are supported by the decode worker."), (e.extensionsRequired?.length || e.extensionsUsed?.length) && g("glTF extensions are not supported by the decode worker."), e.animations?.length && g("Animated glTF models must use the regular loader."), e.skins?.length && g("Skinned glTF models must use the regular loader."), e.cameras?.length && g("glTF cameras must use the regular loader."), S(e);
93
+ for (const t of e.accessors ?? [])
94
+ t.sparse && g("Sparse glTF accessors must use the regular loader."), t.bufferView === void 0 && g("Accessors without a bufferView must use the regular loader."), ["SCALAR", "VEC2", "VEC3", "VEC4"].includes(t.type) || g(`Accessor type ${t.type} must use the regular loader.`), [5120, 5121, 5122, 5123, 5125, 5126].includes(t.componentType) || g(`Accessor component type ${t.componentType} must use the regular loader.`);
95
+ for (const t of e.bufferViews ?? [])
96
+ t.extensions && Object.keys(t.extensions).length > 0 && g("Compressed glTF buffer views must use the regular loader.");
97
+ for (const t of e.nodes ?? [])
98
+ (t.skin !== void 0 || t.weights?.length || t.camera !== void 0) && g("Skinned, morphed, or camera glTF nodes must use the regular loader."), t.extensions && Object.keys(t.extensions).length > 0 && g("Extended glTF nodes must use the regular loader.");
99
+ for (const t of e.meshes ?? [])
100
+ for (const s of t.primitives)
101
+ (s.mode ?? 4) !== 4 && g("Only triangle glTF primitives are supported."), s.targets?.length && g("Morph targets must use the regular loader."), s.extensions && Object.keys(s.extensions).length > 0 && g("Extended glTF primitives must use the regular loader.");
102
+ for (const t of e.materials ?? [])
103
+ t.extensions && Object.keys(t.extensions).length > 0 && g("Extended glTF materials must use the regular loader.");
104
+ for (const t of e.textures ?? [])
105
+ t.extensions && Object.keys(t.extensions).length > 0 && g("Extended glTF textures must use the regular loader.");
106
+ }
107
+ function N(e, t) {
108
+ return e.startsWith("data:") || e.startsWith("blob:") ? e : new URL(e, t).href;
109
+ }
110
+ async function _(e, t, s, o, i, n, l) {
111
+ const h = [...t], f = [];
112
+ for (const c of e.buffers ?? []) {
113
+ let r;
114
+ if (c.uri)
115
+ r = await T(
116
+ c.uri,
117
+ s,
118
+ o,
119
+ i,
120
+ n,
121
+ l,
122
+ (a) => a.arrayBuffer()
123
+ );
124
+ else {
125
+ const a = h.shift();
126
+ if (!a) throw new Error("glTF buffer is missing its GLB binary chunk.");
127
+ r = a;
128
+ }
129
+ if (r.byteLength < c.byteLength)
130
+ throw new Error(`glTF buffer is truncated: expected ${c.byteLength}, received ${r.byteLength}.`);
131
+ f.push(r), Reflect.deleteProperty(c, "uri");
132
+ }
133
+ return f;
134
+ }
135
+ function W(e, t, s, o) {
136
+ const i = e.bufferViews?.[s];
137
+ if (!i) throw new Error(`glTF image references missing bufferView ${s}.`);
138
+ const n = t[i.buffer];
139
+ if (!n) throw new Error(`glTF image references missing buffer ${i.buffer}.`);
140
+ const l = i.byteOffset ?? 0;
141
+ return new Blob([new Uint8Array(n, l, i.byteLength)], {
142
+ type: o ?? "application/octet-stream"
143
+ });
144
+ }
145
+ async function j(e, t, s, o, i, n, l) {
146
+ const h = [], f = [];
147
+ try {
148
+ for (const c of e.images ?? []) {
149
+ let r;
150
+ if (c.uri)
151
+ r = await T(
152
+ c.uri,
153
+ s,
154
+ o,
155
+ i,
156
+ n,
157
+ l,
158
+ (u) => u.blob()
159
+ );
160
+ else if (c.bufferView !== void 0)
161
+ r = W(e, t, c.bufferView, c.mimeType);
162
+ else
163
+ throw new Error("glTF image is missing both uri and bufferView.");
164
+ if (n.aborted) throw n.reason ?? new DOMException("Aborted", "AbortError");
165
+ const a = await globalThis.crypto.subtle.digest("SHA-256", await r.arrayBuffer());
166
+ if (n.aborted) throw n.reason ?? new DOMException("Aborted", "AbortError");
167
+ const d = Array.from(new Uint8Array(a), (u) => u.toString(16).padStart(2, "0")).join("");
168
+ f.push(`${r.type}:${r.size}:${d}`), h.push(await M(r, { imageOrientation: "flipY" })), Reflect.deleteProperty(c, "uri");
169
+ }
170
+ return { images: h, imageKeys: f };
171
+ } catch (c) {
172
+ throw h.forEach((r) => r.close()), c;
173
+ }
174
+ }
175
+ async function P(e, t, s = {}, o = new AbortController().signal, i) {
176
+ const n = V(t), { document: l, binaryChunks: h } = G(n);
177
+ I(l);
178
+ const f = s.resourceBaseUrl ?? e, c = await _(
179
+ l,
180
+ h,
181
+ f,
182
+ e,
183
+ s,
184
+ o,
185
+ i
186
+ ), { images: r, imageKeys: a } = await j(
187
+ l,
188
+ c,
189
+ f,
190
+ e,
191
+ s,
192
+ o,
193
+ i
194
+ );
195
+ return {
196
+ protocolVersion: O,
197
+ kind: "gltf-static",
198
+ url: e,
199
+ document: l,
200
+ buffers: c,
201
+ images: r,
202
+ imageKeys: a
203
+ };
204
+ }
205
+ async function q(e, t = {}, s = new AbortController().signal, o) {
206
+ const i = await $(e, t, s);
207
+ return P(e, i, t, s, o);
208
+ }
209
+ function A(e) {
210
+ return e instanceof Error ? { message: e.message, name: e.name, stack: e.stack } : { message: String(e) };
211
+ }
212
+ function z(e = globalThis) {
213
+ const t = [], s = /* @__PURE__ */ new Set();
214
+ let o = null, i = !1, n = !1;
215
+ const l = (r) => new Promise((a) => {
216
+ r.acknowledge = a;
217
+ }), h = (r, a) => {
218
+ for (const d of r.resources.values())
219
+ d.cleanup(), d.reject(a);
220
+ r.resources.clear();
221
+ }, f = (r) => ({
222
+ async resolve(a, d) {
223
+ if (d.aborted) throw d.reason ?? new DOMException("Aborted", "AbortError");
224
+ const u = r.nextResourceId++, m = await new Promise((p, b) => {
225
+ const x = () => {
226
+ r.resources.delete(u), b(d.reason ?? new DOMException("Aborted", "AbortError"));
227
+ }, y = () => d.removeEventListener("abort", x);
228
+ r.resources.set(u, {
229
+ resolve(w) {
230
+ y(), r.resources.delete(u), p(w);
231
+ },
232
+ reject(w) {
233
+ y(), r.resources.delete(u), b(w);
234
+ },
235
+ cleanup: y
236
+ }), d.addEventListener("abort", x, { once: !0 });
237
+ try {
238
+ e.postMessage({ type: "resolve-resource", id: r.id, resourceId: u, url: a });
239
+ } catch (w) {
240
+ y(), r.resources.delete(u), b(w instanceof Error ? w : new Error(String(w)));
241
+ }
242
+ });
243
+ let v = !1;
244
+ return {
245
+ url: m,
246
+ complete(p) {
247
+ v || (v = !0, e.postMessage({
248
+ type: "resource-complete",
249
+ id: r.id,
250
+ resourceId: u,
251
+ ok: p === void 0,
252
+ error: p === void 0 ? void 0 : A(p)
253
+ }));
254
+ }
255
+ };
256
+ }
257
+ }), c = async () => {
258
+ if (!(i || n)) {
259
+ i = !0;
260
+ try {
261
+ for (; !n && t.length > 0; ) {
262
+ const r = t.shift();
263
+ if (s.delete(r.id)) continue;
264
+ const a = {
265
+ id: r.id,
266
+ controller: new AbortController(),
267
+ nextResourceId: 1,
268
+ resources: /* @__PURE__ */ new Map()
269
+ };
270
+ o = a;
271
+ try {
272
+ const d = await q(
273
+ r.url,
274
+ r.options,
275
+ a.controller.signal,
276
+ f(a)
277
+ );
278
+ if (s.delete(r.id) || n) {
279
+ d.images.forEach((u) => u.close());
280
+ continue;
281
+ }
282
+ try {
283
+ e.postMessage(
284
+ { type: "decoded", id: r.id, packet: d },
285
+ F(d)
286
+ );
287
+ } catch (u) {
288
+ throw d.images.forEach((m) => m.close()), u;
289
+ }
290
+ await l(a);
291
+ } catch (d) {
292
+ const u = s.delete(r.id);
293
+ if (a.controller.signal.aborted || u || n) continue;
294
+ d instanceof L ? e.postMessage({ type: "unsupported", id: r.id, reason: d.message }) : e.postMessage({ type: "error", id: r.id, error: A(d) });
295
+ } finally {
296
+ h(a, new DOMException("Model decode request ended.", "AbortError")), s.delete(r.id), o === a && (o = null);
297
+ }
298
+ }
299
+ } finally {
300
+ i = !1, !n && t.length > 0 && c();
301
+ }
302
+ }
303
+ };
304
+ e.addEventListener("message", (r) => {
305
+ const a = r.data;
306
+ if (a.type === "decode") {
307
+ if (n) return;
308
+ t.push(a), c();
309
+ return;
310
+ }
311
+ if (a.type === "cancel") {
312
+ s.add(a.id), o?.id === a.id && (o.controller.abort(), o.acknowledge?.());
313
+ return;
314
+ }
315
+ if (a.type === "ack") {
316
+ o?.id === a.id && o.acknowledge?.();
317
+ return;
318
+ }
319
+ if (a.type === "resource-resolved") {
320
+ if (o?.id !== a.id) return;
321
+ const d = o.resources.get(a.resourceId);
322
+ if (!d) return;
323
+ if (a.url !== void 0)
324
+ d.resolve(a.url);
325
+ else {
326
+ const u = new Error(a.error?.message ?? "Failed to resolve model resource URL.");
327
+ u.name = a.error?.name ?? "Error", u.stack = a.error?.stack, d.reject(u);
328
+ }
329
+ return;
330
+ }
331
+ a.type === "dispose" && (n = !0, t.length = 0, o?.controller.abort(), o?.acknowledge?.(), e.postMessage({ type: "disposed" }), e.close());
332
+ });
333
+ }
334
+ export {
335
+ O as MODEL_DECODE_PROTOCOL_VERSION,
336
+ L as UnsupportedModelDecodeError,
337
+ z as installModelDecodeWorker,
338
+ S as validateDecodedGltfNodeGraph
339
+ };