u-space 0.0.28 → 0.0.30

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 (73) hide show
  1. package/README.md +9 -0
  2. package/dist/Viewer-BKNV67Jj.cjs +1 -0
  3. package/dist/Viewer-Cs_y7IiH.js +1256 -0
  4. package/dist/index.cjs +3 -3
  5. package/dist/index.js +1715 -1497
  6. package/dist/plugins/atmosphere/AgxToneMapping.d.ts +1 -1
  7. package/dist/plugins/atmosphere/index.cjs +1 -1
  8. package/dist/plugins/atmosphere/index.js +4 -4
  9. package/dist/plugins/curve-movement/index.cjs +1 -1
  10. package/dist/plugins/curve-movement/index.js +1 -1
  11. package/dist/plugins/fire/index.cjs +1 -1
  12. package/dist/plugins/fire/index.js +5 -5
  13. package/dist/plugins/object-controls/index.cjs +1 -1
  14. package/dist/plugins/object-controls/index.js +4 -4
  15. package/dist/plugins/tiles/index.cjs +1 -1
  16. package/dist/plugins/tiles/index.js +5 -5
  17. package/dist/plugins/u-manager/index.cjs +51 -51
  18. package/dist/plugins/u-manager/index.d.ts +1 -1
  19. package/dist/plugins/u-manager/index.js +8330 -8637
  20. package/dist/plugins/u-manager/loaders/SceneEditableBatchLayer.d.ts +17 -0
  21. package/dist/plugins/u-manager/loaders/SceneInstancedLayer.d.ts +3 -3
  22. package/dist/plugins/u-manager/loaders/SceneLoader.d.ts +20 -3
  23. package/dist/plugins/u-manager/loaders/UManagerLoader.d.ts +4 -4
  24. package/dist/plugins/u-manager/semantics/objects/BuildingGroup.d.ts +12 -5
  25. package/dist/plugins/u-manager/semantics/objects/FacilityInstancedLayer.d.ts +4 -4
  26. package/dist/plugins/u-manager/semantics/objects/FloorMesh.d.ts +28 -22
  27. package/dist/plugins/u-manager/semantics/objects/SemanticGroup.d.ts +6 -6
  28. package/dist/protocol-C-OMPz15.js +10 -0
  29. package/dist/protocol-IUAzx0lk.cjs +1 -0
  30. package/dist/src/batches/EditableGeometryBatchLayer.d.ts +50 -0
  31. package/dist/src/batches/ModelInstancedLayer.d.ts +42 -0
  32. package/dist/src/batches/index.d.ts +2 -0
  33. package/dist/src/effects/TSLEffects.d.ts +24 -1
  34. package/dist/src/index.d.ts +2 -0
  35. package/dist/src/instances/InstanceObject.d.ts +57 -0
  36. package/dist/src/instances/index.d.ts +1 -0
  37. package/dist/src/interactions/MeshBVHRaycast.d.ts +9 -0
  38. package/dist/src/interactions/index.d.ts +1 -0
  39. package/dist/src/viewers/RenderPipeline.d.ts +37 -0
  40. package/dist/src/viewers/ReversedDepthSSGICompat.d.ts +10 -0
  41. package/dist/src/viewers/ReversedDepthSSRCompat.d.ts +20 -0
  42. package/dist/src/viewers/Viewer.d.ts +3 -1
  43. package/dist/src/viewers/renderInvalidation.d.ts +2 -0
  44. package/dist/src/worker/FrameTimingWindow.d.ts +16 -0
  45. package/dist/src/worker/OffscreenViewerHost.d.ts +20 -0
  46. package/dist/src/worker/WorkerDomTarget.d.ts +44 -0
  47. package/dist/src/worker/createWorkerViewer.d.ts +18 -0
  48. package/dist/src/worker/index.d.ts +2 -0
  49. package/dist/src/worker/installWorkerImageLoader.d.ts +5 -0
  50. package/dist/src/worker/protocol.d.ts +102 -0
  51. package/dist/src/worker/runtime.d.ts +2 -0
  52. package/dist/worker/index.cjs +1 -0
  53. package/dist/worker/index.js +224 -0
  54. package/dist/worker/runtime.cjs +1 -0
  55. package/dist/worker/runtime.js +418 -0
  56. package/docs/api-batches.md +112 -0
  57. package/docs/api-effects.md +2 -2
  58. package/docs/api-interactions.md +8 -0
  59. package/docs/api-managers.md +1 -1
  60. package/docs/api-objects.md +207 -0
  61. package/docs/api-plugin-u-manager.md +245 -96
  62. package/docs/api-render-pipeline.md +103 -5
  63. package/docs/api-viewer.md +188 -1
  64. package/docs/changelog.md +69 -6
  65. package/docs/examples-guide.md +111 -17
  66. package/docs/getting-started.md +1 -1
  67. package/docs/index.md +11 -4
  68. package/docs/mcp.md +29 -14
  69. package/docs/release.md +95 -0
  70. package/package.json +27 -4
  71. package/dist/plugins/u-manager/instances/SemanticInstanceObject.d.ts +0 -37
  72. package/dist/plugins/u-manager/instances/SemanticModelInstancedLayer.d.ts +0 -33
  73. package/dist/plugins/u-manager/instances/index.d.ts +0 -2
