u-space 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
- import { Raycaster as ue, Vector2 as P, RenderPipeline as Be, Sphere as me, Box3 as ge, Spherical as C, Matrix4 as Re, Quaternion as _e, Vector4 as Ae, Vector3 as we, MathUtils as Ne, PMREMGenerator as Ue, OrthographicCamera as F, TimestampQuery as De, Cache as je, EventDispatcher as ke, Timer as Ge, PerspectiveCamera as W, WebGPURenderer as Fe, PCFShadowMap as He, AgXToneMapping as ze, Scene as $e, Color as J, MeshStandardNodeMaterial as I, Loader as We, LoaderUtils as L, FileLoader as fe, TextureLoader as ye, Group as z, SRGBColorSpace as ve, RepeatWrapping as se, BufferGeometry as Qe, BufferAttribute as ne, Mesh as j, FrontSide as Ke, BackSide as Xe, DoubleSide as qe, REVISION as ie, CubeTextureLoader as Ye, EquirectangularReflectionMapping as Je, Sprite as Ze, SphereGeometry as Ve, TubeGeometry as et, LineCurve3 as tt, CatmullRomCurve3 as st, SpriteNodeMaterial as nt, CanvasTexture as it, ShapeGeometry as rt, Shape as be, ExtrudeGeometry as at, PlaneGeometry as ot, CircleGeometry as ct } from "three/webgpu";
2
- import { pass as q, blendColor as ht, color as A, uv as re, time as Q, pow as K, sin as ae, mix as X, mx_noise_float as oe, Fn as Te, userData as D, materialColor as ce, select as Y, materialOpacity as lt, vec3 as dt } from "three/tsl";
3
- import Ce from "camera-controls";
4
- import { RoomEnvironment as pt } from "three/addons/environments/RoomEnvironment.js";
5
- import { ViewHelper as ut } from "three/addons/helpers/ViewHelper.js";
6
- import { GLTFLoader as Me } from "three/addons/loaders/GLTFLoader.js";
7
- import { FBXLoader as mt } from "three/addons/loaders/FBXLoader.js";
8
- import { OBJLoader as gt } from "three/addons/loaders/OBJLoader.js";
9
- import { STLLoader as wt } from "three/addons/loaders/STLLoader.js";
10
- import { DRACOLoader as ft } from "three/addons/loaders/DRACOLoader.js";
11
- import { KTX2Loader as yt } from "three/addons/loaders/KTX2Loader.js";
12
- import { MeshoptDecoder as he } from "three/addons/libs/meshopt_decoder.module.js";
13
- import { HDRLoader as vt } from "three/addons/loaders/HDRLoader.js";
14
- import { clone as bt } from "three/addons/utils/SkeletonUtils.js";
15
- import { Color as N } from "three";
16
- import { Easing as d, Tween as Tt } from "three/addons/libs/tween.module.js";
17
- class Ct {
1
+ import { Raycaster, Vector2, RenderPipeline as RenderPipeline$1, Sphere, Box3, Spherical, Matrix4, Quaternion, Vector4, Vector3, MathUtils, PMREMGenerator, OrthographicCamera, TimestampQuery, Cache, EventDispatcher, Timer, PerspectiveCamera, WebGPURenderer, PCFShadowMap, AgXToneMapping, Scene, Color, MeshStandardNodeMaterial, Loader, LoaderUtils, FileLoader, TextureLoader, Group, SRGBColorSpace, RepeatWrapping, BufferGeometry, BufferAttribute, Mesh, FrontSide, BackSide, DoubleSide, REVISION, CubeTextureLoader, EquirectangularReflectionMapping, Sprite, SphereGeometry, TubeGeometry, LineCurve3, CatmullRomCurve3, SpriteNodeMaterial, CanvasTexture, ShapeGeometry, Shape, ExtrudeGeometry, PlaneGeometry, CircleGeometry } from "three/webgpu";
2
+ import { pass, blendColor, color, uv, time, pow, sin, mix, mx_noise_float, Fn, userData, materialColor, select, materialOpacity, vec3 } from "three/tsl";
3
+ import CameraControlsBase from "camera-controls";
4
+ import { RoomEnvironment as RoomEnvironment$1 } from "three/addons/environments/RoomEnvironment.js";
5
+ import { ViewHelper } from "three/addons/helpers/ViewHelper.js";
6
+ import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
7
+ import { FBXLoader } from "three/addons/loaders/FBXLoader.js";
8
+ import { OBJLoader } from "three/addons/loaders/OBJLoader.js";
9
+ import { STLLoader } from "three/addons/loaders/STLLoader.js";
10
+ import { DRACOLoader } from "three/addons/loaders/DRACOLoader.js";
11
+ import { KTX2Loader } from "three/addons/loaders/KTX2Loader.js";
12
+ import { MeshoptDecoder } from "three/addons/libs/meshopt_decoder.module.js";
13
+ import { HDRLoader } from "three/addons/loaders/HDRLoader.js";
14
+ import { clone } from "three/addons/utils/SkeletonUtils.js";
15
+ import { Color as Color$1 } from "three";
16
+ import { Easing, Tween as Tween$1 } from "three/addons/libs/tween.module.js";
17
+ class InteractionEvent {
18
18
  /** The type of event (e.g., 'click', 'pointerdown'). */
19
19
  type;
20
20
  /** The original 3D object that triggered the event. */
@@ -25,15 +25,19 @@ class Ct {
25
25
  intersect;
26
26
  /** The original DOM event, or undefined if not applicable. */
27
27
  originalEvent;
28
- _propagationStopped = !1;
29
- constructor(e) {
30
- this.type = e.type, this.target = e.target, this.currentTarget = e.target, this.intersect = e.intersect, this.originalEvent = e.originalEvent;
28
+ _propagationStopped = false;
29
+ constructor(init) {
30
+ this.type = init.type;
31
+ this.target = init.target;
32
+ this.currentTarget = init.target;
33
+ this.intersect = init.intersect;
34
+ this.originalEvent = init.originalEvent;
31
35
  }
32
36
  /**
33
37
  * Stops the event from bubbling up the parent chain.
34
38
  */
35
39
  stopPropagation() {
36
- this._propagationStopped = !0;
40
+ this._propagationStopped = true;
37
41
  }
38
42
  /**
39
43
  * Returns true if `stopPropagation()` has been called.
@@ -42,109 +46,162 @@ class Ct {
42
46
  return this._propagationStopped;
43
47
  }
44
48
  }
45
- class Mt {
49
+ class InteractionManager {
46
50
  domElement;
47
51
  scene;
48
52
  camera;
49
- raycaster = new ue();
50
- pointer = new P();
53
+ raycaster = new Raycaster();
54
+ pointer = new Vector2();
51
55
  hoveredObject = null;
52
56
  pointerDownTime = 0;
53
- pointerDownPos = new P();
57
+ pointerDownPos = new Vector2();
54
58
  clickTimer = null;
55
59
  longPressThreshold = 500;
56
60
  moveThreshold = 0.01;
57
61
  /**
58
- * The objects to check for intersections.
59
- * If not set, it defaults to the children of the scene.
62
+ * The objects to check for intersections. default to all children of the scene (including nested).
60
63
  */
61
- targetObjects = null;
64
+ targetObjects;
62
65
  /**
63
66
  * Whether to enable pointer move events (pointermove, pointerenter, pointerleave).
64
67
  * Disabled by default for performance optimization.
65
68
  */
66
- pointerMoveEventsEnabled = !1;
67
- constructor(e, t, s) {
68
- this.domElement = e, this.scene = t, this.camera = s, this.raycaster.params.Points.threshold = 0.1, this.raycaster.params.Line.threshold = 0.1, this._bindEvents();
69
+ pointerMoveEventsEnabled = false;
70
+ constructor(domElement, scene, camera) {
71
+ this.domElement = domElement;
72
+ this.scene = scene;
73
+ this.camera = camera;
74
+ this.raycaster.params.Points.threshold = 0.1;
75
+ this.raycaster.params.Line.threshold = 0.1;
76
+ this.targetObjects = this.scene.children;
77
+ this._bindEvents();
69
78
  }
70
79
  /**
71
80
  * Updates the camera reference (useful when switching cameras).
72
81
  */
73
- setCamera(e) {
74
- this.camera = e;
82
+ setCamera(camera) {
83
+ this.camera = camera;
75
84
  }
76
85
  _bindEvents() {
77
- this.domElement.addEventListener("click", this._onClick), this.domElement.addEventListener("dblclick", this._onDblClick), this.domElement.addEventListener("contextmenu", this._onContextMenu), this.domElement.addEventListener("pointerdown", this._onPointerDown), this.domElement.addEventListener("pointerup", this._onPointerUp), this.domElement.addEventListener("pointermove", this._onPointerMove);
78
- }
79
- _updatePointer(e) {
80
- const t = this.domElement.getBoundingClientRect();
81
- this.pointer.x = (e.clientX - t.left) / t.width * 2 - 1, this.pointer.y = -((e.clientY - t.top) / t.height) * 2 + 1;
86
+ this.domElement.addEventListener("click", this._onClick);
87
+ this.domElement.addEventListener("dblclick", this._onDblClick);
88
+ this.domElement.addEventListener("contextmenu", this._onContextMenu);
89
+ this.domElement.addEventListener("pointerdown", this._onPointerDown);
90
+ this.domElement.addEventListener("pointerup", this._onPointerUp);
91
+ this.domElement.addEventListener("pointermove", this._onPointerMove);
92
+ }
93
+ _updatePointer(event) {
94
+ const rect = this.domElement.getBoundingClientRect();
95
+ this.pointer.x = (event.clientX - rect.left) / rect.width * 2 - 1;
96
+ this.pointer.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
82
97
  }
83
98
  _getIntersects() {
84
99
  this.raycaster.setFromCamera(this.pointer, this.camera);
85
- const e = this.targetObjects || this.scene.children;
86
- return this.raycaster.intersectObjects(e, !0);
100
+ return this.raycaster.intersectObjects(this.targetObjects, true);
87
101
  }
88
102
  /**
89
103
  * Dispatches an event to the target object and bubbles up the parent chain.
90
104
  */
91
- _dispatchToTarget(e, t, s, n) {
92
- const i = new Ct({
93
- type: e,
94
- target: t,
95
- intersect: s,
96
- originalEvent: n
105
+ _dispatchToTarget(type, target, intersect, originalEvent) {
106
+ const event3d = new InteractionEvent({
107
+ type,
108
+ target,
109
+ intersect,
110
+ originalEvent
97
111
  });
98
- let a = t;
99
- for (; a && !i.propagationStopped; )
100
- i.currentTarget = a, a.dispatchEvent({ type: e, event: i }), a = a.parent;
112
+ let current = target;
113
+ while (current && !event3d.propagationStopped) {
114
+ event3d.currentTarget = current;
115
+ current.dispatchEvent({ type, event: event3d });
116
+ current = current.parent;
117
+ }
101
118
  }
102
119
  /**
103
120
  * Handles a DOM event by raycasting and dispatching to the first intersected object.
104
121
  */
105
- _handleEvent(e, t) {
106
- this._updatePointer(t);
107
- const s = this._getIntersects();
108
- if (s.length === 0) return;
109
- const n = s[0];
110
- this._dispatchToTarget(e, n.object, n, t);
122
+ _handleEvent(type, originalEvent) {
123
+ this._updatePointer(originalEvent);
124
+ const intersects = this._getIntersects();
125
+ if (intersects.length === 0) return;
126
+ const hit = intersects[0];
127
+ this._dispatchToTarget(type, hit.object, hit, originalEvent);
111
128
  }
112
129
  _onClick = (e) => {
113
- const t = Date.now() - this.pointerDownTime, s = this.pointer.distanceTo(this.pointerDownPos);
114
- if (!(t > this.longPressThreshold || s > this.moveThreshold)) {
115
- if (this.clickTimer) {
116
- clearTimeout(this.clickTimer), this.clickTimer = null;
117
- return;
118
- }
119
- this.clickTimer = setTimeout(() => {
120
- this._handleEvent("click", e), this.clickTimer = null;
121
- }, 200);
130
+ const duration = Date.now() - this.pointerDownTime;
131
+ const moveDistance = this.pointer.distanceTo(this.pointerDownPos);
132
+ if (duration > this.longPressThreshold || moveDistance > this.moveThreshold) {
133
+ return;
122
134
  }
135
+ if (this.clickTimer) {
136
+ clearTimeout(this.clickTimer);
137
+ this.clickTimer = null;
138
+ return;
139
+ }
140
+ this.clickTimer = setTimeout(() => {
141
+ this._handleEvent("click", e);
142
+ this.clickTimer = null;
143
+ }, 200);
123
144
  };
124
145
  _onDblClick = (e) => {
125
- this.clickTimer && (clearTimeout(this.clickTimer), this.clickTimer = null), this._handleEvent("dblclick", e);
146
+ if (this.clickTimer) {
147
+ clearTimeout(this.clickTimer);
148
+ this.clickTimer = null;
149
+ }
150
+ this._handleEvent("dblclick", e);
126
151
  };
127
152
  _onContextMenu = (e) => {
128
- e.preventDefault(), this._handleEvent("contextmenu", e);
153
+ e.preventDefault();
129
154
  };
130
155
  _onPointerDown = (e) => {
131
- this.pointerDownTime = Date.now(), this._updatePointer(e), this.pointerDownPos.copy(this.pointer), this._handleEvent("pointerdown", e);
156
+ this.pointerDownTime = Date.now();
157
+ this._updatePointer(e);
158
+ this.pointerDownPos.copy(this.pointer);
159
+ this._handleEvent("pointerdown", e);
160
+ };
161
+ _onPointerUp = (e) => {
162
+ this._updatePointer(e);
163
+ if (e.button === 2) {
164
+ const duration = Date.now() - this.pointerDownTime;
165
+ const moveDistance = this.pointer.distanceTo(this.pointerDownPos);
166
+ if (duration <= this.longPressThreshold && moveDistance <= this.moveThreshold) {
167
+ this._handleEvent("rightclick", e);
168
+ }
169
+ }
170
+ this._handleEvent("pointerup", e);
132
171
  };
133
- _onPointerUp = (e) => this._handleEvent("pointerup", e);
134
172
  _onPointerMove = (e) => {
135
173
  if (!this.pointerMoveEventsEnabled) return;
136
174
  this._updatePointer(e);
137
- const t = this._getIntersects(), s = t.length > 0 ? t[0].object : null, n = t.length > 0 ? t[0] : null;
138
- this.hoveredObject !== s && (this.hoveredObject && this._dispatchToTarget("pointerleave", this.hoveredObject, null, e), this.hoveredObject = s, s && n && this._dispatchToTarget("pointerenter", s, n, e)), s && n && this._dispatchToTarget("pointermove", s, n, e);
175
+ const intersects = this._getIntersects();
176
+ const hitObject = intersects.length > 0 ? intersects[0].object : null;
177
+ const intersect = intersects.length > 0 ? intersects[0] : null;
178
+ if (this.hoveredObject !== hitObject) {
179
+ if (this.hoveredObject) {
180
+ this._dispatchToTarget("pointerleave", this.hoveredObject, null, e);
181
+ }
182
+ this.hoveredObject = hitObject;
183
+ if (hitObject && intersect) {
184
+ this._dispatchToTarget("pointerenter", hitObject, intersect, e);
185
+ }
186
+ }
187
+ if (hitObject && intersect) {
188
+ this._dispatchToTarget("pointermove", hitObject, intersect, e);
189
+ }
139
190
  };
140
191
  /**
141
192
  * Cleans up event listeners.
142
193
  */
143
194
  dispose() {
144
- this.domElement.removeEventListener("click", this._onClick), this.domElement.removeEventListener("dblclick", this._onDblClick), this.domElement.removeEventListener("contextmenu", this._onContextMenu), this.domElement.removeEventListener("pointerdown", this._onPointerDown), this.domElement.removeEventListener("pointerup", this._onPointerUp), this.domElement.removeEventListener("pointermove", this._onPointerMove), this.hoveredObject = null;
195
+ this.domElement.removeEventListener("click", this._onClick);
196
+ this.domElement.removeEventListener("dblclick", this._onDblClick);
197
+ this.domElement.removeEventListener("contextmenu", this._onContextMenu);
198
+ this.domElement.removeEventListener("pointerdown", this._onPointerDown);
199
+ this.domElement.removeEventListener("pointerup", this._onPointerUp);
200
+ this.domElement.removeEventListener("pointermove", this._onPointerMove);
201
+ this.hoveredObject = null;
145
202
  }
146
203
  }
147
- class xt {
204
+ class ObjectManager {
148
205
  idMap = /* @__PURE__ */ new Map();
149
206
  nameMap = /* @__PURE__ */ new Map();
150
207
  typeMap = /* @__PURE__ */ new Map();
@@ -154,85 +211,117 @@ class xt {
154
211
  * Add an object with a custom id.
155
212
  * One object can have multiple ids.
156
213
  */
157
- add(e, t) {
158
- if (this.idMap.has(e)) {
159
- console.warn(`ObjectManager: Object with id ${e} already exists.`);
214
+ add(id, object) {
215
+ if (this.idMap.has(id)) {
216
+ console.warn(`ObjectManager: Object with id ${id} already exists.`);
160
217
  return;
161
218
  }
162
- this.idMap.set(e, t), this.allObjects.add(t), this.objectIds.has(t) || this.objectIds.set(t, /* @__PURE__ */ new Set()), this.objectIds.get(t).add(e), t.name && (this.nameMap.has(t.name) || this.nameMap.set(t.name, /* @__PURE__ */ new Set()), this.nameMap.get(t.name).add(t)), t.type && (this.typeMap.has(t.type) || this.typeMap.set(t.type, /* @__PURE__ */ new Set()), this.typeMap.get(t.type).add(t));
219
+ this.idMap.set(id, object);
220
+ this.allObjects.add(object);
221
+ if (!this.objectIds.has(object)) {
222
+ this.objectIds.set(object, /* @__PURE__ */ new Set());
223
+ }
224
+ this.objectIds.get(object).add(id);
225
+ if (object.name) {
226
+ if (!this.nameMap.has(object.name)) {
227
+ this.nameMap.set(object.name, /* @__PURE__ */ new Set());
228
+ }
229
+ this.nameMap.get(object.name).add(object);
230
+ }
231
+ if (object.type) {
232
+ if (!this.typeMap.has(object.type)) {
233
+ this.typeMap.set(object.type, /* @__PURE__ */ new Set());
234
+ }
235
+ this.typeMap.get(object.type).add(object);
236
+ }
163
237
  }
164
238
  /**
165
239
  * Get an object by its custom id.
166
240
  */
167
- getById(e) {
168
- return this.idMap.get(e);
241
+ getById(id) {
242
+ return this.idMap.get(id);
169
243
  }
170
244
  /**
171
245
  * Get all objects with a given name.
172
246
  */
173
- getByName(e) {
174
- return this.nameMap.get(e) || /* @__PURE__ */ new Set();
247
+ getByName(name) {
248
+ return this.nameMap.get(name) || /* @__PURE__ */ new Set();
175
249
  }
176
250
  /**
177
251
  * Get all objects with a given type.
178
252
  */
179
- getByType(e) {
180
- return this.typeMap.get(e) || /* @__PURE__ */ new Set();
253
+ getByType(type) {
254
+ return this.typeMap.get(type) || /* @__PURE__ */ new Set();
181
255
  }
182
256
  /**
183
257
  * Get all ids associated with an object.
184
258
  */
185
- getObjectIds(e) {
186
- return this.objectIds.get(e) || /* @__PURE__ */ new Set();
259
+ getObjectIds(object) {
260
+ return this.objectIds.get(object) || /* @__PURE__ */ new Set();
187
261
  }
188
262
  /**
189
263
  * Remove an object and all its associated ids.
190
264
  */
191
- remove(e) {
192
- const t = this.objectIds.get(e);
193
- if (t) {
194
- for (const s of t)
195
- this.idMap.delete(s);
196
- this.objectIds.delete(e);
265
+ remove(object) {
266
+ const ids = this.objectIds.get(object);
267
+ if (ids) {
268
+ for (const id of ids) {
269
+ this.idMap.delete(id);
270
+ }
271
+ this.objectIds.delete(object);
197
272
  }
198
- if (e.name && this.nameMap.has(e.name)) {
199
- const s = this.nameMap.get(e.name);
200
- s.delete(e), s.size === 0 && this.nameMap.delete(e.name);
273
+ if (object.name && this.nameMap.has(object.name)) {
274
+ const set = this.nameMap.get(object.name);
275
+ set.delete(object);
276
+ if (set.size === 0) {
277
+ this.nameMap.delete(object.name);
278
+ }
201
279
  }
202
- if (e.type && this.typeMap.has(e.type)) {
203
- const s = this.typeMap.get(e.type);
204
- s.delete(e), s.size === 0 && this.typeMap.delete(e.type);
280
+ if (object.type && this.typeMap.has(object.type)) {
281
+ const set = this.typeMap.get(object.type);
282
+ set.delete(object);
283
+ if (set.size === 0) {
284
+ this.typeMap.delete(object.type);
285
+ }
205
286
  }
206
- this.allObjects.delete(e);
287
+ this.allObjects.delete(object);
207
288
  }
208
289
  /**
209
290
  * Remove an object by its id.
210
291
  */
211
- removeById(e) {
212
- const t = this.idMap.get(e);
213
- t && this.remove(t);
292
+ removeById(id) {
293
+ const object = this.idMap.get(id);
294
+ if (object) {
295
+ this.remove(object);
296
+ }
214
297
  }
215
298
  /**
216
299
  * Remove all objects with a given name.
217
300
  */
218
- removeByName(e) {
219
- const t = this.getByName(e);
220
- for (const s of t)
221
- this.remove(s);
301
+ removeByName(name) {
302
+ const objects = this.getByName(name);
303
+ for (const object of objects) {
304
+ this.remove(object);
305
+ }
222
306
  }
223
307
  /**
224
308
  * Remove all objects with a given type.
225
309
  */
226
- removeByType(e) {
227
- const t = this.getByType(e);
228
- for (const s of t)
229
- this.remove(s);
310
+ removeByType(type) {
311
+ const objects = this.getByType(type);
312
+ for (const object of objects) {
313
+ this.remove(object);
314
+ }
230
315
  }
231
316
  /**
232
317
  * Clear all cached objects.
233
318
  */
234
319
  clear() {
235
- this.idMap.clear(), this.nameMap.clear(), this.typeMap.clear(), this.objectIds.clear(), this.allObjects.clear();
320
+ this.idMap.clear();
321
+ this.nameMap.clear();
322
+ this.typeMap.clear();
323
+ this.objectIds.clear();
324
+ this.allObjects.clear();
236
325
  }
237
326
  /**
238
327
  * Get all cached objects as a Set.
@@ -247,148 +336,202 @@ class xt {
247
336
  return this.allObjects.size;
248
337
  }
249
338
  }
250
- class Et extends Be {
339
+ class RenderPipeline extends RenderPipeline$1 {
251
340
  scene;
252
341
  camera;
253
342
  currentOutputNode;
254
343
  needsUpdateOutputNode;
255
- #e;
256
- constructor(...e) {
257
- const [t, s, n] = e;
258
- super(t), this.scene = s, this.camera = n, this.currentOutputNode = q(s, n), this.needsUpdateOutputNode = !0, this.#e = /* @__PURE__ */ new Set();
259
- }
260
- addOverlayPass(e) {
261
- this.#e.add(e), this.needsUpdateOutputNode = !0;
262
- }
263
- removeOverlayPass(e) {
264
- this.#e.delete(e), this.needsUpdateOutputNode = !0;
265
- }
266
- setCamera(e) {
267
- this.camera = e, this.needsUpdateOutputNode = !0;
268
- }
269
- setCurrentOutputNode(e) {
270
- this.currentOutputNode.dispose(), this.currentOutputNode = e, this.needsUpdateOutputNode = !0;
344
+ #overlayPasses;
345
+ constructor(...args) {
346
+ const [renderer, scene, camera] = args;
347
+ super(renderer);
348
+ this.scene = scene;
349
+ this.camera = camera;
350
+ this.currentOutputNode = pass(scene, camera);
351
+ this.needsUpdateOutputNode = true;
352
+ this.#overlayPasses = /* @__PURE__ */ new Set();
353
+ }
354
+ addOverlayPass(pass2) {
355
+ this.#overlayPasses.add(pass2);
356
+ this.needsUpdateOutputNode = true;
357
+ }
358
+ removeOverlayPass(pass2) {
359
+ this.#overlayPasses.delete(pass2);
360
+ this.needsUpdateOutputNode = true;
361
+ }
362
+ setCamera(camera) {
363
+ this.camera = camera;
364
+ this.needsUpdateOutputNode = true;
365
+ }
366
+ setCurrentOutputNode(node) {
367
+ this.currentOutputNode.dispose();
368
+ this.currentOutputNode = node;
369
+ this.needsUpdateOutputNode = true;
271
370
  }
272
371
  resetCurrentOutputNode() {
273
- this.currentOutputNode.dispose(), this.currentOutputNode = q(this.scene, this.camera), this.needsUpdateOutputNode = !0;
274
- }
275
- #t() {
276
- let e = this.currentOutputNode;
277
- this.#e.size > 0 && this.#e.forEach((t) => {
278
- e = ht(e, t);
279
- }), this.outputNode = e, this.needsUpdate = !0;
372
+ this.currentOutputNode.dispose();
373
+ this.currentOutputNode = pass(this.scene, this.camera);
374
+ this.needsUpdateOutputNode = true;
375
+ }
376
+ #updateOutputNode() {
377
+ let currentNode = this.currentOutputNode;
378
+ if (this.#overlayPasses.size > 0) {
379
+ this.#overlayPasses.forEach((overlayPass) => {
380
+ currentNode = blendColor(currentNode, overlayPass);
381
+ });
382
+ }
383
+ this.outputNode = currentNode;
384
+ this.needsUpdate = true;
280
385
  }
281
386
  render() {
282
- this.needsUpdateOutputNode && (this.#t(), this.needsUpdateOutputNode = !1), super.render();
387
+ if (this.needsUpdateOutputNode) {
388
+ this.#updateOutputNode();
389
+ this.needsUpdateOutputNode = false;
390
+ }
391
+ super.render();
283
392
  }
284
393
  }
285
- const Ot = {
286
- Vector2: P,
287
- Vector3: we,
288
- Vector4: Ae,
289
- Quaternion: _e,
290
- Matrix4: Re,
291
- Spherical: C,
292
- Box3: ge,
293
- Sphere: me,
294
- Raycaster: ue
394
+ const subsetOfTHREE = {
395
+ Vector2,
396
+ Vector3,
397
+ Vector4,
398
+ Quaternion,
399
+ Matrix4,
400
+ Spherical,
401
+ Box3,
402
+ Sphere,
403
+ Raycaster
295
404
  };
296
- Ce.install({ THREE: Ot });
297
- class Pt extends Ce {
298
- constructor(...e) {
299
- super(...e), this.minDistance = 0.2, this.smoothTime = 0.2, this.dollySpeed = 0.2;
405
+ CameraControlsBase.install({ THREE: subsetOfTHREE });
406
+ class CameraControls extends CameraControlsBase {
407
+ constructor(...args) {
408
+ super(...args);
409
+ this.minDistance = 0.2;
410
+ this.smoothTime = 0.2;
411
+ this.dollySpeed = 0.2;
300
412
  }
301
413
  /**
302
414
  * Set absolute angle for azimuth to avoid spinning
303
415
  */
304
416
  absoluteRotations() {
305
- this.azimuthAngle = St(this.azimuthAngle, 0);
417
+ this.azimuthAngle = absoluteAngle(this.azimuthAngle, 0);
306
418
  }
307
- async flyToBox(e, t = {}) {
308
- if (e.isEmpty())
309
- return console.warn("CameraControls.flyToBox: The provided Box3 is empty."), !1;
419
+ async flyToBox(box, options = {}) {
420
+ if (box.isEmpty()) {
421
+ console.warn("CameraControls.flyToBox: The provided Box3 is empty.");
422
+ return false;
423
+ }
310
424
  this.absoluteRotations();
311
- const { viewpoint: s = "frontTop", enableTransition: n = !0, padding: i = 0.1, cover: a = !1 } = t, c = [];
312
- if (s !== "current") {
313
- const r = le[s.toUpperCase()] ?? le.FRONTTOP, h = r.theta, l = r.phi;
314
- c.push(
315
- this.fitToBox(e, n, {
316
- paddingLeft: i,
317
- paddingRight: i,
318
- paddingTop: i,
319
- paddingBottom: i,
320
- cover: a
425
+ const { viewpoint = "frontTop", enableTransition = true, padding = 0.1, cover = false } = options;
426
+ const promises = [];
427
+ if (viewpoint !== "current") {
428
+ const spherical = viewpointsSpherical[viewpoint.toUpperCase()] ?? viewpointsSpherical.FRONTTOP;
429
+ const azimuthAngle = spherical.theta, polarAngle = spherical.phi;
430
+ promises.push(
431
+ this.fitToBox(box, enableTransition, {
432
+ paddingLeft: padding,
433
+ paddingRight: padding,
434
+ paddingTop: padding,
435
+ paddingBottom: padding,
436
+ cover
321
437
  })
322
- ), c.push(this.rotateTo(h, l, n));
438
+ );
439
+ promises.push(this.rotateTo(azimuthAngle, polarAngle, enableTransition));
323
440
  } else {
324
- const r = new me();
325
- e.getBoundingSphere(r), r.radius += i, c.push(this.fitToSphere(r, n));
441
+ const sphere = new Sphere();
442
+ box.getBoundingSphere(sphere);
443
+ sphere.radius += padding;
444
+ promises.push(this.fitToSphere(sphere, enableTransition));
326
445
  }
327
- return await Promise.all(c), !0;
446
+ await Promise.all(promises);
447
+ return true;
328
448
  }
329
- async flyToObject(e, t = {}) {
330
- const s = new ge().setFromObject(e);
331
- return this.flyToBox(s, t);
449
+ async flyToObject(object, options = {}) {
450
+ const box = new Box3().setFromObject(object);
451
+ return this.flyToBox(box, options);
332
452
  }
333
453
  }
334
- const le = {
335
- LEFT: new C(0, Math.PI / 2, -Math.PI / 2),
336
- RIGHT: new C(0, Math.PI / 2, Math.PI / 2),
337
- FRONT: new C(0, Math.PI / 2, 0),
338
- BACK: new C(0, Math.PI / 2, Math.PI),
339
- TOP: new C(0, 0, 0),
340
- BOTTOM: new C(0, Math.PI, 0),
341
- FRONTTOP: new C(0, Math.PI / 4, 0),
342
- BACKTOP: new C(0, Math.PI / 4, Math.PI),
343
- LEFTTOP: new C(0, Math.PI / 4, -Math.PI / 2),
344
- RIGHTTOP: new C(0, Math.PI / 4, Math.PI / 2),
345
- LEFTFRONTTOP: new C(0, Math.PI / 4, -Math.PI / 4),
346
- RIGHTFRONTTOP: new C(0, Math.PI / 4, Math.PI / 4),
347
- LEFTBACKTOP: new C(0, Math.PI / 4, -Math.PI / 4 * 3),
348
- RIGHTBACKTOP: new C(0, Math.PI / 4, Math.PI / 4 * 3)
454
+ const viewpointsSpherical = {
455
+ LEFT: new Spherical(0, Math.PI / 2, -Math.PI / 2),
456
+ RIGHT: new Spherical(0, Math.PI / 2, Math.PI / 2),
457
+ FRONT: new Spherical(0, Math.PI / 2, 0),
458
+ BACK: new Spherical(0, Math.PI / 2, Math.PI),
459
+ TOP: new Spherical(0, 0, 0),
460
+ BOTTOM: new Spherical(0, Math.PI, 0),
461
+ FRONTTOP: new Spherical(0, Math.PI / 4, 0),
462
+ BACKTOP: new Spherical(0, Math.PI / 4, Math.PI),
463
+ LEFTTOP: new Spherical(0, Math.PI / 4, -Math.PI / 2),
464
+ RIGHTTOP: new Spherical(0, Math.PI / 4, Math.PI / 2),
465
+ LEFTFRONTTOP: new Spherical(0, Math.PI / 4, -Math.PI / 4),
466
+ RIGHTFRONTTOP: new Spherical(0, Math.PI / 4, Math.PI / 4),
467
+ LEFTBACKTOP: new Spherical(0, Math.PI / 4, -Math.PI / 4 * 3),
468
+ RIGHTBACKTOP: new Spherical(0, Math.PI / 4, Math.PI / 4 * 3)
349
469
  };
350
- function St(o, e) {
351
- const t = o - e;
352
- return Ne.euclideanModulo(t + Math.PI, Math.PI * 2) - Math.PI;
470
+ function absoluteAngle(targetAngle, sourceAngle) {
471
+ const angle = targetAngle - sourceAngle;
472
+ return MathUtils.euclideanModulo(angle + Math.PI, Math.PI * 2) - Math.PI;
353
473
  }
354
- class Lt {
355
- environment = new pt();
474
+ class RoomEnvironment {
475
+ environment = new RoomEnvironment$1();
356
476
  renderer;
357
477
  pmremGenerator;
358
478
  envMap = null;
359
- constructor(e) {
360
- this.renderer = e, this.pmremGenerator = new Ue(e);
479
+ constructor(renderer) {
480
+ this.renderer = renderer;
481
+ this.pmremGenerator = new PMREMGenerator(renderer);
361
482
  }
362
483
  update() {
363
- this.envMap || (this.envMap = this.pmremGenerator.fromScene(this.environment).texture);
484
+ if (!this.envMap) {
485
+ this.envMap = this.pmremGenerator.fromScene(this.environment).texture;
486
+ }
364
487
  }
365
488
  dispose() {
366
- this.pmremGenerator.dispose(), this.envMap?.dispose();
489
+ this.pmremGenerator.dispose();
490
+ this.envMap?.dispose();
367
491
  }
368
492
  }
369
- const G = 128;
370
- class It extends ut {
493
+ const dim = 128;
494
+ class ViewerHelper extends ViewHelper {
371
495
  viewer;
372
496
  overlayPass;
373
- constructor(e) {
374
- super(e.camera, e.el), this.viewer = e;
375
- const t = new F(-2, 2, 2, -2, 0, 4);
376
- t.position.set(0, 0, 2), this.overlayPass = q(this, t), this.setLabels("x", "y", "z");
497
+ constructor(viewer) {
498
+ super(viewer.camera, viewer.el);
499
+ this.viewer = viewer;
500
+ const orthoCamera = new OrthographicCamera(-2, 2, 2, -2, 0, 4);
501
+ orthoCamera.position.set(0, 0, 2);
502
+ this.overlayPass = pass(this, orthoCamera);
503
+ this.setLabels("x", "y", "z");
377
504
  }
378
505
  _update = () => {
379
506
  this.quaternion.copy(this.viewer.camera.quaternion).invert();
380
- const e = this.location;
381
- let t, s;
382
- e.left !== null ? t = e.left : t = this.viewer.el.offsetWidth - G - e.right, e.top !== null ? s = e.top : s = this.viewer.el.offsetHeight - G - e.bottom, this.overlayPass.setViewport(t, s, G, G);
507
+ const location = this.location;
508
+ let x, y;
509
+ if (location.left !== null) {
510
+ x = location.left;
511
+ } else {
512
+ x = this.viewer.el.offsetWidth - dim - location.right;
513
+ }
514
+ if (location.top !== null) {
515
+ y = location.top;
516
+ } else {
517
+ y = this.viewer.el.offsetHeight - dim - location.bottom;
518
+ }
519
+ this.overlayPass.setViewport(x, y, dim, dim);
383
520
  };
384
521
  enable() {
385
- return this.viewer.renderPipeline.addOverlayPass(this.overlayPass), this.viewer.addEventListener("beforeRender", this._update), this.viewer.render(), this;
522
+ this.viewer.renderPipeline.addOverlayPass(this.overlayPass);
523
+ this.viewer.addEventListener("beforeRender", this._update);
524
+ this.viewer.render();
525
+ return this;
386
526
  }
387
527
  disable() {
388
- return this.viewer.renderPipeline.removeOverlayPass(this.overlayPass), this.viewer.removeEventListener("beforeRender", this._update), this.viewer.render(), this;
528
+ this.viewer.renderPipeline.removeOverlayPass(this.overlayPass);
529
+ this.viewer.removeEventListener("beforeRender", this._update);
530
+ this.viewer.render();
531
+ return this;
389
532
  }
390
533
  }
391
- class Bt {
534
+ class Info {
392
535
  el;
393
536
  renderer;
394
537
  container;
@@ -398,40 +541,79 @@ class Bt {
398
541
  pointsText;
399
542
  linesText;
400
543
  timestampText;
401
- _enabled = !1;
402
- constructor(e, t) {
403
- this.el = e, this.renderer = t;
404
- const s = document.createElement("div");
405
- s.style.position = "absolute", s.style.left = "12px", s.style.bottom = "12px", s.style.fontSize = "12px", s.style.color = "#fff", s.style.pointerEvents = "none", this.container = s;
406
- function n(a, c = !0) {
407
- const r = document.createElement("span");
408
- return c && (r.style.marginLeft = "6px"), r.innerText = a, r;
409
- }
410
- function i() {
544
+ _enabled = false;
545
+ constructor(el, renderer) {
546
+ this.el = el;
547
+ this.renderer = renderer;
548
+ const container = document.createElement("div");
549
+ container.style.position = "absolute";
550
+ container.style.left = "12px";
551
+ container.style.bottom = "12px";
552
+ container.style.fontSize = "12px";
553
+ container.style.color = "#fff";
554
+ container.style.pointerEvents = "none";
555
+ this.container = container;
556
+ function createTextEl(text, isMarginLeft = true) {
557
+ const el2 = document.createElement("span");
558
+ if (isMarginLeft) el2.style.marginLeft = "6px";
559
+ el2.innerText = text;
560
+ return el2;
561
+ }
562
+ function createBr() {
411
563
  return document.createElement("br");
412
564
  }
413
- this.drawCallsText = n("0"), this.frameCallsText = n("0"), this.trianglesText = n("0"), this.linesText = n("0"), this.pointsText = n("0"), this.timestampText = n("0"), this.container.appendChild(n("draw calls", !1)), this.container.appendChild(this.drawCallsText), this.container.appendChild(i()), this.container.appendChild(n("frame calls", !1)), this.container.appendChild(this.frameCallsText), this.container.appendChild(i()), this.container.appendChild(n("triangles", !1)), this.container.appendChild(this.trianglesText), this.container.appendChild(i()), this.container.appendChild(n("points", !1)), this.container.appendChild(this.pointsText), this.container.appendChild(i()), this.container.appendChild(n("lines", !1)), this.container.appendChild(this.linesText), this.container.appendChild(i()), this.container.appendChild(n("timestamp", !1)), this.container.appendChild(this.timestampText), this.container.appendChild(i());
565
+ this.drawCallsText = createTextEl("0");
566
+ this.frameCallsText = createTextEl("0");
567
+ this.trianglesText = createTextEl("0");
568
+ this.linesText = createTextEl("0");
569
+ this.pointsText = createTextEl("0");
570
+ this.timestampText = createTextEl("0");
571
+ this.container.appendChild(createTextEl("draw calls", false));
572
+ this.container.appendChild(this.drawCallsText);
573
+ this.container.appendChild(createBr());
574
+ this.container.appendChild(createTextEl("frame calls", false));
575
+ this.container.appendChild(this.frameCallsText);
576
+ this.container.appendChild(createBr());
577
+ this.container.appendChild(createTextEl("triangles", false));
578
+ this.container.appendChild(this.trianglesText);
579
+ this.container.appendChild(createBr());
580
+ this.container.appendChild(createTextEl("points", false));
581
+ this.container.appendChild(this.pointsText);
582
+ this.container.appendChild(createBr());
583
+ this.container.appendChild(createTextEl("lines", false));
584
+ this.container.appendChild(this.linesText);
585
+ this.container.appendChild(createBr());
586
+ this.container.appendChild(createTextEl("timestamp", false));
587
+ this.container.appendChild(this.timestampText);
588
+ this.container.appendChild(createBr());
414
589
  }
415
590
  update() {
416
591
  if (this._enabled) {
417
- const { render: e } = this.renderer.info;
418
- this.drawCallsText.innerText = e.drawCalls.toString(), this.frameCallsText.innerText = e.frameCalls.toString(), this.trianglesText.innerText = e.triangles.toString(), this.pointsText.innerText = e.points.toString(), this.linesText.innerText = e.lines.toString(), this.renderer.resolveTimestampsAsync(De.RENDER).then((t) => {
419
- this.timestampText.innerText = t?.toFixed(2) ?? "0";
592
+ const { render } = this.renderer.info;
593
+ this.drawCallsText.innerText = render.drawCalls.toString();
594
+ this.frameCallsText.innerText = render.frameCalls.toString();
595
+ this.trianglesText.innerText = render.triangles.toString();
596
+ this.pointsText.innerText = render.points.toString();
597
+ this.linesText.innerText = render.lines.toString();
598
+ this.renderer.resolveTimestampsAsync(TimestampQuery.RENDER).then((timestamps) => {
599
+ this.timestampText.innerText = timestamps?.toFixed(2) ?? "0";
420
600
  });
421
601
  }
422
602
  }
423
603
  enable() {
424
- this._enabled = !0, this.el.appendChild(this.container);
604
+ this._enabled = true;
605
+ this.el.appendChild(this.container);
425
606
  }
426
607
  disable() {
427
- this._enabled = !1, this.container.remove();
608
+ this._enabled = false;
609
+ this.container.remove();
428
610
  }
429
611
  dispose() {
430
612
  this.disable();
431
613
  }
432
614
  }
433
- je.enabled = !0;
434
- class ys extends ke {
615
+ Cache.enabled = true;
616
+ class Viewer extends EventDispatcher {
435
617
  el;
436
618
  renderer;
437
619
  scene;
@@ -446,55 +628,119 @@ class ys extends ke {
446
628
  viewerHelper;
447
629
  frameCount = 1;
448
630
  frameloop = "demand";
449
- constructor({ el: e, rendererOptions: t }) {
450
- super(), this.el = e, this.renderer = this._initRenderer(t), this.scene = this.createScene(), this.camera = this.createPerspectiveCamera(), this.info = new Bt(this.el, this.renderer), this.controls = new Pt(this.camera, this.renderer.domElement), this.renderPipeline = new Et(this.renderer, this.scene, this.camera), this.timer = new Ge(), this.roomEnvironment = new Lt(this.renderer), this.interactionManager = new Mt(this.renderer.domElement, this.scene, this.camera), this.objectManager = new xt(), this.viewerHelper = new It(this), window.addEventListener("resize", this.onWindowResize);
631
+ constructor({ el, rendererOptions }) {
632
+ super();
633
+ this.el = el;
634
+ this.renderer = this._initRenderer(rendererOptions);
635
+ this.scene = this.createScene();
636
+ this.camera = this.createPerspectiveCamera();
637
+ this.info = new Info(this.el, this.renderer);
638
+ this.controls = new CameraControls(this.camera, this.renderer.domElement);
639
+ this.renderPipeline = new RenderPipeline(this.renderer, this.scene, this.camera);
640
+ this.timer = new Timer();
641
+ this.roomEnvironment = new RoomEnvironment(this.renderer);
642
+ this.interactionManager = new InteractionManager(this.renderer.domElement, this.scene, this.camera);
643
+ this.objectManager = new ObjectManager();
644
+ this.viewerHelper = new ViewerHelper(this);
645
+ window.addEventListener("resize", this.onWindowResize);
451
646
  }
452
647
  onWindowResize = () => {
453
- const e = this.el.clientWidth, t = this.el.clientHeight;
454
- this.camera instanceof W ? (this.camera.aspect = e / t, this.camera.updateProjectionMatrix()) : this.camera instanceof F && (this.camera.left = -e / 2, this.camera.right = e / 2, this.camera.top = t / 2, this.camera.bottom = -t / 2, this.camera.updateProjectionMatrix()), this.renderer.setSize(e, t), this.render();
648
+ const width = this.el.clientWidth;
649
+ const height = this.el.clientHeight;
650
+ if (this.camera instanceof PerspectiveCamera) {
651
+ this.camera.aspect = width / height;
652
+ this.camera.updateProjectionMatrix();
653
+ } else if (this.camera instanceof OrthographicCamera) {
654
+ this.camera.left = -width / 2;
655
+ this.camera.right = width / 2;
656
+ this.camera.top = height / 2;
657
+ this.camera.bottom = -height / 2;
658
+ this.camera.updateProjectionMatrix();
659
+ }
660
+ this.renderer.setSize(width, height);
661
+ this.render();
455
662
  };
456
663
  async init() {
457
- await this.renderer.init(), this.roomEnvironment.update(), this.scene.environment = this.roomEnvironment.envMap;
458
- }
459
- setCamera(e) {
460
- this.camera = e, this.controls.camera = e, this.interactionManager.setCamera(e), this.renderPipeline.setCamera(e), this.onWindowResize(), this.dispatchEvent({ type: "cameraChange", camera: e });
461
- }
462
- setCameraByType(e) {
463
- e === "perspective" && !(this.camera instanceof W) ? this.setCamera(this.createPerspectiveCamera()) : e === "orthographic" && !(this.camera instanceof F) && this.setCamera(this.createOrthographicCamera());
664
+ await this.renderer.init();
665
+ this.roomEnvironment.update();
666
+ this.scene.environment = this.roomEnvironment.envMap;
667
+ }
668
+ setCamera(camera) {
669
+ this.camera = camera;
670
+ this.controls.camera = camera;
671
+ this.interactionManager.setCamera(camera);
672
+ this.renderPipeline.setCamera(camera);
673
+ this.onWindowResize();
674
+ this.dispatchEvent({ type: "cameraChange", camera });
675
+ }
676
+ setCameraByType(type) {
677
+ if (type === "perspective" && !(this.camera instanceof PerspectiveCamera)) {
678
+ this.setCamera(this.createPerspectiveCamera());
679
+ } else if (type === "orthographic" && !(this.camera instanceof OrthographicCamera)) {
680
+ this.setCamera(this.createOrthographicCamera());
681
+ }
464
682
  }
465
- render(e = 1) {
466
- return this.frameCount += e, new Promise((t) => {
467
- const s = () => {
468
- this.removeEventListener("afterRender", s), t();
683
+ render(frame = 1) {
684
+ this.frameCount += frame;
685
+ return new Promise((resolve) => {
686
+ const fn = () => {
687
+ this.removeEventListener("afterRender", fn);
688
+ resolve();
469
689
  };
470
- this.addEventListener("afterRender", s);
690
+ this.addEventListener("afterRender", fn);
471
691
  });
472
692
  }
473
- animate = (e) => {
474
- this.timer.update(e), this.dispatchEvent({ type: "beforeControlsUpdate", time: e });
475
- let t = this.controls.update(this.timer.getDelta());
476
- this.dispatchEvent({ type: "afterControlsUpdate", time: e }), this.frameCount > 0 && (this.frameCount--, t = !0), this.frameloop === "always" && (t = !0), t && (this.dispatchEvent({ type: "beforeRender", time: e }), this.renderer.info.reset(), this.renderPipeline.render(), this.info.update(), this.dispatchEvent({ type: "afterRender", time: e }));
693
+ animate = (time2) => {
694
+ this.timer.update(time2);
695
+ this.dispatchEvent({ type: "beforeControlsUpdate", time: time2 });
696
+ let needsRender = this.controls.update(this.timer.getDelta());
697
+ this.dispatchEvent({ type: "afterControlsUpdate", time: time2 });
698
+ if (this.frameCount > 0) {
699
+ this.frameCount--;
700
+ needsRender = true;
701
+ }
702
+ if (this.frameloop === "always") {
703
+ needsRender = true;
704
+ }
705
+ if (needsRender) {
706
+ this.dispatchEvent({ type: "beforeRender", time: time2 });
707
+ this.renderer.info.reset();
708
+ this.renderPipeline.render();
709
+ this.info.update();
710
+ this.dispatchEvent({ type: "afterRender", time: time2 });
711
+ }
477
712
  };
478
- _initRenderer(e) {
479
- const t = new Fe({
480
- logarithmicDepthBuffer: !0,
481
- antialias: !1,
482
- depth: !1,
483
- trackTimestamp: !0,
484
- ...e
713
+ _initRenderer(rendererOptions) {
714
+ const renderer = new WebGPURenderer({
715
+ logarithmicDepthBuffer: true,
716
+ antialias: false,
717
+ depth: false,
718
+ trackTimestamp: true,
719
+ ...rendererOptions
485
720
  });
486
- return t.setSize(this.el.clientWidth, this.el.clientHeight), t.shadowMap.enabled = !0, t.shadowMap.type = He, t.toneMapping = ze, t.toneMappingExposure = 1, t.info.autoReset = !1, t.setPixelRatio(window.devicePixelRatio), t.setAnimationLoop(this.animate), this.el.appendChild(t.domElement), t;
721
+ renderer.setSize(this.el.clientWidth, this.el.clientHeight);
722
+ renderer.shadowMap.enabled = true;
723
+ renderer.shadowMap.type = PCFShadowMap;
724
+ renderer.toneMapping = AgXToneMapping;
725
+ renderer.toneMappingExposure = 1;
726
+ renderer.info.autoReset = false;
727
+ renderer.setPixelRatio(window.devicePixelRatio);
728
+ renderer.setAnimationLoop(this.animate);
729
+ this.el.appendChild(renderer.domElement);
730
+ return renderer;
487
731
  }
488
732
  createScene() {
489
- const e = new $e();
490
- return e.background = new J(0), e;
733
+ const scene = new Scene();
734
+ scene.background = new Color(0);
735
+ return scene;
491
736
  }
492
737
  createPerspectiveCamera() {
493
- const e = new W(50, this.el.clientWidth / this.el.clientHeight, 0.1, 1e5);
494
- return e.position.setScalar(5), e;
738
+ const camera = new PerspectiveCamera(50, this.el.clientWidth / this.el.clientHeight, 0.1, 1e5);
739
+ camera.position.setScalar(5);
740
+ return camera;
495
741
  }
496
742
  createOrthographicCamera() {
497
- const e = new F(
743
+ const camera = new OrthographicCamera(
498
744
  -this.el.clientWidth / 2,
499
745
  this.el.clientWidth / 2,
500
746
  this.el.clientHeight / 2,
@@ -502,415 +748,621 @@ class ys extends ke {
502
748
  0.1,
503
749
  1e5
504
750
  );
505
- return e.position.setScalar(5), e;
751
+ camera.position.setScalar(5);
752
+ return camera;
506
753
  }
507
754
  dispose() {
508
- this.el.removeChild(this.renderer.domElement), window.removeEventListener("resize", this.onWindowResize), this.info.dispose(), this.interactionManager.dispose(), this.roomEnvironment.dispose(), this.renderPipeline.dispose(), this.renderer.dispose();
755
+ this.el.removeChild(this.renderer.domElement);
756
+ window.removeEventListener("resize", this.onWindowResize);
757
+ this.info.dispose();
758
+ this.interactionManager.dispose();
759
+ this.roomEnvironment.dispose();
760
+ this.renderPipeline.dispose();
761
+ this.renderer.dispose();
509
762
  }
510
763
  }
511
- class Rt extends Me {
512
- constructor(e) {
513
- super(e);
514
- }
515
- parse(e, t, s, n) {
516
- if (_t(e.slice(0, 8)) === "SBMG----") {
517
- const a = At(e.slice(8));
518
- return super.parse(a, t, s, n);
519
- } else
520
- return super.parse(e, t, s, n);
764
+ class SBMXLoader extends GLTFLoader {
765
+ constructor(manager) {
766
+ super(manager);
767
+ }
768
+ parse(data, path, onLoad, onError) {
769
+ const formatName = getAsciiString(data.slice(0, 8));
770
+ switch (formatName) {
771
+ case "SBMG----": {
772
+ const swappedBuffer = swapBytes(data.slice(8));
773
+ return super.parse(swappedBuffer, path, onLoad, onError);
774
+ }
775
+ default: {
776
+ return super.parse(data, path, onLoad, onError);
777
+ }
778
+ }
521
779
  }
522
780
  }
523
- function _t(o) {
524
- return new TextDecoder().decode(new Uint8Array(o));
781
+ function getAsciiString(buf) {
782
+ const decoder = new TextDecoder();
783
+ return decoder.decode(new Uint8Array(buf));
525
784
  }
526
- function At(o) {
527
- const e = new DataView(o);
528
- for (let t = 0; t < e.byteLength; t++) {
529
- const s = e.getUint8(t), n = (s >> 4 & 15) + (s << 4 & 240);
530
- e.setUint8(t, n);
531
- }
532
- return e.buffer;
785
+ function swapBytes(buffer) {
786
+ const view = new DataView(buffer);
787
+ for (let i = 0; i < view.byteLength; i++) {
788
+ const byte = view.getUint8(i);
789
+ const swappedByte = (byte >> 4 & 15) + (byte << 4 & 240);
790
+ view.setUint8(i, swappedByte);
791
+ }
792
+ return view.buffer;
533
793
  }
534
- const Nt = 8, Ut = 130, de = 66, Dt = "SBK-----", jt = "SBM-----", xe = new TextDecoder(), kt = new TextEncoder();
535
- function Gt(o) {
536
- let e = Nt;
537
- const t = new Uint8Array(o, 0, e);
538
- if (xe.decode(t) !== Dt)
539
- return o;
540
- e += Ut;
541
- const n = new Uint8Array(o, 0, e);
542
- if (n[40] === 1) {
543
- const a = kt.encode(jt), c = new Uint8Array([n[41]]), r = Ft(n), h = Ht(r);
544
- let l = de % h.length;
545
- const u = e + de, f = new Uint8Array(o, u), p = new Uint8Array(f.length);
546
- for (let w = 0; w < f.length; w++)
547
- p[w] = f[w] ^ h[l], l = (l + 1) % h.length;
548
- const g = new Uint8Array(a.length + c.length + p.length);
549
- return g.set(a), g.set(c, a.length), g.set(p, a.length + c.length), g.buffer;
794
+ const BYTE_LENGTH_MAGIC = 8;
795
+ const BYTE_LENGTH_HEAD = 130;
796
+ const BYTE_LENGTH_ATTACH = 66;
797
+ const MAGIC_SBK = "SBK-----";
798
+ const MAGIC_SBM = "SBM-----";
799
+ const textDecoder = new TextDecoder();
800
+ const textEncoder = new TextEncoder();
801
+ function decodeSbk(buffer) {
802
+ let read = BYTE_LENGTH_MAGIC;
803
+ const magicBytes = new Uint8Array(buffer, 0, read);
804
+ const magic = textDecoder.decode(magicBytes);
805
+ if (magic !== MAGIC_SBK) {
806
+ return buffer;
807
+ }
808
+ read += BYTE_LENGTH_HEAD;
809
+ const headBytes = new Uint8Array(buffer, 0, read);
810
+ const version = headBytes[40];
811
+ if (version === 1) {
812
+ const magicBuf = textEncoder.encode(MAGIC_SBM);
813
+ const versionBuf = new Uint8Array([headBytes[41]]);
814
+ const sbmKey = getSbmKey(headBytes);
815
+ const encodeKey = getLeftKey(sbmKey);
816
+ let j = BYTE_LENGTH_ATTACH % encodeKey.length;
817
+ const offset = read + BYTE_LENGTH_ATTACH;
818
+ const bodyBytes = new Uint8Array(buffer, offset);
819
+ const bodyBuf = new Uint8Array(bodyBytes.length);
820
+ for (let i = 0; i < bodyBytes.length; i++) {
821
+ bodyBuf[i] = bodyBytes[i] ^ encodeKey[j];
822
+ j = (j + 1) % encodeKey.length;
823
+ }
824
+ const buf = new Uint8Array(magicBuf.length + versionBuf.length + bodyBuf.length);
825
+ buf.set(magicBuf);
826
+ buf.set(versionBuf, magicBuf.length);
827
+ buf.set(bodyBuf, magicBuf.length + versionBuf.length);
828
+ return buf.buffer;
550
829
  }
551
830
  }
552
- function Ft(o) {
553
- const e = new Uint8Array(128);
554
- return e.set(o.slice(42, 74), 0), e.set(o.slice(74, 138), 32), e.set(o.slice(8, 40), 96), e;
831
+ function getSbmKey(headBuffer) {
832
+ const bytes = new Uint8Array(128);
833
+ bytes.set(headBuffer.slice(42, 42 + 32), 0);
834
+ bytes.set(headBuffer.slice(74, 74 + 64), 32);
835
+ bytes.set(headBuffer.slice(8, 8 + 32), 96);
836
+ return bytes;
555
837
  }
556
- function Ht(o) {
557
- const e = new Uint8Array(64);
558
- return e.set(o.slice(0, 8), 0), e.set(o.slice(24, 32), 8), e.set(o.slice(40, 56), 16), e.set(o.slice(64, 88), 32), e.set(o.slice(96, 104), 56), e;
838
+ function getLeftKey(sbmKey) {
839
+ const bytes = new Uint8Array(64);
840
+ bytes.set(sbmKey.slice(0, 8), 0);
841
+ bytes.set(sbmKey.slice(24, 24 + 8), 8);
842
+ bytes.set(sbmKey.slice(40, 40 + 16), 16);
843
+ bytes.set(sbmKey.slice(64, 64 + 24), 32);
844
+ bytes.set(sbmKey.slice(96, 96 + 8), 56);
845
+ return bytes;
559
846
  }
560
- const zt = (o, e, t) => {
561
- const s = o.buffer.slice(t, t + e);
562
- let n = xe.decode(s);
563
- return n = n.replace("\\", "/"), n.startsWith("Maps/") || (n = `Maps/${n}`), n;
564
- }, $t = (o, e, t) => {
565
- const [s, n, i, a, c] = e, r = t || a < 1;
566
- return new I({
567
- name: o,
568
- color: new J(s, n, i),
569
- opacity: a,
570
- transparent: r,
847
+ const getTextureName = (dataView, texnamelen, offset) => {
848
+ const temp = dataView.buffer.slice(offset, offset + texnamelen);
849
+ let textureName = textDecoder.decode(temp);
850
+ textureName = textureName.replace("\\", "/");
851
+ if (!textureName.startsWith("Maps/")) {
852
+ textureName = `Maps/${textureName}`;
853
+ }
854
+ return textureName;
855
+ };
856
+ const generateSbmMaterial = (materialId, arr, png) => {
857
+ const [d0, d1, d2, d3, side] = arr;
858
+ const trans = png || d3 < 1;
859
+ const material = new MeshStandardNodeMaterial({
860
+ name: materialId,
861
+ color: new Color(d0, d1, d2),
862
+ opacity: d3,
863
+ transparent: trans,
571
864
  alphaTest: 0.01,
572
- side: c
865
+ side
573
866
  });
574
- }, Wt = (o) => o?.toLowerCase().endsWith(".png") ?? !1;
575
- class Qt {
867
+ return material;
868
+ };
869
+ const isPNG = (textureUrl) => {
870
+ return textureUrl?.toLowerCase().endsWith(".png") ?? false;
871
+ };
872
+ class SBMParser {
576
873
  data;
577
874
  options;
578
875
  textureLoader;
579
- littleEndian = !0;
876
+ littleEndian = true;
580
877
  materials = /* @__PURE__ */ new Map();
581
- constructor(e, t) {
582
- this.data = e, this.options = t, this.textureLoader = new ye(t.manager), this.textureLoader.setCrossOrigin(t.crossOrigin), this.textureLoader.setRequestHeader(t.requestHeader);
583
- }
584
- parse(e, t) {
585
- let s = this.data;
586
- const n = Gt(this.data);
587
- n && (s = n);
588
- const i = new DataView(s);
589
- let a = 8;
590
- const c = i.getUint8(a);
591
- a += 1, c === 1 ? this._parseV2(i, a, e) : c === 2 ? this._parseV2(i, a, e) : c === 3 ? this._parseV3(i, a, e) : t?.(new Error(`SBMLoader: Unsupported SBM version: ${c}`));
592
- }
593
- _parseV2(e, t, s) {
594
- const n = new z(), i = e.getUint16(t, this.littleEndian);
595
- t += 2;
596
- const a = e.getUint16(t, this.littleEndian);
597
- t += 2;
598
- for (let c = 0; c < i; ++c) {
599
- const r = e.getUint16(t, this.littleEndian).toString();
600
- t += 2, t += 4, t += 4, t += 4, t += 4;
601
- const h = e.getFloat32(t, this.littleEndian);
602
- t += 4;
603
- const l = e.getFloat32(t, this.littleEndian);
604
- t += 4;
605
- const u = e.getFloat32(t, this.littleEndian);
606
- t += 4;
607
- const f = e.getFloat32(t, this.littleEndian);
608
- t += 4, t += 4, t += 4, t += 4, t += 4;
609
- let p = e.getUint8(t);
610
- t += 1, p === 0 ? p = Ke : p === 1 ? p = Xe : p === 2 && (p = qe);
611
- const g = e.getUint16(t, this.littleEndian);
612
- t += 2;
613
- const w = g > 0 ? zt(e, g, t) : "";
614
- if (t += g, !this.materials.has(r)) {
615
- const v = $t(r, [h, l, u, f, p], Wt(w));
616
- this.materials.set(r, v), w && this.options.path && this.textureLoader.load(L.resolveURL(w, this.options.path), (b) => {
617
- b.colorSpace = ve, b.wrapS = se, b.wrapT = se, b.flipY = !1, b.anisotropy = 16, v.map = b;
618
- });
878
+ constructor(data, options) {
879
+ this.data = data;
880
+ this.options = options;
881
+ this.textureLoader = new TextureLoader(options.manager);
882
+ this.textureLoader.setCrossOrigin(options.crossOrigin);
883
+ this.textureLoader.setRequestHeader(options.requestHeader);
884
+ }
885
+ parse(onLoad, onError) {
886
+ let buffer = this.data;
887
+ const decodeBuffer = decodeSbk(this.data);
888
+ if (decodeBuffer) {
889
+ buffer = decodeBuffer;
890
+ }
891
+ const dataView = new DataView(buffer);
892
+ let offset = 8;
893
+ const version = dataView.getUint8(offset);
894
+ offset += 1;
895
+ if (version === 1) {
896
+ this._parseV2(dataView, offset, onLoad);
897
+ } else if (version === 2) {
898
+ this._parseV2(dataView, offset, onLoad);
899
+ } else if (version === 3) {
900
+ this._parseV3(dataView, offset, onLoad);
901
+ } else {
902
+ onError?.(new Error(`SBMLoader: Unsupported SBM version: ${version}`));
903
+ }
904
+ }
905
+ _parseV2(dataView, offset, onLoad) {
906
+ const sbm = new Group();
907
+ const materialCount = dataView.getUint16(offset, this.littleEndian);
908
+ offset += 2;
909
+ const meshCount = dataView.getUint16(offset, this.littleEndian);
910
+ offset += 2;
911
+ for (let i = 0; i < materialCount; ++i) {
912
+ const materialId = dataView.getUint16(offset, this.littleEndian).toString();
913
+ offset += 2;
914
+ offset += 4;
915
+ offset += 4;
916
+ offset += 4;
917
+ offset += 4;
918
+ const d0 = dataView.getFloat32(offset, this.littleEndian);
919
+ offset += 4;
920
+ const d1 = dataView.getFloat32(offset, this.littleEndian);
921
+ offset += 4;
922
+ const d2 = dataView.getFloat32(offset, this.littleEndian);
923
+ offset += 4;
924
+ const d3 = dataView.getFloat32(offset, this.littleEndian);
925
+ offset += 4;
926
+ offset += 4;
927
+ offset += 4;
928
+ offset += 4;
929
+ offset += 4;
930
+ let side = dataView.getUint8(offset);
931
+ offset += 1;
932
+ if (side === 0) side = FrontSide;
933
+ else if (side === 1) side = BackSide;
934
+ else if (side === 2) side = DoubleSide;
935
+ const textureNameLength = dataView.getUint16(offset, this.littleEndian);
936
+ offset += 2;
937
+ const textureName = textureNameLength > 0 ? getTextureName(dataView, textureNameLength, offset) : "";
938
+ offset += textureNameLength;
939
+ if (!this.materials.has(materialId)) {
940
+ const materialInfo = [d0, d1, d2, d3, side];
941
+ const material = generateSbmMaterial(materialId, materialInfo, isPNG(textureName));
942
+ this.materials.set(materialId, material);
943
+ if (textureName && this.options.path) {
944
+ this.textureLoader.load(LoaderUtils.resolveURL(textureName, this.options.path), (texture) => {
945
+ texture.colorSpace = SRGBColorSpace;
946
+ texture.wrapS = RepeatWrapping;
947
+ texture.wrapT = RepeatWrapping;
948
+ texture.flipY = false;
949
+ texture.anisotropy = 16;
950
+ material.map = texture;
951
+ });
952
+ }
619
953
  }
620
954
  }
621
- for (let c = 0; c < a; ++c) {
622
- const r = e.getUint16(t, this.littleEndian).toString();
623
- t += 2;
624
- const h = e.getUint16(t, this.littleEndian).toString();
625
- t += 2;
626
- const l = [], u = [], f = [], p = [], g = e.getUint16(t, this.littleEndian);
627
- if (t += 2, g > 0)
628
- for (let m = 0; m < g; m++) {
629
- const y = new we();
630
- y.setX(e.getFloat32(t, this.littleEndian)), t += 4, y.setY(e.getFloat32(t, this.littleEndian)), t += 4, y.setZ(e.getFloat32(t, this.littleEndian)), t += 4, l.push(y);
955
+ for (let i = 0; i < meshCount; ++i) {
956
+ const meshId = dataView.getUint16(offset, this.littleEndian).toString();
957
+ offset += 2;
958
+ const materialId = dataView.getUint16(offset, this.littleEndian).toString();
959
+ offset += 2;
960
+ const vertices = [];
961
+ const texcoords = [];
962
+ const faces = [];
963
+ const faceVertexUvs = [];
964
+ const verticesCount = dataView.getUint16(offset, this.littleEndian);
965
+ offset += 2;
966
+ if (verticesCount > 0) {
967
+ for (let j = 0; j < verticesCount; j++) {
968
+ const vector3 = new Vector3();
969
+ vector3.setX(dataView.getFloat32(offset, this.littleEndian));
970
+ offset += 4;
971
+ vector3.setY(dataView.getFloat32(offset, this.littleEndian));
972
+ offset += 4;
973
+ vector3.setZ(dataView.getFloat32(offset, this.littleEndian));
974
+ offset += 4;
975
+ vertices.push(vector3);
631
976
  }
632
- const w = e.getUint16(t, this.littleEndian);
633
- if (t += 2, w > 0)
634
- for (let m = 0; m < w; m++)
635
- t += 4, t += 4, t += 4;
636
- const T = e.getUint16(t, this.littleEndian);
637
- if (t += 2, T > 0)
638
- for (let m = 0; m < T; m++) {
639
- const y = new P();
640
- y.setX(e.getFloat32(t, this.littleEndian)), t += 4, y.setY(e.getFloat32(t, this.littleEndian)), t += 4, u.push(y);
977
+ }
978
+ const normalsCount = dataView.getUint16(offset, this.littleEndian);
979
+ offset += 2;
980
+ if (normalsCount > 0) {
981
+ for (let j = 0; j < normalsCount; j++) {
982
+ offset += 4;
983
+ offset += 4;
984
+ offset += 4;
641
985
  }
642
- const v = e.getUint16(t, this.littleEndian);
643
- if (t += 2, v > 0)
644
- for (let m = 0; m < v; m++) {
645
- const y = e.getUint16(t, this.littleEndian);
646
- t += 2;
647
- const B = e.getUint16(t, this.littleEndian);
648
- t += 2;
649
- const _ = e.getUint16(t, this.littleEndian);
650
- t += 2;
651
- const O = [y, B, _];
652
- f.push(O), u.length > 0 && p.push([u[O[0]], u[O[1]], u[O[2]]]);
986
+ }
987
+ const texcoordCount = dataView.getUint16(offset, this.littleEndian);
988
+ offset += 2;
989
+ if (texcoordCount > 0) {
990
+ for (let j = 0; j < texcoordCount; j++) {
991
+ const texcoord = new Vector2();
992
+ texcoord.setX(dataView.getFloat32(offset, this.littleEndian));
993
+ offset += 4;
994
+ texcoord.setY(dataView.getFloat32(offset, this.littleEndian));
995
+ offset += 4;
996
+ texcoords.push(texcoord);
997
+ }
998
+ }
999
+ const idxCount = dataView.getUint16(offset, this.littleEndian);
1000
+ offset += 2;
1001
+ if (idxCount > 0) {
1002
+ for (let j = 0; j < idxCount; j++) {
1003
+ const a = dataView.getUint16(offset, this.littleEndian);
1004
+ offset += 2;
1005
+ const b = dataView.getUint16(offset, this.littleEndian);
1006
+ offset += 2;
1007
+ const c = dataView.getUint16(offset, this.littleEndian);
1008
+ offset += 2;
1009
+ const face = [a, b, c];
1010
+ faces.push(face);
1011
+ if (texcoords.length > 0) {
1012
+ faceVertexUvs.push([texcoords[face[0]], texcoords[face[1]], texcoords[face[2]]]);
1013
+ }
1014
+ }
1015
+ }
1016
+ const positions = [], uvs = [];
1017
+ for (let i2 = 0; i2 < faces.length; i2++) {
1018
+ const face = faces[i2];
1019
+ const vertex = vertices[face[0]], vertex2 = vertices[face[1]], vertex3 = vertices[face[2]];
1020
+ positions.push(...vertex.toArray(), ...vertex2.toArray(), ...vertex3.toArray());
1021
+ let uv2 = new Vector2(), uv22 = new Vector2(), uv3 = new Vector2();
1022
+ const vertexUvs = faceVertexUvs[i2];
1023
+ if (vertexUvs !== void 0) {
1024
+ uv2 = vertexUvs[0];
1025
+ uv22 = vertexUvs[1];
1026
+ uv3 = vertexUvs[2];
653
1027
  }
654
- const b = [], M = [];
655
- for (let m = 0; m < f.length; m++) {
656
- const y = f[m], B = l[y[0]], _ = l[y[1]], O = l[y[2]];
657
- b.push(...B.toArray(), ..._.toArray(), ...O.toArray());
658
- let V = new P(), ee = new P(), te = new P();
659
- const k = p[m];
660
- k !== void 0 && (V = k[0], ee = k[1], te = k[2]), M.push(...V.toArray(), ...ee.toArray(), ...te.toArray());
1028
+ uvs.push(...uv2.toArray(), ...uv22.toArray(), ...uv3.toArray());
661
1029
  }
662
- const x = new Float32Array(b), E = new Float32Array(M), S = new Qe();
663
- if (x.length > 0 && S.setAttribute("position", new ne(x, 3)), E.length > 0 && S.setAttribute("uv", new ne(E, 2)), S.computeVertexNormals(), this.materials.has(h)) {
664
- const m = new j(S, this.materials.get(h));
665
- m.name = r, m.castShadow = !0, m.receiveShadow = !0, n.add(m);
1030
+ const positionArray = new Float32Array(positions), uvArray = new Float32Array(uvs);
1031
+ const bufferGeometry = new BufferGeometry();
1032
+ if (positionArray.length > 0) {
1033
+ bufferGeometry.setAttribute("position", new BufferAttribute(positionArray, 3));
1034
+ }
1035
+ if (uvArray.length > 0) {
1036
+ bufferGeometry.setAttribute("uv", new BufferAttribute(uvArray, 2));
1037
+ }
1038
+ bufferGeometry.computeVertexNormals();
1039
+ if (this.materials.has(materialId)) {
1040
+ const sbmChild = new Mesh(bufferGeometry, this.materials.get(materialId));
1041
+ sbmChild.name = meshId;
1042
+ sbmChild.castShadow = true;
1043
+ sbmChild.receiveShadow = true;
1044
+ sbm.add(sbmChild);
666
1045
  }
667
1046
  }
668
- s(n);
1047
+ onLoad(sbm);
669
1048
  }
670
- _parseV3(e, t, s) {
671
- const n = new z();
672
- console.warn("SBMLoader: SBM version 3 is not supported yet."), s(n);
1049
+ _parseV3(_dataView, _offset, onLoad) {
1050
+ const sbm = new Group();
1051
+ console.warn("SBMLoader: SBM version 3 is not supported yet.");
1052
+ onLoad(sbm);
673
1053
  }
674
1054
  }
675
- class Kt extends We {
676
- load(e, t, s, n) {
677
- let i;
678
- if (this.resourcePath !== "")
679
- i = this.resourcePath;
680
- else if (this.path !== "") {
681
- const r = L.extractUrlBase(e);
682
- i = L.resolveURL(r, this.path);
683
- } else
684
- i = L.extractUrlBase(e);
685
- this.manager.itemStart(e);
686
- const a = (r) => {
687
- n ? n(r) : console.error(r), this.manager.itemError(e), this.manager.itemEnd(e);
688
- }, c = new fe(this.manager);
689
- c.setPath(this.path), c.setResponseType("arraybuffer"), c.setRequestHeader(this.requestHeader), c.setWithCredentials(this.withCredentials), c.load(
690
- e,
691
- (r) => {
1055
+ class SBMLoader extends Loader {
1056
+ load(url, onLoad, onProgress, onError) {
1057
+ let resourcePath;
1058
+ if (this.resourcePath !== "") {
1059
+ resourcePath = this.resourcePath;
1060
+ } else if (this.path !== "") {
1061
+ const relativeUrl = LoaderUtils.extractUrlBase(url);
1062
+ resourcePath = LoaderUtils.resolveURL(relativeUrl, this.path);
1063
+ } else {
1064
+ resourcePath = LoaderUtils.extractUrlBase(url);
1065
+ }
1066
+ this.manager.itemStart(url);
1067
+ const _onError = (e) => {
1068
+ if (onError) {
1069
+ onError(e);
1070
+ } else {
1071
+ console.error(e);
1072
+ }
1073
+ this.manager.itemError(url);
1074
+ this.manager.itemEnd(url);
1075
+ };
1076
+ const loader = new FileLoader(this.manager);
1077
+ loader.setPath(this.path);
1078
+ loader.setResponseType("arraybuffer");
1079
+ loader.setRequestHeader(this.requestHeader);
1080
+ loader.setWithCredentials(this.withCredentials);
1081
+ loader.load(
1082
+ url,
1083
+ (data) => {
692
1084
  try {
693
1085
  this.parse(
694
- r,
695
- i,
696
- (h) => {
697
- t(h), this.manager.itemEnd(e);
1086
+ data,
1087
+ resourcePath,
1088
+ (sbm) => {
1089
+ onLoad(sbm);
1090
+ this.manager.itemEnd(url);
698
1091
  },
699
- a
1092
+ _onError
700
1093
  );
701
- } catch (h) {
702
- a(h);
1094
+ } catch (e) {
1095
+ _onError(e);
703
1096
  }
704
1097
  },
705
- s,
706
- a
1098
+ onProgress,
1099
+ _onError
707
1100
  );
708
1101
  }
709
- parse(e, t, s, n) {
710
- const i = new TextDecoder().decode(e.slice(0, 8));
711
- if (i !== "SBK-----" && i !== "SBM-----") {
712
- n?.(new Error(`SBMLoader: Invalid SBM format: ${i}`));
1102
+ parse(data, path, onLoad, onError) {
1103
+ const formatName = new TextDecoder().decode(data.slice(0, 8));
1104
+ if (formatName !== "SBK-----" && formatName !== "SBM-----") {
1105
+ onError?.(new Error(`SBMLoader: Invalid SBM format: ${formatName}`));
713
1106
  return;
714
1107
  }
715
- new Qt(e, {
716
- path: t,
1108
+ const parser = new SBMParser(data, {
1109
+ path,
717
1110
  crossOrigin: this.crossOrigin,
718
1111
  requestHeader: this.requestHeader,
719
1112
  manager: this.manager
720
- }).parse(s, n);
1113
+ });
1114
+ parser.parse(onLoad, onError);
721
1115
  }
722
- parseAsync(e, t) {
723
- return new Promise((s, n) => {
1116
+ parseAsync(data, path) {
1117
+ return new Promise((resolve, reject) => {
724
1118
  this.parse(
725
- e,
726
- t,
727
- (i) => {
728
- s(i);
1119
+ data,
1120
+ path,
1121
+ (sbm) => {
1122
+ resolve(sbm);
729
1123
  },
730
- (i) => {
731
- n(i);
1124
+ (err) => {
1125
+ reject(err);
732
1126
  }
733
1127
  );
734
1128
  });
735
1129
  }
736
1130
  }
737
- class R {
1131
+ class ModelLoaderManager {
738
1132
  static CACHE_NAME = "u-space-model-loader-cache";
739
- static fileLoader = new fe().setResponseType("arraybuffer");
740
- static dracoLoader = new ft().setDecoderPath(
741
- `https://cdn.jsdelivr.net/npm/three@0.${ie}.0/examples/jsm/libs/draco/`
1133
+ static fileLoader = new FileLoader().setResponseType("arraybuffer");
1134
+ static dracoLoader = new DRACOLoader().setDecoderPath(
1135
+ `https://cdn.jsdelivr.net/npm/three@0.${REVISION}.0/examples/jsm/libs/draco/`
742
1136
  );
743
- static ktx2Loader = new yt().setTranscoderPath(
744
- `https://cdn.jsdelivr.net/npm/three@0.${ie}.0/examples/jsm/libs/basis/`
1137
+ static ktx2Loader = new KTX2Loader().setTranscoderPath(
1138
+ `https://cdn.jsdelivr.net/npm/three@0.${REVISION}.0/examples/jsm/libs/basis/`
745
1139
  );
746
- static gltfLoader = new Me().setDRACOLoader(R.dracoLoader).setKTX2Loader(R.ktx2Loader).setMeshoptDecoder(he);
747
- static sbmxLoader = new Rt().setDRACOLoader(R.dracoLoader).setKTX2Loader(R.ktx2Loader).setMeshoptDecoder(he);
748
- static sbmLoader = new Kt();
749
- static fbxLoader = new mt();
750
- static objLoader = new gt();
751
- static stlLoader = new wt();
752
- static setLoadingManager(e) {
753
- this.fileLoader.manager = e, this.dracoLoader.manager = e, this.ktx2Loader.manager = e, this.gltfLoader.manager = e, this.sbmxLoader.manager = e, this.sbmLoader.manager = e, this.fbxLoader.manager = e, this.objLoader.manager = e, this.stlLoader.manager = e;
1140
+ static gltfLoader = new GLTFLoader().setDRACOLoader(ModelLoaderManager.dracoLoader).setKTX2Loader(ModelLoaderManager.ktx2Loader).setMeshoptDecoder(MeshoptDecoder);
1141
+ static sbmxLoader = new SBMXLoader().setDRACOLoader(ModelLoaderManager.dracoLoader).setKTX2Loader(ModelLoaderManager.ktx2Loader).setMeshoptDecoder(MeshoptDecoder);
1142
+ static sbmLoader = new SBMLoader();
1143
+ static fbxLoader = new FBXLoader();
1144
+ static objLoader = new OBJLoader();
1145
+ static stlLoader = new STLLoader();
1146
+ static setLoadingManager(loadingManager) {
1147
+ this.fileLoader.manager = loadingManager;
1148
+ this.dracoLoader.manager = loadingManager;
1149
+ this.ktx2Loader.manager = loadingManager;
1150
+ this.gltfLoader.manager = loadingManager;
1151
+ this.sbmxLoader.manager = loadingManager;
1152
+ this.sbmLoader.manager = loadingManager;
1153
+ this.fbxLoader.manager = loadingManager;
1154
+ this.objLoader.manager = loadingManager;
1155
+ this.stlLoader.manager = loadingManager;
754
1156
  }
755
1157
  /**
756
1158
  * Set the renderer to enable KTX2 support and other renderer-dependent features.
757
1159
  */
758
- static async setRenderer(e) {
759
- await e.init(), this.ktx2Loader.detectSupport(e);
1160
+ static async setRenderer(renderer) {
1161
+ await renderer.init();
1162
+ this.ktx2Loader.detectSupport(renderer);
760
1163
  }
761
1164
  /**
762
1165
  * Configure Draco decoder path.
763
1166
  */
764
- static setDracoPath(e) {
765
- this.dracoLoader.setDecoderPath(e);
1167
+ static setDracoPath(path) {
1168
+ this.dracoLoader.setDecoderPath(path);
766
1169
  }
767
1170
  /**
768
1171
  * Configure KTX2 transcoder path.
769
1172
  */
770
- static setKTX2Path(e) {
771
- this.ktx2Loader.setTranscoderPath(e);
772
- }
773
- static async loadAsync(e, t = { persistent: !0 }) {
774
- const s = e.split(".").pop()?.split("?")[0].toLowerCase();
775
- let n;
776
- switch (t.persistent && typeof caches < "u" ? n = await this.getPersistentData(e) : n = await this.fileLoader.loadAsync(e), s) {
1173
+ static setKTX2Path(path) {
1174
+ this.ktx2Loader.setTranscoderPath(path);
1175
+ }
1176
+ static async loadAsync(url, parameters = { persistent: true }) {
1177
+ const extension = url.split(".").pop()?.split("?")[0].toLowerCase();
1178
+ let buffer;
1179
+ if (parameters.persistent && typeof caches !== "undefined") {
1180
+ buffer = await this.getPersistentData(url);
1181
+ } else {
1182
+ buffer = await this.fileLoader.loadAsync(url);
1183
+ }
1184
+ switch (extension) {
777
1185
  case "gltf":
778
1186
  case "glb":
779
- return (await this.gltfLoader.parseAsync(n, L.extractUrlBase(e))).scene;
1187
+ const gltf = await this.gltfLoader.parseAsync(buffer, LoaderUtils.extractUrlBase(url));
1188
+ return gltf.scene;
780
1189
  case "sbmx":
781
- return (await this.sbmxLoader.parseAsync(n, L.extractUrlBase(e))).scene;
1190
+ const sbmx = await this.sbmxLoader.parseAsync(buffer, LoaderUtils.extractUrlBase(url));
1191
+ return sbmx.scene;
782
1192
  case "sbm":
783
- return await this.sbmLoader.parseAsync(n, L.extractUrlBase(e));
1193
+ const sbm = await this.sbmLoader.parseAsync(buffer, LoaderUtils.extractUrlBase(url));
1194
+ return sbm;
784
1195
  case "fbx":
785
- return this.fbxLoader.parse(n, L.extractUrlBase(e));
1196
+ const fbx = this.fbxLoader.parse(buffer, LoaderUtils.extractUrlBase(url));
1197
+ return fbx;
786
1198
  case "obj":
787
- const h = new TextDecoder().decode(n);
788
- return this.objLoader.parse(h);
1199
+ const text = new TextDecoder().decode(buffer);
1200
+ const obj = this.objLoader.parse(text);
1201
+ return obj;
789
1202
  case "stl":
790
- const u = this.stlLoader.parse(n);
791
- return new j(u, new I());
1203
+ const geometry = this.stlLoader.parse(buffer);
1204
+ const mesh = new Mesh(geometry, new MeshStandardNodeMaterial());
1205
+ return mesh;
792
1206
  default:
793
- throw new Error(`Unsupported model format: ${s}`);
1207
+ throw new Error(`Unsupported model format: ${extension}`);
794
1208
  }
795
1209
  }
796
- static async getPersistentData(e) {
1210
+ static async getPersistentData(url) {
797
1211
  try {
798
- const t = await caches.open(this.CACHE_NAME), s = await t.match(e);
799
- if (s)
800
- return await s.arrayBuffer();
801
- const n = await this.fileLoader.loadAsync(e), i = new Response(n);
802
- return await t.put(e, i), n;
803
- } catch (t) {
804
- return console.warn(`[LoaderManager] Failed to use Cache API for ${e}:`, t), await this.fileLoader.loadAsync(e);
1212
+ const cache = await caches.open(this.CACHE_NAME);
1213
+ const cachedResponse = await cache.match(url);
1214
+ if (cachedResponse) {
1215
+ return await cachedResponse.arrayBuffer();
1216
+ }
1217
+ const buffer = await this.fileLoader.loadAsync(url);
1218
+ const response = new Response(buffer);
1219
+ await cache.put(url, response);
1220
+ return buffer;
1221
+ } catch (error) {
1222
+ console.warn(`[LoaderManager] Failed to use Cache API for ${url}:`, error);
1223
+ return await this.fileLoader.loadAsync(url);
805
1224
  }
806
1225
  }
807
1226
  }
808
- class vs {
809
- static textureLoader = new ye();
810
- static hdrLoader = new vt();
811
- static cubeTextureLoader = new Ye();
812
- static setLoadingManager(e) {
813
- this.textureLoader.manager = e, this.hdrLoader.manager = e, this.cubeTextureLoader.manager = e;
814
- }
815
- static async loadAsyncTexture(e) {
816
- return await this.textureLoader.loadAsync(e);
817
- }
818
- static async loadAsyncHDR(e) {
819
- const t = await this.hdrLoader.loadAsync(e);
820
- return t.mapping = Je, t;
821
- }
822
- static async loadAsyncCubeTexture(e, t) {
823
- return this.cubeTextureLoader.setPath(e), await this.cubeTextureLoader.loadAsync(t);
1227
+ class TextureLoaderManager {
1228
+ static textureLoader = new TextureLoader();
1229
+ static hdrLoader = new HDRLoader();
1230
+ static cubeTextureLoader = new CubeTextureLoader();
1231
+ static setLoadingManager(loadingManager) {
1232
+ this.textureLoader.manager = loadingManager;
1233
+ this.hdrLoader.manager = loadingManager;
1234
+ this.cubeTextureLoader.manager = loadingManager;
1235
+ }
1236
+ static async loadAsyncTexture(url) {
1237
+ const texture = await this.textureLoader.loadAsync(url);
1238
+ return texture;
1239
+ }
1240
+ static async loadAsyncHDR(url) {
1241
+ const dataTexture = await this.hdrLoader.loadAsync(url);
1242
+ dataTexture.mapping = EquirectangularReflectionMapping;
1243
+ return dataTexture;
1244
+ }
1245
+ static async loadAsyncCubeTexture(path, urls) {
1246
+ this.cubeTextureLoader.setPath(path);
1247
+ const cubeTexture = await this.cubeTextureLoader.loadAsync(urls);
1248
+ return cubeTexture;
824
1249
  }
825
1250
  }
826
- class U extends j {
827
- isBaseMesh = !0;
1251
+ class BaseMesh extends Mesh {
1252
+ isBaseMesh = true;
828
1253
  type = "BaseMesh";
829
- ignoreInvisibleWhenRaycast = !0;
830
- constructor(...e) {
831
- super(...e);
1254
+ ignoreInvisibleWhenRaycast = true;
1255
+ constructor(...args) {
1256
+ super(...args);
832
1257
  }
833
- raycast(e, t) {
834
- return this.visible === !1 && this.ignoreInvisibleWhenRaycast === !0 ? !1 : super.raycast(e, t);
1258
+ raycast(raycaster, intersects) {
1259
+ if (this.visible === false && this.ignoreInvisibleWhenRaycast === true) {
1260
+ return false;
1261
+ }
1262
+ return super.raycast(raycaster, intersects);
835
1263
  }
836
1264
  }
837
- class Ee extends z {
838
- isBaseGroup = !0;
1265
+ class BaseGroup extends Group {
1266
+ isBaseGroup = true;
839
1267
  type = "BaseGroup";
840
- ignoreInvisibleWhenRaycast = !0;
841
- constructor(...e) {
842
- super(...e);
1268
+ ignoreInvisibleWhenRaycast = true;
1269
+ constructor(...args) {
1270
+ super(...args);
843
1271
  }
844
- raycast(e, t) {
845
- return this.visible === !1 && this.ignoreInvisibleWhenRaycast === !0 ? !1 : super.raycast(e, t);
1272
+ raycast(raycaster, intersects) {
1273
+ if (this.visible === false && this.ignoreInvisibleWhenRaycast === true) {
1274
+ return false;
1275
+ }
1276
+ return super.raycast(raycaster, intersects);
846
1277
  }
847
1278
  }
848
- class Xt extends Ze {
849
- isBaseSprite = !0;
1279
+ class BaseSprite extends Sprite {
1280
+ isBaseSprite = true;
850
1281
  type = "BaseSprite";
851
- ignoreInvisibleWhenRaycast = !0;
852
- constructor(...e) {
853
- super(...e);
1282
+ ignoreInvisibleWhenRaycast = true;
1283
+ constructor(...args) {
1284
+ super(...args);
854
1285
  }
855
- raycast(e, t) {
856
- return this.visible === !1 && this.ignoreInvisibleWhenRaycast === !0 ? !1 : super.raycast(e, t);
1286
+ raycast(raycaster, intersects) {
1287
+ if (this.visible === false && this.ignoreInvisibleWhenRaycast === true) {
1288
+ return false;
1289
+ }
1290
+ return super.raycast(raycaster, intersects);
857
1291
  }
858
1292
  }
859
- class H extends Ee {
860
- isModel = !0;
1293
+ class Model extends BaseGroup {
1294
+ isModel = true;
861
1295
  type = "Model";
862
1296
  static memoryCache = /* @__PURE__ */ new Map();
863
1297
  constructor() {
864
1298
  super();
865
1299
  }
866
- async loadAsync(e) {
867
- const { url: t, cache: s = !0, persistent: n = !0 } = e;
1300
+ async loadAsync(parameters) {
1301
+ const { url, cache = true, persistent = true } = parameters;
868
1302
  try {
869
- let i;
870
- s ? H.memoryCache.has(t) ? i = H.memoryCache.get(t) : (i = R.loadAsync(t, { persistent: n }), H.memoryCache.set(t, i)) : i = R.loadAsync(t, { persistent: n });
871
- const a = await i, c = bt(a);
872
- return this.add(c), c;
873
- } catch (i) {
874
- return console.error(`[Model] Failed to load model from ${t}:`, i), null;
1303
+ let objectPromise;
1304
+ if (cache) {
1305
+ if (Model.memoryCache.has(url)) {
1306
+ objectPromise = Model.memoryCache.get(url);
1307
+ } else {
1308
+ objectPromise = ModelLoaderManager.loadAsync(url, { persistent });
1309
+ Model.memoryCache.set(url, objectPromise);
1310
+ }
1311
+ } else {
1312
+ objectPromise = ModelLoaderManager.loadAsync(url, { persistent });
1313
+ }
1314
+ const object = await objectPromise;
1315
+ const clonedObject = clone(object);
1316
+ this.add(clonedObject);
1317
+ return clonedObject;
1318
+ } catch (error) {
1319
+ console.error(`[Model] Failed to load model from ${url}:`, error);
1320
+ return null;
875
1321
  }
876
1322
  }
877
1323
  static clearMemoryCache() {
878
1324
  this.memoryCache.clear();
879
1325
  }
880
1326
  static async clearPersistentCache() {
881
- typeof caches < "u" && await caches.delete("u-space-loader-cache");
1327
+ if (typeof caches !== "undefined") {
1328
+ await caches.delete("u-space-loader-cache");
1329
+ }
882
1330
  }
883
1331
  }
884
- class qt extends U {
885
- isSphereMesh = !0;
1332
+ class SphereMesh extends BaseMesh {
1333
+ isSphereMesh = true;
886
1334
  type = "SphereMesh";
887
- constructor({ geometryParameters: e, materialParameters: t } = {}) {
888
- super(), this.geometry = new Ve(
889
- e?.radius,
890
- e?.widthSegments,
891
- e?.heightSegments,
892
- e?.phiStart,
893
- e?.phiLength,
894
- e?.thetaStart,
895
- e?.thetaLength
896
- ), this.material = new I(t);
1335
+ constructor({ geometryParameters, materialParameters } = {}) {
1336
+ super();
1337
+ this.geometry = new SphereGeometry(
1338
+ geometryParameters?.radius,
1339
+ geometryParameters?.widthSegments,
1340
+ geometryParameters?.heightSegments,
1341
+ geometryParameters?.phiStart,
1342
+ geometryParameters?.phiLength,
1343
+ geometryParameters?.thetaStart,
1344
+ geometryParameters?.thetaLength
1345
+ );
1346
+ this.material = new MeshStandardNodeMaterial(materialParameters);
897
1347
  }
898
1348
  }
899
- class pe extends U {
900
- isTubeMesh = !0;
1349
+ class TubeMesh extends BaseMesh {
1350
+ isTubeMesh = true;
901
1351
  type = "TubeMesh";
902
- constructor({ geometryParameters: e, materialParameters: t } = {}) {
903
- super(), this.geometry = new et(
904
- e?.path,
905
- e?.tubularSegments,
906
- e?.radius,
907
- e?.radialSegments,
908
- e?.closed
909
- ), this.material = new I(t);
1352
+ constructor({ geometryParameters, materialParameters } = {}) {
1353
+ super();
1354
+ this.geometry = new TubeGeometry(
1355
+ geometryParameters?.path,
1356
+ geometryParameters?.tubularSegments,
1357
+ geometryParameters?.radius,
1358
+ geometryParameters?.radialSegments,
1359
+ geometryParameters?.closed
1360
+ );
1361
+ this.material = new MeshStandardNodeMaterial(materialParameters);
910
1362
  }
911
1363
  }
912
- class bs extends Ee {
913
- isTopology = !0;
1364
+ class Topology extends BaseGroup {
1365
+ isTopology = true;
914
1366
  type = "Topology";
915
1367
  // Visuals
916
1368
  parameters = {
@@ -925,27 +1377,37 @@ class bs extends Ee {
925
1377
  adjacencyMap = /* @__PURE__ */ new Map();
926
1378
  graphGroup = null;
927
1379
  pathMeshes = [];
928
- constructor(e) {
929
- super(), e && Object.assign(this.parameters, e);
1380
+ constructor(parameters) {
1381
+ super();
1382
+ if (parameters) {
1383
+ Object.assign(this.parameters, parameters);
1384
+ }
930
1385
  }
931
1386
  /**
932
1387
  * Add a node to the topology graph.
933
1388
  * @param id Unique identifier for the node
934
1389
  * @param position 3D position of the node
935
1390
  */
936
- addNode(e, t) {
937
- this.nodes.has(e) && console.warn(`[Topology] Node ${e} already exists. Overwriting.`), this.nodes.set(e, t), this.adjacencyMap.has(e) || this.adjacencyMap.set(e, /* @__PURE__ */ new Map());
1391
+ addNode(id, position) {
1392
+ if (this.nodes.has(id)) {
1393
+ console.warn(`[Topology] Node ${id} already exists. Overwriting.`);
1394
+ }
1395
+ this.nodes.set(id, position);
1396
+ if (!this.adjacencyMap.has(id)) {
1397
+ this.adjacencyMap.set(id, /* @__PURE__ */ new Map());
1398
+ }
938
1399
  }
939
1400
  /**
940
1401
  * Remove a node from the topology graph.
941
1402
  * @param id Unique identifier for the node
942
1403
  */
943
- removeNode(e) {
944
- if (!this.nodes.has(e)) {
945
- console.warn(`[Topology] Node ${e} does not exist.`);
1404
+ removeNode(id) {
1405
+ if (!this.nodes.has(id)) {
1406
+ console.warn(`[Topology] Node ${id} does not exist.`);
946
1407
  return;
947
1408
  }
948
- this.nodes.delete(e), this.adjacencyMap.delete(e);
1409
+ this.nodes.delete(id);
1410
+ this.adjacencyMap.delete(id);
949
1411
  }
950
1412
  /**
951
1413
  * Add an edge between two nodes.
@@ -954,14 +1416,18 @@ class bs extends Ee {
954
1416
  * @param weight Cost of the edge. Defaults to Euclidean distance.
955
1417
  * @param bidirectional If true, adds the reverse edge as well. Default true.
956
1418
  */
957
- addEdge(e, t, s, n = !0) {
958
- const i = this.nodes.get(e), a = this.nodes.get(t);
959
- if (!i || !a) {
960
- console.error(`[Topology] Cannot add edge. One or both nodes not found: ${e}, ${t}`);
1419
+ addEdge(from, to, weight, bidirectional = true) {
1420
+ const fromPos = this.nodes.get(from);
1421
+ const toPos = this.nodes.get(to);
1422
+ if (!fromPos || !toPos) {
1423
+ console.error(`[Topology] Cannot add edge. One or both nodes not found: ${from}, ${to}`);
961
1424
  return;
962
1425
  }
963
- const c = s ?? i.distanceTo(a);
964
- this.getNeighbors(e)?.set(t, c), n && this.getNeighbors(t)?.set(e, c);
1426
+ const dist = weight ?? fromPos.distanceTo(toPos);
1427
+ this.getNeighbors(from)?.set(to, dist);
1428
+ if (bidirectional) {
1429
+ this.getNeighbors(to)?.set(from, dist);
1430
+ }
965
1431
  }
966
1432
  /**
967
1433
  * Remove an edge between two nodes.
@@ -969,51 +1435,80 @@ class bs extends Ee {
969
1435
  * @param to Node ID
970
1436
  * @param bidirectional If true, removes the reverse edge as well. Default true.
971
1437
  */
972
- removeEdge(e, t, s = !0) {
973
- this.getNeighbors(e)?.delete(t), s && this.getNeighbors(t)?.delete(e);
1438
+ removeEdge(from, to, bidirectional = true) {
1439
+ const fromNeighbors = this.getNeighbors(from);
1440
+ fromNeighbors?.delete(to);
1441
+ if (bidirectional) {
1442
+ const toNeighbors = this.getNeighbors(to);
1443
+ toNeighbors?.delete(from);
1444
+ }
974
1445
  }
975
1446
  /**
976
1447
  * Find the shortest path between start and end nodes using Dijkstra's algorithm.
977
1448
  */
978
- getShortestPath(e, t) {
979
- if (!this.nodes.has(e) || !this.nodes.has(t))
980
- return console.warn("[Topology] Start or End node not found."), [];
981
- const s = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Set();
982
- for (const [r] of this.nodes)
983
- s.set(r, 1 / 0), n.set(r, null), i.add(r);
984
- for (s.set(e, 0); i.size > 0; ) {
985
- let r = null, h = 1 / 0;
986
- for (const u of i) {
987
- const f = s.get(u);
988
- f < h && (h = f, r = u);
1449
+ getShortestPath(startId, endId) {
1450
+ if (!this.nodes.has(startId) || !this.nodes.has(endId)) {
1451
+ console.warn(`[Topology] Start or End node not found.`);
1452
+ return [];
1453
+ }
1454
+ const distances = /* @__PURE__ */ new Map();
1455
+ const previous = /* @__PURE__ */ new Map();
1456
+ const unvisited = /* @__PURE__ */ new Set();
1457
+ for (const [id] of this.nodes) {
1458
+ distances.set(id, Infinity);
1459
+ previous.set(id, null);
1460
+ unvisited.add(id);
1461
+ }
1462
+ distances.set(startId, 0);
1463
+ while (unvisited.size > 0) {
1464
+ let currentId = null;
1465
+ let minDist = Infinity;
1466
+ for (const id of unvisited) {
1467
+ const d = distances.get(id);
1468
+ if (d < minDist) {
1469
+ minDist = d;
1470
+ currentId = id;
1471
+ }
1472
+ }
1473
+ if (currentId === null || currentId === endId) {
1474
+ break;
989
1475
  }
990
- if (r === null || r === t || h === 1 / 0)
1476
+ if (minDist === Infinity) {
991
1477
  break;
992
- i.delete(r);
993
- const l = this.adjacencyMap?.get(r);
994
- if (l)
995
- for (const [u, f] of l) {
996
- if (!i.has(u)) continue;
997
- const p = s.get(r) + f;
998
- p < s.get(u) && (s.set(u, p), n.set(u, r));
1478
+ }
1479
+ unvisited.delete(currentId);
1480
+ const neighbors = this.adjacencyMap?.get(currentId);
1481
+ if (!neighbors) {
1482
+ continue;
1483
+ }
1484
+ for (const [to, weight] of neighbors) {
1485
+ if (!unvisited.has(to)) continue;
1486
+ const alt = distances.get(currentId) + weight;
1487
+ if (alt < distances.get(to)) {
1488
+ distances.set(to, alt);
1489
+ previous.set(to, currentId);
999
1490
  }
1491
+ }
1000
1492
  }
1001
- const a = [];
1002
- let c = t;
1003
- if (n.get(t) === null && e !== t)
1493
+ const path = [];
1494
+ let curr = endId;
1495
+ if (previous.get(endId) === null && startId !== endId) {
1004
1496
  return [];
1005
- for (; c !== null; ) {
1006
- const r = this.nodes.get(c);
1007
- r && a.unshift(r), c = n.get(c) || null;
1008
1497
  }
1009
- return a;
1498
+ while (curr !== null) {
1499
+ const pos = this.nodes.get(curr);
1500
+ if (pos) path.unshift(pos);
1501
+ curr = previous.get(curr) || null;
1502
+ }
1503
+ return path;
1010
1504
  }
1011
1505
  /**
1012
1506
  * Renders the entire topology graph structure using TubeGeometry and Spheres.
1013
1507
  */
1014
1508
  renderGraph() {
1015
- this.clearGraph(), this.graphGroup = new z();
1016
- const e = new qt({
1509
+ this.clearGraph();
1510
+ this.graphGroup = new Group();
1511
+ const _dummySphere = new SphereMesh({
1017
1512
  geometryParameters: {
1018
1513
  radius: this.parameters.nodeRadius,
1019
1514
  widthSegments: 16,
@@ -1023,72 +1518,128 @@ class bs extends Ee {
1023
1518
  color: this.parameters.nodeColor
1024
1519
  }
1025
1520
  });
1026
- this.nodes.forEach((s, n) => {
1027
- const i = e.clone();
1028
- i.position.copy(s), Object.assign(i.userData, { id: n, type: "node" }), this.graphGroup.add(i);
1521
+ this.nodes.forEach((pos, id) => {
1522
+ const nodeMesh = _dummySphere.clone();
1523
+ nodeMesh.position.copy(pos);
1524
+ Object.assign(nodeMesh.userData, { id, type: "node" });
1525
+ this.graphGroup.add(nodeMesh);
1029
1526
  });
1030
- const t = /* @__PURE__ */ new Set();
1031
- this.adjacencyMap.forEach((s, n) => {
1032
- s.forEach((i, a) => {
1033
- const c = [n, a].sort().join("-");
1034
- if (t.has(c)) return;
1035
- t.add(c);
1036
- const r = this.nodes.get(n), h = this.nodes.get(a);
1037
- if (r && h) {
1038
- const l = new tt(r, h), u = new pe({
1527
+ const processedEdges = /* @__PURE__ */ new Set();
1528
+ this.adjacencyMap.forEach((edges, from) => {
1529
+ edges.forEach((weight, to) => {
1530
+ const key = [from, to].sort().join("-");
1531
+ if (processedEdges.has(key)) return;
1532
+ processedEdges.add(key);
1533
+ const p1 = this.nodes.get(from);
1534
+ const p2 = this.nodes.get(to);
1535
+ if (p1 && p2) {
1536
+ const path = new LineCurve3(p1, p2);
1537
+ const tubeMesh = new TubeMesh({
1039
1538
  geometryParameters: {
1040
- path: l,
1539
+ path,
1041
1540
  tubularSegments: 1,
1042
1541
  radius: this.parameters.edgeRadius,
1043
1542
  radialSegments: 8,
1044
- closed: !1
1543
+ closed: false
1045
1544
  },
1046
1545
  materialParameters: {
1047
1546
  color: this.parameters.edgeColor
1048
1547
  }
1049
1548
  });
1050
- Object.assign(u.userData, { from: n, to: a, weight: i, type: "edge" }), this.graphGroup.add(u);
1549
+ Object.assign(tubeMesh.userData, { from, to, weight, type: "edge" });
1550
+ this.graphGroup.add(tubeMesh);
1051
1551
  }
1052
1552
  });
1053
- }), this.add(this.graphGroup);
1553
+ });
1554
+ this.add(this.graphGroup);
1054
1555
  }
1055
1556
  clearGraph() {
1056
- this.graphGroup && (this.remove(this.graphGroup), this.graphGroup.traverse((e) => {
1057
- e instanceof j && (e.geometry.dispose(), e.material.dispose());
1058
- }), this.graphGroup = null);
1557
+ if (this.graphGroup) {
1558
+ this.remove(this.graphGroup);
1559
+ this.graphGroup.traverse((child) => {
1560
+ if (child instanceof Mesh) {
1561
+ child.geometry.dispose();
1562
+ child.material.dispose();
1563
+ }
1564
+ });
1565
+ this.graphGroup = null;
1566
+ }
1059
1567
  }
1060
1568
  /**
1061
1569
  * Visualizes a path using TubeGeometry (CatmullRomCurve3).
1062
1570
  */
1063
- renderPath(e, t = this.parameters.pathColor) {
1064
- if (e.length < 2) return;
1065
- const s = new st(e, !1, "catmullrom", 0), n = new pe({
1571
+ renderPath(points, color2 = this.parameters.pathColor) {
1572
+ if (points.length < 2) return;
1573
+ const curve = new CatmullRomCurve3(points, false, "catmullrom", 0);
1574
+ const mesh = new TubeMesh({
1066
1575
  geometryParameters: {
1067
- path: s,
1068
- tubularSegments: e.length * 10,
1576
+ path: curve,
1577
+ tubularSegments: points.length * 10,
1069
1578
  radius: this.parameters.pathRadius,
1070
- closed: !1
1579
+ closed: false
1071
1580
  },
1072
1581
  materialParameters: {
1073
- color: t
1582
+ color: color2
1074
1583
  }
1075
1584
  });
1076
- return this.add(n), this.pathMeshes.push(n), n;
1585
+ this.add(mesh);
1586
+ this.pathMeshes.push(mesh);
1587
+ return mesh;
1077
1588
  }
1078
1589
  clearPaths() {
1079
- this.pathMeshes.forEach((e) => {
1080
- this.remove(e), e.geometry.dispose(), e.material.dispose();
1081
- }), this.pathMeshes = [];
1590
+ this.pathMeshes.forEach((m) => {
1591
+ this.remove(m);
1592
+ m.geometry.dispose();
1593
+ m.material.dispose();
1594
+ });
1595
+ this.pathMeshes = [];
1596
+ }
1597
+ /** Export nodes and edges as a JSON-serializable object. */
1598
+ exportData() {
1599
+ const nodes = {};
1600
+ this.nodes.forEach((pos, id) => {
1601
+ nodes[id] = { x: pos.x, y: pos.y, z: pos.z };
1602
+ });
1603
+ const edges = [];
1604
+ const processed = /* @__PURE__ */ new Set();
1605
+ this.adjacencyMap.forEach((neighbors, from) => {
1606
+ neighbors.forEach((weight, to) => {
1607
+ const key = [from, to].sort().join("-");
1608
+ if (!processed.has(key)) {
1609
+ processed.add(key);
1610
+ edges.push({ from, to, weight });
1611
+ }
1612
+ });
1613
+ });
1614
+ return { nodes, edges };
1615
+ }
1616
+ /**
1617
+ * Load topology from a previously exported data object.
1618
+ * Replaces all current nodes, edges, and path meshes, then re-renders the graph.
1619
+ */
1620
+ importData(data) {
1621
+ this.clearGraph();
1622
+ this.clearPaths();
1623
+ this.nodes.clear();
1624
+ this.adjacencyMap.clear();
1625
+ Object.entries(data.nodes).forEach(([id, pos]) => {
1626
+ this.addNode(id, new Vector3(pos.x, pos.y, pos.z));
1627
+ });
1628
+ data.edges.forEach(({ from, to, weight }) => {
1629
+ this.addEdge(from, to, weight);
1630
+ });
1631
+ this.renderGraph();
1082
1632
  }
1083
1633
  dispose() {
1084
- this.clearGraph(), this.clearPaths();
1634
+ this.clearGraph();
1635
+ this.clearPaths();
1085
1636
  }
1086
- getNeighbors(e) {
1087
- return this.adjacencyMap.get(e);
1637
+ getNeighbors(id) {
1638
+ return this.adjacencyMap.get(id);
1088
1639
  }
1089
1640
  }
1090
- class Ts extends Xt {
1091
- isPoi = !0;
1641
+ class Poi extends BaseSprite {
1642
+ isPoi = true;
1092
1643
  type = "Poi";
1093
1644
  parameters = {
1094
1645
  img: "",
@@ -1098,277 +1649,426 @@ class Ts extends Xt {
1098
1649
  color: "#ffffff",
1099
1650
  iconSize: 64,
1100
1651
  padding: 10,
1101
- backgroundColor: "rgba(0, 0, 0, 0.5)",
1652
+ backgroundColor: "rgba(0, 0, 0, 0)",
1102
1653
  borderRadius: 8,
1103
- textPosition: "right"
1654
+ textPosition: "right",
1655
+ scaleFactor: 0.01
1104
1656
  };
1105
- constructor(e = {}) {
1106
- super(new nt()), Object.assign(this.parameters, e);
1657
+ _canvas = document.createElement("canvas");
1658
+ _lastParametersJSON = "";
1659
+ constructor(parameters = {}) {
1660
+ super(new SpriteNodeMaterial());
1661
+ Object.assign(this.parameters, parameters);
1662
+ this.updateAsync();
1107
1663
  }
1108
1664
  /**
1109
1665
  * Update the POI with new parameters
1110
1666
  * @param parameters Partial POI parameters
1111
1667
  */
1112
- async updateAsync(e = {}) {
1113
- Object.assign(this.parameters, e);
1114
- const t = document.createElement("canvas"), s = t.getContext("2d");
1115
- if (!s) return;
1116
- s.font = `${this.parameters.fontSize}px ${this.parameters.fontFamily}`;
1117
- let n = null;
1118
- this.parameters.img && (n = await this._loadImage(this.parameters.img));
1119
- const { text: i, fontSize: a, color: c, iconSize: r, padding: h, backgroundColor: l, borderRadius: u, textPosition: f } = this.parameters, p = s.measureText(i), g = i ? p.width : 0, w = i ? a : 0;
1120
- let T = 0, v = 0, b = 0, M = 0, x = 0, E = 0;
1121
- const S = !!n, m = !!i;
1122
- if (S && m)
1123
- switch (f) {
1668
+ async updateAsync(parameters = {}) {
1669
+ Object.assign(this.parameters, parameters);
1670
+ const json = JSON.stringify(this.parameters);
1671
+ if (json === this._lastParametersJSON) return;
1672
+ this._lastParametersJSON = json;
1673
+ const canvas = this._canvas;
1674
+ const ctx = canvas.getContext("2d");
1675
+ if (!ctx) return;
1676
+ ctx.font = `${this.parameters.fontSize}px ${this.parameters.fontFamily}`;
1677
+ let image = null;
1678
+ if (this.parameters.img) {
1679
+ image = await this._loadImage(this.parameters.img);
1680
+ }
1681
+ const { text, fontSize, color: color2, iconSize, padding, backgroundColor, borderRadius, textPosition, scaleFactor } = this.parameters;
1682
+ const textMetrics = ctx.measureText(text);
1683
+ const textWidth = text ? textMetrics.width : 0;
1684
+ const textHeight = text ? fontSize : 0;
1685
+ let contentWidth = 0;
1686
+ let contentHeight = 0;
1687
+ let iconX = 0, iconY = 0;
1688
+ let textX = 0, textY = 0;
1689
+ const hasImage = !!image;
1690
+ const hasText = !!text;
1691
+ if (hasImage && hasText) {
1692
+ switch (textPosition) {
1124
1693
  case "top":
1125
- T = Math.max(r, g), v = r + h + w, x = (T - g) / 2, E = w / 2, b = (T - r) / 2, M = w + h;
1694
+ contentWidth = Math.max(iconSize, textWidth);
1695
+ contentHeight = iconSize + padding + textHeight;
1696
+ textX = (contentWidth - textWidth) / 2;
1697
+ textY = textHeight / 2;
1698
+ iconX = (contentWidth - iconSize) / 2;
1699
+ iconY = textHeight + padding;
1126
1700
  break;
1127
1701
  case "bottom":
1128
- T = Math.max(r, g), v = r + h + w, b = (T - r) / 2, M = 0, x = (T - g) / 2, E = r + h + w / 2;
1702
+ contentWidth = Math.max(iconSize, textWidth);
1703
+ contentHeight = iconSize + padding + textHeight;
1704
+ iconX = (contentWidth - iconSize) / 2;
1705
+ iconY = 0;
1706
+ textX = (contentWidth - textWidth) / 2;
1707
+ textY = iconSize + padding + textHeight / 2;
1129
1708
  break;
1130
1709
  case "left":
1131
- T = r + h + g, v = Math.max(r, w), x = 0, E = v / 2, b = g + h, M = (v - r) / 2;
1710
+ contentWidth = iconSize + padding + textWidth;
1711
+ contentHeight = Math.max(iconSize, textHeight);
1712
+ textX = 0;
1713
+ textY = contentHeight / 2;
1714
+ iconX = textWidth + padding;
1715
+ iconY = (contentHeight - iconSize) / 2;
1132
1716
  break;
1717
+ case "right":
1133
1718
  default:
1134
- T = r + h + g, v = Math.max(r, w), b = 0, M = (v - r) / 2, x = r + h, E = v / 2;
1719
+ contentWidth = iconSize + padding + textWidth;
1720
+ contentHeight = Math.max(iconSize, textHeight);
1721
+ iconX = 0;
1722
+ iconY = (contentHeight - iconSize) / 2;
1723
+ textX = iconSize + padding;
1724
+ textY = contentHeight / 2;
1135
1725
  break;
1136
1726
  }
1137
- else S ? (T = r, v = r, b = 0, M = 0) : m && (T = g, v = w, x = 0, E = w / 2);
1138
- const y = T + h * 2, B = v + h * 2;
1139
- t.width = y, t.height = B, s.font = `${a}px ${this.parameters.fontFamily}`, s.textBaseline = "middle", l && (s.fillStyle = l, this._drawRoundedRect(s, 0, 0, y, B, u), s.fill()), S && s.drawImage(n, b + h, M + h, r, r), m && (s.fillStyle = c, s.fillText(i, x + h, E + h)), this.material.map?.dispose();
1140
- const _ = new it(t);
1141
- _.colorSpace = ve, this.material.map = _;
1142
- const O = 0.01;
1143
- this.scale.set(y * O, B * O, 1);
1144
- }
1145
- _loadImage(e) {
1146
- return new Promise((t, s) => {
1147
- if (typeof e == "string") {
1148
- const n = new Image();
1149
- n.crossOrigin = "Anonymous", n.onload = () => t(n), n.onerror = (i) => s(i), n.src = e;
1150
- } else
1151
- t(e);
1727
+ } else if (hasImage) {
1728
+ contentWidth = iconSize;
1729
+ contentHeight = iconSize;
1730
+ iconX = 0;
1731
+ iconY = 0;
1732
+ } else if (hasText) {
1733
+ contentWidth = textWidth;
1734
+ contentHeight = textHeight;
1735
+ textX = 0;
1736
+ textY = textHeight / 2;
1737
+ }
1738
+ const canvasWidth = contentWidth + padding * 2;
1739
+ const canvasHeight = contentHeight + padding * 2;
1740
+ canvas.width = canvasWidth;
1741
+ canvas.height = canvasHeight;
1742
+ ctx.font = `${fontSize}px ${this.parameters.fontFamily}`;
1743
+ if (backgroundColor) {
1744
+ ctx.fillStyle = backgroundColor;
1745
+ this._drawRoundedRect(ctx, 0, 0, canvasWidth, canvasHeight, borderRadius);
1746
+ ctx.fill();
1747
+ }
1748
+ if (hasImage) {
1749
+ ctx.drawImage(image, iconX + padding, iconY + padding, iconSize, iconSize);
1750
+ }
1751
+ if (hasText) {
1752
+ ctx.fillStyle = color2;
1753
+ const metrics = ctx.measureText(text);
1754
+ const actualTextHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
1755
+ const baselineOffset = metrics.actualBoundingBoxAscent - actualTextHeight / 2;
1756
+ ctx.textBaseline = "alphabetic";
1757
+ ctx.fillText(text, textX + padding, textY + padding + baselineOffset);
1758
+ }
1759
+ const oldTexture = this.material.map;
1760
+ const texture = new CanvasTexture(canvas);
1761
+ texture.colorSpace = SRGBColorSpace;
1762
+ this.material.map = texture;
1763
+ oldTexture?.dispose();
1764
+ this.scale.set(canvasWidth * scaleFactor, canvasHeight * scaleFactor, 1);
1765
+ }
1766
+ _loadImage(img) {
1767
+ return new Promise((resolve, reject) => {
1768
+ if (typeof img === "string") {
1769
+ const _img = new Image();
1770
+ _img.crossOrigin = "Anonymous";
1771
+ _img.onload = () => resolve(_img);
1772
+ _img.onerror = () => reject(new Error(`Failed to load image: ${img}`));
1773
+ _img.src = img;
1774
+ } else {
1775
+ resolve(img);
1776
+ }
1152
1777
  });
1153
1778
  }
1154
- _drawRoundedRect(e, t, s, n, i, a) {
1155
- e.beginPath(), e.moveTo(t + a, s), e.lineTo(t + n - a, s), e.quadraticCurveTo(t + n, s, t + n, s + a), e.lineTo(t + n, s + i - a), e.quadraticCurveTo(t + n, s + i, t + n - a, s + i), e.lineTo(t + a, s + i), e.quadraticCurveTo(t, s + i, t, s + i - a), e.lineTo(t, s + a), e.quadraticCurveTo(t, s, t + a, s), e.closePath();
1779
+ _drawRoundedRect(ctx, x, y, width, height, radius) {
1780
+ ctx.beginPath();
1781
+ ctx.moveTo(x + radius, y);
1782
+ ctx.lineTo(x + width - radius, y);
1783
+ ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
1784
+ ctx.lineTo(x + width, y + height - radius);
1785
+ ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
1786
+ ctx.lineTo(x + radius, y + height);
1787
+ ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
1788
+ ctx.lineTo(x, y + radius);
1789
+ ctx.quadraticCurveTo(x, y, x + radius, y);
1790
+ ctx.closePath();
1156
1791
  }
1157
1792
  dispose() {
1158
- this.material.map?.dispose(), this.material.dispose();
1793
+ this.material.map?.dispose();
1794
+ this.material.dispose();
1159
1795
  }
1160
1796
  }
1161
- class Oe extends U {
1162
- isShapeMesh = !0;
1797
+ class ShapeMesh extends BaseMesh {
1798
+ isShapeMesh = true;
1163
1799
  type = "ShapeMesh";
1164
- constructor({ geometryParameters: e, materialParameters: t } = {}) {
1165
- super(), this.geometry = new rt(e?.shape, e?.curveSegments), this.material = new I(t), this.geometry.rotateX(-Math.PI / 2);
1800
+ constructor({ geometryParameters, materialParameters } = {}) {
1801
+ super();
1802
+ this.geometry = new ShapeGeometry(geometryParameters?.shape, geometryParameters?.curveSegments);
1803
+ this.material = new MeshStandardNodeMaterial(materialParameters);
1804
+ this.geometry.rotateX(-Math.PI / 2);
1166
1805
  }
1167
- static createFromPoints(e, t = {}) {
1168
- return new Oe({
1169
- ...t,
1806
+ static createFromPoints(points, parameters = {}) {
1807
+ return new ShapeMesh({
1808
+ ...parameters,
1170
1809
  geometryParameters: {
1171
- ...t.geometryParameters,
1172
- shape: new be(e.map((s) => new P(s.x, -s.z)))
1810
+ ...parameters.geometryParameters,
1811
+ shape: new Shape(points.map((point) => new Vector2(point.x, -point.z)))
1173
1812
  }
1174
1813
  });
1175
1814
  }
1176
1815
  }
1177
- class Pe extends U {
1178
- isExtrudeMesh = !0;
1816
+ class ExtrudeMesh extends BaseMesh {
1817
+ isExtrudeMesh = true;
1179
1818
  type = "ExtrudeMesh";
1180
- constructor({ geometryParameters: e, materialParameters: t } = {}) {
1181
- super(), this.geometry = new at(e?.shape, e?.options), this.material = new I(t), this.geometry.rotateX(-Math.PI / 2);
1819
+ constructor({ geometryParameters, materialParameters } = {}) {
1820
+ super();
1821
+ this.geometry = new ExtrudeGeometry(geometryParameters?.shape, geometryParameters?.options);
1822
+ this.material = new MeshStandardNodeMaterial(materialParameters);
1823
+ this.geometry.rotateX(-Math.PI / 2);
1182
1824
  }
1183
- static createFromPoints(e, t = {}) {
1184
- return new Pe({
1185
- ...t,
1825
+ static createFromPoints(points, parameters = {}) {
1826
+ return new ExtrudeMesh({
1827
+ ...parameters,
1186
1828
  geometryParameters: {
1187
- ...t.geometryParameters,
1188
- shape: new be(e.map((s) => new P(s.x, -s.z)))
1829
+ ...parameters.geometryParameters,
1830
+ shape: new Shape(points.map((point) => new Vector2(point.x, -point.z)))
1189
1831
  }
1190
1832
  });
1191
1833
  }
1192
1834
  }
1193
- class Cs extends U {
1194
- isPlaneMesh = !0;
1835
+ class PlaneMesh extends BaseMesh {
1836
+ isPlaneMesh = true;
1195
1837
  type = "PlaneMesh";
1196
- constructor({ geometryParameters: e, materialParameters: t } = {}) {
1197
- super(), this.geometry = new ot(
1198
- e?.width,
1199
- e?.height,
1200
- e?.widthSegments,
1201
- e?.heightSegments
1202
- ), this.material = new I(t);
1838
+ constructor({ geometryParameters, materialParameters } = {}) {
1839
+ super();
1840
+ this.geometry = new PlaneGeometry(
1841
+ geometryParameters?.width,
1842
+ geometryParameters?.height,
1843
+ geometryParameters?.widthSegments,
1844
+ geometryParameters?.heightSegments
1845
+ );
1846
+ this.material = new MeshStandardNodeMaterial(materialParameters);
1203
1847
  }
1204
1848
  }
1205
- class Ms extends U {
1206
- isCircleMesh = !0;
1849
+ class CircleMesh extends BaseMesh {
1850
+ isCircleMesh = true;
1207
1851
  type = "CircleMesh";
1208
- constructor({ geometryParameters: e, materialParameters: t } = {}) {
1852
+ constructor({ geometryParameters, materialParameters } = {}) {
1209
1853
  super(
1210
- new ct(
1211
- e?.radius,
1212
- e?.segments,
1213
- e?.thetaStart,
1214
- e?.thetaLength
1854
+ new CircleGeometry(
1855
+ geometryParameters?.radius,
1856
+ geometryParameters?.segments,
1857
+ geometryParameters?.thetaStart,
1858
+ geometryParameters?.thetaLength
1215
1859
  ),
1216
- new I(t)
1217
- ), this.geometry.rotateX(-Math.PI / 2);
1860
+ new MeshStandardNodeMaterial(materialParameters)
1861
+ );
1862
+ this.geometry.rotateX(-Math.PI / 2);
1218
1863
  }
1219
1864
  }
1220
- class Yt {
1221
- static traverseMeshes(e, t) {
1222
- e.traverse((s) => {
1223
- s instanceof j && t(s);
1865
+ class ObjectUtils {
1866
+ static traverseMeshes(object, callback) {
1867
+ object.traverse((child) => {
1868
+ if (child instanceof Mesh) {
1869
+ callback(child);
1870
+ }
1224
1871
  });
1225
1872
  }
1226
1873
  }
1227
- class xs {
1228
- static flow(e = {}) {
1229
- const { baseColor: t = 16777215, flowColor: s = 65280, speed: n = 1, scale: i = 3, intensity: a = 4 } = e, c = A(new N(t)), r = A(new N(s)), h = re().x.mul(i).sub(Q.mul(n)), l = K(ae(h).add(1).mul(0.5), a);
1230
- return X(c, r, l);
1231
- }
1232
- static breathe(e = {}) {
1233
- const { baseColor: t = 16777215, breathColor: s = 65280, speed: n = 1, intensity: i = 2 } = e, a = A(new N(t)), c = A(new N(s)), r = ae(Q.mul(n)).add(1).mul(0.5), h = K(r, i);
1234
- return X(a, c, h);
1235
- }
1236
- static fluid(e = {}) {
1874
+ class TSLEffects {
1875
+ static flow(parameters = {}) {
1876
+ const { baseColor = 16777215, flowColor = 65280, speed = 1, scale = 3, intensity = 4 } = parameters;
1877
+ const baseColorNode = color(new Color$1(baseColor));
1878
+ const flowColorNode = color(new Color$1(flowColor));
1879
+ const flow = uv().x.mul(scale).sub(time.mul(speed));
1880
+ const pattern = pow(sin(flow).add(1).mul(0.5), intensity);
1881
+ return mix(baseColorNode, flowColorNode, pattern);
1882
+ }
1883
+ static breathe(parameters = {}) {
1884
+ const { baseColor = 16777215, breathColor = 65280, speed = 1, intensity = 2 } = parameters;
1885
+ const baseColorNode = color(new Color$1(baseColor));
1886
+ const breathColorNode = color(new Color$1(breathColor));
1887
+ const osc = sin(time.mul(speed)).add(1).mul(0.5);
1888
+ const pattern = pow(osc, intensity);
1889
+ return mix(baseColorNode, breathColorNode, pattern);
1890
+ }
1891
+ static fluid(parameters = {}) {
1237
1892
  const {
1238
- baseColor: t = 16777215,
1239
- flowColor: s = 255,
1240
- speed: n = 1,
1241
- scale: i = 1,
1242
- intensity: a = 1,
1243
- distortion: c = 0.5
1244
- } = e, r = A(new N(t)), h = A(new N(s)), l = re().mul(i), u = Q.mul(n), f = oe(l.add(u), 1, 0), p = l.add(f.mul(c)), g = oe(p, 1, 0).add(1).mul(0.5), w = K(g, a);
1245
- return X(r, h, w);
1893
+ baseColor = 16777215,
1894
+ flowColor = 255,
1895
+ speed = 1,
1896
+ scale = 1,
1897
+ intensity = 1,
1898
+ distortion = 0.5
1899
+ } = parameters;
1900
+ const baseColorNode = color(new Color$1(baseColor));
1901
+ const flowColorNode = color(new Color$1(flowColor));
1902
+ const uvNode = uv().mul(scale);
1903
+ const timeNode = time.mul(speed);
1904
+ const noiseNode = mx_noise_float(uvNode.add(timeNode), 1, 0);
1905
+ const distortedUV = uvNode.add(noiseNode.mul(distortion));
1906
+ const pattern = mx_noise_float(distortedUV, 1, 0).add(1).mul(0.5);
1907
+ const fluidPattern = pow(pattern, intensity);
1908
+ return mix(baseColorNode, flowColorNode, fluidPattern);
1246
1909
  }
1247
1910
  }
1248
- function Es(o) {
1911
+ function reinterpretType(_value) {
1249
1912
  }
1250
- const $ = "uSpaceHighlight", Z = `${$}/enabled`, Se = `${$}/opacity`, Le = `${$}/color`, Ie = `${$}/overwrite`, Jt = Te(() => {
1251
- const o = D(Z, "uint"), e = D(Le, "uint"), t = D(Ie, "uint"), s = Vt(e), n = ce.mul(s), i = Y(t.greaterThan(0), s, n);
1252
- return Y(o.greaterThan(0), i, ce);
1253
- })(), Zt = Te(() => {
1254
- const o = D(Z, "uint"), e = D(Se, "float");
1255
- return Y(o.greaterThan(0), e, lt);
1913
+ const _highlightKey = "uSpaceHighlight";
1914
+ const _highlightEnabledKey = `${_highlightKey}/enabled`;
1915
+ const _highlightOpacityKey = `${_highlightKey}/opacity`;
1916
+ const _highlightColorKey = `${_highlightKey}/color`;
1917
+ const _highlightOverwriteKey = `${_highlightKey}/overwrite`;
1918
+ const _highlightColorNode = Fn(() => {
1919
+ const enabled = userData(_highlightEnabledKey, "uint");
1920
+ const colorUint = userData(_highlightColorKey, "uint");
1921
+ const overwrite = userData(_highlightOverwriteKey, "uint");
1922
+ const hlColorRaw = uintToColor(colorUint);
1923
+ const tintedColor = materialColor.mul(hlColorRaw);
1924
+ const finalHlColor = select(overwrite.greaterThan(0), hlColorRaw, tintedColor);
1925
+ const hlColor = select(enabled.greaterThan(0), finalHlColor, materialColor);
1926
+ return hlColor;
1256
1927
  })();
1257
- class Os {
1258
- static highlight(e, t = {}) {
1259
- const s = Object.assign(
1928
+ const _highlightOpacityNode = Fn(() => {
1929
+ const enabled = userData(_highlightEnabledKey, "uint");
1930
+ const opacity = userData(_highlightOpacityKey, "float");
1931
+ const hlOpacity = select(enabled.greaterThan(0), opacity, materialOpacity);
1932
+ return hlOpacity;
1933
+ })();
1934
+ class MaterialEffects {
1935
+ static highlight(object, options = {}) {
1936
+ const highlightOptions = Object.assign(
1260
1937
  {
1261
- enabled: !0,
1938
+ enabled: true,
1262
1939
  opacity: 0.5,
1263
1940
  color: 16711680,
1264
- overwrite: !1
1941
+ overwrite: false
1265
1942
  },
1266
- t
1943
+ options
1267
1944
  );
1268
- s.color = new J(s.color).getHex(), Yt.traverseMeshes(e, (n) => {
1269
- n.userData[Z] = s.enabled ? 1 : 0, n.userData[Se] = s.opacity, n.userData[Le] = s.color, n.userData[Ie] = s.overwrite ? 1 : 0;
1270
- const i = n.material;
1271
- i && !Array.isArray(i) && (i.transparent = !0, i.colorNode = Jt, i.opacityNode = Zt, i.needsUpdate = !0);
1945
+ highlightOptions.color = new Color(highlightOptions.color).getHex();
1946
+ ObjectUtils.traverseMeshes(object, (mesh) => {
1947
+ mesh.userData[_highlightEnabledKey] = highlightOptions.enabled ? 1 : 0;
1948
+ mesh.userData[_highlightOpacityKey] = highlightOptions.opacity;
1949
+ mesh.userData[_highlightColorKey] = highlightOptions.color;
1950
+ mesh.userData[_highlightOverwriteKey] = highlightOptions.overwrite ? 1 : 0;
1951
+ const material = mesh.material;
1952
+ if (material && !Array.isArray(material)) {
1953
+ material.transparent = true;
1954
+ material.colorNode = _highlightColorNode;
1955
+ material.opacityNode = _highlightOpacityNode;
1956
+ material.needsUpdate = true;
1957
+ }
1272
1958
  });
1273
1959
  }
1274
1960
  }
1275
- const Vt = (o) => {
1276
- const e = o.shiftRight(16).bitAnd(255).toFloat().div(255), t = o.shiftRight(8).bitAnd(255).toFloat().div(255), s = o.bitAnd(255).toFloat().div(255);
1277
- return dt(e, t, s);
1961
+ const uintToColor = (colorUint) => {
1962
+ const r = colorUint.shiftRight(16).bitAnd(255).toFloat().div(255);
1963
+ const g = colorUint.shiftRight(8).bitAnd(255).toFloat().div(255);
1964
+ const b = colorUint.bitAnd(255).toFloat().div(255);
1965
+ return vec3(r, g, b);
1278
1966
  };
1279
- class es extends Tt {
1967
+ class Tween extends Tween$1 {
1280
1968
  viewer;
1281
- constructor(e, t) {
1282
- super(t), this.viewer = e;
1283
- }
1284
- _update = ({ time: e }) => {
1285
- this.update(e) && this.viewer.render();
1969
+ constructor(viewer, source) {
1970
+ super(source);
1971
+ this.viewer = viewer;
1972
+ }
1973
+ _update = ({ time: time2 }) => {
1974
+ const needsRender = this.update(time2);
1975
+ if (needsRender) {
1976
+ this.viewer.render();
1977
+ }
1286
1978
  };
1287
- easingByMode(e) {
1288
- const t = ts[e];
1289
- return super.easing(t);
1979
+ easingByMode(mode) {
1980
+ const tweenModeFunc = animationModeEnum[mode];
1981
+ return super.easing(tweenModeFunc);
1290
1982
  }
1291
- start(e, t) {
1292
- return this.viewer.addEventListener("afterControlsUpdate", this._update), super.start(e, t);
1983
+ start(time2, overrideStartingValues) {
1984
+ this.viewer.addEventListener("afterControlsUpdate", this._update);
1985
+ return super.start(time2, overrideStartingValues);
1293
1986
  }
1294
1987
  stop() {
1295
- return this.viewer.removeEventListener("afterControlsUpdate", this._update), super.stop();
1988
+ this.viewer.removeEventListener("afterControlsUpdate", this._update);
1989
+ return super.stop();
1296
1990
  }
1297
1991
  }
1298
- function Ps(o, e, t, s = {}, n, i) {
1299
- return new Promise((a, c) => {
1300
- const { duration: r = 1e3, delay: h = 0, repeat: l = !1, mode: u = "Linear.None", yoyo: f = !1 } = s, p = new es(o, e).to(t, r).easingByMode(u).delay(h).onUpdate((g) => {
1301
- n?.(g, p);
1992
+ function tweenAnimation(viewer, source, target, options = {}, onUpdate, onStart) {
1993
+ return new Promise((resolve, reject) => {
1994
+ const { duration = 1e3, delay = 0, repeat = false, mode = "Linear.None", yoyo = false } = options;
1995
+ const tween = new Tween(viewer, source).to(target, duration).easingByMode(mode).delay(delay).onUpdate((e) => {
1996
+ onUpdate?.(e, tween);
1302
1997
  }).onComplete(() => {
1303
- a();
1998
+ resolve();
1304
1999
  }).onStop(() => {
1305
- c("animation stop");
2000
+ reject("animation stop");
1306
2001
  }).onStart(() => {
1307
- i?.(p);
2002
+ onStart?.(tween);
1308
2003
  });
1309
- typeof l == "number" ? p.repeat(l) : typeof l == "boolean" && l && p.repeat(1 / 0), f && p.repeatDelay(20), p.yoyo(f), p.start();
2004
+ if (typeof repeat === "number") tween.repeat(repeat);
2005
+ else if (typeof repeat === "boolean" && repeat) tween.repeat(Infinity);
2006
+ if (yoyo) tween.repeatDelay(20);
2007
+ tween.yoyo(yoyo);
2008
+ tween.start();
1310
2009
  });
1311
2010
  }
1312
- const ts = {
1313
- "Linear.None": d.Linear.None,
1314
- "Quadratic.In": d.Quadratic.In,
1315
- "Quadratic.Out": d.Quadratic.Out,
1316
- "Quadratic.InOut": d.Quadratic.InOut,
1317
- "Cubic.In": d.Cubic.In,
1318
- "Cubic.Out": d.Cubic.Out,
1319
- "Cubic.InOut": d.Cubic.InOut,
1320
- "Quartic.In": d.Quartic.In,
1321
- "Quartic.Out": d.Quartic.Out,
1322
- "Quartic.InOut": d.Quartic.InOut,
1323
- "Quintic.In": d.Quintic.In,
1324
- "Quintic.Out": d.Quintic.Out,
1325
- "Quintic.InOut": d.Quintic.InOut,
1326
- "Sinusoidal.In": d.Sinusoidal.In,
1327
- "Sinusoidal.Out": d.Sinusoidal.Out,
1328
- "Sinusoidal.InOut": d.Sinusoidal.InOut,
1329
- "Exponential.In": d.Exponential.In,
1330
- "Exponential.Out": d.Exponential.Out,
1331
- "Exponential.InOut": d.Exponential.InOut,
1332
- "Circular.In": d.Circular.In,
1333
- "Circular.Out": d.Circular.Out,
1334
- "Circular.InOut": d.Circular.InOut,
1335
- "Elastic.In": d.Elastic.In,
1336
- "Elastic.Out": d.Elastic.Out,
1337
- "Elastic.InOut": d.Elastic.InOut,
1338
- "Back.In": d.Back.In,
1339
- "Back.Out": d.Back.Out,
1340
- "Back.InOut": d.Back.InOut,
1341
- "Bounce.In": d.Bounce.In,
1342
- "Bounce.Out": d.Bounce.Out,
1343
- "Bounce.InOut": d.Bounce.InOut
2011
+ const animationModeEnum = {
2012
+ "Linear.None": Easing.Linear.None,
2013
+ "Quadratic.In": Easing.Quadratic.In,
2014
+ "Quadratic.Out": Easing.Quadratic.Out,
2015
+ "Quadratic.InOut": Easing.Quadratic.InOut,
2016
+ "Cubic.In": Easing.Cubic.In,
2017
+ "Cubic.Out": Easing.Cubic.Out,
2018
+ "Cubic.InOut": Easing.Cubic.InOut,
2019
+ "Quartic.In": Easing.Quartic.In,
2020
+ "Quartic.Out": Easing.Quartic.Out,
2021
+ "Quartic.InOut": Easing.Quartic.InOut,
2022
+ "Quintic.In": Easing.Quintic.In,
2023
+ "Quintic.Out": Easing.Quintic.Out,
2024
+ "Quintic.InOut": Easing.Quintic.InOut,
2025
+ "Sinusoidal.In": Easing.Sinusoidal.In,
2026
+ "Sinusoidal.Out": Easing.Sinusoidal.Out,
2027
+ "Sinusoidal.InOut": Easing.Sinusoidal.InOut,
2028
+ "Exponential.In": Easing.Exponential.In,
2029
+ "Exponential.Out": Easing.Exponential.Out,
2030
+ "Exponential.InOut": Easing.Exponential.InOut,
2031
+ "Circular.In": Easing.Circular.In,
2032
+ "Circular.Out": Easing.Circular.Out,
2033
+ "Circular.InOut": Easing.Circular.InOut,
2034
+ "Elastic.In": Easing.Elastic.In,
2035
+ "Elastic.Out": Easing.Elastic.Out,
2036
+ "Elastic.InOut": Easing.Elastic.InOut,
2037
+ "Back.In": Easing.Back.In,
2038
+ "Back.Out": Easing.Back.Out,
2039
+ "Back.InOut": Easing.Back.InOut,
2040
+ "Bounce.In": Easing.Bounce.In,
2041
+ "Bounce.Out": Easing.Bounce.Out,
2042
+ "Bounce.InOut": Easing.Bounce.InOut
1344
2043
  };
1345
2044
  export {
1346
- Ee as BaseGroup,
1347
- U as BaseMesh,
1348
- Xt as BaseSprite,
1349
- Pt as CameraControls,
1350
- Ms as CircleMesh,
1351
- Pe as ExtrudeMesh,
1352
- Ct as InteractionEvent,
1353
- Mt as InteractionManager,
1354
- Os as MaterialEffects,
1355
- H as Model,
1356
- R as ModelLoaderManager,
1357
- xt as ObjectManager,
1358
- Yt as ObjectUtils,
1359
- Cs as PlaneMesh,
1360
- Ts as Poi,
1361
- Lt as RoomEnvironment,
1362
- Kt as SBMLoader,
1363
- Rt as SBMXLoader,
1364
- Oe as ShapeMesh,
1365
- qt as SphereMesh,
1366
- xs as TSLEffects,
1367
- vs as TextureLoaderManager,
1368
- bs as Topology,
1369
- pe as TubeMesh,
1370
- es as Tween,
1371
- ys as Viewer,
1372
- Es as reinterpretType,
1373
- Ps as tweenAnimation
2045
+ BaseGroup,
2046
+ BaseMesh,
2047
+ BaseSprite,
2048
+ CameraControls,
2049
+ CircleMesh,
2050
+ ExtrudeMesh,
2051
+ InteractionEvent,
2052
+ InteractionManager,
2053
+ MaterialEffects,
2054
+ Model,
2055
+ ModelLoaderManager,
2056
+ ObjectManager,
2057
+ ObjectUtils,
2058
+ PlaneMesh,
2059
+ Poi,
2060
+ RoomEnvironment,
2061
+ SBMLoader,
2062
+ SBMXLoader,
2063
+ ShapeMesh,
2064
+ SphereMesh,
2065
+ TSLEffects,
2066
+ TextureLoaderManager,
2067
+ Topology,
2068
+ TubeMesh,
2069
+ Tween,
2070
+ Viewer,
2071
+ reinterpretType,
2072
+ tweenAnimation
1374
2073
  };
2074
+ //# sourceMappingURL=index.js.map