@@ -0,0 +1,16 @@
1
+ import type { WorkerFrameTimingStats } from './protocol';
2
+ export interface FrameTimingWindowOptions {
3
+ windowMs?: number;
4
+ idleResetMs?: number;
5
+ missedFrameThresholdMs?: number;
6
+ }
7
+ export declare class FrameTimingWindow {
8
+ #private;
9
+ readonly windowMs: number;
10
+ readonly idleResetMs: number;
11
+ readonly missedFrameThresholdMs: number;
12
+ constructor(options?: FrameTimingWindowOptions);
13
+ add(duration: number, now?: number): WorkerFrameTimingStats;
14
+ snapshot(now?: number): WorkerFrameTimingStats;
15
+ reset(): void;
16
+ }
@@ -0,0 +1,20 @@
1
+ import type { SerializedDomEvent } from './protocol';
2
+ export interface OffscreenViewerHostOptions {
3
+ el: HTMLElement;
4
+ worker: Worker;
5
+ canvas?: HTMLCanvasElement;
6
+ pixelRatio?: number;
7
+ terminateWorkerOnDispose?: boolean;
8
+ }
9
+ export declare function serializeDomEvent(event: Event): SerializedDomEvent;
10
+ export declare class OffscreenViewerHost extends EventTarget {
11
+ #private;
12
+ readonly el: HTMLElement;
13
+ readonly worker: Worker;
14
+ readonly canvas: HTMLCanvasElement;
15
+ constructor(options: OffscreenViewerHostOptions);
16
+ static isSupported(): boolean;
17
+ init(): Promise<void>;
18
+ request<T = unknown>(command: string, payload?: unknown): Promise<T>;
19
+ dispose(): void;
20
+ }
@@ -0,0 +1,44 @@
1
+ import type { SerializedDomEvent, WorkerCanvasSize } from './protocol';
2
+ export type WorkerDomTarget = OffscreenCanvas & HTMLElement;
3
+ declare class WorkerDomEvent {
4
+ readonly type: string;
5
+ readonly timeStamp: number;
6
+ readonly target: WorkerDomTarget;
7
+ readonly currentTarget: WorkerDomTarget;
8
+ readonly cancelable = true;
9
+ readonly bubbles = true;
10
+ defaultPrevented: boolean;
11
+ cancelBubble: boolean;
12
+ immediatePropagationStopped: boolean;
13
+ pointerId: number;
14
+ pointerType: string;
15
+ button: number;
16
+ buttons: number;
17
+ altKey: boolean;
18
+ ctrlKey: boolean;
19
+ metaKey: boolean;
20
+ shiftKey: boolean;
21
+ movementX: number;
22
+ movementY: number;
23
+ clientX: number;
24
+ clientY: number;
25
+ offsetX: number;
26
+ offsetY: number;
27
+ pageX: number;
28
+ pageY: number;
29
+ screenX: number;
30
+ screenY: number;
31
+ deltaX: number;
32
+ deltaY: number;
33
+ deltaZ: number;
34
+ deltaMode: number;
35
+ constructor(data: SerializedDomEvent, target: WorkerDomTarget);
36
+ preventDefault(): void;
37
+ stopPropagation(): void;
38
+ stopImmediatePropagation(): void;
39
+ composedPath(): WorkerDomTarget[];
40
+ }
41
+ export declare function createWorkerDomTarget(canvas: OffscreenCanvas, initialSize: WorkerCanvasSize): WorkerDomTarget;
42
+ export declare function resizeWorkerDomTarget(target: WorkerDomTarget, size: WorkerCanvasSize): void;
43
+ export declare function dispatchWorkerDomEvent(target: WorkerDomTarget, data: SerializedDomEvent): WorkerDomEvent;
44
+ export {};
@@ -0,0 +1,18 @@
1
+ import { Viewer } from '../viewers/Viewer';
2
+ export type WorkerViewerCommand = (payload: unknown) => unknown | Promise<unknown>;
3
+ export type WorkerViewerDispose = () => void | Promise<void>;
4
+ export interface WorkerViewerRuntime {
5
+ readonly viewer: Viewer;
6
+ readonly canvas: OffscreenCanvas;
7
+ status(message: string): void;
8
+ emit(type: string, detail?: unknown): void;
9
+ registerCommand(name: string, command: WorkerViewerCommand): () => void;
10
+ onDispose(dispose: WorkerViewerDispose): () => void;
11
+ ready(detail?: unknown): void;
12
+ }
13
+ /**
14
+ * Creates a u-space Viewer after the main thread transfers an OffscreenCanvas.
15
+ * Call this at module top level; the message listener is installed synchronously
16
+ * before the returned promise waits for the host initialization message.
17
+ */
18
+ export declare function createWorkerViewer(): Promise<WorkerViewerRuntime>;
@@ -0,0 +1,2 @@
1
+ export * from './protocol';
2
+ export * from './OffscreenViewerHost';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Makes Three.js TextureLoader/CubeTextureLoader usable in a Worker by loading
3
+ * images with fetch() and createImageBitmap() instead of document.createElement('img').
4
+ */
5
+ export declare function installWorkerImageLoader(): void;
@@ -0,0 +1,102 @@
1
+ export interface WorkerCanvasSize {
2
+ width: number;
3
+ height: number;
4
+ top: number;
5
+ left: number;
6
+ pixelRatio: number;
7
+ }
8
+ export interface SerializedDomEvent {
9
+ type: string;
10
+ pointerId?: number;
11
+ pointerType?: string;
12
+ button?: number;
13
+ buttons?: number;
14
+ altKey?: boolean;
15
+ ctrlKey?: boolean;
16
+ metaKey?: boolean;
17
+ shiftKey?: boolean;
18
+ movementX?: number;
19
+ movementY?: number;
20
+ clientX?: number;
21
+ clientY?: number;
22
+ offsetX?: number;
23
+ offsetY?: number;
24
+ pageX?: number;
25
+ pageY?: number;
26
+ screenX?: number;
27
+ screenY?: number;
28
+ deltaX?: number;
29
+ deltaY?: number;
30
+ deltaZ?: number;
31
+ deltaMode?: number;
32
+ }
33
+ export interface WorkerRendererStats {
34
+ drawCalls: number;
35
+ frameCalls: number;
36
+ triangles: number;
37
+ points: number;
38
+ lines: number;
39
+ /** Rolling average frame interval in milliseconds. */
40
+ frameTime: number;
41
+ frameTiming: WorkerFrameTimingStats;
42
+ }
43
+ export interface WorkerFrameTimingStats {
44
+ /** Number of actively rendered frames in the rolling window. */
45
+ samples: number;
46
+ fps: number;
47
+ average: number;
48
+ p95: number;
49
+ max: number;
50
+ /** Percentage of samples above the 25 ms budget. */
51
+ missedFramePercent: number;
52
+ }
53
+ export interface WorkerErrorData {
54
+ message: string;
55
+ name?: string;
56
+ stack?: string;
57
+ }
58
+ export type HostToWorkerMessage = {
59
+ type: 'init';
60
+ canvas: OffscreenCanvas;
61
+ size: WorkerCanvasSize;
62
+ } | {
63
+ type: 'resize';
64
+ size: WorkerCanvasSize;
65
+ } | {
66
+ type: 'dom-event';
67
+ event: SerializedDomEvent;
68
+ } | {
69
+ type: 'request';
70
+ id: number;
71
+ command: string;
72
+ payload?: unknown;
73
+ } | {
74
+ type: 'dispose';
75
+ };
76
+ export type WorkerToHostMessage = {
77
+ type: 'initialized';
78
+ } | {
79
+ type: 'ready';
80
+ detail?: unknown;
81
+ } | {
82
+ type: 'status';
83
+ message: string;
84
+ } | {
85
+ type: 'stats';
86
+ stats: WorkerRendererStats;
87
+ } | {
88
+ type: 'event';
89
+ eventType: string;
90
+ detail?: unknown;
91
+ } | {
92
+ type: 'response';
93
+ id: number;
94
+ result?: unknown;
95
+ error?: WorkerErrorData;
96
+ } | {
97
+ type: 'error';
98
+ error: WorkerErrorData;
99
+ } | {
100
+ type: 'disposed';
101
+ };
102
+ export declare function serializeError(error: unknown): WorkerErrorData;
@@ -0,0 +1,2 @@
1
+ export * from './protocol';
2
+ export * from './createWorkerViewer';
@@ -0,0 +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;
@@ -0,0 +1,224 @@
1
+ import { s as f } from "../protocol-C-OMPz15.js";
2
+ const r = [
3
+ "click",
4
+ "dblclick",
5
+ "contextmenu",
6
+ "pointerdown",
7
+ "pointerup",
8
+ "pointermove",
9
+ "pointercancel",
10
+ "wheel"
11
+ ];
12
+ function d(i) {
13
+ const e = i, t = i, s = i;
14
+ return {
15
+ type: i.type,
16
+ pointerId: t.pointerId,
17
+ pointerType: t.pointerType,
18
+ button: e.button,
19
+ buttons: e.buttons,
20
+ altKey: e.altKey,
21
+ ctrlKey: e.ctrlKey,
22
+ metaKey: e.metaKey,
23
+ shiftKey: e.shiftKey,
24
+ movementX: e.movementX,
25
+ movementY: e.movementY,
26
+ clientX: e.clientX,
27
+ clientY: e.clientY,
28
+ offsetX: e.offsetX,
29
+ offsetY: e.offsetY,
30
+ pageX: e.pageX,
31
+ pageY: e.pageY,
32
+ screenX: e.screenX,
33
+ screenY: e.screenY,
34
+ deltaX: s.deltaX,
35
+ deltaY: s.deltaY,
36
+ deltaZ: s.deltaZ,
37
+ deltaMode: s.deltaMode
38
+ };
39
+ }
40
+ function n(i) {
41
+ const e = new Error(i.message);
42
+ return e.name = i.name ?? "WorkerError", i.stack && (e.stack = i.stack), e;
43
+ }
44
+ class o extends EventTarget {
45
+ el;
46
+ worker;
47
+ canvas;
48
+ #u;
49
+ #f;
50
+ #r = null;
51
+ #i = /* @__PURE__ */ new Map();
52
+ #b = 0;
53
+ #t = !1;
54
+ #e = !1;
55
+ #n = null;
56
+ #o = null;
57
+ #a = null;
58
+ #h = /* @__PURE__ */ new Map();
59
+ #s = 0;
60
+ #p = 0;
61
+ 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
+ }
64
+ static isSupported() {
65
+ return typeof Worker < "u" && typeof OffscreenCanvas < "u" && typeof HTMLCanvasElement < "u" && "transferControlToOffscreen" in HTMLCanvasElement.prototype;
66
+ }
67
+ init() {
68
+ if (this.#n) return this.#n;
69
+ if (this.#e) return Promise.reject(new Error("OffscreenViewerHost has been disposed."));
70
+ if (!o.isSupported())
71
+ return Promise.reject(new Error("This browser does not support transferring a canvas to a Worker."));
72
+ this.#n = new Promise((e, t) => {
73
+ this.#o = e, this.#a = t;
74
+ }), this.worker.addEventListener("message", this.#y), this.worker.addEventListener("error", this.#k), this.#z(), this.#C();
75
+ try {
76
+ const e = this.canvas.transferControlToOffscreen(), t = {
77
+ type: "init",
78
+ canvas: e,
79
+ size: this.#v()
80
+ };
81
+ this.worker.postMessage(t, [e]);
82
+ } catch (e) {
83
+ const t = e instanceof Error ? e : new Error(String(e));
84
+ this.#d(t), this.#l();
85
+ }
86
+ return this.#n;
87
+ }
88
+ request(e, t) {
89
+ if (this.#e)
90
+ return Promise.reject(new Error("OffscreenViewerHost has been disposed."));
91
+ if (!this.#t)
92
+ return Promise.reject(new Error("The Worker viewer has not initialized yet."));
93
+ const s = ++this.#b, a = { type: "request", id: s, command: e, payload: t };
94
+ return this.worker.postMessage(a), new Promise((h, c) => {
95
+ this.#i.set(s, {
96
+ resolve: (l) => h(l),
97
+ reject: c
98
+ });
99
+ });
100
+ }
101
+ dispose() {
102
+ const e = new Error("OffscreenViewerHost has been disposed.");
103
+ if (!this.#d(e)) return;
104
+ const t = { type: "dispose" };
105
+ this.worker.postMessage(t), this.#p = window.setTimeout(this.#l, 1e3);
106
+ }
107
+ #z() {
108
+ for (const e of r)
109
+ this.canvas.addEventListener(e, this.#m, {
110
+ passive: e !== "wheel" && e !== "contextmenu"
111
+ });
112
+ }
113
+ #M() {
114
+ for (const e of r)
115
+ this.canvas.removeEventListener(e, this.#m);
116
+ }
117
+ #C() {
118
+ this.#r = new ResizeObserver(this.#c), this.#r.observe(this.el), window.addEventListener("resize", this.#c);
119
+ }
120
+ #v() {
121
+ const e = this.canvas.getBoundingClientRect();
122
+ return {
123
+ width: Math.max(1, e.width || this.el.clientWidth),
124
+ height: Math.max(1, e.height || this.el.clientHeight),
125
+ top: e.top,
126
+ left: e.left,
127
+ pixelRatio: this.#u ?? Math.min(window.devicePixelRatio, 1.5)
128
+ };
129
+ }
130
+ #c = () => {
131
+ if (!this.#t || this.#e) return;
132
+ const e = { type: "resize", size: this.#v() };
133
+ this.worker.postMessage(e);
134
+ };
135
+ #m = (e) => {
136
+ (e.type === "wheel" || e.type === "contextmenu") && e.preventDefault();
137
+ const t = e;
138
+ if (e.type === "pointerdown")
139
+ try {
140
+ this.canvas.setPointerCapture(t.pointerId);
141
+ } catch {
142
+ }
143
+ if (e.type === "pointerup" || e.type === "pointercancel") {
144
+ this.#w();
145
+ try {
146
+ this.canvas.hasPointerCapture(t.pointerId) && this.canvas.releasePointerCapture(t.pointerId);
147
+ } catch {
148
+ }
149
+ }
150
+ const s = d(e);
151
+ if (e.type === "pointermove") {
152
+ this.#h.set(s.pointerId ?? -1, s), this.#s || (this.#s = requestAnimationFrame(this.#w));
153
+ return;
154
+ }
155
+ this.#E(s);
156
+ };
157
+ #w = () => {
158
+ this.#s = 0;
159
+ for (const e of this.#h.values()) this.#E(e);
160
+ this.#h.clear();
161
+ };
162
+ #E(e) {
163
+ if (!this.#t || this.#e) return;
164
+ const t = { type: "dom-event", event: e };
165
+ this.worker.postMessage(t);
166
+ }
167
+ #y = (e) => {
168
+ const t = e.data;
169
+ if (!(this.#e && t.type !== "error" && t.type !== "disposed"))
170
+ switch (t.type) {
171
+ case "initialized":
172
+ if (this.#e) break;
173
+ this.#t = !0, this.#o?.(), this.#o = null, this.#a = null, this.#c(), this.dispatchEvent(new Event("initialized"));
174
+ break;
175
+ case "ready":
176
+ this.dispatchEvent(new CustomEvent("ready", { detail: t.detail }));
177
+ break;
178
+ case "status":
179
+ this.dispatchEvent(new CustomEvent("status", { detail: t.message }));
180
+ break;
181
+ case "stats":
182
+ this.dispatchEvent(new CustomEvent("stats", { detail: t.stats }));
183
+ break;
184
+ case "event":
185
+ this.dispatchEvent(new CustomEvent(t.eventType, { detail: t.detail }));
186
+ break;
187
+ case "response": {
188
+ const s = this.#i.get(t.id);
189
+ if (!s) break;
190
+ this.#i.delete(t.id), t.error ? s.reject(n(t.error)) : s.resolve(t.result);
191
+ break;
192
+ }
193
+ case "error": {
194
+ const s = n(t.error);
195
+ this.#t || this.#g(s), this.dispatchEvent(new CustomEvent("error", { detail: s }));
196
+ break;
197
+ }
198
+ case "disposed":
199
+ this.#d(new Error("The Worker viewer has been disposed.")), this.dispatchEvent(new Event("disposed")), this.#l();
200
+ break;
201
+ }
202
+ };
203
+ #k = (e) => {
204
+ const t = e.error instanceof Error ? e.error : new Error(e.message);
205
+ this.#d(t), this.dispatchEvent(new CustomEvent("error", { detail: t })), this.#l();
206
+ };
207
+ #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
+ };
210
+ #d(e) {
211
+ if (this.#e) return !1;
212
+ 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);
213
+ for (const t of this.#i.values()) t.reject(e);
214
+ return this.#i.clear(), this.canvas.remove(), !0;
215
+ }
216
+ #g(e) {
217
+ this.#a?.(e), this.#o = null, this.#a = null;
218
+ }
219
+ }
220
+ export {
221
+ o as OffscreenViewerHost,
222
+ d as serializeDomEvent,
223
+ f as serializeError
224
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("../protocol-IUAzx0lk.cjs"),D=require("../Viewer-BKNV67Jj.cjs"),M=require("three/webgpu"),x=new WeakMap;class b{type;timeStamp=performance.now();target;currentTarget;cancelable=!0;bubbles=!0;defaultPrevented=!1;cancelBubble=!1;immediatePropagationStopped=!1;pointerId=0;pointerType="mouse";button=0;buttons=0;altKey=!1;ctrlKey=!1;metaKey=!1;shiftKey=!1;movementX=0;movementY=0;clientX=0;clientY=0;offsetX=0;offsetY=0;pageX=0;pageY=0;screenX=0;screenY=0;deltaX=0;deltaY=0;deltaZ=0;deltaMode=0;constructor(e,t){this.type=e.type,this.target=t,this.currentTarget=t;for(const[r,a]of Object.entries(e))r!=="type"&&a!==void 0&&Reflect.set(this,r,a)}preventDefault(){this.defaultPrevented=!0}stopPropagation(){this.cancelBubble=!0}stopImmediatePropagation(){this.cancelBubble=!0,this.immediatePropagationStopped=!0}composedPath(){return[this.target]}}class y{style={cssText:""};innerText="";textContent="";className="";parentElement=null;children=[];appendChild(e){return this.children.push(e),e instanceof y&&(e.parentElement=this),e}removeChild(e){const t=this.children.indexOf(e);return t>=0&&this.children.splice(t,1),e instanceof y&&(e.parentElement=null),e}remove(){this.parentElement?.removeChild(this)}setAttribute(){}addEventListener(){}removeEventListener(){}getContext(){return null}}function A(s){const e=t=>t.toLowerCase()==="canvas"?new OffscreenCanvas(1,1):new y;return{body:s,documentElement:s,pointerLockElement:null,visibilityState:"visible",createElement:e,createElementNS:(t,r)=>e(r),addEventListener:s.addEventListener.bind(s),removeEventListener:s.removeEventListener.bind(s),exitPointerLock(){}}}function c(s,e,t){Object.defineProperty(s,e,{configurable:!0,value:t})}function v(s,e,t){Object.defineProperty(s,e,{configurable:!0,get:t})}function O(s,e){const t={size:{...e},listeners:new Map,listenerWrappers:new WeakMap};x.set(s,t);const r=s,a={cssText:"",position:"relative",touchAction:"none",width:`${e.width}px`,height:`${e.height}px`},l=(i,p)=>{if(!p)return;let d;typeof p=="function"?d=p:(d=t.listenerWrappers.get(p)??(T=>p.handleEvent(T)),t.listenerWrappers.set(p,d));let h=t.listeners.get(i);h||(h=new Set,t.listeners.set(i,h)),h.add(d)},u=(i,p)=>{if(!p)return;const d=t.listeners.get(i);if(d)if(typeof p=="function")d.delete(p);else{const h=t.listenerWrappers.get(p);h&&d.delete(h)}};c(r,"style",a),c(r,"addEventListener",l),c(r,"removeEventListener",u),c(r,"appendChild",i=>i),c(r,"removeChild",i=>i),c(r,"setAttribute",()=>{}),c(r,"removeAttribute",()=>{}),c(r,"setPointerCapture",()=>{}),c(r,"releasePointerCapture",()=>{}),c(r,"hasPointerCapture",()=>!1),c(r,"requestPointerLock",()=>Promise.resolve()),c(r,"focus",()=>{}),c(r,"remove",()=>{}),v(r,"clientWidth",()=>t.size.width),v(r,"clientHeight",()=>t.size.height),v(r,"offsetWidth",()=>t.size.width),v(r,"offsetHeight",()=>t.size.height),v(r,"offsetTop",()=>t.size.top),v(r,"offsetLeft",()=>t.size.left),v(r,"clientTop",()=>t.size.top),v(r,"clientLeft",()=>t.size.left),v(r,"pageXOffset",()=>t.size.left),v(r,"pageYOffset",()=>t.size.top),v(r,"parentElement",()=>r),c(r,"getBoundingClientRect",()=>{const{width:i,height:p,top:d,left:h}=t.size;return{width:i,height:p,top:d,left:h,right:h+i,bottom:d+p,x:h,y:d,toJSON:()=>({width:i,height:p,top:d,left:h})}});const f=A(r);return c(r,"ownerDocument",f),c(r,"documentElement",r),c(r,"devicePixelRatio",e.pixelRatio),V(r,f),r}function F(s,e){const t=x.get(s);if(!t)throw new Error("The OffscreenCanvas has not been configured as a Worker DOM target.");t.size={...e},s.style.width=`${e.width}px`,s.style.height=`${e.height}px`,c(s,"devicePixelRatio",e.pixelRatio)}function I(s,e){const t=x.get(s);if(!t)throw new Error("The OffscreenCanvas has not been configured as a Worker DOM target.");const r=new b(e,s),a=[...t.listeners.get(e.type)??[]];for(const l of a)if(l(r),r.immediatePropagationStopped)break;return r}function V(s,e){const t=globalThis;t.window=s,t.document=e,t.getComputedStyle=()=>({position:"relative"}),t.PointerEvent=b,t.MouseEvent=b,t.WheelEvent=b,t.Image=y}const z=new Map;let P=!1;function $(){P||(P=!0,M.ImageLoader.prototype.load=function(e,t,r,a){let l=e;this.path!==void 0&&(l=this.path+l),l=this.manager.resolveURL(l);const u=M.Cache.get(`image:${l}`);if(this.manager.itemStart(l),u)return queueMicrotask(()=>{t?.(u),this.manager.itemEnd(l)}),u;let f=z.get(l);return f||(f=fetch(l).then(i=>{if(!i.ok)throw new Error(`Failed to load image ${l}: ${i.status} ${i.statusText}`);return i.blob()}).then(i=>createImageBitmap(i,{colorSpaceConversion:"none",premultiplyAlpha:"none"})).then(i=>(M.Cache.add(`image:${l}`,i),i)).finally(()=>z.delete(l)),z.set(l,f)),f.then(i=>{t?.(i),this.manager.itemEnd(l)}).catch(i=>{a?.(i),this.manager.itemError(l),this.manager.itemEnd(l)}),{}})}const B=1e3,j=100,_=25;class U{windowMs;idleResetMs;missedFrameThresholdMs;#e=[];#t=null;constructor(e={}){this.windowMs=e.windowMs??B,this.idleResetMs=e.idleResetMs??j,this.missedFrameThresholdMs=e.missedFrameThresholdMs??_}add(e,t=performance.now()){return!Number.isFinite(e)||e<=0||!Number.isFinite(t)?this.snapshot(t):(this.#t!==null&&t-this.#t>=this.idleResetMs&&(this.#e.length=0),this.#t=t,e<this.idleResetMs&&this.#e.push({at:t,duration:e}),this.snapshot(t))}snapshot(e=performance.now()){this.#r(e);const t=this.#e.map(({duration:f})=>f);if(t.length===0)return{samples:0,fps:0,average:0,p95:0,max:0,missedFramePercent:0};const r=[...t].sort((f,i)=>f-i),a=t.reduce((f,i)=>f+i,0)/t.length,l=Math.max(0,Math.ceil(r.length*.95)-1),u=t.filter(f=>f>this.missedFrameThresholdMs).length;return{samples:t.length,fps:1e3/a,average:a,p95:r[l],max:r[r.length-1],missedFramePercent:u/t.length*100}}reset(){this.#e.length=0,this.#t=null}#r(e){const t=e-this.windowMs;for(;this.#e.length>0&&this.#e[0].at<t;)this.#e.shift()}}function C(s,e){const{render:t}=s.renderer.info;return{drawCalls:t.drawCalls,frameCalls:t.frameCalls,triangles:t.triangles,points:t.points,lines:t.lines,frameTime:e.average,frameTiming:e}}function q(){const s=globalThis,e={viewer:null,canvas:null,domTarget:null,initialized:!1,disposed:!1,ready:!1,lastStatsAt:0},t=new Map,r=new Set,a=new WeakSet;let l=()=>{},u=()=>{};const f=new Promise((n,o)=>{l=n,u=o}),i=(n,o)=>{e.disposed&&n.type!=="disposed"||s.postMessage(n,o)},p=n=>{if(n&&typeof n=="object"){if(a.has(n))return;a.add(n)}i({type:"error",error:E.serializeError(n)})},d=(n,o)=>{if(t.has(n))throw new Error(`Worker viewer command already exists: ${n}`);return t.set(n,o),()=>{t.get(n)===o&&t.delete(n)}},h=async n=>{if(e.initialized||e.viewer)throw new Error("The Worker viewer has already initialized.");if(e.disposed)throw new Error("The Worker viewer has been disposed.");if(!s.navigator.gpu)throw new Error("WebGPU is not exposed in this Worker. Use a current Chromium browser or the main-thread Viewer.");$(),e.canvas=n.canvas,e.domTarget=O(n.canvas,n.size);const o=new D.Viewer({el:e.domTarget,pixelRatio:n.size.pixelRatio,rendererOptions:{canvas:n.canvas,forceWebGL:!1}});e.viewer=o;const m=new U;o.addEventListener("afterRender",({delta:w})=>{const g=performance.now(),R=m.add(w*1e3,g);g-e.lastStatsAt<250||(e.lastStatsAt=g,i({type:"stats",stats:C(o,R)}))}),d("getStats",()=>C(o,m.snapshot())),d("getViewpoint",()=>o.controls.getCameraViewpoint()),d("setViewpoint",async w=>{const g=w;return await o.controls.setCameraViewpoint(g.viewpoint,g.enableTransition??!0),o.controls.getCameraViewpoint()}),d("render",async()=>(await o.render(),C(o,m.snapshot())));const W={viewer:o,get canvas(){return n.canvas},status(w){i({type:"status",message:w})},emit(w,g){i({type:"event",eventType:w,detail:g})},registerCommand:d,onDispose(w){if(e.disposed)throw new Error("The Worker viewer has been disposed.");return r.add(w),()=>r.delete(w)},ready(w){if(e.disposed)throw new Error("The Worker viewer has been disposed.");if(e.ready)throw new Error("The Worker viewer is already ready.");i({type:"ready",detail:w}),e.ready=!0}};if(await o.init(),e.disposed)throw new Error("The Worker viewer was disposed during initialization.");e.initialized=!0,i({type:"initialized"}),l(W)},T=n=>{!e.viewer||!e.domTarget||(F(e.domTarget,n.size),e.viewer.renderer.setPixelRatio(n.size.pixelRatio),e.viewer.onWindowResize())},S=async n=>{try{if(!e.initialized)throw new Error("The Worker viewer has not initialized.");const o=t.get(n.command);if(!o)throw new Error(`Unknown Worker viewer command: ${n.command}`);const m=await o(n.payload),W=m instanceof ArrayBuffer?[m]:X(m);i({type:"response",id:n.id,result:m},W)}catch(o){i({type:"response",id:n.id,error:E.serializeError(o)})}},L=async()=>{if(e.disposed)return;e.disposed=!0;const n=[];for(const o of[...r].reverse())try{await o()}catch(m){n.push(m)}r.clear();try{e.viewer?.dispose()}catch(o){n.push(o)}e.viewer=null,e.canvas=null,e.domTarget=null,e.initialized||u(new Error("The Worker viewer was disposed before initialization."));for(const o of n)s.postMessage({type:"error",error:E.serializeError(o)});s.postMessage({type:"disposed"}),s.close()},k=n=>{p(n),e.ready||L()};return s.addEventListener("error",n=>{k(n.error??new Error(n.message)),n.preventDefault()}),s.addEventListener("unhandledrejection",n=>{k(n.reason),n.preventDefault()}),s.addEventListener("message",n=>{const o=n.data;o.type==="init"?h(o).catch(m=>{u(m),k(m)}):o.type==="resize"?T(o):o.type==="dom-event"?e.domTarget&&I(e.domTarget,o.event):o.type==="request"?S(o):o.type==="dispose"&&L()}),f}function X(s){const e=new Set,t=new WeakSet,r=a=>{if(!(!a||typeof a!="object")){if(a instanceof ArrayBuffer){e.add(a);return}if(ArrayBuffer.isView(a)){a.buffer instanceof ArrayBuffer&&e.add(a.buffer);return}if(!t.has(a)){if(t.add(a),a instanceof Map){a.forEach((l,u)=>{r(u),r(l)});return}if(a instanceof Set){a.forEach(r);return}Object.values(a).forEach(r)}}};return r(s),[...e]}exports.serializeError=E.serializeError;exports.createWorkerViewer=q;