belowjs 1.4.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/belowjs.js CHANGED
@@ -1,6 +1,6 @@
1
- import * as u from "three";
2
- import { Controls as Oi, Vector3 as R, MOUSE as Ce, TOUCH as pe, Quaternion as Ue, Spherical as Dt, Vector2 as V, Ray as Hi, Plane as qi, MathUtils as Bt, TrianglesDrawMode as ji, TriangleFanDrawMode as ht, TriangleStripDrawMode as li, Loader as yt, LoaderUtils as ve, FileLoader as le, MeshPhysicalMaterial as ee, Color as re, LinearSRGBColorSpace as Y, SRGBColorSpace as se, SpotLight as Ki, PointLight as zi, DirectionalLight as Yi, Matrix4 as Ie, InstancedMesh as ci, InstancedBufferAttribute as Ji, Object3D as Oe, TextureLoader as Wi, ImageBitmapLoader as Xi, BufferAttribute as Re, InterleavedBuffer as Zi, InterleavedBufferAttribute as Ae, LinearMipmapLinearFilter as He, NearestMipmapLinearFilter as $i, LinearMipmapNearestFilter as es, NearestMipmapNearestFilter as ts, LinearFilter as he, NearestFilter as hi, RepeatWrapping as dt, MirroredRepeatWrapping as is, ClampToEdgeWrapping as ss, PointsMaterial as os, Material as ze, LineBasicMaterial as ns, MeshStandardMaterial as wt, DoubleSide as rs, MeshBasicMaterial as fe, PropertyBinding as as, BufferGeometry as di, SkinnedMesh as As, Mesh as Qt, LineSegments as ls, Line as cs, LineLoop as hs, Points as ds, Group as Ye, PerspectiveCamera as gs, OrthographicCamera as us, Skeleton as ps, AnimationClip as fs, Bone as ms, InterpolateDiscrete as bs, InterpolateLinear as gi, Texture as Tt, VectorKeyframeTrack as Lt, NumberKeyframeTrack as Ft, QuaternionKeyframeTrack as kt, ColorManagement as gt, FrontSide as Cs, Interpolant as Es, Box3 as qe, Sphere as St, CompressedCubeTexture as Is, CompressedArrayTexture as Bs, CompressedTexture as ui, NoColorSpace as _t, RGBA_BPTC_Format as ut, RGBA_S3TC_DXT5_Format as pt, RGBA_S3TC_DXT3_Format as Gt, RGB_S3TC_DXT1_Format as Pt, RGBA_S3TC_DXT1_Format as ft, RGBA_ASTC_6x6_Format as Nt, RGBA_ASTC_4x4_Format as Ge, RGBA_ETC2_EAC_Format as pi, RGB_ETC2_Format as fi, RedFormat as Me, RGFormat as xe, RGBAFormat as me, UnsignedByteType as z, HalfFloatType as be, FloatType as De, DataTexture as ys, Data3DTexture as ws, RGB_PVRTC_4BPPV1_Format as Qs, RGB_ETC1_Format as Ss, RGBA_PVRTC_4BPPV1_Format as Ms, RGB_BPTC_UNSIGNED_Format as xs, SphereGeometry as mi, BoxGeometry as vs, DynamicDrawUsage as Rs, InstancedBufferGeometry as Ds, Float32BufferAttribute as Ut, InstancedInterleavedBuffer as mt, WireframeGeometry as Ts, ShaderMaterial as Ls, ShaderLib as Pe, UniformsUtils as bi, UniformsLib as Ne, Vector4 as Te, Line3 as Fs } from "three";
3
- class je {
1
+ import * as g from "three";
2
+ import { Controls as Oi, Vector3 as L, MOUSE as Ce, TOUCH as pe, Quaternion as Ve, Spherical as Dt, Vector2 as V, Ray as Hi, Plane as qi, MathUtils as Bt, TrianglesDrawMode as ji, TriangleFanDrawMode as ht, TriangleStripDrawMode as li, Loader as yt, LoaderUtils as xe, FileLoader as le, MeshPhysicalMaterial as ee, Color as re, LinearSRGBColorSpace as Y, SRGBColorSpace as se, SpotLight as Ki, PointLight as zi, DirectionalLight as Yi, Matrix4 as Ie, InstancedMesh as ci, InstancedBufferAttribute as Ji, Object3D as He, TextureLoader as Wi, ImageBitmapLoader as Xi, BufferAttribute as Re, InterleavedBuffer as Zi, InterleavedBufferAttribute as Ae, LinearMipmapLinearFilter as qe, NearestMipmapLinearFilter as $i, LinearMipmapNearestFilter as es, NearestMipmapNearestFilter as ts, LinearFilter as he, NearestFilter as hi, RepeatWrapping as dt, MirroredRepeatWrapping as is, ClampToEdgeWrapping as ss, PointsMaterial as os, Material as ze, LineBasicMaterial as ns, MeshStandardMaterial as wt, DoubleSide as rs, MeshBasicMaterial as fe, PropertyBinding as as, BufferGeometry as di, SkinnedMesh as As, Mesh as St, LineSegments as ls, Line as cs, LineLoop as hs, Points as ds, Group as Ye, PerspectiveCamera as us, OrthographicCamera as gs, Skeleton as ps, AnimationClip as fs, Bone as ms, InterpolateDiscrete as bs, InterpolateLinear as ui, Texture as Lt, VectorKeyframeTrack as Tt, NumberKeyframeTrack as kt, QuaternionKeyframeTrack as Ft, ColorManagement as ut, FrontSide as Cs, Interpolant as Es, Box3 as je, Sphere as Qt, CompressedCubeTexture as Is, CompressedArrayTexture as Bs, CompressedTexture as gi, NoColorSpace as _t, RGBA_BPTC_Format as gt, RGBA_S3TC_DXT5_Format as pt, RGBA_S3TC_DXT3_Format as Gt, RGB_S3TC_DXT1_Format as Pt, RGBA_S3TC_DXT1_Format as ft, RGBA_ASTC_6x6_Format as Nt, RGBA_ASTC_4x4_Format as Pe, RGBA_ETC2_EAC_Format as pi, RGB_ETC2_Format as fi, RedFormat as Me, RGFormat as ve, RGBAFormat as me, UnsignedByteType as z, HalfFloatType as be, FloatType as De, DataTexture as ys, Data3DTexture as ws, RGB_PVRTC_4BPPV1_Format as Ss, RGB_ETC1_Format as Qs, RGBA_PVRTC_4BPPV1_Format as Ms, RGB_BPTC_UNSIGNED_Format as vs, SphereGeometry as mi, BoxGeometry as xs, DynamicDrawUsage as Rs, InstancedBufferGeometry as Ds, Float32BufferAttribute as Ut, InstancedInterleavedBuffer as mt, WireframeGeometry as Ls, ShaderMaterial as Ts, ShaderLib as Ne, UniformsUtils as bi, UniformsLib as Ue, Vector4 as Le, Line3 as ks } from "three";
3
+ class Te {
4
4
  /**
5
5
  * Creates a new EventSystem instance
6
6
  */
@@ -143,13 +143,13 @@ class Ke {
143
143
  return Array.isArray(t) ? t.some((s) => i(e, s)) : i(e, t);
144
144
  }
145
145
  }
146
- class ks {
146
+ class Fs {
147
147
  constructor(e = {}) {
148
- this.config = e, this.scene = new u.Scene(), this.init();
148
+ this.config = e, this.scene = new g.Scene(), this.init();
149
149
  }
150
150
  init() {
151
151
  let e = "#001122";
152
- this.config.background && (typeof this.config.background == "object" && this.config.background.value ? e = this.config.background.value : typeof this.config.background == "string" && (e = this.config.background)), this.scene.background = new u.Color(e);
152
+ this.config.background && (typeof this.config.background == "object" && this.config.background.value ? e = this.config.background.value : typeof this.config.background == "string" && (e = this.config.background)), this.scene.background = new g.Color(e);
153
153
  }
154
154
  add(e) {
155
155
  this.scene.add(e);
@@ -164,7 +164,7 @@ class ks {
164
164
  this.scene.clear();
165
165
  }
166
166
  }
167
- const Vt = { type: "change" }, Mt = { type: "start" }, Ci = { type: "end" }, Le = new Hi(), Ot = new qi(), _s = Math.cos(70 * Bt.DEG2RAD), k = new R(), U = 2 * Math.PI, x = {
167
+ const Vt = { type: "change" }, Mt = { type: "start" }, Ci = { type: "end" }, ke = new Hi(), Ot = new qi(), _s = Math.cos(70 * Bt.DEG2RAD), F = new L(), U = 2 * Math.PI, x = {
168
168
  NONE: -1,
169
169
  ROTATE: 0,
170
170
  DOLLY: 1,
@@ -182,7 +182,7 @@ class Gs extends Oi {
182
182
  * @param {?HTMLDOMElement} domElement - The HTML element used for event listeners.
183
183
  */
184
184
  constructor(e, t = null) {
185
- super(e, t), this.state = x.NONE, this.target = new R(), this.cursor = new R(), this.minDistance = 0, this.maxDistance = 1 / 0, this.minZoom = 0, this.maxZoom = 1 / 0, this.minTargetRadius = 0, this.maxTargetRadius = 1 / 0, this.minPolarAngle = 0, this.maxPolarAngle = Math.PI, this.minAzimuthAngle = -1 / 0, this.maxAzimuthAngle = 1 / 0, this.enableDamping = !1, this.dampingFactor = 0.05, this.enableZoom = !0, this.zoomSpeed = 1, this.enableRotate = !0, this.rotateSpeed = 1, this.keyRotateSpeed = 1, this.enablePan = !0, this.panSpeed = 1, this.screenSpacePanning = !0, this.keyPanSpeed = 7, this.zoomToCursor = !1, this.autoRotate = !1, this.autoRotateSpeed = 2, this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" }, this.mouseButtons = { LEFT: Ce.ROTATE, MIDDLE: Ce.DOLLY, RIGHT: Ce.PAN }, this.touches = { ONE: pe.ROTATE, TWO: pe.DOLLY_PAN }, this.target0 = this.target.clone(), this.position0 = this.object.position.clone(), this.zoom0 = this.object.zoom, this._domElementKeyEvents = null, this._lastPosition = new R(), this._lastQuaternion = new Ue(), this._lastTargetPosition = new R(), this._quat = new Ue().setFromUnitVectors(e.up, new R(0, 1, 0)), this._quatInverse = this._quat.clone().invert(), this._spherical = new Dt(), this._sphericalDelta = new Dt(), this._scale = 1, this._panOffset = new R(), this._rotateStart = new V(), this._rotateEnd = new V(), this._rotateDelta = new V(), this._panStart = new V(), this._panEnd = new V(), this._panDelta = new V(), this._dollyStart = new V(), this._dollyEnd = new V(), this._dollyDelta = new V(), this._dollyDirection = new R(), this._mouse = new V(), this._performCursorZoom = !1, this._pointers = [], this._pointerPositions = {}, this._controlActive = !1, this._onPointerMove = Ns.bind(this), this._onPointerDown = Ps.bind(this), this._onPointerUp = Us.bind(this), this._onContextMenu = zs.bind(this), this._onMouseWheel = Hs.bind(this), this._onKeyDown = qs.bind(this), this._onTouchStart = js.bind(this), this._onTouchMove = Ks.bind(this), this._onMouseDown = Vs.bind(this), this._onMouseMove = Os.bind(this), this._interceptControlDown = Ys.bind(this), this._interceptControlUp = Js.bind(this), this.domElement !== null && this.connect(this.domElement), this.update();
185
+ super(e, t), this.state = x.NONE, this.target = new L(), this.cursor = new L(), this.minDistance = 0, this.maxDistance = 1 / 0, this.minZoom = 0, this.maxZoom = 1 / 0, this.minTargetRadius = 0, this.maxTargetRadius = 1 / 0, this.minPolarAngle = 0, this.maxPolarAngle = Math.PI, this.minAzimuthAngle = -1 / 0, this.maxAzimuthAngle = 1 / 0, this.enableDamping = !1, this.dampingFactor = 0.05, this.enableZoom = !0, this.zoomSpeed = 1, this.enableRotate = !0, this.rotateSpeed = 1, this.keyRotateSpeed = 1, this.enablePan = !0, this.panSpeed = 1, this.screenSpacePanning = !0, this.keyPanSpeed = 7, this.zoomToCursor = !1, this.autoRotate = !1, this.autoRotateSpeed = 2, this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" }, this.mouseButtons = { LEFT: Ce.ROTATE, MIDDLE: Ce.DOLLY, RIGHT: Ce.PAN }, this.touches = { ONE: pe.ROTATE, TWO: pe.DOLLY_PAN }, this.target0 = this.target.clone(), this.position0 = this.object.position.clone(), this.zoom0 = this.object.zoom, this._domElementKeyEvents = null, this._lastPosition = new L(), this._lastQuaternion = new Ve(), this._lastTargetPosition = new L(), this._quat = new Ve().setFromUnitVectors(e.up, new L(0, 1, 0)), this._quatInverse = this._quat.clone().invert(), this._spherical = new Dt(), this._sphericalDelta = new Dt(), this._scale = 1, this._panOffset = new L(), this._rotateStart = new V(), this._rotateEnd = new V(), this._rotateDelta = new V(), this._panStart = new V(), this._panEnd = new V(), this._panDelta = new V(), this._dollyStart = new V(), this._dollyEnd = new V(), this._dollyDelta = new V(), this._dollyDirection = new L(), this._mouse = new V(), this._performCursorZoom = !1, this._pointers = [], this._pointerPositions = {}, this._controlActive = !1, this._onPointerMove = Ns.bind(this), this._onPointerDown = Ps.bind(this), this._onPointerUp = Us.bind(this), this._onContextMenu = zs.bind(this), this._onMouseWheel = Hs.bind(this), this._onKeyDown = qs.bind(this), this._onTouchStart = js.bind(this), this._onTouchMove = Ks.bind(this), this._onMouseDown = Vs.bind(this), this._onMouseMove = Os.bind(this), this._interceptControlDown = Ys.bind(this), this._interceptControlUp = Js.bind(this), this.domElement !== null && this.connect(this.domElement), this.update();
186
186
  }
187
187
  connect(e) {
188
188
  super.connect(e), this.domElement.addEventListener("pointerdown", this._onPointerDown), this.domElement.addEventListener("pointercancel", this._onPointerUp), this.domElement.addEventListener("contextmenu", this._onContextMenu), this.domElement.addEventListener("wheel", this._onMouseWheel, { passive: !1 }), this.domElement.getRootNode().addEventListener("keydown", this._interceptControlDown, { passive: !0, capture: !0 }), this.domElement.style.touchAction = "none";
@@ -247,7 +247,7 @@ class Gs extends Oi {
247
247
  }
248
248
  update(e = null) {
249
249
  const t = this.object.position;
250
- k.copy(t).sub(this.target), k.applyQuaternion(this._quat), this._spherical.setFromVector3(k), this.autoRotate && this.state === x.NONE && this._rotateLeft(this._getAutoRotationAngle(e)), this.enableDamping ? (this._spherical.theta += this._sphericalDelta.theta * this.dampingFactor, this._spherical.phi += this._sphericalDelta.phi * this.dampingFactor) : (this._spherical.theta += this._sphericalDelta.theta, this._spherical.phi += this._sphericalDelta.phi);
250
+ F.copy(t).sub(this.target), F.applyQuaternion(this._quat), this._spherical.setFromVector3(F), this.autoRotate && this.state === x.NONE && this._rotateLeft(this._getAutoRotationAngle(e)), this.enableDamping ? (this._spherical.theta += this._sphericalDelta.theta * this.dampingFactor, this._spherical.phi += this._sphericalDelta.phi * this.dampingFactor) : (this._spherical.theta += this._sphericalDelta.theta, this._spherical.phi += this._sphericalDelta.phi);
251
251
  let i = this.minAzimuthAngle, s = this.maxAzimuthAngle;
252
252
  isFinite(i) && isFinite(s) && (i < -Math.PI ? i += U : i > Math.PI && (i -= U), s < -Math.PI ? s += U : s > Math.PI && (s -= U), i <= s ? this._spherical.theta = Math.max(i, Math.min(s, this._spherical.theta)) : this._spherical.theta = this._spherical.theta > (i + s) / 2 ? Math.max(i, this._spherical.theta) : Math.min(s, this._spherical.theta)), this._spherical.phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this._spherical.phi)), this._spherical.makeSafe(), this.enableDamping === !0 ? this.target.addScaledVector(this._panOffset, this.dampingFactor) : this.target.add(this._panOffset), this.target.sub(this.cursor), this.target.clampLength(this.minTargetRadius, this.maxTargetRadius), this.target.add(this.cursor);
253
253
  let o = !1;
@@ -257,23 +257,23 @@ class Gs extends Oi {
257
257
  const n = this._spherical.radius;
258
258
  this._spherical.radius = this._clampDistance(this._spherical.radius * this._scale), o = n != this._spherical.radius;
259
259
  }
260
- if (k.setFromSpherical(this._spherical), k.applyQuaternion(this._quatInverse), t.copy(this.target).add(k), this.object.lookAt(this.target), this.enableDamping === !0 ? (this._sphericalDelta.theta *= 1 - this.dampingFactor, this._sphericalDelta.phi *= 1 - this.dampingFactor, this._panOffset.multiplyScalar(1 - this.dampingFactor)) : (this._sphericalDelta.set(0, 0, 0), this._panOffset.set(0, 0, 0)), this.zoomToCursor && this._performCursorZoom) {
260
+ if (F.setFromSpherical(this._spherical), F.applyQuaternion(this._quatInverse), t.copy(this.target).add(F), this.object.lookAt(this.target), this.enableDamping === !0 ? (this._sphericalDelta.theta *= 1 - this.dampingFactor, this._sphericalDelta.phi *= 1 - this.dampingFactor, this._panOffset.multiplyScalar(1 - this.dampingFactor)) : (this._sphericalDelta.set(0, 0, 0), this._panOffset.set(0, 0, 0)), this.zoomToCursor && this._performCursorZoom) {
261
261
  let n = null;
262
262
  if (this.object.isPerspectiveCamera) {
263
- const r = k.length();
263
+ const r = F.length();
264
264
  n = this._clampDistance(r * this._scale);
265
265
  const A = r - n;
266
266
  this.object.position.addScaledVector(this._dollyDirection, A), this.object.updateMatrixWorld(), o = !!A;
267
267
  } else if (this.object.isOrthographicCamera) {
268
- const r = new R(this._mouse.x, this._mouse.y, 0);
268
+ const r = new L(this._mouse.x, this._mouse.y, 0);
269
269
  r.unproject(this.object);
270
270
  const A = this.object.zoom;
271
271
  this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / this._scale)), this.object.updateProjectionMatrix(), o = A !== this.object.zoom;
272
- const a = new R(this._mouse.x, this._mouse.y, 0);
273
- a.unproject(this.object), this.object.position.sub(a).add(r), this.object.updateMatrixWorld(), n = k.length();
272
+ const a = new L(this._mouse.x, this._mouse.y, 0);
273
+ a.unproject(this.object), this.object.position.sub(a).add(r), this.object.updateMatrixWorld(), n = F.length();
274
274
  } else
275
275
  console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."), this.zoomToCursor = !1;
276
- n !== null && (this.screenSpacePanning ? this.target.set(0, 0, -1).transformDirection(this.object.matrix).multiplyScalar(n).add(this.object.position) : (Le.origin.copy(this.object.position), Le.direction.set(0, 0, -1).transformDirection(this.object.matrix), Math.abs(this.object.up.dot(Le.direction)) < _s ? this.object.lookAt(this.target) : (Ot.setFromNormalAndCoplanarPoint(this.object.up, this.target), Le.intersectPlane(Ot, this.target))));
276
+ n !== null && (this.screenSpacePanning ? this.target.set(0, 0, -1).transformDirection(this.object.matrix).multiplyScalar(n).add(this.object.position) : (ke.origin.copy(this.object.position), ke.direction.set(0, 0, -1).transformDirection(this.object.matrix), Math.abs(this.object.up.dot(ke.direction)) < _s ? this.object.lookAt(this.target) : (Ot.setFromNormalAndCoplanarPoint(this.object.up, this.target), ke.intersectPlane(Ot, this.target))));
277
277
  } else if (this.object.isOrthographicCamera) {
278
278
  const n = this.object.zoom;
279
279
  this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / this._scale)), n !== this.object.zoom && (this.object.updateProjectionMatrix(), o = !0);
@@ -294,18 +294,18 @@ class Gs extends Oi {
294
294
  this._sphericalDelta.phi -= e;
295
295
  }
296
296
  _panLeft(e, t) {
297
- k.setFromMatrixColumn(t, 0), k.multiplyScalar(-e), this._panOffset.add(k);
297
+ F.setFromMatrixColumn(t, 0), F.multiplyScalar(-e), this._panOffset.add(F);
298
298
  }
299
299
  _panUp(e, t) {
300
- this.screenSpacePanning === !0 ? k.setFromMatrixColumn(t, 1) : (k.setFromMatrixColumn(t, 0), k.crossVectors(this.object.up, k)), k.multiplyScalar(e), this._panOffset.add(k);
300
+ this.screenSpacePanning === !0 ? F.setFromMatrixColumn(t, 1) : (F.setFromMatrixColumn(t, 0), F.crossVectors(this.object.up, F)), F.multiplyScalar(e), this._panOffset.add(F);
301
301
  }
302
302
  // deltaX and deltaY are in pixels; right and down are positive
303
303
  _pan(e, t) {
304
304
  const i = this.domElement;
305
305
  if (this.object.isPerspectiveCamera) {
306
306
  const s = this.object.position;
307
- k.copy(s).sub(this.target);
308
- let o = k.length();
307
+ F.copy(s).sub(this.target);
308
+ let o = F.length();
309
309
  o *= Math.tan(this.object.fov / 2 * Math.PI / 180), this._panLeft(2 * e * o / i.clientHeight, this.object.matrix), this._panUp(2 * t * o / i.clientHeight, this.object.matrix);
310
310
  } else this.object.isOrthographicCamera ? (this._panLeft(e * (this.object.right - this.object.left) / this.object.zoom / i.clientWidth, this.object.matrix), this._panUp(t * (this.object.top - this.object.bottom) / this.object.zoom / i.clientHeight, this.object.matrix)) : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."), this.enablePan = !1);
311
311
  }
@@ -618,7 +618,7 @@ function Ys(c) {
618
618
  function Js(c) {
619
619
  c.key === "Control" && (this._controlActive = !1, this.domElement.getRootNode().removeEventListener("keyup", this._interceptControlUp, { passive: !0, capture: !0 }));
620
620
  }
621
- class Ws extends je {
621
+ class Ws extends Te {
622
622
  /**
623
623
  * Creates a new Camera instance
624
624
  *
@@ -628,7 +628,7 @@ class Ws extends je {
628
628
  super(), this.config = e, this.camera = null, this.controls = null, this.focusAnimation = null, this.init();
629
629
  }
630
630
  init() {
631
- this.camera = new u.PerspectiveCamera(
631
+ this.camera = new g.PerspectiveCamera(
632
632
  this.config.fov || 65,
633
633
  window.innerWidth / window.innerHeight,
634
634
  this.config.near || 0.05,
@@ -714,8 +714,8 @@ class Ws extends je {
714
714
  };
715
715
  this.controls.addEventListener("start", a, { once: !0 });
716
716
  const l = () => {
717
- const h = performance.now() - A, d = Math.min(h / r, 1), g = 1 - Math.pow(1 - d, 3);
718
- this.controls.target.lerpVectors(i, e, g), this.camera.position.lerpVectors(s, n, g), d < 1 ? this.focusAnimation = requestAnimationFrame(l) : (this.focusAnimation = null, this.controls.removeEventListener("start", a), this.emit("focus-complete", { target: e, position: n }));
717
+ const h = performance.now() - A, d = Math.min(h / r, 1), u = 1 - Math.pow(1 - d, 3);
718
+ this.controls.target.lerpVectors(i, e, u), this.camera.position.lerpVectors(s, n, u), d < 1 ? this.focusAnimation = requestAnimationFrame(l) : (this.focusAnimation = null, this.controls.removeEventListener("start", a), this.emit("focus-complete", { target: e, position: n }));
719
719
  };
720
720
  this.focusAnimation = requestAnimationFrame(l), this.emit("focus-start", { target: e, startPosition: s, newPosition: n });
721
721
  }
@@ -765,7 +765,7 @@ function Ht(c, e) {
765
765
  } else
766
766
  return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:", e), c;
767
767
  }
768
- class xt extends yt {
768
+ class vt extends yt {
769
769
  /**
770
770
  * Constructs a new glTF loader.
771
771
  *
@@ -778,10 +778,10 @@ class xt extends yt {
778
778
  return new io(t);
779
779
  }), this.register(function(t) {
780
780
  return new ho(t);
781
- }), this.register(function(t) {
782
- return new go(t);
783
781
  }), this.register(function(t) {
784
782
  return new uo(t);
783
+ }), this.register(function(t) {
784
+ return new go(t);
785
785
  }), this.register(function(t) {
786
786
  return new oo(t);
787
787
  }), this.register(function(t) {
@@ -823,10 +823,10 @@ class xt extends yt {
823
823
  if (this.resourcePath !== "")
824
824
  n = this.resourcePath;
825
825
  else if (this.path !== "") {
826
- const a = ve.extractUrlBase(e);
827
- n = ve.resolveURL(a, this.path);
826
+ const a = xe.extractUrlBase(e);
827
+ n = xe.resolveURL(a, this.path);
828
828
  } else
829
- n = ve.extractUrlBase(e);
829
+ n = xe.extractUrlBase(e);
830
830
  this.manager.itemStart(e);
831
831
  const r = function(a) {
832
832
  s ? s(a) : console.error(a), o.manager.itemError(e), o.manager.itemEnd(e);
@@ -907,12 +907,12 @@ class xt extends yt {
907
907
  else if (e instanceof ArrayBuffer)
908
908
  if (A.decode(new Uint8Array(e, 0, 4)) === Ei) {
909
909
  try {
910
- n[S.KHR_BINARY_GLTF] = new mo(e);
910
+ n[Q.KHR_BINARY_GLTF] = new mo(e);
911
911
  } catch (h) {
912
912
  s && s(h);
913
913
  return;
914
914
  }
915
- o = JSON.parse(n[S.KHR_BINARY_GLTF].content);
915
+ o = JSON.parse(n[Q.KHR_BINARY_GLTF].content);
916
916
  } else
917
917
  o = JSON.parse(A.decode(e));
918
918
  else
@@ -938,16 +938,16 @@ class xt extends yt {
938
938
  for (let l = 0; l < o.extensionsUsed.length; ++l) {
939
939
  const h = o.extensionsUsed[l], d = o.extensionsRequired || [];
940
940
  switch (h) {
941
- case S.KHR_MATERIALS_UNLIT:
941
+ case Q.KHR_MATERIALS_UNLIT:
942
942
  n[h] = new $s();
943
943
  break;
944
- case S.KHR_DRACO_MESH_COMPRESSION:
944
+ case Q.KHR_DRACO_MESH_COMPRESSION:
945
945
  n[h] = new bo(o, this.dracoLoader);
946
946
  break;
947
- case S.KHR_TEXTURE_TRANSFORM:
947
+ case Q.KHR_TEXTURE_TRANSFORM:
948
948
  n[h] = new Co();
949
949
  break;
950
- case S.KHR_MESH_QUANTIZATION:
950
+ case Q.KHR_MESH_QUANTIZATION:
951
951
  n[h] = new Eo();
952
952
  break;
953
953
  default:
@@ -988,7 +988,7 @@ function Xs() {
988
988
  }
989
989
  };
990
990
  }
991
- const S = {
991
+ const Q = {
992
992
  KHR_BINARY_GLTF: "KHR_binary_glTF",
993
993
  KHR_DRACO_MESH_COMPRESSION: "KHR_draco_mesh_compression",
994
994
  KHR_LIGHTS_PUNCTUAL: "KHR_lights_punctual",
@@ -1014,7 +1014,7 @@ const S = {
1014
1014
  };
1015
1015
  class Zs {
1016
1016
  constructor(e) {
1017
- this.parser = e, this.name = S.KHR_LIGHTS_PUNCTUAL, this.cache = { refs: {}, uses: {} };
1017
+ this.parser = e, this.name = Q.KHR_LIGHTS_PUNCTUAL, this.cache = { refs: {}, uses: {} };
1018
1018
  }
1019
1019
  _markDefs() {
1020
1020
  const e = this.parser, t = this.parser.json.nodes || [];
@@ -1060,7 +1060,7 @@ class Zs {
1060
1060
  }
1061
1061
  class $s {
1062
1062
  constructor() {
1063
- this.name = S.KHR_MATERIALS_UNLIT;
1063
+ this.name = Q.KHR_MATERIALS_UNLIT;
1064
1064
  }
1065
1065
  getMaterialType() {
1066
1066
  return fe;
@@ -1081,7 +1081,7 @@ class $s {
1081
1081
  }
1082
1082
  class eo {
1083
1083
  constructor(e) {
1084
- this.parser = e, this.name = S.KHR_MATERIALS_EMISSIVE_STRENGTH;
1084
+ this.parser = e, this.name = Q.KHR_MATERIALS_EMISSIVE_STRENGTH;
1085
1085
  }
1086
1086
  extendMaterialParams(e, t) {
1087
1087
  const s = this.parser.json.materials[e];
@@ -1093,7 +1093,7 @@ class eo {
1093
1093
  }
1094
1094
  class to {
1095
1095
  constructor(e) {
1096
- this.parser = e, this.name = S.KHR_MATERIALS_CLEARCOAT;
1096
+ this.parser = e, this.name = Q.KHR_MATERIALS_CLEARCOAT;
1097
1097
  }
1098
1098
  getMaterialType(e) {
1099
1099
  const i = this.parser.json.materials[e];
@@ -1113,7 +1113,7 @@ class to {
1113
1113
  }
1114
1114
  class io {
1115
1115
  constructor(e) {
1116
- this.parser = e, this.name = S.KHR_MATERIALS_DISPERSION;
1116
+ this.parser = e, this.name = Q.KHR_MATERIALS_DISPERSION;
1117
1117
  }
1118
1118
  getMaterialType(e) {
1119
1119
  const i = this.parser.json.materials[e];
@@ -1129,7 +1129,7 @@ class io {
1129
1129
  }
1130
1130
  class so {
1131
1131
  constructor(e) {
1132
- this.parser = e, this.name = S.KHR_MATERIALS_IRIDESCENCE;
1132
+ this.parser = e, this.name = Q.KHR_MATERIALS_IRIDESCENCE;
1133
1133
  }
1134
1134
  getMaterialType(e) {
1135
1135
  const i = this.parser.json.materials[e];
@@ -1145,7 +1145,7 @@ class so {
1145
1145
  }
1146
1146
  class oo {
1147
1147
  constructor(e) {
1148
- this.parser = e, this.name = S.KHR_MATERIALS_SHEEN;
1148
+ this.parser = e, this.name = Q.KHR_MATERIALS_SHEEN;
1149
1149
  }
1150
1150
  getMaterialType(e) {
1151
1151
  const i = this.parser.json.materials[e];
@@ -1167,7 +1167,7 @@ class oo {
1167
1167
  }
1168
1168
  class no {
1169
1169
  constructor(e) {
1170
- this.parser = e, this.name = S.KHR_MATERIALS_TRANSMISSION;
1170
+ this.parser = e, this.name = Q.KHR_MATERIALS_TRANSMISSION;
1171
1171
  }
1172
1172
  getMaterialType(e) {
1173
1173
  const i = this.parser.json.materials[e];
@@ -1183,7 +1183,7 @@ class no {
1183
1183
  }
1184
1184
  class ro {
1185
1185
  constructor(e) {
1186
- this.parser = e, this.name = S.KHR_MATERIALS_VOLUME;
1186
+ this.parser = e, this.name = Q.KHR_MATERIALS_VOLUME;
1187
1187
  }
1188
1188
  getMaterialType(e) {
1189
1189
  const i = this.parser.json.materials[e];
@@ -1201,7 +1201,7 @@ class ro {
1201
1201
  }
1202
1202
  class ao {
1203
1203
  constructor(e) {
1204
- this.parser = e, this.name = S.KHR_MATERIALS_IOR;
1204
+ this.parser = e, this.name = Q.KHR_MATERIALS_IOR;
1205
1205
  }
1206
1206
  getMaterialType(e) {
1207
1207
  const i = this.parser.json.materials[e];
@@ -1217,7 +1217,7 @@ class ao {
1217
1217
  }
1218
1218
  class Ao {
1219
1219
  constructor(e) {
1220
- this.parser = e, this.name = S.KHR_MATERIALS_SPECULAR;
1220
+ this.parser = e, this.name = Q.KHR_MATERIALS_SPECULAR;
1221
1221
  }
1222
1222
  getMaterialType(e) {
1223
1223
  const i = this.parser.json.materials[e];
@@ -1235,7 +1235,7 @@ class Ao {
1235
1235
  }
1236
1236
  class lo {
1237
1237
  constructor(e) {
1238
- this.parser = e, this.name = S.EXT_MATERIALS_BUMP;
1238
+ this.parser = e, this.name = Q.EXT_MATERIALS_BUMP;
1239
1239
  }
1240
1240
  getMaterialType(e) {
1241
1241
  const i = this.parser.json.materials[e];
@@ -1251,7 +1251,7 @@ class lo {
1251
1251
  }
1252
1252
  class co {
1253
1253
  constructor(e) {
1254
- this.parser = e, this.name = S.KHR_MATERIALS_ANISOTROPY;
1254
+ this.parser = e, this.name = Q.KHR_MATERIALS_ANISOTROPY;
1255
1255
  }
1256
1256
  getMaterialType(e) {
1257
1257
  const i = this.parser.json.materials[e];
@@ -1267,7 +1267,7 @@ class co {
1267
1267
  }
1268
1268
  class ho {
1269
1269
  constructor(e) {
1270
- this.parser = e, this.name = S.KHR_TEXTURE_BASISU;
1270
+ this.parser = e, this.name = Q.KHR_TEXTURE_BASISU;
1271
1271
  }
1272
1272
  loadTexture(e) {
1273
1273
  const t = this.parser, i = t.json, s = i.textures[e];
@@ -1282,9 +1282,9 @@ class ho {
1282
1282
  return t.loadTextureImage(e, o.source, n);
1283
1283
  }
1284
1284
  }
1285
- class go {
1285
+ class uo {
1286
1286
  constructor(e) {
1287
- this.parser = e, this.name = S.EXT_TEXTURE_WEBP;
1287
+ this.parser = e, this.name = Q.EXT_TEXTURE_WEBP;
1288
1288
  }
1289
1289
  loadTexture(e) {
1290
1290
  const t = this.name, i = this.parser, s = i.json, o = s.textures[e];
@@ -1299,9 +1299,9 @@ class go {
1299
1299
  return i.loadTextureImage(e, n.source, A);
1300
1300
  }
1301
1301
  }
1302
- class uo {
1302
+ class go {
1303
1303
  constructor(e) {
1304
- this.parser = e, this.name = S.EXT_TEXTURE_AVIF;
1304
+ this.parser = e, this.name = Q.EXT_TEXTURE_AVIF;
1305
1305
  }
1306
1306
  loadTexture(e) {
1307
1307
  const t = this.name, i = this.parser, s = i.json, o = s.textures[e];
@@ -1318,7 +1318,7 @@ class uo {
1318
1318
  }
1319
1319
  class po {
1320
1320
  constructor(e) {
1321
- this.name = S.EXT_MESHOPT_COMPRESSION, this.parser = e;
1321
+ this.name = Q.EXT_MESHOPT_COMPRESSION, this.parser = e;
1322
1322
  }
1323
1323
  loadBufferView(e) {
1324
1324
  const t = this.parser.json, i = t.bufferViews[e];
@@ -1331,11 +1331,11 @@ class po {
1331
1331
  }
1332
1332
  return o.then(function(r) {
1333
1333
  const A = s.byteOffset || 0, a = s.byteLength || 0, l = s.count, h = s.byteStride, d = new Uint8Array(r, A, a);
1334
- return n.decodeGltfBufferAsync ? n.decodeGltfBufferAsync(l, h, d, s.mode, s.filter).then(function(g) {
1335
- return g.buffer;
1334
+ return n.decodeGltfBufferAsync ? n.decodeGltfBufferAsync(l, h, d, s.mode, s.filter).then(function(u) {
1335
+ return u.buffer;
1336
1336
  }) : n.ready.then(function() {
1337
- const g = new ArrayBuffer(l * h);
1338
- return n.decodeGltfBuffer(new Uint8Array(g), l, h, d, s.mode, s.filter), g;
1337
+ const u = new ArrayBuffer(l * h);
1338
+ return n.decodeGltfBuffer(new Uint8Array(u), l, h, d, s.mode, s.filter), u;
1339
1339
  });
1340
1340
  });
1341
1341
  } else
@@ -1344,7 +1344,7 @@ class po {
1344
1344
  }
1345
1345
  class fo {
1346
1346
  constructor(e) {
1347
- this.name = S.EXT_MESH_GPU_INSTANCING, this.parser = e;
1347
+ this.name = Q.EXT_MESH_GPU_INSTANCING, this.parser = e;
1348
1348
  }
1349
1349
  createNodeMesh(e) {
1350
1350
  const t = this.parser.json, i = t.nodes[e];
@@ -1358,27 +1358,27 @@ class fo {
1358
1358
  for (const a in n)
1359
1359
  r.push(this.parser.getDependency("accessor", n[a]).then((l) => (A[a] = l, A[a])));
1360
1360
  return r.length < 1 ? null : (r.push(this.parser.createNodeMesh(e)), Promise.all(r).then((a) => {
1361
- const l = a.pop(), h = l.isGroup ? l.children : [l], d = a[0].count, g = [];
1361
+ const l = a.pop(), h = l.isGroup ? l.children : [l], d = a[0].count, u = [];
1362
1362
  for (const p of h) {
1363
- const C = new Ie(), E = new R(), f = new Ue(), m = new R(1, 1, 1), I = new ci(p.geometry, p.material, d);
1364
- for (let b = 0; b < d; b++)
1365
- A.TRANSLATION && E.fromBufferAttribute(A.TRANSLATION, b), A.ROTATION && f.fromBufferAttribute(A.ROTATION, b), A.SCALE && m.fromBufferAttribute(A.SCALE, b), I.setMatrixAt(b, C.compose(E, f, m));
1366
- for (const b in A)
1367
- if (b === "_COLOR_0") {
1368
- const B = A[b];
1363
+ const b = new Ie(), E = new L(), f = new Ve(), m = new L(1, 1, 1), I = new ci(p.geometry, p.material, d);
1364
+ for (let C = 0; C < d; C++)
1365
+ A.TRANSLATION && E.fromBufferAttribute(A.TRANSLATION, C), A.ROTATION && f.fromBufferAttribute(A.ROTATION, C), A.SCALE && m.fromBufferAttribute(A.SCALE, C), I.setMatrixAt(C, b.compose(E, f, m));
1366
+ for (const C in A)
1367
+ if (C === "_COLOR_0") {
1368
+ const B = A[C];
1369
1369
  I.instanceColor = new Ji(B.array, B.itemSize, B.normalized);
1370
- } else b !== "TRANSLATION" && b !== "ROTATION" && b !== "SCALE" && p.geometry.setAttribute(b, A[b]);
1371
- Oe.prototype.copy.call(I, p), this.parser.assignFinalMaterial(I), g.push(I);
1370
+ } else C !== "TRANSLATION" && C !== "ROTATION" && C !== "SCALE" && p.geometry.setAttribute(C, A[C]);
1371
+ He.prototype.copy.call(I, p), this.parser.assignFinalMaterial(I), u.push(I);
1372
1372
  }
1373
- return l.isGroup ? (l.clear(), l.add(...g), l) : g[0];
1373
+ return l.isGroup ? (l.clear(), l.add(...u), l) : u[0];
1374
1374
  }));
1375
1375
  }
1376
1376
  }
1377
- const Ei = "glTF", Qe = 12, qt = { JSON: 1313821514, BIN: 5130562 };
1377
+ const Ei = "glTF", Se = 12, qt = { JSON: 1313821514, BIN: 5130562 };
1378
1378
  class mo {
1379
1379
  constructor(e) {
1380
- this.name = S.KHR_BINARY_GLTF, this.content = null, this.body = null;
1381
- const t = new DataView(e, 0, Qe), i = new TextDecoder();
1380
+ this.name = Q.KHR_BINARY_GLTF, this.content = null, this.body = null;
1381
+ const t = new DataView(e, 0, Se), i = new TextDecoder();
1382
1382
  if (this.header = {
1383
1383
  magic: i.decode(new Uint8Array(e.slice(0, 4))),
1384
1384
  version: t.getUint32(4, !0),
@@ -1387,17 +1387,17 @@ class mo {
1387
1387
  throw new Error("THREE.GLTFLoader: Unsupported glTF-Binary header.");
1388
1388
  if (this.header.version < 2)
1389
1389
  throw new Error("THREE.GLTFLoader: Legacy binary file detected.");
1390
- const s = this.header.length - Qe, o = new DataView(e, Qe);
1390
+ const s = this.header.length - Se, o = new DataView(e, Se);
1391
1391
  let n = 0;
1392
1392
  for (; n < s; ) {
1393
1393
  const r = o.getUint32(n, !0);
1394
1394
  n += 4;
1395
1395
  const A = o.getUint32(n, !0);
1396
1396
  if (n += 4, A === qt.JSON) {
1397
- const a = new Uint8Array(e, Qe + n, r);
1397
+ const a = new Uint8Array(e, Se + n, r);
1398
1398
  this.content = i.decode(a);
1399
1399
  } else if (A === qt.BIN) {
1400
- const a = Qe + n;
1400
+ const a = Se + n;
1401
1401
  this.body = e.slice(a, a + r);
1402
1402
  }
1403
1403
  n += r;
@@ -1410,7 +1410,7 @@ class bo {
1410
1410
  constructor(e, t) {
1411
1411
  if (!t)
1412
1412
  throw new Error("THREE.GLTFLoader: No DRACOLoader instance provided.");
1413
- this.name = S.KHR_DRACO_MESH_COMPRESSION, this.json = e, this.dracoLoader = t, this.dracoLoader.preload();
1413
+ this.name = Q.KHR_DRACO_MESH_COMPRESSION, this.json = e, this.dracoLoader = t, this.dracoLoader.preload();
1414
1414
  }
1415
1415
  decodePrimitive(e, t) {
1416
1416
  const i = this.json, s = this.dracoLoader, o = e.extensions[this.name].bufferView, n = e.extensions[this.name].attributes, r = {}, A = {}, a = {};
@@ -1421,18 +1421,18 @@ class bo {
1421
1421
  for (const l in e.attributes) {
1422
1422
  const h = bt[l] || l.toLowerCase();
1423
1423
  if (n[l] !== void 0) {
1424
- const d = i.accessors[e.attributes[l]], g = Ee[d.componentType];
1425
- a[h] = g.name, A[h] = d.normalized === !0;
1424
+ const d = i.accessors[e.attributes[l]], u = Ee[d.componentType];
1425
+ a[h] = u.name, A[h] = d.normalized === !0;
1426
1426
  }
1427
1427
  }
1428
1428
  return t.getDependency("bufferView", o).then(function(l) {
1429
1429
  return new Promise(function(h, d) {
1430
- s.decodeDracoFile(l, function(g) {
1431
- for (const p in g.attributes) {
1432
- const C = g.attributes[p], E = A[p];
1433
- E !== void 0 && (C.normalized = E);
1430
+ s.decodeDracoFile(l, function(u) {
1431
+ for (const p in u.attributes) {
1432
+ const b = u.attributes[p], E = A[p];
1433
+ E !== void 0 && (b.normalized = E);
1434
1434
  }
1435
- h(g);
1435
+ h(u);
1436
1436
  }, r, a, Y, d);
1437
1437
  });
1438
1438
  });
@@ -1440,7 +1440,7 @@ class bo {
1440
1440
  }
1441
1441
  class Co {
1442
1442
  constructor() {
1443
- this.name = S.KHR_TEXTURE_TRANSFORM;
1443
+ this.name = Q.KHR_TEXTURE_TRANSFORM;
1444
1444
  }
1445
1445
  extendTexture(e, t) {
1446
1446
  return (t.texCoord === void 0 || t.texCoord === e.channel) && t.offset === void 0 && t.rotation === void 0 && t.scale === void 0 || (e = e.clone(), t.texCoord !== void 0 && (e.channel = t.texCoord), t.offset !== void 0 && e.offset.fromArray(t.offset), t.rotation !== void 0 && (e.rotation = t.rotation), t.scale !== void 0 && e.repeat.fromArray(t.scale), e.needsUpdate = !0), e;
@@ -1448,7 +1448,7 @@ class Co {
1448
1448
  }
1449
1449
  class Eo {
1450
1450
  constructor() {
1451
- this.name = S.KHR_MESH_QUANTIZATION;
1451
+ this.name = Q.KHR_MESH_QUANTIZATION;
1452
1452
  }
1453
1453
  }
1454
1454
  class Ii extends Es {
@@ -1462,15 +1462,15 @@ class Ii extends Es {
1462
1462
  return t;
1463
1463
  }
1464
1464
  interpolate_(e, t, i, s) {
1465
- const o = this.resultBuffer, n = this.sampleValues, r = this.valueSize, A = r * 2, a = r * 3, l = s - t, h = (i - t) / l, d = h * h, g = d * h, p = e * a, C = p - a, E = -2 * g + 3 * d, f = g - d, m = 1 - E, I = f - d + h;
1466
- for (let b = 0; b !== r; b++) {
1467
- const B = n[C + b + r], y = n[C + b + A] * l, w = n[p + b + r], L = n[p + b] * l;
1468
- o[b] = m * B + I * y + E * w + f * L;
1465
+ const o = this.resultBuffer, n = this.sampleValues, r = this.valueSize, A = r * 2, a = r * 3, l = s - t, h = (i - t) / l, d = h * h, u = d * h, p = e * a, b = p - a, E = -2 * u + 3 * d, f = u - d, m = 1 - E, I = f - d + h;
1466
+ for (let C = 0; C !== r; C++) {
1467
+ const B = n[b + C + r], y = n[b + C + A] * l, w = n[p + C + r], M = n[p + C] * l;
1468
+ o[C] = m * B + I * y + E * w + f * M;
1469
1469
  }
1470
1470
  return o;
1471
1471
  }
1472
1472
  }
1473
- const Io = new Ue();
1473
+ const Io = new Ve();
1474
1474
  class Bo extends Ii {
1475
1475
  interpolate_(e, t, i, s) {
1476
1476
  const o = super.interpolate_(e, t, i, s);
@@ -1498,7 +1498,7 @@ const j = {
1498
1498
  9984: ts,
1499
1499
  9985: es,
1500
1500
  9986: $i,
1501
- 9987: He
1501
+ 9987: qe
1502
1502
  }, Kt = {
1503
1503
  33071: ss,
1504
1504
  33648: is,
@@ -1531,7 +1531,7 @@ const j = {
1531
1531
  CUBICSPLINE: void 0,
1532
1532
  // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each
1533
1533
  // keyframe track will be initialized with a default interpolation type, then modified.
1534
- LINEAR: gi,
1534
+ LINEAR: ui,
1535
1535
  STEP: bs
1536
1536
  }, Xe = {
1537
1537
  OPAQUE: "OPAQUE",
@@ -1556,7 +1556,7 @@ function ae(c, e, t) {
1556
1556
  function ie(c, e) {
1557
1557
  e.extras !== void 0 && (typeof e.extras == "object" ? Object.assign(c.userData, e.extras) : console.warn("THREE.GLTFLoader: Ignoring primitive type .extras, " + e.extras));
1558
1558
  }
1559
- function Qo(c, e, t) {
1559
+ function So(c, e, t) {
1560
1560
  let i = !1, s = !1, o = !1;
1561
1561
  for (let a = 0, l = e.length; a < l; a++) {
1562
1562
  const h = e[a];
@@ -1588,7 +1588,7 @@ function Qo(c, e, t) {
1588
1588
  return i && (c.morphAttributes.position = l), s && (c.morphAttributes.normal = h), o && (c.morphAttributes.color = d), c.morphTargetsRelative = !0, c;
1589
1589
  });
1590
1590
  }
1591
- function So(c, e) {
1591
+ function Qo(c, e) {
1592
1592
  if (c.updateMorphTargets(), e.weights !== void 0)
1593
1593
  for (let t = 0, i = e.weights.length; t < i; t++)
1594
1594
  c.morphTargetInfluences[t] = e.weights[t];
@@ -1604,7 +1604,7 @@ function So(c, e) {
1604
1604
  }
1605
1605
  function Mo(c) {
1606
1606
  let e;
1607
- const t = c.extensions && c.extensions[S.KHR_DRACO_MESH_COMPRESSION];
1607
+ const t = c.extensions && c.extensions[Q.KHR_DRACO_MESH_COMPRESSION];
1608
1608
  if (t ? e = "draco:" + t.bufferView + ":" + t.indices + ":" + Ze(t.attributes) : e = c.indices + ":" + Ze(c.attributes) + ":" + c.mode, c.targets !== void 0)
1609
1609
  for (let i = 0, s = c.targets.length; i < s; i++)
1610
1610
  e += ":" + Ze(c.targets[i]);
@@ -1631,10 +1631,10 @@ function Ct(c) {
1631
1631
  throw new Error("THREE.GLTFLoader: Unsupported normalized accessor component type.");
1632
1632
  }
1633
1633
  }
1634
- function xo(c) {
1634
+ function vo(c) {
1635
1635
  return c.search(/\.jpe?g($|\?)/i) > 0 || c.search(/^data\:image\/jpeg/) === 0 ? "image/jpeg" : c.search(/\.webp($|\?)/i) > 0 || c.search(/^data\:image\/webp/) === 0 ? "image/webp" : c.search(/\.ktx2($|\?)/i) > 0 || c.search(/^data\:image\/ktx2/) === 0 ? "image/ktx2" : "image/png";
1636
1636
  }
1637
- const vo = new Ie();
1637
+ const xo = new Ie();
1638
1638
  class Ro {
1639
1639
  constructor(e = {}, t = {}) {
1640
1640
  this.json = e, this.extensions = {}, this.plugins = {}, this.options = t, this.cache = new Xs(), this.associations = /* @__PURE__ */ new Map(), this.primitiveCache = {}, this.nodeCache = {}, this.meshCache = { refs: {}, uses: {} }, this.cameraCache = { refs: {}, uses: {} }, this.lightCache = { refs: {}, uses: {} }, this.sourceCache = {}, this.textureCache = {}, this.nodeNamesUsed = {};
@@ -1853,10 +1853,10 @@ class Ro {
1853
1853
  if (t.type && t.type !== "arraybuffer")
1854
1854
  throw new Error("THREE.GLTFLoader: " + t.type + " buffer type is not supported.");
1855
1855
  if (t.uri === void 0 && e === 0)
1856
- return Promise.resolve(this.extensions[S.KHR_BINARY_GLTF].body);
1856
+ return Promise.resolve(this.extensions[Q.KHR_BINARY_GLTF].body);
1857
1857
  const s = this.options;
1858
1858
  return new Promise(function(o, n) {
1859
- i.load(ve.resolveURL(t.uri, s.path), o, void 0, function() {
1859
+ i.load(xe.resolveURL(t.uri, s.path), o, void 0, function() {
1860
1860
  n(new Error('THREE.GLTFLoader: Failed to load buffer "' + t.uri + '".'));
1861
1861
  });
1862
1862
  });
@@ -1890,18 +1890,18 @@ class Ro {
1890
1890
  }
1891
1891
  const o = [];
1892
1892
  return s.bufferView !== void 0 ? o.push(this.getDependency("bufferView", s.bufferView)) : o.push(null), s.sparse !== void 0 && (o.push(this.getDependency("bufferView", s.sparse.indices.bufferView)), o.push(this.getDependency("bufferView", s.sparse.values.bufferView))), Promise.all(o).then(function(n) {
1893
- const r = n[0], A = We[s.type], a = Ee[s.componentType], l = a.BYTES_PER_ELEMENT, h = l * A, d = s.byteOffset || 0, g = s.bufferView !== void 0 ? i.bufferViews[s.bufferView].byteStride : void 0, p = s.normalized === !0;
1894
- let C, E;
1895
- if (g && g !== h) {
1896
- const f = Math.floor(d / g), m = "InterleavedBuffer:" + s.bufferView + ":" + s.componentType + ":" + f + ":" + s.count;
1893
+ const r = n[0], A = We[s.type], a = Ee[s.componentType], l = a.BYTES_PER_ELEMENT, h = l * A, d = s.byteOffset || 0, u = s.bufferView !== void 0 ? i.bufferViews[s.bufferView].byteStride : void 0, p = s.normalized === !0;
1894
+ let b, E;
1895
+ if (u && u !== h) {
1896
+ const f = Math.floor(d / u), m = "InterleavedBuffer:" + s.bufferView + ":" + s.componentType + ":" + f + ":" + s.count;
1897
1897
  let I = t.cache.get(m);
1898
- I || (C = new a(r, f * g, s.count * g / l), I = new Zi(C, g / l), t.cache.add(m, I)), E = new Ae(I, A, d % g / l, p);
1898
+ I || (b = new a(r, f * u, s.count * u / l), I = new Zi(b, u / l), t.cache.add(m, I)), E = new Ae(I, A, d % u / l, p);
1899
1899
  } else
1900
- r === null ? C = new a(s.count * A) : C = new a(r, d, s.count * A), E = new Re(C, A, p);
1900
+ r === null ? b = new a(s.count * A) : b = new a(r, d, s.count * A), E = new Re(b, A, p);
1901
1901
  if (s.sparse !== void 0) {
1902
- const f = We.SCALAR, m = Ee[s.sparse.indices.componentType], I = s.sparse.indices.byteOffset || 0, b = s.sparse.values.byteOffset || 0, B = new m(n[1], I, s.sparse.count * f), y = new a(n[2], b, s.sparse.count * A);
1902
+ const f = We.SCALAR, m = Ee[s.sparse.indices.componentType], I = s.sparse.indices.byteOffset || 0, C = s.sparse.values.byteOffset || 0, B = new m(n[1], I, s.sparse.count * f), y = new a(n[2], C, s.sparse.count * A);
1903
1903
  r !== null && (E = new Re(E.array.slice(), E.itemSize, E.normalized)), E.normalized = !1;
1904
- for (let w = 0, L = B.length; w < L; w++) {
1904
+ for (let w = 0, M = B.length; w < M; w++) {
1905
1905
  const D = B[w];
1906
1906
  if (E.setX(D, y[w * A]), A >= 2 && E.setY(D, y[w * A + 1]), A >= 3 && E.setZ(D, y[w * A + 2]), A >= 4 && E.setW(D, y[w * A + 3]), A >= 5) throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.");
1907
1907
  }
@@ -1933,7 +1933,7 @@ class Ro {
1933
1933
  const a = this.loadImageSource(t, i).then(function(l) {
1934
1934
  l.flipY = !1, l.name = n.name || r.name || "", l.name === "" && typeof r.uri == "string" && r.uri.startsWith("data:image/") === !1 && (l.name = r.uri);
1935
1935
  const d = (o.samplers || {})[n.sampler] || {};
1936
- return l.magFilter = jt[d.magFilter] || he, l.minFilter = jt[d.minFilter] || He, l.wrapS = Kt[d.wrapS] || dt, l.wrapT = Kt[d.wrapT] || dt, l.generateMipmaps = !l.isCompressedTexture && l.minFilter !== hi && l.minFilter !== he, s.associations.set(l, { textures: e }), l;
1936
+ return l.magFilter = jt[d.magFilter] || he, l.minFilter = jt[d.minFilter] || qe, l.wrapS = Kt[d.wrapS] || dt, l.wrapT = Kt[d.wrapT] || dt, l.generateMipmaps = !l.isCompressedTexture && l.minFilter !== hi && l.minFilter !== he, s.associations.set(l, { textures: e }), l;
1937
1937
  }).catch(function() {
1938
1938
  return null;
1939
1939
  });
@@ -1954,15 +1954,15 @@ class Ro {
1954
1954
  else if (n.uri === void 0)
1955
1955
  throw new Error("THREE.GLTFLoader: Image " + e + " is missing URI and bufferView");
1956
1956
  const l = Promise.resolve(A).then(function(h) {
1957
- return new Promise(function(d, g) {
1957
+ return new Promise(function(d, u) {
1958
1958
  let p = d;
1959
- t.isImageBitmapLoader === !0 && (p = function(C) {
1960
- const E = new Tt(C);
1959
+ t.isImageBitmapLoader === !0 && (p = function(b) {
1960
+ const E = new Lt(b);
1961
1961
  E.needsUpdate = !0, d(E);
1962
- }), t.load(ve.resolveURL(h, o.path), p, void 0, g);
1962
+ }), t.load(xe.resolveURL(h, o.path), p, void 0, u);
1963
1963
  });
1964
1964
  }).then(function(h) {
1965
- return a === !0 && r.revokeObjectURL(A), ie(h, n), h.userData.mimeType = n.mimeType || xo(n.uri), h;
1965
+ return a === !0 && r.revokeObjectURL(A), ie(h, n), h.userData.mimeType = n.mimeType || vo(n.uri), h;
1966
1966
  }).catch(function(h) {
1967
1967
  throw console.error("THREE.GLTFLoader: Couldn't load texture", A), h;
1968
1968
  });
@@ -1982,11 +1982,11 @@ class Ro {
1982
1982
  const o = this;
1983
1983
  return this.getDependency("texture", i.index).then(function(n) {
1984
1984
  if (!n) return null;
1985
- if (i.texCoord !== void 0 && i.texCoord > 0 && (n = n.clone(), n.channel = i.texCoord), o.extensions[S.KHR_TEXTURE_TRANSFORM]) {
1986
- const r = i.extensions !== void 0 ? i.extensions[S.KHR_TEXTURE_TRANSFORM] : void 0;
1985
+ if (i.texCoord !== void 0 && i.texCoord > 0 && (n = n.clone(), n.channel = i.texCoord), o.extensions[Q.KHR_TEXTURE_TRANSFORM]) {
1986
+ const r = i.extensions !== void 0 ? i.extensions[Q.KHR_TEXTURE_TRANSFORM] : void 0;
1987
1987
  if (r) {
1988
1988
  const A = o.associations.get(n);
1989
- n = o.extensions[S.KHR_TEXTURE_TRANSFORM].extendTexture(n, r), o.associations.set(n, A);
1989
+ n = o.extensions[Q.KHR_TEXTURE_TRANSFORM].extendTexture(n, r), o.associations.set(n, A);
1990
1990
  }
1991
1991
  }
1992
1992
  return s !== void 0 && (n.colorSpace = s), e[t] = n, n;
@@ -2037,8 +2037,8 @@ class Ro {
2037
2037
  const t = this, i = this.json, s = this.extensions, o = i.materials[e];
2038
2038
  let n;
2039
2039
  const r = {}, A = o.extensions || {}, a = [];
2040
- if (A[S.KHR_MATERIALS_UNLIT]) {
2041
- const h = s[S.KHR_MATERIALS_UNLIT];
2040
+ if (A[Q.KHR_MATERIALS_UNLIT]) {
2041
+ const h = s[Q.KHR_MATERIALS_UNLIT];
2042
2042
  n = h.getMaterialType(), a.push(h.extendParams(r, o, t));
2043
2043
  } else {
2044
2044
  const h = o.pbrMetallicRoughness || {};
@@ -2090,7 +2090,7 @@ class Ro {
2090
2090
  loadGeometries(e) {
2091
2091
  const t = this, i = this.extensions, s = this.primitiveCache;
2092
2092
  function o(r) {
2093
- return i[S.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(r, t).then(function(A) {
2093
+ return i[Q.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(r, t).then(function(A) {
2094
2094
  return zt(A, r, t);
2095
2095
  });
2096
2096
  }
@@ -2101,7 +2101,7 @@ class Ro {
2101
2101
  n.push(h.promise);
2102
2102
  else {
2103
2103
  let d;
2104
- a.extensions && a.extensions[S.KHR_DRACO_MESH_COMPRESSION] ? d = o(a) : d = zt(new di(), a, t), s[l] = { primitive: a, promise: d }, n.push(d);
2104
+ a.extensions && a.extensions[Q.KHR_DRACO_MESH_COMPRESSION] ? d = o(a) : d = zt(new di(), a, t), s[l] = { primitive: a, promise: d }, n.push(d);
2105
2105
  }
2106
2106
  }
2107
2107
  return Promise.all(n);
@@ -2121,35 +2121,35 @@ class Ro {
2121
2121
  }
2122
2122
  return r.push(t.loadGeometries(n)), Promise.all(r).then(function(A) {
2123
2123
  const a = A.slice(0, A.length - 1), l = A[A.length - 1], h = [];
2124
- for (let g = 0, p = l.length; g < p; g++) {
2125
- const C = l[g], E = n[g];
2124
+ for (let u = 0, p = l.length; u < p; u++) {
2125
+ const b = l[u], E = n[u];
2126
2126
  let f;
2127
- const m = a[g];
2127
+ const m = a[u];
2128
2128
  if (E.mode === j.TRIANGLES || E.mode === j.TRIANGLE_STRIP || E.mode === j.TRIANGLE_FAN || E.mode === void 0)
2129
- f = o.isSkinnedMesh === !0 ? new As(C, m) : new Qt(C, m), f.isSkinnedMesh === !0 && f.normalizeSkinWeights(), E.mode === j.TRIANGLE_STRIP ? f.geometry = Ht(f.geometry, li) : E.mode === j.TRIANGLE_FAN && (f.geometry = Ht(f.geometry, ht));
2129
+ f = o.isSkinnedMesh === !0 ? new As(b, m) : new St(b, m), f.isSkinnedMesh === !0 && f.normalizeSkinWeights(), E.mode === j.TRIANGLE_STRIP ? f.geometry = Ht(f.geometry, li) : E.mode === j.TRIANGLE_FAN && (f.geometry = Ht(f.geometry, ht));
2130
2130
  else if (E.mode === j.LINES)
2131
- f = new ls(C, m);
2131
+ f = new ls(b, m);
2132
2132
  else if (E.mode === j.LINE_STRIP)
2133
- f = new cs(C, m);
2133
+ f = new cs(b, m);
2134
2134
  else if (E.mode === j.LINE_LOOP)
2135
- f = new hs(C, m);
2135
+ f = new hs(b, m);
2136
2136
  else if (E.mode === j.POINTS)
2137
- f = new ds(C, m);
2137
+ f = new ds(b, m);
2138
2138
  else
2139
2139
  throw new Error("THREE.GLTFLoader: Primitive mode unsupported: " + E.mode);
2140
- Object.keys(f.geometry.morphAttributes).length > 0 && So(f, o), f.name = t.createUniqueName(o.name || "mesh_" + e), ie(f, o), E.extensions && ae(s, f, E), t.assignFinalMaterial(f), h.push(f);
2140
+ Object.keys(f.geometry.morphAttributes).length > 0 && Qo(f, o), f.name = t.createUniqueName(o.name || "mesh_" + e), ie(f, o), E.extensions && ae(s, f, E), t.assignFinalMaterial(f), h.push(f);
2141
2141
  }
2142
- for (let g = 0, p = h.length; g < p; g++)
2143
- t.associations.set(h[g], {
2142
+ for (let u = 0, p = h.length; u < p; u++)
2143
+ t.associations.set(h[u], {
2144
2144
  meshes: e,
2145
- primitives: g
2145
+ primitives: u
2146
2146
  });
2147
2147
  if (h.length === 1)
2148
2148
  return o.extensions && ae(s, h[0], o), h[0];
2149
2149
  const d = new Ye();
2150
2150
  o.extensions && ae(s, d, o), t.associations.set(d, { meshes: e });
2151
- for (let g = 0, p = h.length; g < p; g++)
2152
- d.add(h[g]);
2151
+ for (let u = 0, p = h.length; u < p; u++)
2152
+ d.add(h[u]);
2153
2153
  return d;
2154
2154
  });
2155
2155
  }
@@ -2167,7 +2167,7 @@ class Ro {
2167
2167
  console.warn("THREE.GLTFLoader: Missing camera parameters.");
2168
2168
  return;
2169
2169
  }
2170
- return i.type === "perspective" ? t = new gs(Bt.radToDeg(s.yfov), s.aspectRatio || 1, s.znear || 1, s.zfar || 2e6) : i.type === "orthographic" && (t = new us(-s.xmag, s.xmag, s.ymag, -s.ymag, s.znear, s.zfar)), i.name && (t.name = this.createUniqueName(i.name)), ie(t, i), Promise.resolve(t);
2170
+ return i.type === "perspective" ? t = new us(Bt.radToDeg(s.yfov), s.aspectRatio || 1, s.znear || 1, s.zfar || 2e6) : i.type === "orthographic" && (t = new gs(-s.xmag, s.xmag, s.ymag, -s.ymag, s.znear, s.zfar)), i.name && (t.name = this.createUniqueName(i.name)), ie(t, i), Promise.resolve(t);
2171
2171
  }
2172
2172
  /**
2173
2173
  * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins
@@ -2204,8 +2204,8 @@ class Ro {
2204
2204
  loadAnimation(e) {
2205
2205
  const t = this.json, i = this, s = t.animations[e], o = s.name ? s.name : "animation_" + e, n = [], r = [], A = [], a = [], l = [];
2206
2206
  for (let h = 0, d = s.channels.length; h < d; h++) {
2207
- const g = s.channels[h], p = s.samplers[g.sampler], C = g.target, E = C.node, f = s.parameters !== void 0 ? s.parameters[p.input] : p.input, m = s.parameters !== void 0 ? s.parameters[p.output] : p.output;
2208
- C.node !== void 0 && (n.push(this.getDependency("node", E)), r.push(this.getDependency("accessor", f)), A.push(this.getDependency("accessor", m)), a.push(p), l.push(C));
2207
+ const u = s.channels[h], p = s.samplers[u.sampler], b = u.target, E = b.node, f = s.parameters !== void 0 ? s.parameters[p.input] : p.input, m = s.parameters !== void 0 ? s.parameters[p.output] : p.output;
2208
+ b.node !== void 0 && (n.push(this.getDependency("node", E)), r.push(this.getDependency("accessor", f)), A.push(this.getDependency("accessor", m)), a.push(p), l.push(b));
2209
2209
  }
2210
2210
  return Promise.all([
2211
2211
  Promise.all(n),
@@ -2214,15 +2214,15 @@ class Ro {
2214
2214
  Promise.all(a),
2215
2215
  Promise.all(l)
2216
2216
  ]).then(function(h) {
2217
- const d = h[0], g = h[1], p = h[2], C = h[3], E = h[4], f = [];
2217
+ const d = h[0], u = h[1], p = h[2], b = h[3], E = h[4], f = [];
2218
2218
  for (let m = 0, I = d.length; m < I; m++) {
2219
- const b = d[m], B = g[m], y = p[m], w = C[m], L = E[m];
2220
- if (b === void 0) continue;
2221
- b.updateMatrix && b.updateMatrix();
2222
- const D = i._createAnimationTracks(b, B, y, w, L);
2219
+ const C = d[m], B = u[m], y = p[m], w = b[m], M = E[m];
2220
+ if (C === void 0) continue;
2221
+ C.updateMatrix && C.updateMatrix();
2222
+ const D = i._createAnimationTracks(C, B, y, w, M);
2223
2223
  if (D)
2224
- for (let Q = 0; Q < D.length; Q++)
2225
- f.push(D[Q]);
2224
+ for (let S = 0; S < D.length; S++)
2225
+ f.push(D[S]);
2226
2226
  }
2227
2227
  return new fs(o, void 0, f);
2228
2228
  });
@@ -2256,11 +2256,11 @@ class Ro {
2256
2256
  A
2257
2257
  ]).then(function(a) {
2258
2258
  const l = a[0], h = a[1], d = a[2];
2259
- d !== null && l.traverse(function(g) {
2260
- g.isSkinnedMesh && g.bind(d, vo);
2259
+ d !== null && l.traverse(function(u) {
2260
+ u.isSkinnedMesh && u.bind(d, xo);
2261
2261
  });
2262
- for (let g = 0, p = h.length; g < p; g++)
2263
- l.add(h[g]);
2262
+ for (let u = 0, p = h.length; u < p; u++)
2263
+ l.add(h[u]);
2264
2264
  return l;
2265
2265
  });
2266
2266
  }
@@ -2281,7 +2281,7 @@ class Ro {
2281
2281
  r.push(a);
2282
2282
  }), this.nodeCache[e] = Promise.all(r).then(function(a) {
2283
2283
  let l;
2284
- if (o.isBone === !0 ? l = new ms() : a.length > 1 ? l = new Ye() : a.length === 1 ? l = a[0] : l = new Oe(), l !== a[0])
2284
+ if (o.isBone === !0 ? l = new ms() : a.length > 1 ? l = new Ye() : a.length === 1 ? l = a[0] : l = new He(), l !== a[0])
2285
2285
  for (let h = 0, d = a.length; h < d; h++)
2286
2286
  l.add(a[h]);
2287
2287
  if (o.name && (l.userData.name = o.name, l.name = n), ie(l, o), o.extensions && ae(i, l, o), o.matrix !== void 0) {
@@ -2316,11 +2316,11 @@ class Ro {
2316
2316
  o.add(A[l]);
2317
2317
  const a = (l) => {
2318
2318
  const h = /* @__PURE__ */ new Map();
2319
- for (const [d, g] of s.associations)
2320
- (d instanceof ze || d instanceof Tt) && h.set(d, g);
2319
+ for (const [d, u] of s.associations)
2320
+ (d instanceof ze || d instanceof Lt) && h.set(d, u);
2321
2321
  return l.traverse((d) => {
2322
- const g = s.associations.get(d);
2323
- g != null && h.set(d, g);
2322
+ const u = s.associations.get(d);
2323
+ u != null && h.set(d, u);
2324
2324
  }), h;
2325
2325
  };
2326
2326
  return s.associations = a(o), o;
@@ -2334,30 +2334,30 @@ class Ro {
2334
2334
  let a;
2335
2335
  switch (ne[o.path]) {
2336
2336
  case ne.weights:
2337
- a = Ft;
2337
+ a = kt;
2338
2338
  break;
2339
2339
  case ne.rotation:
2340
- a = kt;
2340
+ a = Ft;
2341
2341
  break;
2342
2342
  case ne.translation:
2343
2343
  case ne.scale:
2344
- a = Lt;
2344
+ a = Tt;
2345
2345
  break;
2346
2346
  default:
2347
2347
  switch (i.itemSize) {
2348
2348
  case 1:
2349
- a = Ft;
2349
+ a = kt;
2350
2350
  break;
2351
2351
  case 2:
2352
2352
  case 3:
2353
2353
  default:
2354
- a = Lt;
2354
+ a = Tt;
2355
2355
  break;
2356
2356
  }
2357
2357
  break;
2358
2358
  }
2359
- const l = s.interpolation !== void 0 ? yo[s.interpolation] : gi, h = this._getArrayFromAccessor(i);
2360
- for (let d = 0, g = A.length; d < g; d++) {
2359
+ const l = s.interpolation !== void 0 ? yo[s.interpolation] : ui, h = this._getArrayFromAccessor(i);
2360
+ for (let d = 0, u = A.length; d < u; d++) {
2361
2361
  const p = new a(
2362
2362
  A[d] + "." + ne[o.path],
2363
2363
  t.array,
@@ -2380,19 +2380,19 @@ class Ro {
2380
2380
  }
2381
2381
  _createCubicSplineTrackInterpolant(e) {
2382
2382
  e.createInterpolant = function(i) {
2383
- const s = this instanceof kt ? Bo : Ii;
2383
+ const s = this instanceof Ft ? Bo : Ii;
2384
2384
  return new s(this.times, this.values, this.getValueSize() / 3, i);
2385
2385
  }, e.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = !0;
2386
2386
  }
2387
2387
  }
2388
2388
  function Do(c, e, t) {
2389
- const i = e.attributes, s = new qe();
2389
+ const i = e.attributes, s = new je();
2390
2390
  if (i.POSITION !== void 0) {
2391
2391
  const r = t.json.accessors[i.POSITION], A = r.min, a = r.max;
2392
2392
  if (A !== void 0 && a !== void 0) {
2393
2393
  if (s.set(
2394
- new R(A[0], A[1], A[2]),
2395
- new R(a[0], a[1], a[2])
2394
+ new L(A[0], A[1], A[2]),
2395
+ new L(a[0], a[1], a[2])
2396
2396
  ), r.normalized) {
2397
2397
  const l = Ct(Ee[r.componentType]);
2398
2398
  s.min.multiplyScalar(l), s.max.multiplyScalar(l);
@@ -2405,15 +2405,15 @@ function Do(c, e, t) {
2405
2405
  return;
2406
2406
  const o = e.targets;
2407
2407
  if (o !== void 0) {
2408
- const r = new R(), A = new R();
2408
+ const r = new L(), A = new L();
2409
2409
  for (let a = 0, l = o.length; a < l; a++) {
2410
2410
  const h = o[a];
2411
2411
  if (h.POSITION !== void 0) {
2412
- const d = t.json.accessors[h.POSITION], g = d.min, p = d.max;
2413
- if (g !== void 0 && p !== void 0) {
2414
- if (A.setX(Math.max(Math.abs(g[0]), Math.abs(p[0]))), A.setY(Math.max(Math.abs(g[1]), Math.abs(p[1]))), A.setZ(Math.max(Math.abs(g[2]), Math.abs(p[2]))), d.normalized) {
2415
- const C = Ct(Ee[d.componentType]);
2416
- A.multiplyScalar(C);
2412
+ const d = t.json.accessors[h.POSITION], u = d.min, p = d.max;
2413
+ if (u !== void 0 && p !== void 0) {
2414
+ if (A.setX(Math.max(Math.abs(u[0]), Math.abs(p[0]))), A.setY(Math.max(Math.abs(u[1]), Math.abs(p[1]))), A.setZ(Math.max(Math.abs(u[2]), Math.abs(p[2]))), d.normalized) {
2415
+ const b = Ct(Ee[d.componentType]);
2416
+ A.multiplyScalar(b);
2417
2417
  }
2418
2418
  r.max(A);
2419
2419
  } else
@@ -2423,7 +2423,7 @@ function Do(c, e, t) {
2423
2423
  s.expandByVector(r);
2424
2424
  }
2425
2425
  c.boundingBox = s;
2426
- const n = new St();
2426
+ const n = new Qt();
2427
2427
  s.getCenter(n.center), n.radius = s.min.distanceTo(s.max) / 2, c.boundingSphere = n;
2428
2428
  }
2429
2429
  function zt(c, e, t) {
@@ -2443,12 +2443,12 @@ function zt(c, e, t) {
2443
2443
  });
2444
2444
  s.push(n);
2445
2445
  }
2446
- return gt.workingColorSpace !== Y && "COLOR_0" in i && console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${gt.workingColorSpace}" not supported.`), ie(c, e), Do(c, e, t), Promise.all(s).then(function() {
2447
- return e.targets !== void 0 ? Qo(c, e.targets, t) : c;
2446
+ return ut.workingColorSpace !== Y && "COLOR_0" in i && console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${ut.workingColorSpace}" not supported.`), ie(c, e), Do(c, e, t), Promise.all(s).then(function() {
2447
+ return e.targets !== void 0 ? So(c, e.targets, t) : c;
2448
2448
  });
2449
2449
  }
2450
2450
  const $e = /* @__PURE__ */ new WeakMap();
2451
- class To extends yt {
2451
+ class Lo extends yt {
2452
2452
  /**
2453
2453
  * Constructs a new Draco loader.
2454
2454
  *
@@ -2567,7 +2567,7 @@ class To extends yt {
2567
2567
  if (t !== se) return;
2568
2568
  const i = new re();
2569
2569
  for (let s = 0, o = e.count; s < o; s++)
2570
- i.fromBufferAttribute(e, s), gt.colorSpaceToWorking(i, se), e.setXYZ(s, i.r, i.g, i.b);
2570
+ i.fromBufferAttribute(e, s), ut.colorSpaceToWorking(i, se), e.setXYZ(s, i.r, i.g, i.b);
2571
2571
  }
2572
2572
  _loadLibrary(e, t) {
2573
2573
  const i = new le(this.manager);
@@ -2584,7 +2584,7 @@ class To extends yt {
2584
2584
  return e ? t.push(this._loadLibrary("draco_decoder.js", "text")) : (t.push(this._loadLibrary("draco_wasm_wrapper.js", "text")), t.push(this._loadLibrary("draco_decoder.wasm", "arraybuffer"))), this.decoderPending = Promise.all(t).then((i) => {
2585
2585
  const s = i[0];
2586
2586
  e || (this.decoderConfig.wasmBinary = i[1]);
2587
- const o = Lo.toString(), n = [
2587
+ const o = To.toString(), n = [
2588
2588
  "/* draco decoder */",
2589
2589
  s,
2590
2590
  "",
@@ -2632,7 +2632,7 @@ class To extends yt {
2632
2632
  return this.workerPool.length = 0, this.workerSourceURL !== "" && URL.revokeObjectURL(this.workerSourceURL), this;
2633
2633
  }
2634
2634
  }
2635
- function Lo() {
2635
+ function To() {
2636
2636
  let c, e;
2637
2637
  onmessage = function(n) {
2638
2638
  const r = n.data;
@@ -2649,10 +2649,10 @@ function Lo() {
2649
2649
  e.then((l) => {
2650
2650
  const h = l.draco, d = new h.Decoder();
2651
2651
  try {
2652
- const g = t(h, d, new Int8Array(A), a), p = g.attributes.map((C) => C.array.buffer);
2653
- g.index && p.push(g.index.array.buffer), self.postMessage({ type: "decode", id: r.id, geometry: g }, p);
2654
- } catch (g) {
2655
- console.error(g), self.postMessage({ type: "error", id: r.id, error: g.message });
2652
+ const u = t(h, d, new Int8Array(A), a), p = u.attributes.map((b) => b.array.buffer);
2653
+ u.index && p.push(u.index.array.buffer), self.postMessage({ type: "decode", id: r.id, geometry: u }, p);
2654
+ } catch (u) {
2655
+ console.error(u), self.postMessage({ type: "error", id: r.id, error: u.message });
2656
2656
  } finally {
2657
2657
  h.destroy(d);
2658
2658
  }
@@ -2662,17 +2662,17 @@ function Lo() {
2662
2662
  };
2663
2663
  function t(n, r, A, a) {
2664
2664
  const l = a.attributeIDs, h = a.attributeTypes;
2665
- let d, g;
2665
+ let d, u;
2666
2666
  const p = r.GetEncodedGeometryType(A);
2667
2667
  if (p === n.TRIANGULAR_MESH)
2668
- d = new n.Mesh(), g = r.DecodeArrayToMesh(A, A.byteLength, d);
2668
+ d = new n.Mesh(), u = r.DecodeArrayToMesh(A, A.byteLength, d);
2669
2669
  else if (p === n.POINT_CLOUD)
2670
- d = new n.PointCloud(), g = r.DecodeArrayToPointCloud(A, A.byteLength, d);
2670
+ d = new n.PointCloud(), u = r.DecodeArrayToPointCloud(A, A.byteLength, d);
2671
2671
  else
2672
2672
  throw new Error("THREE.DRACOLoader: Unexpected geometry type.");
2673
- if (!g.ok() || d.ptr === 0)
2674
- throw new Error("THREE.DRACOLoader: Decoding failed: " + g.error_msg());
2675
- const C = { index: null, attributes: [] };
2673
+ if (!u.ok() || d.ptr === 0)
2674
+ throw new Error("THREE.DRACOLoader: Decoding failed: " + u.error_msg());
2675
+ const b = { index: null, attributes: [] };
2676
2676
  for (const E in l) {
2677
2677
  const f = self[h[E]];
2678
2678
  let m, I;
@@ -2682,20 +2682,20 @@ function Lo() {
2682
2682
  if (I = r.GetAttributeId(d, n[l[E]]), I === -1) continue;
2683
2683
  m = r.GetAttribute(d, I);
2684
2684
  }
2685
- const b = s(n, r, d, E, f, m);
2686
- E === "color" && (b.vertexColorSpace = a.vertexColorSpace), C.attributes.push(b);
2685
+ const C = s(n, r, d, E, f, m);
2686
+ E === "color" && (C.vertexColorSpace = a.vertexColorSpace), b.attributes.push(C);
2687
2687
  }
2688
- return p === n.TRIANGULAR_MESH && (C.index = i(n, r, d)), n.destroy(d), C;
2688
+ return p === n.TRIANGULAR_MESH && (b.index = i(n, r, d)), n.destroy(d), b;
2689
2689
  }
2690
2690
  function i(n, r, A) {
2691
2691
  const l = A.num_faces() * 3, h = l * 4, d = n._malloc(h);
2692
2692
  r.GetTrianglesUInt32Array(A, h, d);
2693
- const g = new Uint32Array(n.HEAPF32.buffer, d, l).slice();
2694
- return n._free(d), { array: g, itemSize: 1 };
2693
+ const u = new Uint32Array(n.HEAPF32.buffer, d, l).slice();
2694
+ return n._free(d), { array: u, itemSize: 1 };
2695
2695
  }
2696
2696
  function s(n, r, A, a, l, h) {
2697
- const d = h.num_components(), p = A.num_points() * d, C = p * l.BYTES_PER_ELEMENT, E = o(n, l), f = n._malloc(C);
2698
- r.GetAttributeDataArrayForAllPoints(A, h, E, C, f);
2697
+ const d = h.num_components(), p = A.num_points() * d, b = p * l.BYTES_PER_ELEMENT, E = o(n, l), f = n._malloc(b);
2698
+ r.GetAttributeDataArrayForAllPoints(A, h, E, b, f);
2699
2699
  const m = new l(n.HEAPF32.buffer, f, p).slice();
2700
2700
  return n._free(f), {
2701
2701
  name: a,
@@ -2722,7 +2722,7 @@ function Lo() {
2722
2722
  }
2723
2723
  }
2724
2724
  }
2725
- class Fo {
2725
+ class ko {
2726
2726
  /**
2727
2727
  * Constructs a new Worker pool.
2728
2728
  *
@@ -2788,13 +2788,13 @@ class Fo {
2788
2788
  this.workers.forEach((e) => e.terminate()), this.workersResolve.length = 0, this.workers.length = 0, this.queue.length = 0, this.workerStatus = 0;
2789
2789
  }
2790
2790
  }
2791
- const ko = 0, Yt = 2, _o = 1, Jt = 2, Go = 0, Po = 1, No = 10, Uo = 0, Bi = 9, yi = 15, wi = 16, Qi = 22, Si = 37, Mi = 43, xi = 76, vi = 83, Ri = 97, Di = 100, Ti = 103, Li = 109, Vo = 131, Oo = 132, Ho = 133, qo = 134, jo = 137, Ko = 138, zo = 141, Yo = 142, Jo = 145, Wo = 146, Fi = 148, ki = 152, Xo = 157, Zo = 158, _i = 165, Gi = 166, vt = 1000066e3;
2791
+ const Fo = 0, Yt = 2, _o = 1, Jt = 2, Go = 0, Po = 1, No = 10, Uo = 0, Bi = 9, yi = 15, wi = 16, Si = 22, Qi = 37, Mi = 43, vi = 76, xi = 83, Ri = 97, Di = 100, Li = 103, Ti = 109, Vo = 131, Oo = 132, Ho = 133, qo = 134, jo = 137, Ko = 138, zo = 141, Yo = 142, Jo = 145, Wo = 146, ki = 148, Fi = 152, Xo = 157, Zo = 158, _i = 165, Gi = 166, xt = 1000066e3;
2792
2792
  class $o {
2793
2793
  constructor() {
2794
2794
  this.vkFormat = 0, this.typeSize = 1, this.pixelWidth = 0, this.pixelHeight = 0, this.pixelDepth = 0, this.layerCount = 0, this.faceCount = 1, this.supercompressionScheme = 0, this.levels = [], this.dataFormatDescriptor = [{ vendorId: 0, descriptorType: 0, descriptorBlockSize: 0, versionNumber: 2, colorModel: 0, colorPrimaries: 1, transferFunction: 2, flags: 0, texelBlockDimension: [0, 0, 0, 0], bytesPlane: [0, 0, 0, 0, 0, 0, 0, 0], samples: [] }], this.keyValue = {}, this.globalData = null;
2795
2795
  }
2796
2796
  }
2797
- class Se {
2797
+ class Qe {
2798
2798
  constructor(e, t, i, s) {
2799
2799
  this._dataView = void 0, this._littleEndian = void 0, this._offset = void 0, this._dataView = new DataView(e.buffer, e.byteOffset + t, i), this._littleEndian = s, this._offset = 0;
2800
2800
  }
@@ -2840,32 +2840,32 @@ function Wt(c) {
2840
2840
  function en(c) {
2841
2841
  const e = new Uint8Array(c.buffer, c.byteOffset, N.length);
2842
2842
  if (e[0] !== N[0] || e[1] !== N[1] || e[2] !== N[2] || e[3] !== N[3] || e[4] !== N[4] || e[5] !== N[5] || e[6] !== N[6] || e[7] !== N[7] || e[8] !== N[8] || e[9] !== N[9] || e[10] !== N[10] || e[11] !== N[11]) throw new Error("Missing KTX 2.0 identifier.");
2843
- const t = new $o(), i = 17 * Uint32Array.BYTES_PER_ELEMENT, s = new Se(c, N.length, i, !0);
2843
+ const t = new $o(), i = 17 * Uint32Array.BYTES_PER_ELEMENT, s = new Qe(c, N.length, i, !0);
2844
2844
  t.vkFormat = s._nextUint32(), t.typeSize = s._nextUint32(), t.pixelWidth = s._nextUint32(), t.pixelHeight = s._nextUint32(), t.pixelDepth = s._nextUint32(), t.layerCount = s._nextUint32(), t.faceCount = s._nextUint32();
2845
2845
  const o = s._nextUint32();
2846
2846
  t.supercompressionScheme = s._nextUint32();
2847
- const n = s._nextUint32(), r = s._nextUint32(), A = s._nextUint32(), a = s._nextUint32(), l = s._nextUint64(), h = s._nextUint64(), d = new Se(c, N.length + i, 3 * o * 8, !0);
2848
- for (let F = 0; F < o; F++) t.levels.push({ levelData: new Uint8Array(c.buffer, c.byteOffset + d._nextUint64(), d._nextUint64()), uncompressedByteLength: d._nextUint64() });
2849
- const g = new Se(c, n, r, !0), p = { vendorId: g._skip(4)._nextUint16(), descriptorType: g._nextUint16(), versionNumber: g._nextUint16(), descriptorBlockSize: g._nextUint16(), colorModel: g._nextUint8(), colorPrimaries: g._nextUint8(), transferFunction: g._nextUint8(), flags: g._nextUint8(), texelBlockDimension: [g._nextUint8(), g._nextUint8(), g._nextUint8(), g._nextUint8()], bytesPlane: [g._nextUint8(), g._nextUint8(), g._nextUint8(), g._nextUint8(), g._nextUint8(), g._nextUint8(), g._nextUint8(), g._nextUint8()], samples: [] }, C = (p.descriptorBlockSize / 4 - 6) / 4;
2850
- for (let F = 0; F < C; F++) {
2851
- const H = { bitOffset: g._nextUint16(), bitLength: g._nextUint8(), channelType: g._nextUint8(), samplePosition: [g._nextUint8(), g._nextUint8(), g._nextUint8(), g._nextUint8()], sampleLower: -1 / 0, sampleUpper: 1 / 0 };
2852
- 64 & H.channelType ? (H.sampleLower = g._nextInt32(), H.sampleUpper = g._nextInt32()) : (H.sampleLower = g._nextUint32(), H.sampleUpper = g._nextUint32()), p.samples[F] = H;
2847
+ const n = s._nextUint32(), r = s._nextUint32(), A = s._nextUint32(), a = s._nextUint32(), l = s._nextUint64(), h = s._nextUint64(), d = new Qe(c, N.length + i, 3 * o * 8, !0);
2848
+ for (let k = 0; k < o; k++) t.levels.push({ levelData: new Uint8Array(c.buffer, c.byteOffset + d._nextUint64(), d._nextUint64()), uncompressedByteLength: d._nextUint64() });
2849
+ const u = new Qe(c, n, r, !0), p = { vendorId: u._skip(4)._nextUint16(), descriptorType: u._nextUint16(), versionNumber: u._nextUint16(), descriptorBlockSize: u._nextUint16(), colorModel: u._nextUint8(), colorPrimaries: u._nextUint8(), transferFunction: u._nextUint8(), flags: u._nextUint8(), texelBlockDimension: [u._nextUint8(), u._nextUint8(), u._nextUint8(), u._nextUint8()], bytesPlane: [u._nextUint8(), u._nextUint8(), u._nextUint8(), u._nextUint8(), u._nextUint8(), u._nextUint8(), u._nextUint8(), u._nextUint8()], samples: [] }, b = (p.descriptorBlockSize / 4 - 6) / 4;
2850
+ for (let k = 0; k < b; k++) {
2851
+ const H = { bitOffset: u._nextUint16(), bitLength: u._nextUint8(), channelType: u._nextUint8(), samplePosition: [u._nextUint8(), u._nextUint8(), u._nextUint8(), u._nextUint8()], sampleLower: -1 / 0, sampleUpper: 1 / 0 };
2852
+ 64 & H.channelType ? (H.sampleLower = u._nextInt32(), H.sampleUpper = u._nextInt32()) : (H.sampleLower = u._nextUint32(), H.sampleUpper = u._nextUint32()), p.samples[k] = H;
2853
2853
  }
2854
2854
  t.dataFormatDescriptor.length = 0, t.dataFormatDescriptor.push(p);
2855
- const E = new Se(c, A, a, !0);
2855
+ const E = new Qe(c, A, a, !0);
2856
2856
  for (; E._offset < a; ) {
2857
- const F = E._nextUint32(), H = E._scan(F), oe = Wt(H);
2858
- if (t.keyValue[oe] = E._nextUint8Array(F - H.byteLength - 1), oe.match(/^ktx/i)) {
2857
+ const k = E._nextUint32(), H = E._scan(k), oe = Wt(H);
2858
+ if (t.keyValue[oe] = E._nextUint8Array(k - H.byteLength - 1), oe.match(/^ktx/i)) {
2859
2859
  const we = Wt(t.keyValue[oe]);
2860
2860
  t.keyValue[oe] = we.substring(0, we.lastIndexOf("\0"));
2861
2861
  }
2862
- E._skip(F % 4 ? 4 - F % 4 : 0);
2862
+ E._skip(k % 4 ? 4 - k % 4 : 0);
2863
2863
  }
2864
2864
  if (h <= 0) return t;
2865
- const f = new Se(c, l, h, !0), m = f._nextUint16(), I = f._nextUint16(), b = f._nextUint32(), B = f._nextUint32(), y = f._nextUint32(), w = f._nextUint32(), L = [];
2866
- for (let F = 0; F < o; F++) L.push({ imageFlags: f._nextUint32(), rgbSliceByteOffset: f._nextUint32(), rgbSliceByteLength: f._nextUint32(), alphaSliceByteOffset: f._nextUint32(), alphaSliceByteLength: f._nextUint32() });
2867
- const D = l + f._offset, Q = D + b, v = Q + B, M = v + y, J = new Uint8Array(c.buffer, c.byteOffset + D, b), W = new Uint8Array(c.buffer, c.byteOffset + Q, B), ye = new Uint8Array(c.buffer, c.byteOffset + v, y), q = new Uint8Array(c.buffer, c.byteOffset + M, w);
2868
- return t.globalData = { endpointCount: m, selectorCount: I, imageDescs: L, endpointsData: J, selectorsData: W, tablesData: ye, extendedData: q }, t;
2865
+ const f = new Qe(c, l, h, !0), m = f._nextUint16(), I = f._nextUint16(), C = f._nextUint32(), B = f._nextUint32(), y = f._nextUint32(), w = f._nextUint32(), M = [];
2866
+ for (let k = 0; k < o; k++) M.push({ imageFlags: f._nextUint32(), rgbSliceByteOffset: f._nextUint32(), rgbSliceByteLength: f._nextUint32(), alphaSliceByteOffset: f._nextUint32(), alphaSliceByteLength: f._nextUint32() });
2867
+ const D = l + f._offset, S = D + C, R = S + B, v = R + y, J = new Uint8Array(c.buffer, c.byteOffset + D, C), W = new Uint8Array(c.buffer, c.byteOffset + S, B), ye = new Uint8Array(c.buffer, c.byteOffset + R, y), q = new Uint8Array(c.buffer, c.byteOffset + v, w);
2868
+ return t.globalData = { endpointCount: m, selectorCount: I, imageDescs: M, endpointsData: J, selectorsData: W, tablesData: ye, extendedData: q }, t;
2869
2869
  }
2870
2870
  let et, te, Et;
2871
2871
  const tt = { env: { emscripten_notify_memory_growth: function(c) {
@@ -2895,7 +2895,7 @@ class K extends yt {
2895
2895
  * @param {LoadingManager} [manager] - The loading manager.
2896
2896
  */
2897
2897
  constructor(e) {
2898
- super(e), this.transcoderPath = "", this.transcoderBinary = null, this.transcoderPending = null, this.workerPool = new Fo(), this.workerSourceURL = "", this.workerConfig = null, typeof MSC_TRANSCODER < "u" && console.warn(
2898
+ super(e), this.transcoderPath = "", this.transcoderBinary = null, this.transcoderPending = null, this.workerPool = new ko(), this.workerSourceURL = "", this.workerConfig = null, typeof MSC_TRANSCODER < "u" && console.warn(
2899
2899
  'THREE.KTX2Loader: Please update to latest "basis_transcoder". "msc_basis_transcoder" is no longer supported in three.js r125+.'
2900
2900
  );
2901
2901
  }
@@ -3036,9 +3036,9 @@ class K extends yt {
3036
3036
  h = new Is(o, A, a);
3037
3037
  else {
3038
3038
  const d = o[0].mipmaps;
3039
- h = t.layerCount > 1 ? new Bs(d, n, r, t.layerCount, A, a) : new ui(d, n, r, A, a);
3039
+ h = t.layerCount > 1 ? new Bs(d, n, r, t.layerCount, A, a) : new gi(d, n, r, A, a);
3040
3040
  }
3041
- return h.minFilter = o[0].mipmaps.length === 1 ? he : He, h.magFilter = he, h.generateMipmaps = !1, h.needsUpdate = !0, h.colorSpace = Pi(t), h.premultiplyAlpha = !!(l & _o), h;
3041
+ return h.minFilter = o[0].mipmaps.length === 1 ? he : qe, h.magFilter = he, h.generateMipmaps = !1, h.needsUpdate = !0, h.colorSpace = Pi(t), h.premultiplyAlpha = !!(l & _o), h;
3042
3042
  }
3043
3043
  /**
3044
3044
  * @private
@@ -3047,7 +3047,7 @@ class K extends yt {
3047
3047
  * @return {Promise<CompressedTexture|CompressedArrayTexture|DataTexture|Data3DTexture>}
3048
3048
  */
3049
3049
  async _createTexture(e, t = {}) {
3050
- const i = en(new Uint8Array(e)), s = i.vkFormat === vt && i.dataFormatDescriptor[0].colorModel === 167;
3050
+ const i = en(new Uint8Array(e)), s = i.vkFormat === xt && i.dataFormatDescriptor[0].colorModel === 167;
3051
3051
  if (!(i.vkFormat === Uo || s && !this.workerConfig.astcHDRSupported))
3052
3052
  return rn(i);
3053
3053
  const n = t, r = this.init().then(() => this.workerPool.postMessage({ type: "transcode", buffer: e, taskConfig: n }, [e])).then((A) => this._createTextureFrom(A.data, i));
@@ -3090,15 +3090,15 @@ K.TranscoderFormat = {
3090
3090
  };
3091
3091
  K.EngineFormat = {
3092
3092
  RGBAFormat: me,
3093
- RGBA_ASTC_4x4_Format: Ge,
3094
- RGB_BPTC_UNSIGNED_Format: xs,
3095
- RGBA_BPTC_Format: ut,
3093
+ RGBA_ASTC_4x4_Format: Pe,
3094
+ RGB_BPTC_UNSIGNED_Format: vs,
3095
+ RGBA_BPTC_Format: gt,
3096
3096
  RGBA_ETC2_EAC_Format: pi,
3097
3097
  RGBA_PVRTC_4BPPV1_Format: Ms,
3098
3098
  RGBA_S3TC_DXT5_Format: pt,
3099
- RGB_ETC1_Format: Ss,
3099
+ RGB_ETC1_Format: Qs,
3100
3100
  RGB_ETC2_Format: fi,
3101
- RGB_PVRTC_4BPPV1_Format: Qs,
3101
+ RGB_PVRTC_4BPPV1_Format: Ss,
3102
3102
  RGBA_S3TC_DXT1_Format: ft
3103
3103
  };
3104
3104
  K.EngineType = {
@@ -3110,72 +3110,72 @@ K.BasisWorker = function() {
3110
3110
  let c, e, t;
3111
3111
  const i = _EngineFormat, s = _EngineType, o = _TranscoderFormat, n = _BasisFormat;
3112
3112
  self.addEventListener("message", function(p) {
3113
- const C = p.data;
3114
- switch (C.type) {
3113
+ const b = p.data;
3114
+ switch (b.type) {
3115
3115
  case "init":
3116
- c = C.config, r(C.transcoderBinary);
3116
+ c = b.config, r(b.transcoderBinary);
3117
3117
  break;
3118
3118
  case "transcode":
3119
3119
  e.then(() => {
3120
3120
  try {
3121
- const { faces: E, buffers: f, width: m, height: I, hasAlpha: b, format: B, type: y, dfdFlags: w } = A(C.buffer);
3122
- self.postMessage({ type: "transcode", id: C.id, data: { faces: E, width: m, height: I, hasAlpha: b, format: B, type: y, dfdFlags: w } }, f);
3121
+ const { faces: E, buffers: f, width: m, height: I, hasAlpha: C, format: B, type: y, dfdFlags: w } = A(b.buffer);
3122
+ self.postMessage({ type: "transcode", id: b.id, data: { faces: E, width: m, height: I, hasAlpha: C, format: B, type: y, dfdFlags: w } }, f);
3123
3123
  } catch (E) {
3124
- console.error(E), self.postMessage({ type: "error", id: C.id, error: E.message });
3124
+ console.error(E), self.postMessage({ type: "error", id: b.id, error: E.message });
3125
3125
  }
3126
3126
  });
3127
3127
  break;
3128
3128
  }
3129
3129
  });
3130
3130
  function r(p) {
3131
- e = new Promise((C) => {
3132
- t = { wasmBinary: p, onRuntimeInitialized: C }, BASIS(t);
3131
+ e = new Promise((b) => {
3132
+ t = { wasmBinary: p, onRuntimeInitialized: b }, BASIS(t);
3133
3133
  }).then(() => {
3134
3134
  t.initializeBasis(), t.KTX2File === void 0 && console.warn("THREE.KTX2Loader: Please update Basis Universal transcoder.");
3135
3135
  });
3136
3136
  }
3137
3137
  function A(p) {
3138
- const C = new t.KTX2File(new Uint8Array(p));
3138
+ const b = new t.KTX2File(new Uint8Array(p));
3139
3139
  function E() {
3140
- C.close(), C.delete();
3140
+ b.close(), b.delete();
3141
3141
  }
3142
- if (!C.isValid())
3142
+ if (!b.isValid())
3143
3143
  throw E(), new Error("THREE.KTX2Loader: Invalid or unsupported .ktx2 file");
3144
3144
  let f;
3145
- if (C.isUASTC())
3145
+ if (b.isUASTC())
3146
3146
  f = n.UASTC;
3147
- else if (C.isETC1S())
3147
+ else if (b.isETC1S())
3148
3148
  f = n.ETC1S;
3149
- else if (C.isHDR())
3149
+ else if (b.isHDR())
3150
3150
  f = n.UASTC_HDR;
3151
3151
  else
3152
3152
  throw new Error("THREE.KTX2Loader: Unknown Basis encoding");
3153
- const m = C.getWidth(), I = C.getHeight(), b = C.getLayers() || 1, B = C.getLevels(), y = C.getFaces(), w = C.getHasAlpha(), L = C.getDFDFlags(), { transcoderFormat: D, engineFormat: Q, engineType: v } = h(f, m, I, w);
3153
+ const m = b.getWidth(), I = b.getHeight(), C = b.getLayers() || 1, B = b.getLevels(), y = b.getFaces(), w = b.getHasAlpha(), M = b.getDFDFlags(), { transcoderFormat: D, engineFormat: S, engineType: R } = h(f, m, I, w);
3154
3154
  if (!m || !I || !B)
3155
3155
  throw E(), new Error("THREE.KTX2Loader: Invalid texture");
3156
- if (!C.startTranscoding())
3156
+ if (!b.startTranscoding())
3157
3157
  throw E(), new Error("THREE.KTX2Loader: .startTranscoding failed");
3158
- const M = [], J = [];
3158
+ const v = [], J = [];
3159
3159
  for (let W = 0; W < y; W++) {
3160
3160
  const ye = [];
3161
3161
  for (let q = 0; q < B; q++) {
3162
- const F = [];
3162
+ const k = [];
3163
3163
  let H, oe;
3164
- for (let de = 0; de < b; de++) {
3165
- const ge = C.getImageLevelInfo(q, de, W);
3166
- W === 0 && q === 0 && de === 0 && (ge.origWidth % 4 !== 0 || ge.origHeight % 4 !== 0) && console.warn("THREE.KTX2Loader: ETC1S and UASTC textures should use multiple-of-four dimensions."), B > 1 ? (H = ge.origWidth, oe = ge.origHeight) : (H = ge.width, oe = ge.height);
3167
- let ue = new Uint8Array(C.getImageTranscodedSizeInBytes(q, de, 0, D));
3168
- const Vi = C.transcodeImage(ue, q, de, W, D, 0, -1, -1);
3169
- if (v === s.HalfFloatType && (ue = new Uint16Array(ue.buffer, ue.byteOffset, ue.byteLength / Uint16Array.BYTES_PER_ELEMENT)), !Vi)
3164
+ for (let de = 0; de < C; de++) {
3165
+ const ue = b.getImageLevelInfo(q, de, W);
3166
+ W === 0 && q === 0 && de === 0 && (ue.origWidth % 4 !== 0 || ue.origHeight % 4 !== 0) && console.warn("THREE.KTX2Loader: ETC1S and UASTC textures should use multiple-of-four dimensions."), B > 1 ? (H = ue.origWidth, oe = ue.origHeight) : (H = ue.width, oe = ue.height);
3167
+ let ge = new Uint8Array(b.getImageTranscodedSizeInBytes(q, de, 0, D));
3168
+ const Vi = b.transcodeImage(ge, q, de, W, D, 0, -1, -1);
3169
+ if (R === s.HalfFloatType && (ge = new Uint16Array(ge.buffer, ge.byteOffset, ge.byteLength / Uint16Array.BYTES_PER_ELEMENT)), !Vi)
3170
3170
  throw E(), new Error("THREE.KTX2Loader: .transcodeImage failed.");
3171
- F.push(ue);
3171
+ k.push(ge);
3172
3172
  }
3173
- const we = g(F);
3173
+ const we = u(k);
3174
3174
  ye.push({ data: we, width: H, height: oe }), J.push(we.buffer);
3175
3175
  }
3176
- M.push({ mipmaps: ye, width: m, height: I, format: Q, type: v });
3176
+ v.push({ mipmaps: ye, width: m, height: I, format: S, type: R });
3177
3177
  }
3178
- return E(), { faces: M, buffers: J, width: m, height: I, hasAlpha: w, dfdFlags: L, format: Q, type: v };
3178
+ return E(), { faces: v, buffers: J, width: m, height: I, hasAlpha: w, dfdFlags: M, format: S, type: R };
3179
3179
  }
3180
3180
  const a = [
3181
3181
  {
@@ -3270,16 +3270,16 @@ K.BasisWorker = function() {
3270
3270
  // a historical accident shown to avoid performance pitfalls for Linux with
3271
3271
  // Firefox & AMD GPU (RadeonSI). Further work needed.
3272
3272
  // See https://github.com/mrdoob/three.js/pull/29730.
3273
- [n.ETC1S]: a.filter((p) => p.basisFormat.includes(n.ETC1S)).sort((p, C) => p.priorityUASTC - C.priorityUASTC),
3274
- [n.UASTC]: a.filter((p) => p.basisFormat.includes(n.UASTC)).sort((p, C) => p.priorityUASTC - C.priorityUASTC),
3275
- [n.UASTC_HDR]: a.filter((p) => p.basisFormat.includes(n.UASTC_HDR)).sort((p, C) => p.priorityHDR - C.priorityHDR)
3273
+ [n.ETC1S]: a.filter((p) => p.basisFormat.includes(n.ETC1S)).sort((p, b) => p.priorityUASTC - b.priorityUASTC),
3274
+ [n.UASTC]: a.filter((p) => p.basisFormat.includes(n.UASTC)).sort((p, b) => p.priorityUASTC - b.priorityUASTC),
3275
+ [n.UASTC_HDR]: a.filter((p) => p.basisFormat.includes(n.UASTC_HDR)).sort((p, b) => p.priorityHDR - b.priorityHDR)
3276
3276
  };
3277
- function h(p, C, E, f) {
3277
+ function h(p, b, E, f) {
3278
3278
  const m = l[p];
3279
3279
  for (let I = 0; I < m.length; I++) {
3280
- const b = m[I];
3281
- if (b.if && !c[b.if] || !b.basisFormat.includes(p) || f && b.transcoderFormat.length < 2 || b.needsPowerOfTwo && !(d(C) && d(E))) continue;
3282
- const B = b.transcoderFormat[f ? 1 : 0], y = b.engineFormat[f ? 1 : 0], w = b.engineType[0];
3280
+ const C = m[I];
3281
+ if (C.if && !c[C.if] || !C.basisFormat.includes(p) || f && C.transcoderFormat.length < 2 || C.needsPowerOfTwo && !(d(b) && d(E))) continue;
3282
+ const B = C.transcoderFormat[f ? 1 : 0], y = C.engineFormat[f ? 1 : 0], w = C.engineType[0];
3283
3283
  return { transcoderFormat: B, engineFormat: y, engineType: w };
3284
3284
  }
3285
3285
  throw new Error("THREE.KTX2Loader: Failed to identify transcoding target.");
@@ -3287,14 +3287,14 @@ K.BasisWorker = function() {
3287
3287
  function d(p) {
3288
3288
  return p <= 2 ? !0 : (p & p - 1) === 0 && p !== 0;
3289
3289
  }
3290
- function g(p) {
3290
+ function u(p) {
3291
3291
  if (p.length === 1) return p[0];
3292
- let C = 0;
3292
+ let b = 0;
3293
3293
  for (let m = 0; m < p.length; m++) {
3294
3294
  const I = p[m];
3295
- C += I.byteLength;
3295
+ b += I.byteLength;
3296
3296
  }
3297
- const E = new Uint8Array(C);
3297
+ const E = new Uint8Array(b);
3298
3298
  let f = 0;
3299
3299
  for (let m = 0; m < p.length; m++) {
3300
3300
  const I = p[m];
@@ -3303,24 +3303,24 @@ K.BasisWorker = function() {
3303
3303
  return E;
3304
3304
  }
3305
3305
  };
3306
- const nn = /* @__PURE__ */ new Set([me, xe, Me]), nt = {
3307
- [Li]: me,
3306
+ const nn = /* @__PURE__ */ new Set([me, ve, Me]), nt = {
3307
+ [Ti]: me,
3308
3308
  [Ri]: me,
3309
- [Si]: me,
3309
+ [Qi]: me,
3310
3310
  [Mi]: me,
3311
- [Ti]: xe,
3312
- [vi]: xe,
3313
- [wi]: xe,
3314
- [Qi]: xe,
3311
+ [Li]: ve,
3312
+ [xi]: ve,
3313
+ [wi]: ve,
3314
+ [Si]: ve,
3315
3315
  [Di]: Me,
3316
- [xi]: Me,
3316
+ [vi]: Me,
3317
3317
  [yi]: Me,
3318
3318
  [Bi]: Me,
3319
- [Fi]: fi,
3320
- [ki]: pi,
3321
- [vt]: Ge,
3322
- [Zo]: Ge,
3323
- [Xo]: Ge,
3319
+ [ki]: fi,
3320
+ [Fi]: pi,
3321
+ [xt]: Pe,
3322
+ [Zo]: Pe,
3323
+ [Xo]: Pe,
3324
3324
  [Gi]: Nt,
3325
3325
  [_i]: Nt,
3326
3326
  [Ho]: ft,
@@ -3331,24 +3331,24 @@ const nn = /* @__PURE__ */ new Set([me, xe, Me]), nt = {
3331
3331
  [jo]: Gt,
3332
3332
  [Yo]: pt,
3333
3333
  [zo]: pt,
3334
- [Wo]: ut,
3335
- [Jo]: ut
3334
+ [Wo]: gt,
3335
+ [Jo]: gt
3336
3336
  }, rt = {
3337
- [Li]: De,
3337
+ [Ti]: De,
3338
3338
  [Ri]: be,
3339
- [Si]: z,
3339
+ [Qi]: z,
3340
3340
  [Mi]: z,
3341
- [Ti]: De,
3342
- [vi]: be,
3341
+ [Li]: De,
3342
+ [xi]: be,
3343
3343
  [wi]: z,
3344
- [Qi]: z,
3344
+ [Si]: z,
3345
3345
  [Di]: De,
3346
- [xi]: be,
3346
+ [vi]: be,
3347
3347
  [yi]: z,
3348
3348
  [Bi]: z,
3349
- [Fi]: z,
3350
3349
  [ki]: z,
3351
- [vt]: be,
3350
+ [Fi]: z,
3351
+ [xt]: be,
3352
3352
  [Gi]: z,
3353
3353
  [_i]: z
3354
3354
  };
@@ -3365,7 +3365,7 @@ async function rn(c) {
3365
3365
  for (let o = 0; o < c.levels.length; o++) {
3366
3366
  const n = Math.max(1, c.pixelWidth >> o), r = Math.max(1, c.pixelHeight >> o), A = c.pixelDepth ? Math.max(1, c.pixelDepth >> o) : 0, a = c.levels[o];
3367
3367
  let l;
3368
- if (c.supercompressionScheme === ko)
3368
+ if (c.supercompressionScheme === Fo)
3369
3369
  l = a.levelData;
3370
3370
  else if (c.supercompressionScheme === Yt)
3371
3371
  l = t.decode(a.levelData, a.uncompressedByteLength);
@@ -3392,7 +3392,7 @@ async function rn(c) {
3392
3392
  s = c.pixelDepth === 0 ? new ys(i[0].data, c.pixelWidth, c.pixelHeight) : new ws(i[0].data, c.pixelWidth, c.pixelHeight, c.pixelDepth);
3393
3393
  else {
3394
3394
  if (c.pixelDepth > 0) throw new Error("THREE.KTX2Loader: Unsupported pixelDepth.");
3395
- s = new ui(i, c.pixelWidth, c.pixelHeight), s.minFilter = i.length === 1 ? he : He, s.magFilter = he;
3395
+ s = new gi(i, c.pixelWidth, c.pixelHeight), s.minFilter = i.length === 1 ? he : qe, s.magFilter = he;
3396
3396
  }
3397
3397
  return s.mipmaps = i, s.type = rt[e], s.format = nt[e], s.colorSpace = Pi(c), s.needsUpdate = !0, Promise.resolve(s);
3398
3398
  }
@@ -3524,18 +3524,18 @@ var an = function() {
3524
3524
  });
3525
3525
  function r(f) {
3526
3526
  for (var m = new Uint8Array(f.length), I = 0; I < f.length; ++I) {
3527
- var b = f.charCodeAt(I);
3528
- m[I] = b > 96 ? b - 97 : b > 64 ? b - 39 : b + 4;
3527
+ var C = f.charCodeAt(I);
3528
+ m[I] = C > 96 ? C - 97 : C > 64 ? C - 39 : C + 4;
3529
3529
  }
3530
3530
  for (var B = 0, I = 0; I < f.length; ++I)
3531
3531
  m[B++] = m[I] < 60 ? i[m[I]] : (m[I] - 60) * 64 + m[++I];
3532
3532
  return m.buffer.slice(0, B);
3533
3533
  }
3534
- function A(f, m, I, b, B, y, w) {
3535
- var L = f.exports.sbrk, D = b + 3 & -4, Q = L(D * B), v = L(y.length), M = new Uint8Array(f.exports.memory.buffer);
3536
- M.set(y, v);
3537
- var J = m(Q, b, B, v, y.length);
3538
- if (J == 0 && w && w(Q, D, B), I.set(M.subarray(Q, Q + b * B)), L(Q - L(0)), J != 0)
3534
+ function A(f, m, I, C, B, y, w) {
3535
+ var M = f.exports.sbrk, D = C + 3 & -4, S = M(D * B), R = M(y.length), v = new Uint8Array(f.exports.memory.buffer);
3536
+ v.set(y, R);
3537
+ var J = m(S, C, B, R, y.length);
3538
+ if (J == 0 && w && w(S, D, B), I.set(v.subarray(S, S + C * B)), M(S - M(0)), J != 0)
3539
3539
  throw new Error("Malformed buffer data: " + J);
3540
3540
  }
3541
3541
  var a = {
@@ -3548,30 +3548,30 @@ var an = function() {
3548
3548
  TRIANGLES: "meshopt_decodeIndexBuffer",
3549
3549
  INDICES: "meshopt_decodeIndexSequence"
3550
3550
  }, h = [], d = 0;
3551
- function g(f) {
3551
+ function u(f) {
3552
3552
  var m = {
3553
3553
  object: new Worker(f),
3554
3554
  pending: 0,
3555
3555
  requests: {}
3556
3556
  };
3557
3557
  return m.object.onmessage = function(I) {
3558
- var b = I.data;
3559
- m.pending -= b.count, m.requests[b.id][b.action](b.value), delete m.requests[b.id];
3558
+ var C = I.data;
3559
+ m.pending -= C.count, m.requests[C.id][C.action](C.value), delete m.requests[C.id];
3560
3560
  }, m;
3561
3561
  }
3562
3562
  function p(f) {
3563
- for (var m = "self.ready = WebAssembly.instantiate(new Uint8Array([" + new Uint8Array(s) + "]), {}).then(function(result) { result.instance.exports.__wasm_call_ctors(); return result.instance; });self.onmessage = " + E.name + ";" + A.toString() + E.toString(), I = new Blob([m], { type: "text/javascript" }), b = URL.createObjectURL(I), B = h.length; B < f; ++B)
3564
- h[B] = g(b);
3563
+ for (var m = "self.ready = WebAssembly.instantiate(new Uint8Array([" + new Uint8Array(s) + "]), {}).then(function(result) { result.instance.exports.__wasm_call_ctors(); return result.instance; });self.onmessage = " + E.name + ";" + A.toString() + E.toString(), I = new Blob([m], { type: "text/javascript" }), C = URL.createObjectURL(I), B = h.length; B < f; ++B)
3564
+ h[B] = u(C);
3565
3565
  for (var B = f; B < h.length; ++B)
3566
3566
  h[B].object.postMessage({});
3567
- h.length = f, URL.revokeObjectURL(b);
3567
+ h.length = f, URL.revokeObjectURL(C);
3568
3568
  }
3569
- function C(f, m, I, b, B) {
3569
+ function b(f, m, I, C, B) {
3570
3570
  for (var y = h[0], w = 1; w < h.length; ++w)
3571
3571
  h[w].pending < y.pending && (y = h[w]);
3572
- return new Promise(function(L, D) {
3573
- var Q = new Uint8Array(I), v = ++d;
3574
- y.pending += f, y.requests[v] = { resolve: L, reject: D }, y.object.postMessage({ id: v, count: f, size: m, source: Q, mode: b, filter: B }, [Q.buffer]);
3572
+ return new Promise(function(M, D) {
3573
+ var S = new Uint8Array(I), R = ++d;
3574
+ y.pending += f, y.requests[R] = { resolve: M, reject: D }, y.object.postMessage({ id: R, count: f, size: m, source: S, mode: C, filter: B }, [S.buffer]);
3575
3575
  });
3576
3576
  }
3577
3577
  function E(f) {
@@ -3580,8 +3580,8 @@ var an = function() {
3580
3580
  return self.close();
3581
3581
  self.ready.then(function(I) {
3582
3582
  try {
3583
- var b = new Uint8Array(m.count * m.size);
3584
- A(I, I.exports[m.mode], b, m.count, m.size, m.source, I.exports[m.filter]), self.postMessage({ id: m.id, count: m.count, action: "resolve", value: b }, [b.buffer]);
3583
+ var C = new Uint8Array(m.count * m.size);
3584
+ A(I, I.exports[m.mode], C, m.count, m.size, m.source, I.exports[m.filter]), self.postMessage({ id: m.id, count: m.count, action: "resolve", value: C }, [C.buffer]);
3585
3585
  } catch (B) {
3586
3586
  self.postMessage({ id: m.id, count: m.count, action: "reject", value: B });
3587
3587
  }
@@ -3593,22 +3593,22 @@ var an = function() {
3593
3593
  useWorkers: function(f) {
3594
3594
  p(f);
3595
3595
  },
3596
- decodeVertexBuffer: function(f, m, I, b, B) {
3597
- A(o, o.exports.meshopt_decodeVertexBuffer, f, m, I, b, o.exports[a[B]]);
3596
+ decodeVertexBuffer: function(f, m, I, C, B) {
3597
+ A(o, o.exports.meshopt_decodeVertexBuffer, f, m, I, C, o.exports[a[B]]);
3598
3598
  },
3599
- decodeIndexBuffer: function(f, m, I, b) {
3600
- A(o, o.exports.meshopt_decodeIndexBuffer, f, m, I, b);
3599
+ decodeIndexBuffer: function(f, m, I, C) {
3600
+ A(o, o.exports.meshopt_decodeIndexBuffer, f, m, I, C);
3601
3601
  },
3602
- decodeIndexSequence: function(f, m, I, b) {
3603
- A(o, o.exports.meshopt_decodeIndexSequence, f, m, I, b);
3602
+ decodeIndexSequence: function(f, m, I, C) {
3603
+ A(o, o.exports.meshopt_decodeIndexSequence, f, m, I, C);
3604
3604
  },
3605
- decodeGltfBuffer: function(f, m, I, b, B, y) {
3606
- A(o, o.exports[l[B]], f, m, I, b, o.exports[a[y]]);
3605
+ decodeGltfBuffer: function(f, m, I, C, B, y) {
3606
+ A(o, o.exports[l[B]], f, m, I, C, o.exports[a[y]]);
3607
3607
  },
3608
- decodeGltfBufferAsync: function(f, m, I, b, B) {
3609
- return h.length > 0 ? C(f, m, I, l[b], a[B]) : n.then(function() {
3608
+ decodeGltfBufferAsync: function(f, m, I, C, B) {
3609
+ return h.length > 0 ? b(f, m, I, l[C], a[B]) : n.then(function() {
3610
3610
  var y = new Uint8Array(f * m);
3611
- return A(o, o.exports[l[b]], y, f, m, I, o.exports[a[B]]), y;
3611
+ return A(o, o.exports[l[C]], y, f, m, I, o.exports[a[B]]), y;
3612
3612
  });
3613
3613
  }
3614
3614
  };
@@ -3628,11 +3628,20 @@ function at(c) {
3628
3628
  });
3629
3629
  }
3630
3630
  function ln() {
3631
- u.Cache && typeof u.Cache.clear == "function" && u.Cache.clear();
3631
+ g.Cache && typeof g.Cache.clear == "function" && g.Cache.clear();
3632
3632
  }
3633
3633
  class O {
3634
3634
  constructor(e = null) {
3635
- this.renderer = e, this.isIOSWebKit = O.isIOSWebKit(), this.platformKey = O.getPlatformKey(), this.loader = new xt(), this.dracoLoader = new To(), this.ktx2Loader = null, this.loadQueue = Promise.resolve(), this.activeIOSLoad = !1, this.dracoLoader.setDecoderPath("https://www.gstatic.com/draco/versioned/decoders/1.5.6/"), this.isIOSWebKit && typeof this.dracoLoader.setWorkerLimit == "function" && this.dracoLoader.setWorkerLimit(1), this.loader.setDRACOLoader(this.dracoLoader), this.loader.setMeshoptDecoder(an), this.cache = /* @__PURE__ */ new Map(), this.ktx2SetupComplete = !1, this.setupKTX2Loader();
3635
+ this.renderer = e, this.isIOSWebKit = O.isIOSWebKit(), this.platformKey = O.getPlatformKey(), this.loader = new vt(), this.dracoLoader = new Lo(), this.ktx2Loader = null, this.loadQueue = Promise.resolve(), this.activeIOSLoad = !1, this.dracoLoader.setDecoderPath("https://www.gstatic.com/draco/versioned/decoders/1.5.6/"), this.isIOSWebKit && typeof this.dracoLoader.setWorkerLimit == "function" && this.dracoLoader.setWorkerLimit(1), this.loader.setDRACOLoader(this.dracoLoader), this.loader.setMeshoptDecoder(an), this.loader.register((t) => ({
3636
+ name: "KHR_materials_pbrSpecularGlossiness",
3637
+ extendMaterialParams: async (i, s) => {
3638
+ const o = t.json.materials[i];
3639
+ if (!o.extensions || !o.extensions.KHR_materials_pbrSpecularGlossiness)
3640
+ return Promise.resolve();
3641
+ const n = o.extensions.KHR_materials_pbrSpecularGlossiness;
3642
+ return n.diffuseTexture !== void 0 && (s.map = await t.getDependency("texture", n.diffuseTexture.index)), n.diffuseFactor !== void 0 && (s.color = new g.Color().fromArray(n.diffuseFactor)), n.glossinessFactor !== void 0 && (s.roughness = 1 - n.glossinessFactor), s.metalness = 0, Promise.resolve();
3643
+ }
3644
+ })), this.cache = /* @__PURE__ */ new Map(), this.ktx2SetupComplete = !1, this.setupKTX2Loader();
3636
3645
  }
3637
3646
  setupKTX2Loader() {
3638
3647
  const e = this.platformKey;
@@ -3716,16 +3725,23 @@ class O {
3716
3725
  const n = Array.isArray(o.material) ? o.material : [o.material];
3717
3726
  n.forEach((r, A) => {
3718
3727
  if (r.emissive && r.emissive.setHex(0), r.emissiveIntensity !== void 0 && (r.emissiveIntensity = 0), r.emissiveMap && (r.emissiveMap = null), r.lightMap && (r.lightMap = null), r.lightMapIntensity !== void 0 && (r.lightMapIntensity = 0), r.type === "MeshBasicMaterial" || r.type === "MeshPhongMaterial") {
3719
- const l = new u.MeshLambertMaterial({
3728
+ const l = new g.MeshStandardMaterial({
3720
3729
  // Only include common, safe params; set specialized textures conditionally below
3721
- color: r.color || new u.Color(16777215),
3722
- side: r.side !== void 0 ? r.side : u.FrontSide,
3730
+ color: r.color || new g.Color(16777215),
3731
+ side: r.side !== void 0 ? r.side : g.FrontSide,
3723
3732
  wireframe: r.wireframe || !1,
3724
3733
  vertexColors: r.vertexColors || !1,
3725
3734
  fog: r.fog !== void 0 ? r.fog : !0,
3726
- flatShading: !1
3735
+ flatShading: !1,
3736
+ // Realistic shipwreck appearance
3737
+ roughness: 0.8,
3738
+ // Weathered, corroded metal/wood
3739
+ metalness: 0.3
3740
+ // Mix of metal and non-metal
3727
3741
  });
3728
- r.map && (l.map = r.map), r.alphaMap && (l.alphaMap = r.alphaMap), r.aoMap && (l.aoMap = r.aoMap), typeof r.aoMapIntensity == "number" && (l.aoMapIntensity = r.aoMapIntensity), r.envMap && (l.envMap = r.envMap), typeof r.reflectivity == "number" && (l.reflectivity = r.reflectivity), typeof r.refractionRatio == "number" && (l.refractionRatio = r.refractionRatio), r.combine !== void 0 && (l.combine = r.combine), r.transparent !== void 0 && (l.transparent = r.transparent), typeof r.opacity == "number" && (l.opacity = r.opacity), r.normalMap && (l.normalMap = r.normalMap, l.normalScale = r.normalScale || new u.Vector2(1, 1)), l.map && i !== null && (l.map.anisotropy = i, l.map.needsUpdate = !0), l.normalMap && i !== null && (l.normalMap.anisotropy = i, l.normalMap.needsUpdate = !0), l.needsUpdate = !0, Array.isArray(o.material) ? o.material[A] = l : o.material = l, r !== l && typeof r?.dispose == "function" && r.dispose();
3742
+ r.map && (l.map = r.map), r.alphaMap && (l.alphaMap = r.alphaMap), r.aoMap && (l.aoMap = r.aoMap), typeof r.aoMapIntensity == "number" && (l.aoMapIntensity = r.aoMapIntensity), r.envMap && (l.envMap = r.envMap), r.roughnessMap && (l.roughnessMap = r.roughnessMap), r.metalnessMap && (l.metalnessMap = r.metalnessMap), r.transparent !== void 0 && (l.transparent = r.transparent), typeof r.opacity == "number" && (l.opacity = r.opacity), r.normalMap && (l.normalMap = r.normalMap, l.normalScale = r.normalScale || new g.Vector2(1, 1)), i !== null && ["map", "normalMap", "roughnessMap", "metalnessMap", "aoMap"].forEach((d) => {
3743
+ l[d] && (l[d].anisotropy = i, l[d].needsUpdate = !0);
3744
+ }), l.needsUpdate = !0, Array.isArray(o.material) ? o.material[A] = l : o.material = l, r !== l && typeof r?.dispose == "function" && r.dispose();
3729
3745
  } else (r.type === "MeshStandardMaterial" || r.type === "MeshPhysicalMaterial") && (i !== null && ["map", "normalMap", "roughnessMap", "metalnessMap", "aoMap", "emissiveMap"].forEach((h) => {
3730
3746
  r[h] && (r[h].anisotropy = i, r[h].needsUpdate = !0);
3731
3747
  }), r.needsUpdate = !0);
@@ -3734,7 +3750,7 @@ class O {
3734
3750
  }), o.geometry && (o.geometry.computeVertexNormals(), o.geometry.normalizeNormals(), n.some((A) => A.normalMap) && o.geometry.computeTangents());
3735
3751
  }
3736
3752
  });
3737
- const s = new u.Box3().setFromObject(t);
3753
+ const s = new g.Box3().setFromObject(t);
3738
3754
  return t.userData.boundingBox = s, t;
3739
3755
  }
3740
3756
  getMaxAnisotropy() {
@@ -3829,8 +3845,8 @@ class Be {
3829
3845
  const i = document.createElement("button");
3830
3846
  function s() {
3831
3847
  let a = null;
3832
- async function l(g) {
3833
- g.addEventListener("end", h), await e.xr.setSession(g), i.textContent = "EXIT VR", a = g;
3848
+ async function l(u) {
3849
+ u.addEventListener("end", h), await e.xr.setSession(u), i.textContent = "EXIT VR", a = u;
3834
3850
  }
3835
3851
  function h() {
3836
3852
  a.removeEventListener("end", h), i.textContent = "ENTER VR", a = null;
@@ -3850,11 +3866,11 @@ class Be {
3850
3866
  }, i.onmouseleave = function() {
3851
3867
  i.style.opacity = "0.5";
3852
3868
  }, i.onclick = function() {
3853
- a === null ? navigator.xr.requestSession("immersive-vr", d).then(l) : (a.end(), navigator.xr.offerSession !== void 0 && navigator.xr.offerSession("immersive-vr", d).then(l).catch((g) => {
3854
- console.warn(g);
3869
+ a === null ? navigator.xr.requestSession("immersive-vr", d).then(l) : (a.end(), navigator.xr.offerSession !== void 0 && navigator.xr.offerSession("immersive-vr", d).then(l).catch((u) => {
3870
+ console.warn(u);
3855
3871
  }));
3856
- }, navigator.xr.offerSession !== void 0 && navigator.xr.offerSession("immersive-vr", d).then(l).catch((g) => {
3857
- console.warn(g);
3872
+ }, navigator.xr.offerSession !== void 0 && navigator.xr.offerSession("immersive-vr", d).then(l).catch((u) => {
3873
+ console.warn(u);
3858
3874
  });
3859
3875
  }
3860
3876
  function o() {
@@ -4128,13 +4144,13 @@ async function dn(c, e, t = null, i = !0) {
4128
4144
  }
4129
4145
  return { profile: n, assetPath: r };
4130
4146
  }
4131
- const gn = {
4147
+ const un = {
4132
4148
  xAxis: 0,
4133
4149
  yAxis: 0,
4134
4150
  button: 0,
4135
4151
  state: T.ComponentState.DEFAULT
4136
4152
  };
4137
- function un(c = 0, e = 0) {
4153
+ function gn(c = 0, e = 0) {
4138
4154
  let t = c, i = e;
4139
4155
  if (Math.sqrt(c * c + e * e) > 1) {
4140
4156
  const n = Math.atan2(e, c);
@@ -4147,7 +4163,7 @@ function un(c = 0, e = 0) {
4147
4163
  }
4148
4164
  class pn {
4149
4165
  constructor(e) {
4150
- this.componentProperty = e.componentProperty, this.states = e.states, this.valueNodeName = e.valueNodeName, this.valueNodeProperty = e.valueNodeProperty, this.valueNodeProperty === T.VisualResponseProperty.TRANSFORM && (this.minNodeName = e.minNodeName, this.maxNodeName = e.maxNodeName), this.value = 0, this.updateFromComponent(gn);
4166
+ this.componentProperty = e.componentProperty, this.states = e.states, this.valueNodeName = e.valueNodeName, this.valueNodeProperty = e.valueNodeProperty, this.valueNodeProperty === T.VisualResponseProperty.TRANSFORM && (this.minNodeName = e.minNodeName, this.maxNodeName = e.maxNodeName), this.value = 0, this.updateFromComponent(un);
4151
4167
  }
4152
4168
  /**
4153
4169
  * Computes the visual response's interpolation weight based on component state
@@ -4163,7 +4179,7 @@ class pn {
4163
4179
  button: i,
4164
4180
  state: s
4165
4181
  }) {
4166
- const { normalizedXAxis: o, normalizedYAxis: n } = un(e, t);
4182
+ const { normalizedXAxis: o, normalizedYAxis: n } = gn(e, t);
4167
4183
  switch (this.componentProperty) {
4168
4184
  case T.ComponentProperty.X_AXIS:
4169
4185
  this.value = this.states.includes(s) ? o : 0.5;
@@ -4258,7 +4274,7 @@ class mn {
4258
4274
  }
4259
4275
  }
4260
4276
  const bn = "https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles", Cn = "generic-trigger";
4261
- class En extends Oe {
4277
+ class En extends He {
4262
4278
  /**
4263
4279
  * Constructs a new XR controller model.
4264
4280
  */
@@ -4305,7 +4321,7 @@ function In(c, e) {
4305
4321
  const { type: i, touchPointNodeName: s, visualResponses: o } = t;
4306
4322
  if (i === T.ComponentType.TOUCHPAD)
4307
4323
  if (t.touchPointNode = e.getObjectByName(s), t.touchPointNode) {
4308
- const n = new mi(1e-3), r = new fe({ color: 255 }), A = new Qt(n, r);
4324
+ const n = new mi(1e-3), r = new fe({ color: 255 }), A = new St(n, r);
4309
4325
  t.touchPointNode.add(A);
4310
4326
  } else
4311
4327
  console.warn(`Could not find touch dot, ${t.touchPointNodeName}, in touchpad component ${t.id}`);
@@ -4338,7 +4354,7 @@ class Bn {
4338
4354
  * @param {?Function} [onLoad=null] - A callback that is executed when a controller model has been loaded.
4339
4355
  */
4340
4356
  constructor(e = null, t = null) {
4341
- this.gltfLoader = e, this.path = bn, this._assetCache = {}, this.onLoad = t, this.gltfLoader || (this.gltfLoader = new xt());
4357
+ this.gltfLoader = e, this.path = bn, this._assetCache = {}, this.onLoad = t, this.gltfLoader || (this.gltfLoader = new vt());
4342
4358
  }
4343
4359
  /**
4344
4360
  * Sets the path to the model repository.
@@ -4394,9 +4410,9 @@ class Bn {
4394
4410
  class yn {
4395
4411
  constructor(e, t) {
4396
4412
  this.renderer = e, this.camera = t, this.controller1 = null, this.controller2 = null, this.controllerGrip1 = null, this.controllerGrip2 = null, this.controllers = [], this.controllerGrips = [], this.buttonStates = /* @__PURE__ */ new Map(), this.inputDeadzone = 0.15, this.turnSmoothingFactor = 0.1, this.lastTurnInput = 0, this.onSelectStart = null, this.onSelectEnd = null, this.onSqueezeStart = null, this.onSqueezeEnd = null, this.onModeToggle = null, this.onMovementStart = null, this.onMovementStop = null, this.handsActive = !1, this.handStates = {
4397
- left: { pinch: !1, fist: !1, direction: new u.Vector3() },
4398
- right: { pinch: !1, fist: !1, direction: new u.Vector3() }
4399
- };
4413
+ left: { pinch: !1, fist: !1, direction: new g.Vector3() },
4414
+ right: { pinch: !1, fist: !1, direction: new g.Vector3() }
4415
+ }, this._fallbackHandedness = /* @__PURE__ */ new Map();
4400
4416
  }
4401
4417
  init() {
4402
4418
  this.initControllers(), this.initHands();
@@ -4424,26 +4440,26 @@ class yn {
4424
4440
  if (!s || !o || !s.transform || !o.transform)
4425
4441
  this.handStates[i].pinch = !1;
4426
4442
  else {
4427
- const A = new u.Vector3().setFromMatrixPosition(new u.Matrix4().fromArray(s.transform.matrix)), a = new u.Vector3().setFromMatrixPosition(new u.Matrix4().fromArray(o.transform.matrix)), l = A.distanceTo(a);
4443
+ const A = new g.Vector3().setFromMatrixPosition(new g.Matrix4().fromArray(s.transform.matrix)), a = new g.Vector3().setFromMatrixPosition(new g.Matrix4().fromArray(o.transform.matrix)), l = A.distanceTo(a);
4428
4444
  this.handStates[i].pinch = l < 0.025;
4429
4445
  }
4430
4446
  let n = !0;
4431
4447
  const r = t.hand.get("wrist");
4432
4448
  if (r && r.transform) {
4433
- const A = new u.Vector3().setFromMatrixPosition(new u.Matrix4().fromArray(r.transform.matrix));
4449
+ const A = new g.Vector3().setFromMatrixPosition(new g.Matrix4().fromArray(r.transform.matrix));
4434
4450
  for (const a of ["index-finger-tip", "middle-finger-tip", "ring-finger-tip", "pinky-finger-tip"]) {
4435
4451
  const l = t.hand.get(a);
4436
4452
  if (!l || !l.transform) {
4437
4453
  n = !1;
4438
4454
  continue;
4439
4455
  }
4440
- new u.Vector3().setFromMatrixPosition(new u.Matrix4().fromArray(l.transform.matrix)).distanceTo(A) > 0.045 && (n = !1);
4456
+ new g.Vector3().setFromMatrixPosition(new g.Matrix4().fromArray(l.transform.matrix)).distanceTo(A) > 0.045 && (n = !1);
4441
4457
  }
4442
4458
  } else
4443
4459
  n = !1;
4444
4460
  if (this.handStates[i].fist = n, o && r && o.transform && r.transform) {
4445
- const A = new u.Vector3().setFromMatrixPosition(new u.Matrix4().fromArray(r.transform.matrix)), a = new u.Vector3().setFromMatrixPosition(new u.Matrix4().fromArray(o.transform.matrix));
4446
- this.handStates[i].direction = new u.Vector3().subVectors(a, A).normalize();
4461
+ const A = new g.Vector3().setFromMatrixPosition(new g.Matrix4().fromArray(r.transform.matrix)), a = new g.Vector3().setFromMatrixPosition(new g.Matrix4().fromArray(o.transform.matrix));
4462
+ this.handStates[i].direction = new g.Vector3().subVectors(a, A).normalize();
4447
4463
  }
4448
4464
  }
4449
4465
  }
@@ -4490,9 +4506,9 @@ class yn {
4490
4506
  this.onSqueezeEnd && this.onSqueezeEnd(i, e, t);
4491
4507
  }
4492
4508
  checkControllerButtons() {
4493
- const e = this.renderer.xr.getSession();
4494
- if (e) {
4495
- for (const t of e.inputSources)
4509
+ const e = this.getInputSources();
4510
+ if (!(!e || e.length === 0)) {
4511
+ for (const t of e)
4496
4512
  if (t.gamepad && t.handedness) {
4497
4513
  const i = t.gamepad, s = t.handedness, o = `debug-${s}`;
4498
4514
  this.buttonStates.get(o) || this.buttonStates.set(o, !0);
@@ -4507,20 +4523,20 @@ class yn {
4507
4523
  }
4508
4524
  }
4509
4525
  getControllerInput() {
4510
- const e = this.renderer.xr.getSession();
4511
- if (!e) return { movement: null, teleport: null };
4526
+ const e = this.getInputSources();
4527
+ if (!e || e.length === 0) return { movement: null, teleport: null };
4512
4528
  let t = null, i = null;
4513
- for (const s of e.inputSources)
4529
+ for (const s of e)
4514
4530
  if (s.gamepad && s.handedness) {
4515
4531
  const o = s.gamepad, n = s.handedness;
4516
4532
  if (o.axes.length >= 4) {
4517
- const r = o.axes[2] || 0, A = o.axes[3] || 0, a = o.axes[0] || 0, l = o.axes[1] || 0, h = Math.abs(r) > this.inputDeadzone ? r : 0, d = Math.abs(A) > this.inputDeadzone ? A : 0, g = Math.abs(a) > this.inputDeadzone ? a : 0, p = Math.abs(l) > this.inputDeadzone ? l : 0;
4533
+ const r = o.axes[2] || 0, A = o.axes[3] || 0, a = o.axes[0] || 0, l = o.axes[1] || 0, h = Math.abs(r) > this.inputDeadzone ? r : 0, d = Math.abs(A) > this.inputDeadzone ? A : 0, u = Math.abs(a) > this.inputDeadzone ? a : 0, p = Math.abs(l) > this.inputDeadzone ? l : 0;
4518
4534
  n === "left" ? (h !== 0 || d !== 0) && (t = {
4519
4535
  x: h,
4520
4536
  y: d,
4521
4537
  handedness: "left"
4522
- }) : n === "right" && (g !== 0 || p !== 0) && (i = {
4523
- x: g,
4538
+ }) : n === "right" && (u !== 0 || p !== 0) && (i = {
4539
+ x: u,
4524
4540
  y: p,
4525
4541
  handedness: "right"
4526
4542
  });
@@ -4528,6 +4544,33 @@ class yn {
4528
4544
  }
4529
4545
  return { movement: t, teleport: i };
4530
4546
  }
4547
+ getInputSources() {
4548
+ const e = this.renderer.xr.getSession && this.renderer.xr.getSession();
4549
+ return e && e.inputSources ? Array.from(e.inputSources) : this._getFallbackInputSources();
4550
+ }
4551
+ _getFallbackInputSources() {
4552
+ if (typeof navigator > "u" || !navigator.getGamepads) return [];
4553
+ const e = navigator.getGamepads();
4554
+ if (!e) return [];
4555
+ const t = [];
4556
+ let i = 0;
4557
+ for (const s of e) {
4558
+ if (!s || !s.buttons || !s.axes) continue;
4559
+ const o = this._resolveHandedness(s, i);
4560
+ if (!o) {
4561
+ i += 1;
4562
+ continue;
4563
+ }
4564
+ t.push({ gamepad: s, handedness: o }), i += 1;
4565
+ }
4566
+ return t;
4567
+ }
4568
+ _resolveHandedness(e, t) {
4569
+ const i = (e.hand || "").toLowerCase();
4570
+ if (i === "left" || i === "right") return i;
4571
+ const s = (e.id || "").toLowerCase();
4572
+ return s.includes("left") ? "left" : s.includes("right") ? "right" : this._fallbackHandedness.has(e.index) ? this._fallbackHandedness.get(e.index) : t === 0 ? (this._fallbackHandedness.set(e.index, "left"), "left") : t === 1 ? (this._fallbackHandedness.set(e.index, "right"), "right") : null;
4573
+ }
4531
4574
  getControllers() {
4532
4575
  return {
4533
4576
  controller1: this.controller1,
@@ -4548,7 +4591,11 @@ class yn {
4548
4591
  }
4549
4592
  class wn {
4550
4593
  constructor(e, t) {
4551
- this.scene = e, this.camera = t, this.teleportController = null, this.teleportMarker = null, this.teleportCurve = null, this.teleportFloor = null, this.validTeleportPosition = null, this.teleportThreshold = 0.7, this.teleportReleaseThreshold = 0.3, this.teleportPressed = !1, this.teleportMaxMagnitude = 0, this.teleportFloorHeight = null, this.teleportFloorMin = -10, this.teleportFloorMax = 10, this.lastSnapTurnTime = 0, this.onTeleport = null, this.onTeleportStart = null, this.onTeleportEnd = null;
4594
+ this.scene = e, this.camera = t, this.style = {
4595
+ neutralColor: 14870768,
4596
+ accentColor: 9741240,
4597
+ floorColor: 6583435
4598
+ }, this.teleportController = null, this.teleportMarker = null, this.teleportCurve = null, this.teleportFloor = null, this.validTeleportPosition = null, this.teleportThreshold = 0.7, this.teleportReleaseThreshold = 0.3, this.teleportPressed = !1, this.teleportMaxMagnitude = 0, this.teleportMinDistance = 1.5, this.teleportMaxDistance = 20, this.teleportFloorHeight = null, this.teleportFloorMin = -10, this.teleportFloorMax = 10, this.lastSnapTurnTime = 0, this.onTeleport = null, this.onTeleportStart = null, this.onTeleportEnd = null;
4552
4599
  }
4553
4600
  init() {
4554
4601
  this.setupTeleportation();
@@ -4558,41 +4605,39 @@ class wn {
4558
4605
  }
4559
4606
  createTeleportArc() {
4560
4607
  const e = [
4561
- new u.Vector3(0, 0, 0),
4562
- new u.Vector3(0, 1, -5)
4563
- ], t = new u.CatmullRomCurve3(e), i = new u.TubeGeometry(t, 20, 0.03, 8, !1), s = new u.MeshBasicMaterial({
4564
- color: 16777215,
4608
+ new g.Vector3(0, 0, 0),
4609
+ new g.Vector3(0, 1, -5)
4610
+ ], t = new g.CatmullRomCurve3(e), i = new g.TubeGeometry(t, 20, 0.03, 8, !1), s = new g.MeshBasicMaterial({
4611
+ color: this.style.accentColor,
4565
4612
  transparent: !0,
4566
- opacity: 0.8,
4567
- side: u.DoubleSide
4613
+ opacity: 0.62,
4614
+ side: g.DoubleSide
4568
4615
  });
4569
- if (this.teleportCurve = new u.Mesh(i, s), this.teleportCurve.visible = !1, this.scene.add(this.teleportCurve), !this.teleportMarker) {
4570
- const o = new u.RingGeometry(0.4, 0.6, 20), n = new u.MeshBasicMaterial({
4571
- color: 16777215,
4616
+ if (this.teleportCurve = new g.Mesh(i, s), this.teleportCurve.visible = !1, this.scene.add(this.teleportCurve), !this.teleportMarker) {
4617
+ const o = new g.RingGeometry(0.34, 0.5, 28), n = new g.MeshBasicMaterial({
4618
+ color: this.style.neutralColor,
4572
4619
  transparent: !0,
4573
- opacity: 0.9,
4574
- side: u.DoubleSide
4620
+ opacity: 0.78,
4621
+ side: g.DoubleSide
4575
4622
  });
4576
- this.teleportMarker = new u.Mesh(o, n), this.teleportMarker.rotation.x = -Math.PI / 2, this.teleportMarker.visible = !1, this.scene.add(this.teleportMarker);
4577
- const r = new u.RingGeometry(0.3, 0.7, 20), A = new u.MeshBasicMaterial({
4578
- color: 16777215,
4623
+ this.teleportMarker = new g.Mesh(o, n), this.teleportMarker.rotation.x = -Math.PI / 2, this.teleportMarker.visible = !1, this.scene.add(this.teleportMarker);
4624
+ const r = new g.RingGeometry(0.46, 0.72, 28), A = new g.MeshBasicMaterial({
4625
+ color: this.style.accentColor,
4579
4626
  transparent: !0,
4580
- opacity: 0.3,
4581
- side: u.DoubleSide
4582
- }), a = new u.Mesh(r, A);
4627
+ opacity: 0.18,
4628
+ side: g.DoubleSide
4629
+ }), a = new g.Mesh(r, A);
4583
4630
  a.rotation.x = -Math.PI / 2, this.teleportMarker.add(a);
4584
4631
  }
4585
4632
  if (!this.teleportFloor) {
4586
- const o = new u.PlaneGeometry(100, 100), n = new u.MeshBasicMaterial({
4587
- color: 65280,
4633
+ const o = new g.PlaneGeometry(14, 14), n = new g.MeshBasicMaterial({
4634
+ color: this.style.floorColor,
4588
4635
  transparent: !0,
4589
- opacity: 0.1,
4590
- // Very subtle when visible
4591
- side: u.DoubleSide,
4636
+ opacity: 0.06,
4637
+ side: g.DoubleSide,
4592
4638
  visible: !1
4593
- // Invisible by default
4594
4639
  });
4595
- this.teleportFloor = new u.Mesh(o, n), this.teleportFloor.rotation.x = -Math.PI / 2, this.teleportFloor.visible = !1, this.scene.add(this.teleportFloor);
4640
+ this.teleportFloor = new g.Mesh(o, n), this.teleportFloor.rotation.x = -Math.PI / 2, this.teleportFloor.visible = !1, this.scene.add(this.teleportFloor);
4596
4641
  }
4597
4642
  }
4598
4643
  executeTeleport() {
@@ -4643,59 +4688,59 @@ class wn {
4643
4688
  }
4644
4689
  updateTeleportArc() {
4645
4690
  if (!this.teleportController || !this.teleportCurve) return;
4646
- const e = new u.Vector3();
4691
+ const e = new g.Vector3();
4647
4692
  this.teleportController.getWorldPosition(e);
4648
- const t = new u.Quaternion();
4693
+ const t = new g.Quaternion();
4649
4694
  this.teleportController.getWorldQuaternion(t);
4650
- const i = new u.Vector3(0, 0, -1);
4695
+ const i = new g.Vector3(0, 0, -1);
4651
4696
  i.applyQuaternion(t);
4652
- const s = 3, o = 30, n = Math.min(this.teleportMaxMagnitude / this.teleportThreshold, 1), r = o - s, A = Math.pow(n, 0.7), a = s + r * A, l = [], h = 40, d = -9.8;
4653
- let g = Math.sqrt(a * Math.abs(d) / 2);
4654
- if (i.y > 0.3 ? g *= 1 - i.y * 0.5 : i.y < -0.5 && (g *= 1 + Math.abs(i.y) * 0.3), Math.sqrt(i.x * i.x + i.z * i.z) > 0.1) {
4655
- const Q = Math.min(1, a / (g * 2));
4656
- g *= Q;
4657
- }
4658
- const C = i.x * g, E = Math.max(i.y * g, g * 0.3), f = i.z * g, m = E / Math.abs(d), I = Math.max(m * 2.2, 1.5), b = this.teleportFloorHeight;
4659
- let B = null, y = !1, w = e.y, L = 0;
4697
+ const s = this.teleportMinDistance, o = this.teleportMaxDistance, n = Math.min(this.teleportMaxMagnitude / this.teleportThreshold, 1), r = o - s, A = Math.pow(n, 0.78), a = s + r * A, l = [], h = 32, d = -9.8;
4698
+ let u = Math.sqrt(a * Math.abs(d) / 2);
4699
+ if (i.y > 0.3 ? u *= 1 - i.y * 0.5 : i.y < -0.5 && (u *= 1 + Math.abs(i.y) * 0.3), Math.sqrt(i.x * i.x + i.z * i.z) > 0.1) {
4700
+ const S = Math.min(1, a / (u * 2));
4701
+ u *= S;
4702
+ }
4703
+ const b = i.x * u, E = Math.max(i.y * u, u * 0.3), f = i.z * u, m = E / Math.abs(d), I = Math.max(m * 2.2, 1.5), C = this.teleportFloorHeight;
4704
+ let B = null, y = !1, w = e.y, M = 0;
4660
4705
  const D = 8;
4661
- for (let Q = 0; Q <= h; Q++) {
4662
- const v = Q / h * I, M = new u.Vector3(
4663
- e.x + C * v,
4664
- e.y + E * v + 0.5 * d * v * v,
4665
- e.z + f * v
4706
+ for (let S = 0; S <= h; S++) {
4707
+ const R = S / h * I, v = new g.Vector3(
4708
+ e.x + b * R,
4709
+ e.y + E * R + 0.5 * d * R * R,
4710
+ e.z + f * R
4666
4711
  );
4667
- Math.abs(M.y - e.y) > D && (M.y = e.y + Math.sign(M.y - e.y) * D), !y && M.y < w && (y = !0, L = v), l.push(M);
4668
- const J = y ? v - L : 0, W = y && J > 0.1;
4669
- if (!B && W && M.y <= b) {
4670
- if (Q > 0) {
4671
- const q = l[Q - 1], F = (b - q.y) / (M.y - q.y);
4672
- B = new u.Vector3().lerpVectors(q, M, F), B.y = b;
4712
+ Math.abs(v.y - e.y) > D && (v.y = e.y + Math.sign(v.y - e.y) * D), !y && v.y < w && (y = !0, M = R), l.push(v);
4713
+ const J = y ? R - M : 0, W = y && J > 0.1;
4714
+ if (!B && W && v.y <= C) {
4715
+ if (S > 0) {
4716
+ const q = l[S - 1], k = (C - q.y) / (v.y - q.y);
4717
+ B = new g.Vector3().lerpVectors(q, v, k), B.y = C;
4673
4718
  } else
4674
- B = M.clone(), B.y = b;
4675
- l[Q] = B, l.length = Q + 1;
4719
+ B = v.clone(), B.y = C;
4720
+ l[S] = B, l.length = S + 1;
4676
4721
  break;
4677
4722
  }
4678
- if (w = M.y, Math.sqrt(
4679
- Math.pow(M.x - e.x, 2) + Math.pow(M.z - e.z, 2)
4723
+ if (w = v.y, Math.sqrt(
4724
+ Math.pow(v.x - e.x, 2) + Math.pow(v.z - e.z, 2)
4680
4725
  ) > o) {
4681
- W && (B = new u.Vector3(M.x, b, M.z), l[Q] = B, l.length = Q + 1);
4726
+ W && (B = new g.Vector3(v.x, C, v.z), l[S] = B, l.length = S + 1);
4682
4727
  break;
4683
4728
  }
4684
4729
  }
4685
4730
  if (!B && l.length > 0) {
4686
- let Q = l[0], v = 0;
4687
- for (let M = 1; M < l.length; M++)
4688
- l[M].y < Q.y && (Q = l[M], v = M);
4689
- v > l.length / 3 && (B = new u.Vector3(Q.x, b, Q.z), l.length = v + 1, l[v] = B);
4731
+ let S = l[0], R = 0;
4732
+ for (let v = 1; v < l.length; v++)
4733
+ l[v].y < S.y && (S = l[v], R = v);
4734
+ R > l.length / 3 && (B = new g.Vector3(S.x, C, S.z), l.length = R + 1, l[R] = B);
4690
4735
  }
4691
4736
  if (l.length > 1) {
4692
- const Q = new u.CatmullRomCurve3(l), v = new u.TubeGeometry(Q, 20, 0.03, 6, !1);
4693
- this.teleportCurve.geometry && this.teleportCurve.geometry.dispose(), this.teleportCurve.geometry = v;
4737
+ const S = new g.CatmullRomCurve3(l), R = new g.TubeGeometry(S, 20, 0.022, 6, !1);
4738
+ this.teleportCurve.geometry && this.teleportCurve.geometry.dispose(), this.teleportCurve.geometry = R;
4694
4739
  }
4695
- this.teleportMarker && B && (this.teleportMarker.position.copy(B), this.teleportMarker.visible = !0, this.teleportFloorHeight < -0.5 ? this.teleportMarker.material.color.setHex(8965375) : this.teleportFloorHeight > 0.5 ? this.teleportMarker.material.color.setHex(16777096) : this.teleportMarker.material.color.setHex(16777215));
4740
+ this.teleportMarker && B && (this.teleportMarker.position.copy(B), this.teleportMarker.visible = !0, this.teleportMarker.material.color.setHex(this.style.neutralColor));
4696
4741
  }
4697
4742
  updateTeleportFloor() {
4698
- this.teleportFloor && this.teleportFloorHeight !== null && (this.teleportFloor.position.y = this.teleportFloorHeight, this.teleportFloor.visible = !0, this.teleportFloor.material.visible = !0, this.teleportFloor.material.opacity = 0.15, this.teleportFloorHeight < -0.5 ? this.teleportFloor.material.color.setHex(4491519) : this.teleportFloorHeight > 0.5 ? this.teleportFloor.material.color.setHex(16777028) : this.teleportFloor.material.color.setHex(4521864), this.updateTeleportArc());
4743
+ this.teleportFloor && this.teleportFloorHeight !== null && (this.teleportFloor.position.y = this.teleportFloorHeight, this.teleportFloor.visible = !0, this.teleportFloor.material.visible = !0, this.teleportFloor.material.opacity = 0.06, this.teleportFloor.material.color.setHex(this.style.floorColor), this.updateTeleportArc());
4699
4744
  }
4700
4745
  updateTeleportArcHeight() {
4701
4746
  this.updateTeleportFloor();
@@ -4705,8 +4750,8 @@ class wn {
4705
4750
  const e = this.teleportMarker.position.clone(), t = this.camera.parent.position, i = Math.sqrt(
4706
4751
  Math.pow(e.x - t.x, 2) + Math.pow(e.z - t.z, 2)
4707
4752
  );
4708
- if (i >= 3 && i <= 30) {
4709
- const s = new u.Vector3(e.x, this.teleportFloorHeight, e.z);
4753
+ if (i >= this.teleportMinDistance && i <= this.teleportMaxDistance) {
4754
+ const s = new g.Vector3(e.x, this.teleportFloorHeight, e.z);
4710
4755
  this.validTeleportPosition = s, this.executeTeleport(), this.teleportFloorHeight = null;
4711
4756
  }
4712
4757
  }
@@ -4733,9 +4778,9 @@ class wn {
4733
4778
  this.lastSnapTurnTime = 0;
4734
4779
  }
4735
4780
  }
4736
- class Qn {
4781
+ class Sn {
4737
4782
  constructor(e, t) {
4738
- this.camera = e, this.renderer = t, this.MOVE_SPEED = 2, this.TURN_SPEED = 1.5, this.FLY_SPEED = 1, this.currentSpeed = 0, this.targetSpeed = 0, this.currentBoostLevel = 0, this.targetBoostLevel = 0, this.SPEED_RAMP_RATE = 3, this.BOOST_RAMP_RATE = 6, this.handMoveActive = !1, this.handMoveBoost = !1, this.handMoveDirection = new u.Vector3(), this.isMoving = !1, this.inputDeadzone = 0.15, this.turnSmoothingFactor = 0.1, this.lastTurnInput = 0, this.comfortSettings = {
4783
+ this.camera = e, this.renderer = t, this.MOVE_SPEED = 2, this.TURN_SPEED = 1.5, this.FLY_SPEED = 1, this.currentSpeed = 0, this.targetSpeed = 0, this.currentBoostLevel = 0, this.targetBoostLevel = 0, this.SPEED_RAMP_RATE = 3, this.BOOST_RAMP_RATE = 6, this.handMoveActive = !1, this.handMoveBoost = !1, this.handMoveDirection = new g.Vector3(), this.isMoving = !1, this.inputDeadzone = 0.15, this.turnSmoothingFactor = 0.1, this.lastTurnInput = 0, this.comfortSettings = {
4739
4784
  locomotionMode: "smooth",
4740
4785
  // 'smooth', 'teleport'
4741
4786
  turningMode: "smooth",
@@ -4763,95 +4808,97 @@ class Qn {
4763
4808
  this.teleportSystem = e;
4764
4809
  }
4765
4810
  updateMovement(e, t) {
4766
- const i = this.renderer.xr.getSession();
4767
- if (!i || i.visibilityState !== "visible")
4811
+ const i = this.renderer.xr.getSession && this.renderer.xr.getSession();
4812
+ if (i && i.visibilityState !== "visible")
4768
4813
  return;
4769
- if (t.updateHandGestures && t.handsActive) {
4814
+ const s = t?.inputSources || (i ? Array.from(i.inputSources || []) : []);
4815
+ if (!s || s.length === 0)
4816
+ return;
4817
+ if (i && t.updateHandGestures && t.handsActive) {
4770
4818
  t.updateHandGestures();
4771
- let h = null;
4772
- const d = new u.Vector3();
4773
- let g = !1;
4774
- for (const p of ["left", "right"])
4775
- if (t.handStates[p].pinch) {
4776
- h = p, d.copy(t.handStates[p].direction), g = t.handStates[p].fist;
4819
+ let u = null;
4820
+ const p = new g.Vector3();
4821
+ let b = !1;
4822
+ for (const E of ["left", "right"])
4823
+ if (t.handStates[E].pinch) {
4824
+ u = E, p.copy(t.handStates[E].direction), b = t.handStates[E].fist;
4777
4825
  break;
4778
4826
  }
4779
- if (h) {
4780
- this.handMoveActive = !0, this.handMoveBoost = g, this.handMoveDirection.copy(d);
4781
- const p = this.MOVE_SPEED * (g ? 3 : 1) * e;
4782
- this.camera.parent.position.addScaledVector(d, p), this.isMoving = !0, this.onMovementStart && !this._wasMoving && this.onMovementStart(), this.onMovementUpdate && this.onMovementUpdate({
4827
+ if (u) {
4828
+ this.handMoveActive = !0, this.handMoveBoost = b, this.handMoveDirection.copy(p);
4829
+ const E = this.camera.parent || this.camera, f = this.MOVE_SPEED * (b ? 3 : 1) * e;
4830
+ E.position.addScaledVector(p, f), this.isMoving = !0, this.onMovementStart && !this._wasMoving && this.onMovementStart(), this.onMovementUpdate && this.onMovementUpdate({
4783
4831
  isMoving: !0,
4784
4832
  currentSpeed: this.MOVE_SPEED,
4785
- isBoosted: g,
4786
- currentBoostLevel: g ? 1 : 0
4833
+ isBoosted: b,
4834
+ currentBoostLevel: b ? 1 : 0
4787
4835
  }), this._wasMoving = !0;
4788
4836
  return;
4789
4837
  } else
4790
4838
  this.handMoveActive && this.onMovementStop && this.onMovementStop(), this.handMoveActive = !1, this.isMoving = !1, this._wasMoving = !1;
4791
4839
  }
4792
- if (!t.controller1 || !t.controller2)
4793
- return;
4794
- let s = !1, o = !1;
4795
- for (let h = 0; h < i.inputSources.length; h++) {
4796
- const d = i.inputSources[h];
4797
- if (!d || !d.gamepad || !d.gamepad.buttons || !d.gamepad.axes || d.gamepad.axes.length < 4)
4840
+ const o = this.camera.parent || this.camera;
4841
+ let n = !1, r = !1;
4842
+ for (let u = 0; u < s.length; u++) {
4843
+ const p = s[u];
4844
+ if (!p || !p.gamepad || !p.gamepad.buttons || !p.gamepad.axes || p.gamepad.axes.length < 4)
4798
4845
  continue;
4799
- const g = d.gamepad, C = d.handedness === "left" ? t.controller1 : t.controller2;
4800
- if (!C) continue;
4801
- const E = g.axes[2] || 0, f = g.axes[3] || 0;
4802
- if (d.handedness === "left") {
4803
- const m = g.buttons[1], I = m && m.pressed ? 3 : 1, b = this.comfortSettings.reducedMotion ? this.comfortSettings.comfortSpeed : 1;
4804
- if (m && m.pressed && (o = !0), this.comfortSettings.locomotionMode === "teleport" && this.teleportSystem) {
4805
- this.teleportSystem.processTeleportation(C, E, f);
4846
+ const b = p.gamepad, f = p.handedness === "left" ? t.controller1 : t.controller2;
4847
+ if (!f) continue;
4848
+ const m = b.axes[2] || 0, I = b.axes[3] || 0;
4849
+ if (p.handedness === "left") {
4850
+ const C = b.buttons[1], B = C && C.pressed ? 3 : 1, y = this.comfortSettings.reducedMotion ? this.comfortSettings.comfortSpeed : 1;
4851
+ if (C && C.pressed && (r = !0), this.comfortSettings.locomotionMode === "teleport" && this.teleportSystem && f) {
4852
+ this.teleportSystem.processTeleportation(f, m, I);
4806
4853
  continue;
4807
4854
  } else {
4808
- const B = new u.Vector3();
4809
- this.camera.getWorldDirection(B), B.y = 0, B.normalize();
4810
- const y = new u.Vector3().crossVectors(B, this.camera.up).normalize();
4811
- if (Math.abs(f) > 0.1) {
4812
- const w = this.MOVE_SPEED * I * b * this.currentSpeed * e;
4813
- this.camera.parent.position.addScaledVector(B, -f * w), s = !0;
4855
+ const M = new g.Vector3();
4856
+ this.camera.getWorldDirection(M), M.y = 0, M.normalize();
4857
+ const D = new g.Vector3().crossVectors(M, this.camera.up).normalize();
4858
+ if (Math.abs(I) > 0.1) {
4859
+ const S = this.MOVE_SPEED * B * y * this.currentSpeed * e;
4860
+ o.position.addScaledVector(M, -I * S), n = !0;
4814
4861
  }
4815
- if (Math.abs(E) > 0.1) {
4816
- const w = this.MOVE_SPEED * I * b * this.currentSpeed * e;
4817
- this.camera.parent.position.addScaledVector(y, E * w), s = !0;
4862
+ if (Math.abs(m) > 0.1) {
4863
+ const S = this.MOVE_SPEED * B * y * this.currentSpeed * e;
4864
+ o.position.addScaledVector(D, m * S), n = !0;
4818
4865
  }
4819
4866
  }
4820
4867
  }
4821
- if (d.handedness === "right") {
4822
- const m = g.buttons[1], I = m && m.pressed ? 3 : 1, b = this.comfortSettings.reducedMotion ? this.comfortSettings.comfortSpeed : 1;
4823
- if (m && m.pressed && Math.abs(f) > 0.1 && (o = !0), this.teleportSystem && this.teleportSystem.teleportPressed && this.teleportSystem.teleportCurve && this.teleportSystem.teleportCurve.visible) {
4824
- if (Math.abs(f) > 0.1) {
4825
- const B = 4 * e;
4826
- this.teleportSystem.adjustFloorHeight(f * B);
4868
+ if (p.handedness === "right") {
4869
+ const C = b.buttons[1], B = C && C.pressed ? 3 : 1, y = this.comfortSettings.reducedMotion ? this.comfortSettings.comfortSpeed : 1;
4870
+ if (C && C.pressed && Math.abs(I) > 0.1 && (r = !0), this.teleportSystem && this.teleportSystem.teleportPressed && this.teleportSystem.teleportCurve && this.teleportSystem.teleportCurve.visible) {
4871
+ if (Math.abs(I) > 0.1) {
4872
+ const w = 4 * e;
4873
+ this.teleportSystem.adjustFloorHeight(I * w);
4827
4874
  }
4828
4875
  } else {
4829
4876
  if (this.comfortSettings.turningMode === "snap" && this.teleportSystem)
4830
- this.teleportSystem.processSnapTurn(E, this.comfortSettings.snapTurnAngle);
4831
- else if (Math.abs(E) > this.inputDeadzone) {
4832
- const B = this.lastTurnInput * this.turnSmoothingFactor + E * (1 - this.turnSmoothingFactor);
4833
- if (this.lastTurnInput = B, Math.abs(B) > this.inputDeadzone) {
4834
- const y = this.comfortSettings.reducedMotion ? this.TURN_SPEED * 0.5 : this.TURN_SPEED, w = B * y * Math.min(e, 1 / 30);
4835
- this.camera.parent.rotation.y -= w, this.camera.parent.rotation.y = this.normalizeAngle(this.camera.parent.rotation.y);
4877
+ this.teleportSystem.processSnapTurn(m, this.comfortSettings.snapTurnAngle);
4878
+ else if (Math.abs(m) > this.inputDeadzone) {
4879
+ const w = this.lastTurnInput * this.turnSmoothingFactor + m * (1 - this.turnSmoothingFactor);
4880
+ if (this.lastTurnInput = w, Math.abs(w) > this.inputDeadzone) {
4881
+ const M = this.comfortSettings.reducedMotion ? this.TURN_SPEED * 0.5 : this.TURN_SPEED, D = w * M * Math.min(e, 1 / 30);
4882
+ o.rotation.y -= D, o.rotation.y = this.normalizeAngle(o.rotation.y);
4836
4883
  }
4837
4884
  } else
4838
4885
  this.lastTurnInput *= 0.9;
4839
- if (Math.abs(f) > 0.1) {
4840
- const B = this.FLY_SPEED * I * b * this.currentSpeed * e;
4841
- this.camera.parent.position.y -= f * B, s = !0;
4886
+ if (Math.abs(I) > 0.1) {
4887
+ const w = this.FLY_SPEED * B * y * this.currentSpeed * e;
4888
+ o.position.y -= I * w, n = !0;
4842
4889
  }
4843
4890
  }
4844
4891
  }
4845
4892
  }
4846
- const n = this.isMoving;
4847
- this.isMoving = s;
4848
- const A = (this.isMoving ? this.MOVE_SPEED : 0) - this.currentSpeed;
4849
- this.currentSpeed += A * this.SPEED_RAMP_RATE * e, this.currentSpeed = Math.max(0, this.currentSpeed);
4850
- const l = (o ? 1 : 0) - this.currentBoostLevel;
4851
- this.currentBoostLevel += l * this.BOOST_RAMP_RATE * e, this.currentBoostLevel = Math.max(0, Math.min(1, this.currentBoostLevel)), !n && this.isMoving && this.onMovementStart && this.onMovementStart(), n && !this.isMoving && this.onMovementStop && this.onMovementStop(), this.onMovementUpdate && this.onMovementUpdate({
4893
+ const A = this.isMoving;
4894
+ this.isMoving = n;
4895
+ const l = (this.isMoving ? this.MOVE_SPEED : 0) - this.currentSpeed;
4896
+ this.currentSpeed += l * this.SPEED_RAMP_RATE * e, this.currentSpeed = Math.max(0, this.currentSpeed);
4897
+ const d = (r ? 1 : 0) - this.currentBoostLevel;
4898
+ this.currentBoostLevel += d * this.BOOST_RAMP_RATE * e, this.currentBoostLevel = Math.max(0, Math.min(1, this.currentBoostLevel)), !A && this.isMoving && this.onMovementStart && this.onMovementStart(), A && !this.isMoving && this.onMovementStop && this.onMovementStop(), this.onMovementUpdate && this.onMovementUpdate({
4852
4899
  isMoving: this.isMoving,
4853
4900
  currentSpeed: this.currentSpeed,
4854
- isBoosted: o,
4901
+ isBoosted: r,
4855
4902
  currentBoostLevel: this.currentBoostLevel
4856
4903
  });
4857
4904
  }
@@ -4861,8 +4908,8 @@ class Qn {
4861
4908
  return e;
4862
4909
  }
4863
4910
  correctDrift() {
4864
- const e = this.camera.parent;
4865
- e.rotation.y = this.normalizeAngle(e.rotation.y), e.position.x = Math.round(e.position.x * 1e3) / 1e3, e.position.y = Math.round(e.position.y * 1e3) / 1e3, e.position.z = Math.round(e.position.z * 1e3) / 1e3;
4911
+ const e = this.camera.parent || this.camera;
4912
+ e && (e.rotation.y = this.normalizeAngle(e.rotation.y), e.position.x = Math.round(e.position.x * 1e3) / 1e3, e.position.y = Math.round(e.position.y * 1e3) / 1e3, e.position.z = Math.round(e.position.z * 1e3) / 1e3);
4866
4913
  }
4867
4914
  setComfortSettings(e) {
4868
4915
  const t = ["smooth", "teleport"], i = ["smooth", "snap"];
@@ -4883,10 +4930,10 @@ class Qn {
4883
4930
  return e === "comfort" ? (this.setComfortSettings({
4884
4931
  locomotionMode: "teleport",
4885
4932
  turningMode: "snap",
4886
- snapTurnAngle: 30,
4933
+ snapTurnAngle: 22.5,
4887
4934
  reducedMotion: !0,
4888
4935
  showTeleportArc: !0,
4889
- comfortSpeed: 0.3
4936
+ comfortSpeed: 0.45
4890
4937
  }), !0) : e === "free" ? (this.setComfortSettings({
4891
4938
  locomotionMode: "smooth",
4892
4939
  turningMode: "smooth",
@@ -4920,7 +4967,7 @@ class Qn {
4920
4967
  };
4921
4968
  }
4922
4969
  }
4923
- class Sn {
4970
+ class Qn {
4924
4971
  constructor() {
4925
4972
  this.soundEnabled = !1, this.audioContext = null, this._basePath = "./sound/", this.dpvSound = null, this.dpvHighSound = null, this.ambienceSound = null, this.currentMovementSound = null, this.currentBoostSound = null, this.currentAmbienceSound = null, this.baseGainNode = null, this.boostGainNode = null, this.ambienceGainNode = null, this.baseVolumeMultiplier = 1.52, this.boostVolumeMultiplier = 1.01, this.ambienceVolume = 0.1;
4926
4973
  }
@@ -5066,7 +5113,7 @@ class Mn {
5066
5113
  * @param {boolean} [enableAudio=false] - Enable VR audio system
5067
5114
  */
5068
5115
  constructor(e, t, i, s = "./sound/", o = !1, n = null) {
5069
- this.renderer = e, this.camera = t, this.scene = i, this.audioPath = s, this.enableAudio = o, this.container = n, this.vrCore = new cn(e, t, i, n), this.vrControllers = new yn(e, t), this.vrTeleport = new wn(i, t), this.vrLocomotion = new Qn(t, e), this.vrAudio = this.enableAudio ? new Sn() : null, this.isVRSupported = !1, this.isVRPresenting = !1, this.controller1 = null, this.controller2 = null, this.controllerGrip1 = null, this.controllerGrip2 = null, this.controllers = [], this.controllerGrips = [], this._preVRCameraState = {
5116
+ this.renderer = e, this.camera = t, this.scene = i, this.audioPath = s, this.enableAudio = o, this.container = n, this.vrCore = new cn(e, t, i, n), this.vrControllers = new yn(e, t), this.vrTeleport = new wn(i, t), this.vrLocomotion = new Sn(t, e), this.vrAudio = this.enableAudio ? new Qn() : null, this.isVRSupported = !1, this.isVRPresenting = !1, this.controller1 = null, this.controller2 = null, this.controllerGrip1 = null, this.controllerGrip2 = null, this.controllers = [], this.controllerGrips = [], this._preVRCameraState = {
5070
5117
  target: null,
5071
5118
  position: null,
5072
5119
  zoom: null,
@@ -5081,7 +5128,7 @@ class Mn {
5081
5128
  autoRotateSpeed: null,
5082
5129
  controls: null
5083
5130
  // Reference to controls object
5084
- }, this._initialPositions = null, this.lastComfortLog = 0, this.onModeToggle = null, this.onMovementStart = null, this.onMovementStop = null, this.onMovementUpdate = null, this.init();
5131
+ }, this._initialPositions = null, this.lastComfortLog = 0, this.onModeToggle = null, this.onMovementStart = null, this.onMovementStop = null, this.onMovementUpdate = null, this.onComfortModeChange = null, this.init();
5085
5132
  }
5086
5133
  init() {
5087
5134
  this.vrCore.init(), this.vrControllers.init(), this.vrTeleport.init(), this.vrLocomotion.init(), this.setupModuleConnections();
@@ -5114,6 +5161,7 @@ class Mn {
5114
5161
  this.vrControllers.checkControllerButtons();
5115
5162
  const t = {
5116
5163
  ...this.vrControllers.getControllers(),
5164
+ inputSources: this.vrControllers.getInputSources(),
5117
5165
  handsActive: this.vrControllers.handsActive,
5118
5166
  handStates: this.vrControllers.handStates,
5119
5167
  updateHandGestures: this.vrControllers.updateHandGestures ? this.vrControllers.updateHandGestures.bind(this.vrControllers) : void 0
@@ -5181,7 +5229,47 @@ class Mn {
5181
5229
  * @since 1.0.0
5182
5230
  */
5183
5231
  setComfortPreset(e) {
5184
- this.vrLocomotion.setComfortPreset(e);
5232
+ const t = this.isComfortModeEnabled(), i = this.vrLocomotion.setComfortPreset(e);
5233
+ if (i && typeof this.onComfortModeChange == "function") {
5234
+ const s = this.isComfortModeEnabled();
5235
+ this.onComfortModeChange({
5236
+ enabled: s,
5237
+ changed: s !== t,
5238
+ preset: s ? "comfort" : "free",
5239
+ inVR: this.isVRPresenting,
5240
+ settings: this.getComfortSettings()
5241
+ });
5242
+ }
5243
+ return i;
5244
+ }
5245
+ /**
5246
+ * Enable or disable comfort mode explicitly.
5247
+ *
5248
+ * Works both inside and outside active VR sessions by updating locomotion state.
5249
+ *
5250
+ * @param {boolean} enabled
5251
+ * @returns {boolean}
5252
+ */
5253
+ setComfortMode(e) {
5254
+ return this.setComfortPreset(e ? "comfort" : "free");
5255
+ }
5256
+ /**
5257
+ * Toggle comfort mode.
5258
+ *
5259
+ * @returns {boolean} The new comfort mode state.
5260
+ */
5261
+ toggleComfortMode() {
5262
+ const e = !this.isComfortModeEnabled();
5263
+ return this.setComfortMode(e), e;
5264
+ }
5265
+ /**
5266
+ * Check whether comfort mode is currently enabled.
5267
+ *
5268
+ * @returns {boolean}
5269
+ */
5270
+ isComfortModeEnabled() {
5271
+ const e = this.vrLocomotion.getComfortSettings();
5272
+ return e.locomotionMode === "teleport" && e.reducedMotion === !0;
5185
5273
  }
5186
5274
  ensureComfortSettingsApplied() {
5187
5275
  if (!this.isVRPresenting) return;
@@ -5290,7 +5378,7 @@ class Mn {
5290
5378
  return this.vrLocomotion.normalizeAngle(e);
5291
5379
  }
5292
5380
  }
5293
- class xn {
5381
+ class vn {
5294
5382
  /**
5295
5383
  * Constructs a new AR button.
5296
5384
  *
@@ -5304,12 +5392,12 @@ class xn {
5304
5392
  if (t.domOverlay === void 0) {
5305
5393
  const d = document.createElement("div");
5306
5394
  d.style.display = "none", document.body.appendChild(d);
5307
- const g = document.createElementNS("http://www.w3.org/2000/svg", "svg");
5308
- g.setAttribute("width", 38), g.setAttribute("height", 38), g.style.position = "absolute", g.style.right = "20px", g.style.top = "20px", g.addEventListener("click", function() {
5395
+ const u = document.createElementNS("http://www.w3.org/2000/svg", "svg");
5396
+ u.setAttribute("width", 38), u.setAttribute("height", 38), u.style.position = "absolute", u.style.right = "20px", u.style.top = "20px", u.addEventListener("click", function() {
5309
5397
  a.end();
5310
- }), d.appendChild(g);
5398
+ }), d.appendChild(u);
5311
5399
  const p = document.createElementNS("http://www.w3.org/2000/svg", "path");
5312
- p.setAttribute("d", "M 12,12 L 28,28 M 28,12 12,28"), p.setAttribute("stroke", "#fff"), p.setAttribute("stroke-width", 2), g.appendChild(p), t.optionalFeatures === void 0 && (t.optionalFeatures = []), t.optionalFeatures.push("dom-overlay"), t.domOverlay = { root: d };
5400
+ p.setAttribute("d", "M 12,12 L 28,28 M 28,12 12,28"), p.setAttribute("stroke", "#fff"), p.setAttribute("stroke-width", 2), u.appendChild(p), t.optionalFeatures === void 0 && (t.optionalFeatures = []), t.optionalFeatures.push("dom-overlay"), t.domOverlay = { root: d };
5313
5401
  }
5314
5402
  let a = null;
5315
5403
  async function l(d) {
@@ -5352,7 +5440,7 @@ class xn {
5352
5440
  }
5353
5441
  }
5354
5442
  }
5355
- class vn {
5443
+ class xn {
5356
5444
  constructor(e, t, i, s = null) {
5357
5445
  this.renderer = e, this.camera = t, this.scene = i, this.container = s || document.body, this.isARSupported = !1, this.isARPresenting = !1, this.isQuest2 = !1, this.isQuest3 = !1, this.arButton = null, this.buttonObserver = null, this.onSessionStart = null, this.onSessionEnd = null;
5358
5446
  }
@@ -5386,7 +5474,7 @@ class vn {
5386
5474
  requiredFeatures: ["local"],
5387
5475
  optionalFeatures: this.getOptionalFeatures()
5388
5476
  };
5389
- this.arButton = xn.createButton(this.renderer, e), this.arButton.innerHTML = '<span class="ar-icon">👁️</span>ENTER AR', this.arButton.className = "ar-button--glass ar-button-available", this.arButton.disabled = !1, this.arButton.style.cssText = `
5477
+ this.arButton = vn.createButton(this.renderer, e), this.arButton.innerHTML = '<span class="ar-icon">👁️</span>ENTER AR', this.arButton.className = "ar-button--glass ar-button-available", this.arButton.disabled = !1, this.arButton.style.cssText = `
5390
5478
  position: fixed !important;
5391
5479
  bottom: 140px !important;
5392
5480
  left: 50% !important;
@@ -5473,7 +5561,7 @@ class vn {
5473
5561
  this.buttonObserver && (this.buttonObserver.disconnect(), this.buttonObserver = null), this.arButton && this.arButton.parentNode && this.arButton.parentNode.removeChild(this.arButton), this.isQuest2 = !1, this.isQuest3 = !1, this.isARSupported = !1, this.isARPresenting = !1;
5474
5562
  }
5475
5563
  }
5476
- const $t = new Ie(), ei = new R();
5564
+ const $t = new Ie(), ei = new L();
5477
5565
  class ti {
5478
5566
  /**
5479
5567
  * Constructs a new XR hand primitive model.
@@ -5487,7 +5575,7 @@ class ti {
5487
5575
  constructor(e, t, i, s, o) {
5488
5576
  this.controller = t, this.handModel = e, this.envMap = null;
5489
5577
  let n;
5490
- !o || !o.primitive || o.primitive === "sphere" ? n = new mi(1, 10, 10) : o.primitive === "box" && (n = new vs(1, 1, 1));
5578
+ !o || !o.primitive || o.primitive === "sphere" ? n = new mi(1, 10, 10) : o.primitive === "box" && (n = new xs(1, 1, 1));
5491
5579
  const r = new wt();
5492
5580
  this.handMesh = new ci(n, r, 30), this.handMesh.frustumCulled = !1, this.handMesh.instanceMatrix.setUsage(Rs), this.handMesh.castShadow = !0, this.handMesh.receiveShadow = !0, this.handModel.add(this.handMesh), this.joints = [
5493
5581
  "wrist",
@@ -5543,7 +5631,7 @@ class Dn {
5543
5631
  * @param {?Function} [onLoad=null] - A callback that is executed when a controller model has been loaded.
5544
5632
  */
5545
5633
  constructor(e, t, i, s, o = null, n = null) {
5546
- this.controller = t, this.handModel = e, this.bones = [], o === null && (o = new xt(), o.setPath(i || Rn)), o.load(`${s}.glb`, (r) => {
5634
+ this.controller = t, this.handModel = e, this.bones = [], o === null && (o = new vt(), o.setPath(i || Rn)), o.load(`${s}.glb`, (r) => {
5547
5635
  const A = r.scene.children[0];
5548
5636
  this.handModel.add(A);
5549
5637
  const a = A.getObjectByProperty("type", "SkinnedMesh");
@@ -5596,7 +5684,7 @@ class Dn {
5596
5684
  }
5597
5685
  }
5598
5686
  }
5599
- class Tn extends Oe {
5687
+ class Ln extends He {
5600
5688
  /**
5601
5689
  * Constructs a new XR hand model.
5602
5690
  *
@@ -5615,7 +5703,7 @@ class Tn extends Oe {
5615
5703
  super.updateMatrixWorld(e), this.motionController && this.motionController.updateMesh();
5616
5704
  }
5617
5705
  }
5618
- class Ln {
5706
+ class Tn {
5619
5707
  /**
5620
5708
  * Constructs a new XR hand model factory.
5621
5709
  *
@@ -5642,7 +5730,7 @@ class Ln {
5642
5730
  * @return {XRHandModel} The XR hand model.
5643
5731
  */
5644
5732
  createHandModel(e, t) {
5645
- const i = new Tn(e);
5733
+ const i = new Ln(e);
5646
5734
  return e.addEventListener("connected", (s) => {
5647
5735
  const o = s.data;
5648
5736
  o.hand && !i.motionController && (i.xrInputSource = o, t === void 0 || t === "spheres" ? i.motionController = new ti(i, e, this.path, o.handedness, { primitive: "sphere" }) : t === "boxes" ? i.motionController = new ti(i, e, this.path, o.handedness, { primitive: "box" }) : t === "mesh" && (i.motionController = new Dn(i, e, this.path, o.handedness, this.gltfLoader, this.onLoad))), e.visible = !0;
@@ -5651,13 +5739,13 @@ class Ln {
5651
5739
  }), i;
5652
5740
  }
5653
5741
  }
5654
- class Fn {
5742
+ class kn {
5655
5743
  constructor(e) {
5656
- this.renderer = e, this.handModelFactory = new Ln(), this.hand1 = null, this.hand2 = null, this.interactionEnabled = !0, this.dragging = !1, this.scaling = !1, this.rotating = !1, this.dragStartPos = new u.Vector3(), this.scaleStartDistance = 0, this.rotateStartAngle = 0, this.pinchIntent = {
5744
+ this.renderer = e, this.handModelFactory = new Tn(), this.hand1 = null, this.hand2 = null, this.interactionEnabled = !0, this.dragging = !1, this.scaling = !1, this.rotating = !1, this.dragStartPos = new g.Vector3(), this.scaleStartDistance = 0, this.rotateStartAngle = 0, this.pinchIntent = {
5657
5745
  hand1Start: 0,
5658
5746
  hand2Start: 0,
5659
5747
  delay: 100
5660
- }, this.inertiaActive = !1, this.posVelocity = new u.Vector3(), this.rotVelocity = 0, this.scaleVelocity = 0, this.POSITION_DAMPING = 100, this.ROTATION_DAMPING = 8, this.SCALE_DAMPING = 8, this.MAX_ROT_VELOCITY = Math.PI, this.MAX_SCALE_VELOCITY = 0.5, this.MIN_SCALE = 0.01, this.MAX_SCALE = 1, this.VELOCITY_DEAD_ZONE = 1e-3, this.DISTANCE_GAIN_THRESHOLD = 5, this.MAX_DISTANCE_GAIN = 3, this.MAX_DELTA_PER_FRAME = 0.5, this.VELOCITY_SMOOTHING = 0.3, this.tempVec1 = new u.Vector3(), this.tempVec2 = new u.Vector3(), this.onGestureStart = null, this.onGestureEnd = null;
5748
+ }, this.inertiaActive = !1, this.posVelocity = new g.Vector3(), this.rotVelocity = 0, this.scaleVelocity = 0, this.POSITION_DAMPING = 100, this.ROTATION_DAMPING = 8, this.SCALE_DAMPING = 8, this.MAX_ROT_VELOCITY = Math.PI, this.MAX_SCALE_VELOCITY = 0.5, this.MIN_SCALE = 0.01, this.MAX_SCALE = 1, this.VELOCITY_DEAD_ZONE = 1e-3, this.DISTANCE_GAIN_THRESHOLD = 5, this.MAX_DISTANCE_GAIN = 3, this.MAX_DELTA_PER_FRAME = 0.5, this.VELOCITY_SMOOTHING = 0.3, this.tempVec1 = new g.Vector3(), this.tempVec2 = new g.Vector3(), this.onGestureStart = null, this.onGestureEnd = null;
5661
5749
  }
5662
5750
  init(e) {
5663
5751
  this.hand1 = this.setupHand(e, 0, "hand1Start"), this.hand2 = this.setupHand(e, 1, "hand2Start");
@@ -5676,7 +5764,7 @@ class Fn {
5676
5764
  }
5677
5765
  styleHandModel(e, t, i) {
5678
5766
  e.traverse((s) => {
5679
- s.isMesh && (s.material = new u.MeshStandardMaterial({
5767
+ s.isMesh && (s.material = new g.MeshStandardMaterial({
5680
5768
  color: t,
5681
5769
  roughness: 0.8,
5682
5770
  metalness: 0.2,
@@ -5702,15 +5790,15 @@ class Fn {
5702
5790
  (this.scaling || this.rotating) && (this.rotVelocity = 0, this.scaleVelocity = 0), this.dragging = !0, this.scaling = !1, this.rotating = !1, l.getWorldPosition(this.dragStartPos), this.onGestureStart && this.onGestureStart("drag");
5703
5791
  else {
5704
5792
  l.getWorldPosition(this.tempVec1);
5705
- let h = this.tempVec1.clone().sub(this.dragStartPos);
5793
+ const h = this.tempVec1.clone().sub(this.dragStartPos);
5706
5794
  if (h.length() > this.MAX_DELTA_PER_FRAME && h.normalize().multiplyScalar(this.MAX_DELTA_PER_FRAME), i) {
5707
5795
  const d = i.position.distanceTo(t.position);
5708
5796
  if (d > this.DISTANCE_GAIN_THRESHOLD) {
5709
- const g = Math.min(
5797
+ const u = Math.min(
5710
5798
  this.MAX_DISTANCE_GAIN,
5711
5799
  1 + (d - this.DISTANCE_GAIN_THRESHOLD) / 7.5
5712
5800
  );
5713
- h.multiplyScalar(g);
5801
+ h.multiplyScalar(u);
5714
5802
  }
5715
5803
  }
5716
5804
  if (t.position.add(h), e > 0) {
@@ -5725,17 +5813,17 @@ class Fn {
5725
5813
  const a = this.tempVec2.x - this.tempVec1.x, l = this.tempVec2.z - this.tempVec1.z;
5726
5814
  this.rotateStartAngle = Math.atan2(l, a), this.onGestureStart && this.onGestureStart("two-hand");
5727
5815
  } else {
5728
- const a = this.tempVec1.distanceTo(this.tempVec2), l = a / this.scaleStartDistance, h = Math.log(t.scale.x), d = Math.log(l), g = h + d, p = Math.max(this.MIN_SCALE, Math.min(this.MAX_SCALE, Math.exp(g)));
5816
+ const a = this.tempVec1.distanceTo(this.tempVec2), l = a / this.scaleStartDistance, h = Math.log(t.scale.x), d = Math.log(l), u = h + d, p = Math.max(this.MIN_SCALE, Math.min(this.MAX_SCALE, Math.exp(u)));
5729
5817
  if (t.scale.setScalar(p), e > 0) {
5730
- const I = d / e, b = Math.max(-this.MAX_SCALE_VELOCITY, Math.min(this.MAX_SCALE_VELOCITY, I));
5731
- this.scaleVelocity = this.scaleVelocity * (1 - this.VELOCITY_SMOOTHING) + b * this.VELOCITY_SMOOTHING;
5818
+ const I = d / e, C = Math.max(-this.MAX_SCALE_VELOCITY, Math.min(this.MAX_SCALE_VELOCITY, I));
5819
+ this.scaleVelocity = this.scaleVelocity * (1 - this.VELOCITY_SMOOTHING) + C * this.VELOCITY_SMOOTHING;
5732
5820
  }
5733
5821
  this.scaleStartDistance = a;
5734
- const C = this.tempVec2.x - this.tempVec1.x, E = this.tempVec2.z - this.tempVec1.z, f = Math.atan2(E, C);
5822
+ const b = this.tempVec2.x - this.tempVec1.x, E = this.tempVec2.z - this.tempVec1.z, f = Math.atan2(E, b);
5735
5823
  let m = f - this.rotateStartAngle;
5736
5824
  if (m > Math.PI && (m -= 2 * Math.PI), m < -Math.PI && (m += 2 * Math.PI), t.rotation.y -= m, e > 0) {
5737
- const I = -m / e, b = Math.max(-this.MAX_ROT_VELOCITY, Math.min(this.MAX_ROT_VELOCITY, I));
5738
- this.rotVelocity = this.rotVelocity * (1 - this.VELOCITY_SMOOTHING) + b * this.VELOCITY_SMOOTHING;
5825
+ const I = -m / e, C = Math.max(-this.MAX_ROT_VELOCITY, Math.min(this.MAX_ROT_VELOCITY, I));
5826
+ this.rotVelocity = this.rotVelocity * (1 - this.VELOCITY_SMOOTHING) + C * this.VELOCITY_SMOOTHING;
5739
5827
  }
5740
5828
  this.rotateStartAngle = f;
5741
5829
  }
@@ -5767,7 +5855,7 @@ class Fn {
5767
5855
  this.hand1 && this.hand1.clear(), this.hand2 && this.hand2.clear(), this.stop();
5768
5856
  }
5769
5857
  }
5770
- class kn extends je {
5858
+ class Fn extends Te {
5771
5859
  constructor(e, t, i, s = {}, o = null) {
5772
5860
  super(), this.renderer = e, this.camera = t, this.scene = i, this.config = {
5773
5861
  enableHandTracking: !0,
@@ -5776,7 +5864,7 @@ class kn extends je {
5776
5864
  worldCubeSize: 1e3,
5777
5865
  worldCubeOpacity: 0.1,
5778
5866
  ...s
5779
- }, this.container = o, this.arCore = new vn(e, t, i, o), this.handTracking = this.config.enableHandTracking ? new Fn(e) : null, this.modelGroup = new u.Group(), this.modelGroup.name = "AR Model Group", this.scene.add(this.modelGroup), this.currentModel = null, this.pendingModel = null, this.pendingModelConfig = null, this.currentModelScale = this.config.defaultScale, this.worldCube = null, this.config.enableWorldCube && this.createWorldCube(), this.isARPresenting = !1, this.previousGestureType = null, this.init();
5867
+ }, this.container = o, this.arCore = new xn(e, t, i, o), this.handTracking = this.config.enableHandTracking ? new kn(e) : null, this.modelGroup = new g.Group(), this.modelGroup.name = "AR Model Group", this.scene.add(this.modelGroup), this.currentModel = null, this.pendingModel = null, this.pendingModelConfig = null, this.currentModelScale = this.config.defaultScale, this.worldCube = null, this.config.enableWorldCube && this.createWorldCube(), this.isARPresenting = !1, this.previousGestureType = null, this.init();
5780
5868
  }
5781
5869
  init() {
5782
5870
  this.arCore.init(), this.handTracking && (this.handTracking.init(this.scene), this.handTracking.onGestureStart = (e) => {
@@ -5814,14 +5902,14 @@ class kn extends je {
5814
5902
  this.handTracking && this.handTracking.update(t, this.modelGroup, this.camera);
5815
5903
  }
5816
5904
  createWorldCube() {
5817
- const e = this.config.worldCubeSize, t = new u.BoxGeometry(e, e, e), i = new u.MeshBasicMaterial({
5905
+ const e = this.config.worldCubeSize, t = new g.BoxGeometry(e, e, e), i = new g.MeshBasicMaterial({
5818
5906
  color: 0,
5819
5907
  transparent: !0,
5820
5908
  opacity: this.config.worldCubeOpacity,
5821
- side: u.BackSide,
5909
+ side: g.BackSide,
5822
5910
  depthWrite: !1
5823
5911
  });
5824
- this.worldCube = new u.Mesh(t, i), this.worldCube.name = "AR World Cube", this.worldCube.visible = !1, this.scene.add(this.worldCube);
5912
+ this.worldCube = new g.Mesh(t, i), this.worldCube.name = "AR World Cube", this.worldCube.visible = !1, this.scene.add(this.worldCube);
5825
5913
  }
5826
5914
  setWorldCubeOpacity(e) {
5827
5915
  this.worldCube && (this.worldCube.material.opacity = Math.max(0, Math.min(1, e)));
@@ -6000,18 +6088,28 @@ class ii {
6000
6088
  }
6001
6089
  };
6002
6090
  return console.log("🌊 Particle information:"), console.table(i), i;
6091
+ }, window.stereo = (t, i) => {
6092
+ if (t === void 0) {
6093
+ const s = {
6094
+ enabled: e.stereoEnabled || !1,
6095
+ mode: e.stereoMode || "sbs",
6096
+ eyeSeparation: e.stereoEyeSeparation || 0.064
6097
+ };
6098
+ return console.log("👓 Stereo information:"), console.table(s), console.log(""), console.log("Usage:"), console.log(" stereo(true) - Enable stereo mode"), console.log(" stereo(false) - Disable stereo mode"), console.log(" stereo(true, 0.065) - Enable with custom eye separation"), s;
6099
+ }
6100
+ return e.setStereoEnabled(t), i !== void 0 && e.setStereoEyeSeparation(i), console.log(`👓 Stereo ${t ? "enabled" : "disabled"}`), i !== void 0 && console.log(`👓 Eye separation: ${i}m`), { enabled: t, eyeSeparation: e.stereoEyeSeparation };
6003
6101
  }, window.debugHelp = () => {
6004
- console.log("🔧 BelowJS Debug Commands:"), console.log(" camera() - Get current camera position data"), console.log(" scene() - Get scene information and object counts"), console.log(" models() - Get loaded models information"), console.log(" particles() - Get particle system information"), console.log(" vr() - Get VR state and settings"), console.log(" debugHelp() - Show this help message"), console.log(""), console.log("Global objects:"), console.log(" belowViewer - Direct access to BelowViewer instance");
6102
+ console.log("🔧 BelowJS Debug Commands:"), console.log(" camera() - Get current camera position data"), console.log(" scene() - Get scene information and object counts"), console.log(" models() - Get loaded models information"), console.log(" particles() - Get particle system information"), console.log(" vr() - Get VR state and settings"), console.log(" stereo() - Get/set stereo mode and eye separation"), console.log(" debugHelp() - Show this help message"), console.log(""), console.log("Global objects:"), console.log(" belowViewer - Direct access to BelowViewer instance");
6005
6103
  });
6006
6104
  }
6007
6105
  /**
6008
6106
  * Clean up debug commands when viewer is disposed
6009
6107
  */
6010
6108
  static cleanup() {
6011
- typeof window > "u" || (delete window.camera, delete window.scene, delete window.models, delete window.particles, delete window.vr, delete window.debugHelp, delete window.belowViewer);
6109
+ typeof window > "u" || (delete window.camera, delete window.scene, delete window.models, delete window.particles, delete window.vr, delete window.stereo, delete window.debugHelp, delete window.belowViewer);
6012
6110
  }
6013
6111
  }
6014
- class _n extends je {
6112
+ class _n extends Te {
6015
6113
  /**
6016
6114
  * Creates a new BelowViewer instance
6017
6115
  *
@@ -6059,12 +6157,27 @@ class _n extends je {
6059
6157
  default: {
6060
6158
  antialias: !0,
6061
6159
  alpha: !1,
6062
- powerPreference: "high-performance"
6160
+ powerPreference: "high-performance",
6161
+ logarithmicDepthBuffer: !1
6063
6162
  },
6064
6163
  schema: {
6065
6164
  antialias: { type: "boolean", default: !0 },
6066
6165
  alpha: { type: "boolean", default: !1 },
6067
- powerPreference: { type: "string", default: "high-performance" }
6166
+ powerPreference: { type: "string", default: "high-performance" },
6167
+ logarithmicDepthBuffer: { type: "boolean", default: !1 }
6168
+ }
6169
+ },
6170
+ stereo: {
6171
+ type: "object",
6172
+ default: {
6173
+ enabled: !1,
6174
+ mode: "sbs",
6175
+ eyeSeparation: 0.064
6176
+ },
6177
+ schema: {
6178
+ enabled: { type: "boolean", default: !1 },
6179
+ mode: { type: "string", default: "sbs" },
6180
+ eyeSeparation: { type: "number", default: 0.064 }
6068
6181
  }
6069
6182
  },
6070
6183
  vr: {
@@ -6094,33 +6207,39 @@ class _n extends je {
6094
6207
  audioPath: { type: "string", default: "./sound/" },
6095
6208
  enableVRAudio: { type: "boolean", default: !1 }
6096
6209
  };
6097
- this.config = new Ke(i).validate(t), this.renderer = null, this.sceneManager = null, this.cameraManager = null, this.modelLoader = null, this.vrManager = null, this.arManager = null, this.isVREnabled = this.config.vr?.enabled !== !1, this.isAREnabled = this.config.ar?.enabled === !0, this.dolly = null, this.isInitialized = !1, this.loadedModels = [], this.currentAbortController = null, this.skipRenderDuringLoad = !1, this.pixelRatioBeforeThrottle = 1, this.originalPixelRatio = 1, this.isConstrainedSafari = !1, this.init();
6210
+ this.config = new Ke(i).validate(t), this.renderer = null, this.sceneManager = null, this.cameraManager = null, this.modelLoader = null, this.vrManager = null, this.arManager = null, this.stereoCamera = null, this.isVREnabled = this.config.vr?.enabled !== !1, this.isAREnabled = this.config.ar?.enabled === !0, this.stereoEnabled = this.config.stereo?.enabled === !0, this.stereoMode = this.config.stereo?.mode || "sbs";
6211
+ const s = this.config.stereo?.eyeSeparation ?? 0.064;
6212
+ this.stereoEyeSeparation = Math.max(0.05, Math.min(0.07, s)), this.stereoEyeSeparation !== s && console.warn(`[BelowJS] Initial eye separation ${s}m clamped to ${this.stereoEyeSeparation}m (comfortable range for screens: 0.050-0.070m)`), this.dolly = null, this.isInitialized = !1, this.loadedModels = [], this.currentAbortController = null, this.skipRenderDuringLoad = !1, this.pixelRatioBeforeThrottle = 1, this.originalPixelRatio = 1, this.isConstrainedSafari = !1, this.init();
6098
6213
  }
6099
6214
  init() {
6100
6215
  try {
6101
- this.initRenderer(), this.sceneManager = new ks(this.config.scene), this.cameraManager = new Ws(this.config.camera), this.modelLoader = new O(this.renderer), this.isConstrainedSafari = this.modelLoader?.isIOSWebKit || !1, this.renderer?.getPixelRatio ? this.originalPixelRatio = this.renderer.getPixelRatio() : typeof window < "u" && (this.originalPixelRatio = window.devicePixelRatio || 1), this.pixelRatioBeforeThrottle = this.originalPixelRatio, this.isVREnabled && this.initVR(), this.isAREnabled && this.initAR(), this.cameraManager.initControls(this.renderer.domElement), this.setupEventListeners(), this.startRenderLoop(), this.isInitialized = !0, typeof window < "u" && ii.init(this), this.emit("initialized");
6216
+ this.initRenderer(), this.sceneManager = new Fs(this.config.scene), this.cameraManager = new Ws(this.config.camera), this.modelLoader = new O(this.renderer), this.isConstrainedSafari = this.modelLoader?.isIOSWebKit || !1, this.initStereo(), this.renderer?.getPixelRatio ? this.originalPixelRatio = this.renderer.getPixelRatio() : typeof window < "u" && (this.originalPixelRatio = window.devicePixelRatio || 1), this.pixelRatioBeforeThrottle = this.originalPixelRatio, this.isVREnabled && this.initVR(), this.isAREnabled && this.initAR(), this.cameraManager.initControls(this.renderer.domElement), this.setupEventListeners(), this.startRenderLoop(), this.isInitialized = !0, typeof window < "u" && ii.init(this), this.emit("initialized");
6102
6217
  } catch (e) {
6103
6218
  console.error("Failed to initialize BelowViewer:", e), this.emit("error", e);
6104
6219
  }
6105
6220
  }
6106
6221
  initRenderer() {
6107
- this.renderer = new u.WebGLRenderer({
6222
+ this.renderer = new g.WebGLRenderer({
6108
6223
  antialias: this.config.renderer.antialias,
6109
6224
  alpha: this.config.renderer.alpha,
6110
6225
  powerPreference: this.config.renderer.powerPreference,
6226
+ logarithmicDepthBuffer: this.config.renderer.logarithmicDepthBuffer,
6111
6227
  preserveDrawingBuffer: !0
6112
- }), this.renderer.setSize(this.container.clientWidth, this.container.clientHeight), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.shadowMap.enabled = !0, this.renderer.shadowMap.type = u.PCFSoftShadowMap, this.renderer.outputColorSpace = u.SRGBColorSpace;
6228
+ }), this.renderer.setSize(this.container.clientWidth, this.container.clientHeight), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.shadowMap.enabled = !0, this.renderer.shadowMap.type = g.PCFSoftShadowMap, this.renderer.outputColorSpace = g.SRGBColorSpace;
6113
6229
  const e = {
6114
- none: u.NoToneMapping,
6115
- linear: u.LinearToneMapping,
6116
- reinhard: u.ReinhardToneMapping,
6117
- cineon: u.CineonToneMapping,
6118
- "aces-filmic": u.ACESFilmicToneMapping
6230
+ none: g.NoToneMapping,
6231
+ linear: g.LinearToneMapping,
6232
+ reinhard: g.ReinhardToneMapping,
6233
+ cineon: g.CineonToneMapping,
6234
+ "aces-filmic": g.ACESFilmicToneMapping
6119
6235
  };
6120
6236
  this.config.renderer.toneMapping && e[this.config.renderer.toneMapping] && (this.renderer.toneMapping = e[this.config.renderer.toneMapping]), this.renderer.toneMappingExposure = this.config.renderer.toneMappingExposure, this.container.appendChild(this.renderer.domElement);
6121
6237
  }
6238
+ initStereo() {
6239
+ this.stereoCamera || (this.stereoCamera = new g.StereoCamera()), this.stereoCamera.eyeSep = this.stereoEyeSeparation;
6240
+ }
6122
6241
  initVR() {
6123
- this.dolly = new u.Group(), this.dolly.add(this.cameraManager.camera), this.sceneManager.scene.add(this.dolly);
6242
+ this.dolly = new g.Group(), this.dolly.add(this.cameraManager.camera), this.sceneManager.scene.add(this.dolly);
6124
6243
  const e = this.config.audioPath || "./sound/", t = this.config.enableVRAudio === !0;
6125
6244
  this.vrManager = new Mn(this.renderer, this.cameraManager.camera, this.sceneManager.scene, e, t, this.container), this.vrManager.setControls(this.cameraManager.controls), this.config.initialPositions && this.vrManager.setInitialPositions(this.config.initialPositions), this.vrManager.onModeToggle = () => {
6126
6245
  this.emit("vr-mode-toggle");
@@ -6142,7 +6261,7 @@ class _n extends je {
6142
6261
  }
6143
6262
  initAR() {
6144
6263
  const e = this.config.ar?.settings || {};
6145
- this.arManager = new kn(
6264
+ this.arManager = new Fn(
6146
6265
  this.renderer,
6147
6266
  this.cameraManager.camera,
6148
6267
  this.sceneManager.scene,
@@ -6229,10 +6348,10 @@ class _n extends je {
6229
6348
  }
6230
6349
  frameModel(e) {
6231
6350
  if (!e.userData.boundingBox) {
6232
- const o = new u.Box3().setFromObject(e);
6351
+ const o = new g.Box3().setFromObject(e);
6233
6352
  e.userData.boundingBox = o;
6234
6353
  }
6235
- const t = e.userData.boundingBox, i = t.getSize(new u.Vector3()).length(), s = t.getCenter(new u.Vector3());
6354
+ const t = e.userData.boundingBox, i = t.getSize(new g.Vector3()).length(), s = t.getCenter(new g.Vector3());
6236
6355
  this.cameraManager.frameObject(s, i);
6237
6356
  }
6238
6357
  /**
@@ -6244,11 +6363,11 @@ class _n extends je {
6244
6363
  */
6245
6364
  centerModelAndRecalculateBounds(e) {
6246
6365
  if (!e.userData.boundingBox) {
6247
- const s = new u.Box3().setFromObject(e);
6366
+ const s = new g.Box3().setFromObject(e);
6248
6367
  e.userData.boundingBox = s;
6249
6368
  }
6250
- const i = e.userData.boundingBox.getCenter(new u.Vector3());
6251
- return e.position.sub(i), e.userData.boundingBox = new u.Box3().setFromObject(e), i;
6369
+ const i = e.userData.boundingBox.getCenter(new g.Vector3());
6370
+ return e.position.sub(i), e.userData.boundingBox = new g.Box3().setFromObject(e), i;
6252
6371
  }
6253
6372
  startRenderLoop() {
6254
6373
  let e = 0;
@@ -6256,10 +6375,59 @@ class _n extends je {
6256
6375
  const s = Math.min((i - e) / 1e3, 0.1);
6257
6376
  e = i, this.vrManager && this.vrManager.update(s), this.arManager && this.arManager.update(s * 1e3), this.cameraManager && this.cameraManager.update(), this.emit("before-render", s);
6258
6377
  const o = this.renderer?.xr?.isPresenting;
6259
- this.renderer && this.sceneManager && this.cameraManager && (!this.skipRenderDuringLoad || o) && this.renderer.render(this.sceneManager.scene, this.cameraManager.camera);
6378
+ this.renderer && this.sceneManager && this.cameraManager && (!this.skipRenderDuringLoad || o) && (this.stereoEnabled && !o && this.stereoMode === "sbs" ? this.renderSbsStereo() : this.renderer.render(this.sceneManager.scene, this.cameraManager.camera));
6260
6379
  };
6261
6380
  this.renderer.setAnimationLoop(t);
6262
6381
  }
6382
+ renderSbsStereo() {
6383
+ if (!this.stereoCamera || !this.renderer || !this.sceneManager || !this.cameraManager)
6384
+ return;
6385
+ const e = this.renderer.getSize(new g.Vector2()), t = e.width, i = e.height, s = Math.floor(t / 2), o = t - s;
6386
+ this.stereoCamera.aspect = i > 0 ? s / i : 1, this.stereoCamera.update(this.cameraManager.camera), this.renderer.setScissorTest(!0), this.renderer.setViewport(0, 0, s, i), this.renderer.setScissor(0, 0, s, i), this.renderer.render(this.sceneManager.scene, this.stereoCamera.cameraL), this.renderer.setViewport(s, 0, o, i), this.renderer.setScissor(s, 0, o, i), this.renderer.render(this.sceneManager.scene, this.stereoCamera.cameraR), this.renderer.setScissorTest(!1), this.renderer.setViewport(0, 0, t, i);
6387
+ }
6388
+ /**
6389
+ * Enable or disable stereo rendering.
6390
+ *
6391
+ * Note: Stereo rendering (SBS) is automatically disabled when entering VR/XR mode,
6392
+ * as VR headsets provide native stereoscopic rendering. When exiting VR, stereo
6393
+ * rendering will resume if it was enabled before entering VR.
6394
+ *
6395
+ * @param {boolean} enabled - Whether stereo rendering is enabled.
6396
+ */
6397
+ setStereoEnabled(e) {
6398
+ this.stereoEnabled = e === !0, this.stereoEnabled && this.initStereo();
6399
+ }
6400
+ /**
6401
+ * Set the eye separation distance for stereo rendering.
6402
+ *
6403
+ * @param {number} eyeSeparation - Eye separation in meters (clamped to 0.050-0.070m for screen comfort).
6404
+ */
6405
+ setStereoEyeSeparation(e) {
6406
+ if (typeof e != "number" || Number.isNaN(e))
6407
+ return;
6408
+ const t = Math.max(0.05, Math.min(0.07, e));
6409
+ t !== e && console.warn(`[BelowJS] Eye separation ${e}m clamped to ${t}m (comfortable range for screens: 0.050-0.070m)`), this.stereoEyeSeparation = t, this.stereoCamera && (this.stereoCamera.eyeSep = t);
6410
+ }
6411
+ /**
6412
+ * Set the stereo mode (currently only 'sbs').
6413
+ *
6414
+ * @param {string} mode - Stereo mode string.
6415
+ */
6416
+ setStereoMode(e) {
6417
+ e === "sbs" && (this.stereoMode = e);
6418
+ }
6419
+ /**
6420
+ * Get the current stereo configuration.
6421
+ *
6422
+ * @returns {{enabled: boolean, mode: string, eyeSeparation: number}}
6423
+ */
6424
+ getStereoSettings() {
6425
+ return {
6426
+ enabled: this.stereoEnabled,
6427
+ mode: this.stereoMode,
6428
+ eyeSeparation: this.stereoEyeSeparation
6429
+ };
6430
+ }
6263
6431
  applyLoadRenderingConstraints(e) {
6264
6432
  if (!(!this.isConstrainedSafari || !this.renderer))
6265
6433
  if (e) {
@@ -6455,7 +6623,34 @@ class _n extends je {
6455
6623
  * @since 1.0.0
6456
6624
  */
6457
6625
  setVRComfortPreset(e) {
6458
- this.vrManager && this.vrManager.setComfortPreset(e);
6626
+ return this.vrManager ? this.vrManager.setComfortPreset(e) : !1;
6627
+ }
6628
+ /**
6629
+ * Enable or disable comfort mode.
6630
+ *
6631
+ * Works while in VR and before entering VR by pre-configuring locomotion settings.
6632
+ *
6633
+ * @param {boolean} enabled
6634
+ * @returns {boolean}
6635
+ */
6636
+ setVRComfortMode(e) {
6637
+ return this.vrManager ? this.vrManager.setComfortMode(e) : !1;
6638
+ }
6639
+ /**
6640
+ * Toggle comfort mode and return the new state.
6641
+ *
6642
+ * @returns {boolean}
6643
+ */
6644
+ toggleVRComfortMode() {
6645
+ return this.vrManager ? this.vrManager.toggleComfortMode() : !1;
6646
+ }
6647
+ /**
6648
+ * Check if comfort mode is enabled.
6649
+ *
6650
+ * @returns {boolean}
6651
+ */
6652
+ isVRComfortModeEnabled() {
6653
+ return this.vrManager ? this.vrManager.isComfortModeEnabled() : !1;
6459
6654
  }
6460
6655
  applyInitialPositions(e) {
6461
6656
  if (!e) return;
@@ -6463,7 +6658,7 @@ class _n extends je {
6463
6658
  t && e.vr && this.vrManager ? this.vrManager.applyVRPositions(e) : !t && e.desktop && this.applyDesktopPositions(e.desktop);
6464
6659
  }
6465
6660
  }
6466
- const si = new qe(), Fe = new R();
6661
+ const si = new je(), Fe = new L();
6467
6662
  class Ui extends Ds {
6468
6663
  /**
6469
6664
  * Constructs a new line segments geometry.
@@ -6534,7 +6729,7 @@ class Ui extends Ds {
6534
6729
  * @return {LineSegmentsGeometry} A reference to this geometry.
6535
6730
  */
6536
6731
  fromMesh(e) {
6537
- return this.fromWireframeGeometry(new Ts(e.geometry)), this;
6732
+ return this.fromWireframeGeometry(new Ls(e.geometry)), this;
6538
6733
  }
6539
6734
  /**
6540
6735
  * Setups this line segments geometry from the given line segments.
@@ -6548,12 +6743,12 @@ class Ui extends Ds {
6548
6743
  return this.setPositions(t.attributes.position.array), this;
6549
6744
  }
6550
6745
  computeBoundingBox() {
6551
- this.boundingBox === null && (this.boundingBox = new qe());
6746
+ this.boundingBox === null && (this.boundingBox = new je());
6552
6747
  const e = this.attributes.instanceStart, t = this.attributes.instanceEnd;
6553
6748
  e !== void 0 && t !== void 0 && (this.boundingBox.setFromBufferAttribute(e), si.setFromBufferAttribute(t), this.boundingBox.union(si));
6554
6749
  }
6555
6750
  computeBoundingSphere() {
6556
- this.boundingSphere === null && (this.boundingSphere = new St()), this.boundingBox === null && this.computeBoundingBox();
6751
+ this.boundingSphere === null && (this.boundingSphere = new Qt()), this.boundingBox === null && this.computeBoundingBox();
6557
6752
  const e = this.attributes.instanceStart, t = this.attributes.instanceEnd;
6558
6753
  if (e !== void 0 && t !== void 0) {
6559
6754
  const i = this.boundingSphere.center;
@@ -6567,7 +6762,7 @@ class Ui extends Ds {
6567
6762
  toJSON() {
6568
6763
  }
6569
6764
  }
6570
- Ne.line = {
6765
+ Ue.line = {
6571
6766
  worldUnits: { value: 1 },
6572
6767
  linewidth: { value: 1 },
6573
6768
  resolution: { value: new V(1, 1) },
@@ -6577,11 +6772,11 @@ Ne.line = {
6577
6772
  gapSize: { value: 1 }
6578
6773
  // todo FIX - maybe change to totalSize
6579
6774
  };
6580
- Pe.line = {
6775
+ Ne.line = {
6581
6776
  uniforms: bi.merge([
6582
- Ne.common,
6583
- Ne.fog,
6584
- Ne.line
6777
+ Ue.common,
6778
+ Ue.fog,
6779
+ Ue.line
6585
6780
  ]),
6586
6781
  vertexShader: (
6587
6782
  /* glsl */
@@ -6961,7 +7156,7 @@ Pe.line = {
6961
7156
  `
6962
7157
  )
6963
7158
  };
6964
- class Ve extends Ls {
7159
+ class Oe extends Ts {
6965
7160
  /**
6966
7161
  * Constructs a new line segments geometry.
6967
7162
  *
@@ -6974,9 +7169,9 @@ class Ve extends Ls {
6974
7169
  constructor(e) {
6975
7170
  super({
6976
7171
  type: "LineMaterial",
6977
- uniforms: bi.clone(Pe.line.uniforms),
6978
- vertexShader: Pe.line.vertexShader,
6979
- fragmentShader: Pe.line.fragmentShader,
7172
+ uniforms: bi.clone(Ne.line.uniforms),
7173
+ vertexShader: Ne.line.vertexShader,
7174
+ fragmentShader: Ne.line.fragmentShader,
6980
7175
  clipping: !0
6981
7176
  // required for clipping support
6982
7177
  }), this.isLineMaterial = !0, this.setValues(e);
@@ -7116,7 +7311,7 @@ class Ve extends Ls {
7116
7311
  this.defines && (e === !0 !== this.alphaToCoverage && (this.needsUpdate = !0), e === !0 ? this.defines.USE_ALPHA_TO_COVERAGE = "" : delete this.defines.USE_ALPHA_TO_COVERAGE);
7117
7312
  }
7118
7313
  }
7119
- const At = new Te(), oi = new R(), ni = new R(), _ = new Te(), G = new Te(), X = new Te(), lt = new R(), ct = new Ie(), P = new Fs(), ri = new R(), ke = new qe(), _e = new St(), Z = new Te();
7314
+ const At = new Le(), oi = new L(), ni = new L(), _ = new Le(), G = new Le(), X = new Le(), lt = new L(), ct = new Ie(), P = new ks(), ri = new L(), _e = new je(), Ge = new Qt(), Z = new Le();
7120
7315
  let $, ce;
7121
7316
  function ai(c, e, t) {
7122
7317
  return Z.set(0, 0, -e, 1).applyMatrix4(c.projectionMatrix), Z.multiplyScalar(1 / Z.w), Z.x = ce / t.width, Z.y = ce / t.height, Z.applyMatrix4(c.projectionMatrixInverse), Z.multiplyScalar(1 / Z.w), Math.abs(Math.max(Z.x, Z.y));
@@ -7125,7 +7320,7 @@ function Gn(c, e) {
7125
7320
  const t = c.matrixWorld, i = c.geometry, s = i.attributes.instanceStart, o = i.attributes.instanceEnd, n = Math.min(i.instanceCount, s.count);
7126
7321
  for (let r = 0, A = n; r < A; r++) {
7127
7322
  P.start.fromBufferAttribute(s, r), P.end.fromBufferAttribute(o, r), P.applyMatrix4(t);
7128
- const a = new R(), l = new R();
7323
+ const a = new L(), l = new L();
7129
7324
  $.distanceSqToSegment(P.start, P.end, l, a), l.distanceTo(a) < ce * 0.5 && e.push({
7130
7325
  point: l,
7131
7326
  pointOnLine: a,
@@ -7141,27 +7336,27 @@ function Gn(c, e) {
7141
7336
  function Pn(c, e, t) {
7142
7337
  const i = e.projectionMatrix, o = c.material.resolution, n = c.matrixWorld, r = c.geometry, A = r.attributes.instanceStart, a = r.attributes.instanceEnd, l = Math.min(r.instanceCount, A.count), h = -e.near;
7143
7338
  $.at(1, X), X.w = 1, X.applyMatrix4(e.matrixWorldInverse), X.applyMatrix4(i), X.multiplyScalar(1 / X.w), X.x *= o.x / 2, X.y *= o.y / 2, X.z = 0, lt.copy(X), ct.multiplyMatrices(e.matrixWorldInverse, n);
7144
- for (let d = 0, g = l; d < g; d++) {
7339
+ for (let d = 0, u = l; d < u; d++) {
7145
7340
  if (_.fromBufferAttribute(A, d), G.fromBufferAttribute(a, d), _.w = 1, G.w = 1, _.applyMatrix4(ct), G.applyMatrix4(ct), _.z > h && G.z > h)
7146
7341
  continue;
7147
7342
  if (_.z > h) {
7148
- const I = _.z - G.z, b = (_.z - h) / I;
7149
- _.lerp(G, b);
7343
+ const I = _.z - G.z, C = (_.z - h) / I;
7344
+ _.lerp(G, C);
7150
7345
  } else if (G.z > h) {
7151
- const I = G.z - _.z, b = (G.z - h) / I;
7152
- G.lerp(_, b);
7346
+ const I = G.z - _.z, C = (G.z - h) / I;
7347
+ G.lerp(_, C);
7153
7348
  }
7154
7349
  _.applyMatrix4(i), G.applyMatrix4(i), _.multiplyScalar(1 / _.w), G.multiplyScalar(1 / G.w), _.x *= o.x / 2, _.y *= o.y / 2, G.x *= o.x / 2, G.y *= o.y / 2, P.start.copy(_), P.start.z = 0, P.end.copy(G), P.end.z = 0;
7155
- const C = P.closestPointToPointParameter(lt, !0);
7156
- P.at(C, ri);
7157
- const E = Bt.lerp(_.z, G.z, C), f = E >= -1 && E <= 1, m = lt.distanceTo(ri) < ce * 0.5;
7350
+ const b = P.closestPointToPointParameter(lt, !0);
7351
+ P.at(b, ri);
7352
+ const E = Bt.lerp(_.z, G.z, b), f = E >= -1 && E <= 1, m = lt.distanceTo(ri) < ce * 0.5;
7158
7353
  if (f && m) {
7159
7354
  P.start.fromBufferAttribute(A, d), P.end.fromBufferAttribute(a, d), P.start.applyMatrix4(n), P.end.applyMatrix4(n);
7160
- const I = new R(), b = new R();
7161
- $.distanceSqToSegment(P.start, P.end, b, I), t.push({
7162
- point: b,
7355
+ const I = new L(), C = new L();
7356
+ $.distanceSqToSegment(P.start, P.end, C, I), t.push({
7357
+ point: C,
7163
7358
  pointOnLine: I,
7164
- distance: $.origin.distanceTo(b),
7359
+ distance: $.origin.distanceTo(C),
7165
7360
  object: c,
7166
7361
  face: null,
7167
7362
  faceIndex: d,
@@ -7171,14 +7366,14 @@ function Pn(c, e, t) {
7171
7366
  }
7172
7367
  }
7173
7368
  }
7174
- class Nn extends Qt {
7369
+ class Nn extends St {
7175
7370
  /**
7176
7371
  * Constructs a new wide line.
7177
7372
  *
7178
7373
  * @param {LineSegmentsGeometry} [geometry] - The line geometry.
7179
7374
  * @param {LineMaterial} [material] - The line material.
7180
7375
  */
7181
- constructor(e = new Ui(), t = new Ve({ color: Math.random() * 16777215 })) {
7376
+ constructor(e = new Ui(), t = new Oe({ color: Math.random() * 16777215 })) {
7182
7377
  super(e, t), this.isLineSegments2 = !0, this.type = "LineSegments2";
7183
7378
  }
7184
7379
  /**
@@ -7207,25 +7402,25 @@ class Nn extends Qt {
7207
7402
  const o = e.params.Line2 !== void 0 && e.params.Line2.threshold || 0;
7208
7403
  $ = e.ray;
7209
7404
  const n = this.matrixWorld, r = this.geometry, A = this.material;
7210
- ce = A.linewidth + o, r.boundingSphere === null && r.computeBoundingSphere(), _e.copy(r.boundingSphere).applyMatrix4(n);
7405
+ ce = A.linewidth + o, r.boundingSphere === null && r.computeBoundingSphere(), Ge.copy(r.boundingSphere).applyMatrix4(n);
7211
7406
  let a;
7212
7407
  if (i)
7213
7408
  a = ce * 0.5;
7214
7409
  else {
7215
- const h = Math.max(s.near, _e.distanceToPoint($.origin));
7410
+ const h = Math.max(s.near, Ge.distanceToPoint($.origin));
7216
7411
  a = ai(s, h, A.resolution);
7217
7412
  }
7218
- if (_e.radius += a, $.intersectsSphere(_e) === !1)
7413
+ if (Ge.radius += a, $.intersectsSphere(Ge) === !1)
7219
7414
  return;
7220
- r.boundingBox === null && r.computeBoundingBox(), ke.copy(r.boundingBox).applyMatrix4(n);
7415
+ r.boundingBox === null && r.computeBoundingBox(), _e.copy(r.boundingBox).applyMatrix4(n);
7221
7416
  let l;
7222
7417
  if (i)
7223
7418
  l = ce * 0.5;
7224
7419
  else {
7225
- const h = Math.max(s.near, ke.distanceToPoint($.origin));
7420
+ const h = Math.max(s.near, _e.distanceToPoint($.origin));
7226
7421
  l = ai(s, h, A.resolution);
7227
7422
  }
7228
- ke.expandByScalar(l), $.intersectsBox(ke) !== !1 && (i ? Gn(this, t) : Pn(this, s, t));
7423
+ _e.expandByScalar(l), $.intersectsBox(_e) !== !1 && (i ? Gn(this, t) : Pn(this, s, t));
7229
7424
  }
7230
7425
  onBeforeRender(e) {
7231
7426
  const t = this.material.uniforms;
@@ -7293,7 +7488,7 @@ class Ai extends Nn {
7293
7488
  * @param {LineGeometry} [geometry] - The line geometry.
7294
7489
  * @param {LineMaterial} [material] - The line material.
7295
7490
  */
7296
- constructor(e = new It(), t = new Ve({ color: Math.random() * 16777215 })) {
7491
+ constructor(e = new It(), t = new Oe({ color: Math.random() * 16777215 })) {
7297
7492
  super(e, t), this.isLine2 = !0, this.type = "Line2";
7298
7493
  }
7299
7494
  }
@@ -7340,24 +7535,24 @@ class Un {
7340
7535
  *
7341
7536
  * @param {MeasurementSystemConfig} config - Configuration object
7342
7537
  */
7343
- constructor({ scene: e, camera: t, renderer: i, controls: s, dolly: o, config: n = {}, theme: r = "dark", showMeasurementLabels: A = !1 }) {
7538
+ constructor({ scene: e, camera: t, renderer: i, controls: s, dolly: o, uiParent: n, getRaycastInfo: r, config: A = {}, theme: a = "dark", showMeasurementLabels: l = !1 }) {
7344
7539
  this.ghostSpheres = {
7345
7540
  left: null,
7346
7541
  right: null
7347
- }, this.MAX_SPHERES = 2, this.measurementSpheres = [], this.measurementLine = null, this.measurementLabel = null, this.previousTriggerState = {}, this.unifiedMeasurementPoints = [], this.unifiedMeasurementLine = null, this.desktopMeasurementPoints = [], this.desktopMeasurementLine = null, typeof window < "u" && (window.measurementSystem = this), this.scene = e, this.camera = t, this.renderer = i, this.controls = s, this.dolly = o, this.config = n, this.theme = r, this.showMeasurementLabels = A, this._raycastTargets = e && e.children ? e.children : [], this.enabled = !0, this.isVR = !1, this.measurementPanel = null, this.desktopMeasurementMode = !1, this.measurementSystemEnabled = !0, this.desktopMeasurementPoints = [], this.connectionLine = null, this.desktopMeasurementLine = null, this.measurementSprite = null, this.measurementCanvas = null, this.measurementTexture = null, this.lastClickTime = 0, this.lastTriggerTime = 0, this._wasInVR = !1, this.focusAnimation = null, this.mouse = new u.Vector2(), this.raycaster = new u.Raycaster();
7348
- const a = () => {
7349
- let l = null, h = null;
7350
- const d = null, g = null;
7351
- if (e && e.children && e.children.forEach((p) => {
7352
- p && p.inputSource && p.inputSource.handedness && (p.inputSource.handedness === "left" && (l = p), p.inputSource.handedness === "right" && (h = p));
7353
- }), (!l || !h) && i && i.xr && i.xr.getController)
7542
+ }, this.MAX_SPHERES = 2, this.measurementSpheres = [], this.measurementLine = null, this.measurementLabel = null, this.previousTriggerState = {}, this.unifiedMeasurementPoints = [], this.unifiedMeasurementLine = null, this.desktopMeasurementPoints = [], this.desktopMeasurementLine = null, typeof window < "u" && (window.measurementSystem = this), this.scene = e, this.camera = t, this.renderer = i, this.uiParent = n || null, this.getRaycastInfo = typeof r == "function" ? r : null, this.controls = s, this.dolly = o, this.config = A, this.theme = a, this.showMeasurementLabels = l, this._raycastTargets = e && e.children ? e.children : [], this.enabled = !0, this.isVR = !1, this.measurementPanel = null, this.desktopMeasurementMode = !1, this.measurementSystemEnabled = !0, this.measurementAvailable = !0, this.desktopMeasurementPoints = [], this.connectionLine = null, this.desktopMeasurementLine = null, this.measurementSprite = null, this.measurementCanvas = null, this.measurementTexture = null, this.lastClickTime = 0, this.lastTriggerTime = 0, this._wasInVR = !1, this.focusAnimation = null, this._cancelFocusOnUserInput = null, this.mouse = new g.Vector2(), this.raycaster = new g.Raycaster();
7543
+ const h = () => {
7544
+ let d = null, u = null;
7545
+ const p = null, b = null;
7546
+ if (e && e.children && e.children.forEach((E) => {
7547
+ E && E.inputSource && E.inputSource.handedness && (E.inputSource.handedness === "left" && (d = E), E.inputSource.handedness === "right" && (u = E));
7548
+ }), (!d || !u) && i && i.xr && i.xr.getController)
7354
7549
  try {
7355
- l = l || i.xr.getController(0), h = h || i.xr.getController(1);
7550
+ d = d || i.xr.getController(0), u = u || i.xr.getController(1);
7356
7551
  } catch {
7357
7552
  }
7358
- l && h ? (this.attachVR({ controller1: l, controller2: h, controllerGrip1: d, controllerGrip2: g }), this.ghostSpheres && this.ghostSpheres.left && this.ghostSpheres.right && (this.ghostSpheres.left.visible = !0, this.ghostSpheres.right.visible = !0)) : (this._ghostSphereAttachRetries || (this._ghostSphereAttachRetries = 0), this._ghostSphereAttachRetries < 40 ? (this._ghostSphereAttachRetries++, setTimeout(a, 250)) : typeof window < "u" && window.console && console.warn("[MeasurementSystem] Could not find VR controllers to attach ghost spheres after multiple attempts."));
7553
+ d && u ? (this.attachVR({ controller1: d, controller2: u, controllerGrip1: p, controllerGrip2: b }), this.ghostSpheres && this.ghostSpheres.left && this.ghostSpheres.right && (this.ghostSpheres.left.visible = !0, this.ghostSpheres.right.visible = !0)) : (this._ghostSphereAttachRetries || (this._ghostSphereAttachRetries = 0), this._ghostSphereAttachRetries < 40 ? (this._ghostSphereAttachRetries++, setTimeout(h, 250)) : typeof window < "u" && window.console && console.warn("[MeasurementSystem] Could not find VR controllers to attach ghost spheres after multiple attempts."));
7359
7554
  };
7360
- if (a(), i && i.xr && i.xr.addEventListener && i.xr.addEventListener("sessionstart", a), this.sphereGeometry = new u.SphereGeometry(0.02, 8, 6), this.placedMaterial = new u.MeshBasicMaterial({ color: 16777215 }), this.vrLineMaterial = new Ve({
7555
+ if (h(), i && i.xr && i.xr.addEventListener && i.xr.addEventListener("sessionstart", h), this.sphereGeometry = new g.SphereGeometry(0.02, 8, 6), this.placedMaterial = new g.MeshBasicMaterial({ color: 16777215 }), this.vrLineMaterial = new Oe({
7361
7556
  color: 16777215,
7362
7557
  linewidth: 3,
7363
7558
  transparent: !0,
@@ -7365,7 +7560,7 @@ class Un {
7365
7560
  depthTest: !1,
7366
7561
  vertexColors: !1,
7367
7562
  dashed: !1
7368
- }), this.desktopLineMaterial = new Ve({
7563
+ }), this.desktopLineMaterial = new Oe({
7369
7564
  color: 16777215,
7370
7565
  linewidth: 3,
7371
7566
  transparent: !0,
@@ -7374,19 +7569,19 @@ class Un {
7374
7569
  vertexColors: !1,
7375
7570
  dashed: !1
7376
7571
  }), this.MAX_DESKTOP_POINTS = 2, this.DRAG_THRESHOLD = 5, this.isDragging = !1, this.dragStartPosition = { x: 0, y: 0 }, this.createMeasurementPanel(), this.updateMeasurementPanel(), this._boundOnMouseClick = this.onMouseClick.bind(this), this._boundOnMouseDown = this.onMouseDown.bind(this), this._boundOnMouseMove = this.onMouseMove.bind(this), this._boundOnMouseUp = this.onMouseUp.bind(this), this.renderer.domElement.addEventListener("click", this._boundOnMouseClick, !1), this.renderer.domElement.addEventListener("mousedown", this._boundOnMouseDown, !1), this.renderer.domElement.addEventListener("mousemove", this._boundOnMouseMove, !1), this.renderer.domElement.addEventListener("mouseup", this._boundOnMouseUp, !1), i && i.xr && typeof i.xr.getController == "function") {
7377
- const l = () => {
7572
+ const d = () => {
7378
7573
  if (i.xr.isPresenting) {
7379
- const h = i.xr.getController(0), d = i.xr.getController(1), g = i.xr.getControllerGrip ? i.xr.getControllerGrip(0) : void 0, p = i.xr.getControllerGrip ? i.xr.getControllerGrip(1) : void 0;
7380
- this.attachVR({ controller1: h, controller2: d, controllerGrip1: g, controllerGrip2: p });
7574
+ const u = i.xr.getController(0), p = i.xr.getController(1), b = i.xr.getControllerGrip ? i.xr.getControllerGrip(0) : void 0, E = i.xr.getControllerGrip ? i.xr.getControllerGrip(1) : void 0;
7575
+ this.attachVR({ controller1: u, controller2: p, controllerGrip1: b, controllerGrip2: E });
7381
7576
  }
7382
7577
  };
7383
- if (i.xr.addEventListener && i.xr.addEventListener("sessionstart", l), i.xr.isPresenting && l(), i.xr && typeof i.xr.requestSession == "function" && !i.xr._measurementSystemPatched) {
7384
- const h = i.xr.requestSession.bind(i.xr);
7385
- i.xr.requestSession = async (...d) => {
7386
- const g = await h(...d);
7578
+ if (i.xr.addEventListener && i.xr.addEventListener("sessionstart", d), i.xr.isPresenting && d(), i.xr && typeof i.xr.requestSession == "function" && !i.xr._measurementSystemPatched) {
7579
+ const u = i.xr.requestSession.bind(i.xr);
7580
+ i.xr.requestSession = async (...p) => {
7581
+ const b = await u(...p);
7387
7582
  return setTimeout(() => {
7388
- l();
7389
- }, 100), g;
7583
+ d();
7584
+ }, 100), b;
7390
7585
  }, i.xr._measurementSystemPatched = !0;
7391
7586
  }
7392
7587
  }
@@ -7446,7 +7641,10 @@ class Un {
7446
7641
  }), this.unifiedMeasurementPoints.length = 0), this.unifiedMeasurementLine && (this.scene.remove(this.unifiedMeasurementLine), this.unifiedMeasurementLine = null), this.measurementSprite && (this.measurementSprite.visible = !1, this.scene.remove(this.measurementSprite), this.measurementSprite = null), this.updateMeasurementPanel();
7447
7642
  }
7448
7643
  clearVRMeasurement() {
7449
- this.measurementSpheres && (this.measurementSpheres.forEach((e) => this.scene.remove(e)), this.measurementSpheres.length = 0), this.measurementLine && (this.scene.remove(this.measurementLine), this.measurementLine = null), this.measurementLabel && (this.scene.remove(this.measurementLabel), this.measurementLabel = null), this.placedSpheres && (this.placedSpheres.forEach((e) => this.scene.remove(e)), this.placedSpheres.length = 0), this.connectionLine && (this.scene.remove(this.connectionLine), this.connectionLine = null), this.measurementSprite && (this.measurementSprite.visible = !1), this.measurementSystemEnabled = !0, this.updateMeasurementPanel();
7644
+ this.measurementSpheres && (this.measurementSpheres.forEach((e) => this.scene.remove(e)), this.measurementSpheres.length = 0), this.measurementLine && (this.scene.remove(this.measurementLine), this.measurementLine = null), this.measurementLabel && (this.scene.remove(this.measurementLabel), this.measurementLabel = null), this.placedSpheres && (this.placedSpheres.forEach((e) => this.scene.remove(e)), this.placedSpheres.length = 0), this.connectionLine && (this.scene.remove(this.connectionLine), this.connectionLine = null), this.measurementSprite && (this.measurementSprite.visible = !1), this.measurementSystemEnabled = this.measurementAvailable, this.updateMeasurementPanel();
7645
+ }
7646
+ setMeasurementAvailability(e) {
7647
+ this.measurementAvailable = e !== !1, this.measurementAvailable ? (this.measurementSystemEnabled = !0, this.renderer && this.renderer.xr && this.renderer.xr.isPresenting && (this.ghostSpheres.left && (this.ghostSpheres.left.visible = !0), this.ghostSpheres.right && (this.ghostSpheres.right.visible = !0))) : (this.desktopMeasurementMode = !1, this.measurementSystemEnabled = !1, this.clearUnifiedMeasurement(), this.clearLegacyDesktopMeasurement(), this.clearLegacyVRMeasurement(), this.ghostSpheres.left && (this.ghostSpheres.left.visible = !1), this.ghostSpheres.right && (this.ghostSpheres.right.visible = !1), this.setRaycastTargets([])), this.updateMeasurementPanel();
7450
7648
  }
7451
7649
  /**
7452
7650
  * Clear legacy VR measurements (old system compatibility)
@@ -7459,16 +7657,16 @@ class Un {
7459
7657
  syncToVR() {
7460
7658
  if (this.desktopMeasurementPoints.length === 2) {
7461
7659
  if (this.clearVRMeasurement(), this.desktopMeasurementPoints.forEach((e) => {
7462
- const t = new u.Mesh(this.sphereGeometry, this.placedMaterial);
7660
+ const t = new g.Mesh(this.sphereGeometry, this.placedMaterial);
7463
7661
  t.position.copy(e.position), this.scene.add(t), this.measurementSpheres.push(t);
7464
7662
  }), this.measurementSpheres.length === 2) {
7465
- const e = new u.BufferGeometry().setFromPoints([
7663
+ const e = new g.BufferGeometry().setFromPoints([
7466
7664
  this.measurementSpheres[0].position,
7467
7665
  this.measurementSpheres[1].position
7468
- ]), t = this.vrLineMaterial || new u.LineBasicMaterial({ color: 16777215, transparent: !0, opacity: 0.8, depthTest: !1 });
7469
- this.connectionLine = new u.Line(e, t), this.scene.add(this.connectionLine), this.createMeasurementDisplay(this.measurementSpheres[0].position.distanceTo(this.measurementSpheres[1].position)), this.measurementSprite && !this.scene.children.includes(this.measurementSprite) && this.scene.add(this.measurementSprite);
7666
+ ]), t = this.vrLineMaterial || new g.LineBasicMaterial({ color: 16777215, transparent: !0, opacity: 0.8, depthTest: !1 });
7667
+ this.connectionLine = new g.Line(e, t), this.scene.add(this.connectionLine), this.createMeasurementDisplay(this.measurementSpheres[0].position.distanceTo(this.measurementSpheres[1].position)), this.measurementSprite && !this.scene.children.includes(this.measurementSprite) && this.scene.add(this.measurementSprite);
7470
7668
  }
7471
- this.measurementSystemEnabled = !0, this.updateMeasurementPanel();
7669
+ this.measurementSystemEnabled = this.measurementAvailable, this.updateMeasurementPanel();
7472
7670
  }
7473
7671
  }
7474
7672
  syncToDesktop() {
@@ -7478,10 +7676,10 @@ class Un {
7478
7676
  const t = this.measurementSpheres[e].position.clone();
7479
7677
  let i = t;
7480
7678
  if (this._raycastTargets && this._raycastTargets.length > 0 && this.camera) {
7481
- const o = t.clone().sub(this.camera.position).normalize(), r = new u.Raycaster(this.camera.position, o).intersectObjects(this._raycastTargets, !0);
7679
+ const o = t.clone().sub(this.camera.position).normalize(), r = new g.Raycaster(this.camera.position, o).intersectObjects(this._raycastTargets, !0);
7482
7680
  r.length > 0 && (i = r[0].point);
7483
7681
  }
7484
- const s = new u.Mesh(this.sphereGeometry, this.placedMaterial);
7682
+ const s = new g.Mesh(this.sphereGeometry, this.placedMaterial);
7485
7683
  s.position.copy(i), this.scene.add(s), this.desktopMeasurementPoints.push(s);
7486
7684
  }
7487
7685
  if (this.desktopMeasurementPoints.length === 2) {
@@ -7496,7 +7694,7 @@ class Un {
7496
7694
  ]), this.desktopMeasurementLine = new Ai(e, this.desktopLineMaterial), this.desktopMeasurementLine.computeLineDistances(), this.scene.add(this.desktopMeasurementLine);
7497
7695
  const t = this.desktopMeasurementPoints[0].position.distanceTo(this.desktopMeasurementPoints[1].position);
7498
7696
  if (this.createMeasurementDisplay(t), this.measurementSprite) {
7499
- const i = new u.Vector3();
7697
+ const i = new g.Vector3();
7500
7698
  i.addVectors(this.desktopMeasurementPoints[0].position, this.desktopMeasurementPoints[1].position), i.multiplyScalar(0.5);
7501
7699
  const s = Math.max(0.05, Math.min(0.2, t * 0.03));
7502
7700
  i.y += s, this.measurementSprite.position.copy(i), this.measurementSprite.visible = !1, this.scene.children.includes(this.measurementSprite) || this.scene.add(this.measurementSprite);
@@ -7505,6 +7703,10 @@ class Un {
7505
7703
  this.updateMeasurementPanel();
7506
7704
  }
7507
7705
  }
7706
+ formatDistance(e) {
7707
+ const t = e * 100;
7708
+ return t <= 20 ? `${t.toFixed(2)} cm` : `${e.toFixed(2)}m`;
7709
+ }
7508
7710
  createMeasurementDisplay(e) {
7509
7711
  const t = (window.devicePixelRatio || 1) * 4, i = 256, s = 64, o = i * t, n = s * t;
7510
7712
  this.measurementCanvas || (this.measurementCanvas = document.createElement("canvas")), (this.measurementCanvas.width !== o || this.measurementCanvas.height !== n) && (this.measurementCanvas.width = o, this.measurementCanvas.height = n);
@@ -7515,14 +7717,14 @@ class Un {
7515
7717
  e <= 2 ? a = 0.4 + e / 2 * 0.3 : e <= 4 ? a = 0.7 + (e - 2) / 2 * 0.2 : a = 0.9 + Math.min((e - 4) / 16, 1) * 0.5;
7516
7718
  const l = Math.round(A * a);
7517
7719
  r.font = `600 ${l}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif`;
7518
- const h = `${e.toFixed(2)}m`, g = r.measureText(h).width, p = l, C = Math.max(6, l * 0.3), E = g + C * 2, f = p + C * 2, m = (i - E) / 2, I = (s - f) / 2;
7519
- if (r.fillStyle = "rgba(0, 0, 0, 0.8)", r.beginPath(), r.roundRect(m, I, E, f, Math.max(4, l * 0.2)), r.fill(), r.fillStyle = "white", r.textAlign = "center", r.textBaseline = "middle", r.fillText(h, i / 2, s / 2), r.restore(), this.measurementTexture ? this.measurementTexture.needsUpdate = !0 : (this.measurementTexture = new u.CanvasTexture(this.measurementCanvas), this.measurementTexture.minFilter = u.LinearFilter, this.measurementTexture.magFilter = u.LinearFilter), !this.measurementSprite) {
7520
- const w = new u.SpriteMaterial({
7720
+ const h = this.formatDistance(e), u = r.measureText(h).width, p = l, b = Math.max(6, l * 0.3), E = u + b * 2, f = p + b * 2, m = (i - E) / 2, I = (s - f) / 2;
7721
+ if (r.fillStyle = "rgba(0, 0, 0, 0.8)", r.beginPath(), r.roundRect(m, I, E, f, Math.max(4, l * 0.2)), r.fill(), r.fillStyle = "white", r.textAlign = "center", r.textBaseline = "middle", r.fillText(h, i / 2, s / 2), r.restore(), this.measurementTexture ? this.measurementTexture.needsUpdate = !0 : (this.measurementTexture = new g.CanvasTexture(this.measurementCanvas), this.measurementTexture.minFilter = g.LinearFilter, this.measurementTexture.magFilter = g.LinearFilter), !this.measurementSprite) {
7722
+ const w = new g.SpriteMaterial({
7521
7723
  map: this.measurementTexture,
7522
7724
  depthTest: !1,
7523
7725
  depthWrite: !1
7524
7726
  });
7525
- this.measurementSprite = new u.Sprite(w);
7727
+ this.measurementSprite = new g.Sprite(w);
7526
7728
  }
7527
7729
  const B = 0.3 * a, y = i / s;
7528
7730
  return this.measurementSprite.scale.set(B * y, B, 1), this.measurementSprite;
@@ -7554,7 +7756,7 @@ class Un {
7554
7756
  */
7555
7757
  attachVR({ controller1: e, controller2: t, controllerGrip1: i, controllerGrip2: s }) {
7556
7758
  this.controller1 = e, this.controller2 = t, this.controllerGrip1 = i, this.controllerGrip2 = s;
7557
- const o = new u.MeshBasicMaterial({
7759
+ const o = new g.MeshBasicMaterial({
7558
7760
  color: 8947848,
7559
7761
  // ghostly grey
7560
7762
  transparent: !0,
@@ -7562,7 +7764,7 @@ class Un {
7562
7764
  depthTest: !1,
7563
7765
  depthWrite: !1
7564
7766
  });
7565
- this.ghostSpheres.left && this.ghostSpheres.left.parent && this.ghostSpheres.left.parent.remove(this.ghostSpheres.left), this.ghostSpheres.right && this.ghostSpheres.right.parent && this.ghostSpheres.right.parent.remove(this.ghostSpheres.right), this.ghostSpheres.left = new u.Mesh(this.sphereGeometry, o.clone()), this.ghostSpheres.right = new u.Mesh(this.sphereGeometry, o.clone()), this.ghostSpheres.left.scale.set(1, 1, 1), this.ghostSpheres.right.scale.set(1, 1, 1), this.ghostSpheres.left.position.set(0, 0, -0.05), this.ghostSpheres.right.position.set(0, 0, -0.05), this.ghostSpheres.left.visible = !0, this.ghostSpheres.right.visible = !0, this.controller1 && this.controller1.add(this.ghostSpheres.left), this.controller2 && this.controller2.add(this.ghostSpheres.right), this.yButtonPressed = !1, this.MAX_SPHERES = 2, this.triggerState = {
7767
+ this.ghostSpheres.left && this.ghostSpheres.left.parent && this.ghostSpheres.left.parent.remove(this.ghostSpheres.left), this.ghostSpheres.right && this.ghostSpheres.right.parent && this.ghostSpheres.right.parent.remove(this.ghostSpheres.right), this.ghostSpheres.left = new g.Mesh(this.sphereGeometry, o.clone()), this.ghostSpheres.right = new g.Mesh(this.sphereGeometry, o.clone()), this.ghostSpheres.left.scale.set(0.5, 0.5, 0.5), this.ghostSpheres.right.scale.set(0.5, 0.5, 0.5), this.ghostSpheres.left.position.set(0, 0, -0.07), this.ghostSpheres.right.position.set(0, 0, -0.07), this.ghostSpheres.left.visible = !0, this.ghostSpheres.right.visible = !0, this.controller1 && this.controller1.add(this.ghostSpheres.left), this.controller2 && this.controller2.add(this.ghostSpheres.right), this.yButtonPressed = !1, this.MAX_SPHERES = 2, this.triggerState = {
7566
7768
  left: !1,
7567
7769
  right: !1
7568
7770
  }, this._onVRTriggerDown = this._onVRTriggerDown.bind(this), this._onVRTriggerUp = this._onVRTriggerUp.bind(this), this._onVRYButtonDown = this._onVRYButtonDown.bind(this), this._onVRYButtonUp = this._onVRYButtonUp.bind(this), this.controller1 && this.controller2 && (this.controller1.addEventListener("selectstart", this._onVRTriggerDown), this.controller1.addEventListener("selectend", this._onVRTriggerUp), this.controller2.addEventListener("selectstart", this._onVRTriggerDown), this.controller2.addEventListener("selectend", this._onVRTriggerUp), this.controller1.addEventListener("ybuttondown", this._onVRYButtonDown), this.controller1.addEventListener("ybuttonup", this._onVRYButtonUp), this.controller2.addEventListener("ybuttondown", this._onVRYButtonDown), this.controller2.addEventListener("ybuttonup", this._onVRYButtonUp)), this.isVR = !0, this.refreshMeasurementDisplayForVR();
@@ -7570,15 +7772,16 @@ class Un {
7570
7772
  _onVRTriggerDown() {
7571
7773
  }
7572
7774
  _onVRTriggerUp(e) {
7775
+ if (!this.measurementAvailable) return;
7573
7776
  const t = e.target, i = performance.now();
7574
7777
  if (!(this.lastTriggerTime && i - this.lastTriggerTime < 200) && (this.lastTriggerTime = i, this.measurementSystemEnabled)) {
7575
- const s = new u.Vector3();
7778
+ const s = new g.Vector3();
7576
7779
  let o = null;
7577
7780
  if (t === this.controller1 && this.ghostSpheres.left ? o = this.ghostSpheres.left : t === this.controller2 && this.ghostSpheres.right && (o = this.ghostSpheres.right), o)
7578
7781
  o.getWorldPosition(s);
7579
7782
  else {
7580
7783
  t.getWorldPosition(s);
7581
- const n = new u.Vector3(0, 0, -0.05);
7784
+ const n = new g.Vector3(0, 0, -0.05);
7582
7785
  n.applyQuaternion(t.quaternion), s.add(n);
7583
7786
  }
7584
7787
  this._placeVRMeasurementPoint(s);
@@ -7590,11 +7793,11 @@ class Un {
7590
7793
  _onVRYButtonUp() {
7591
7794
  }
7592
7795
  _getVRControllerIntersection(e) {
7593
- const t = new u.Matrix4();
7796
+ const t = new g.Matrix4();
7594
7797
  t.identity().extractRotation(e.matrixWorld);
7595
- const i = new u.Vector3(), s = new u.Vector3(0, 0, -1).applyMatrix4(t);
7798
+ const i = new g.Vector3(), s = new g.Vector3(0, 0, -1).applyMatrix4(t);
7596
7799
  e.getWorldPosition(i);
7597
- const r = new u.Raycaster(i, s.normalize()).intersectObjects(this.scene.children, !0).filter((A) => {
7800
+ const r = new g.Raycaster(i, s.normalize()).intersectObjects(this.scene.children, !0).filter((A) => {
7598
7801
  const a = this.unifiedMeasurementPoints.some((d) => d.sphere === A.object), l = A.object === this.unifiedMeasurementLine, h = this.isMeasurementHelper(A.object);
7599
7802
  return !a && !l && !h;
7600
7803
  });
@@ -7621,8 +7824,8 @@ class Un {
7621
7824
  const s = this.unifiedMeasurementPoints.shift();
7622
7825
  s.sphere && this.scene.remove(s.sphere);
7623
7826
  }
7624
- const i = new u.Mesh(this.sphereGeometry, this.placedMaterial);
7625
- i.position.copy(e), i.userData.isMeasurementSphere = !0, this.scene.add(i), this.unifiedMeasurementPoints.push({
7827
+ const i = new g.Mesh(this.sphereGeometry, this.placedMaterial);
7828
+ i.position.copy(e), i.scale.setScalar(0.5), i.userData.isMeasurementSphere = !0, this.scene.add(i), this.unifiedMeasurementPoints.push({
7626
7829
  position: e.clone(),
7627
7830
  sphere: i,
7628
7831
  source: t
@@ -7643,13 +7846,17 @@ class Un {
7643
7846
  t.z
7644
7847
  ]), this.unifiedMeasurementLine = new Ai(i, this.desktopLineMaterial), this.unifiedMeasurementLine.computeLineDistances(), this.unifiedMeasurementLine.userData.isMeasurementLine = !0, this.scene.add(this.unifiedMeasurementLine);
7645
7848
  const s = e.distanceTo(t);
7646
- if (this.createMeasurementDisplay(s), this.measurementSprite) {
7647
- const o = new u.Vector3();
7648
- o.addVectors(e, t), o.multiplyScalar(0.5);
7649
- const n = Math.max(0.05, Math.min(0.2, s * 0.03));
7650
- o.y += n, this.measurementSprite.position.copy(o), this.scene.children.includes(this.measurementSprite) || this.scene.add(this.measurementSprite);
7651
- const r = this.renderer && this.renderer.xr && this.renderer.xr.isPresenting;
7652
- this.measurementSprite.visible = r || this.showMeasurementLabels;
7849
+ this.createMeasurementDisplay(s);
7850
+ const o = s * 100 <= 20 ? 0.125 : 0.5;
7851
+ if (this.unifiedMeasurementPoints.forEach((n) => {
7852
+ n.sphere && n.sphere.scale.setScalar(o);
7853
+ }), this.measurementSprite) {
7854
+ const n = new g.Vector3();
7855
+ n.addVectors(e, t), n.multiplyScalar(0.5);
7856
+ const r = Math.max(0.05, Math.min(0.2, s * 0.03));
7857
+ n.y += r, this.measurementSprite.position.copy(n), this.scene.children.includes(this.measurementSprite) || this.scene.add(this.measurementSprite);
7858
+ const A = this.renderer && this.renderer.xr && this.renderer.xr.isPresenting;
7859
+ this.measurementSprite.visible = A || this.showMeasurementLabels;
7653
7860
  }
7654
7861
  this.desktopMeasurementMode || (this.desktopMeasurementMode = !0);
7655
7862
  }
@@ -7659,7 +7866,7 @@ class Un {
7659
7866
  * Useful when VR coordinate systems get corrupted (e.g., returning from Quest browser)
7660
7867
  */
7661
7868
  resetGhostSpherePositions() {
7662
- this.isVR && this.ghostSpheres && (this.ghostSpheres.left && this.controller1 && this.ghostSpheres.left.parent === this.controller1 && (this.ghostSpheres.left.position.set(0, 0, -0.05), this.ghostSpheres.left.rotation.set(0, 0, 0), this.ghostSpheres.left.scale.set(1, 1, 1)), this.ghostSpheres.right && this.controller2 && this.ghostSpheres.right.parent === this.controller2 && (this.ghostSpheres.right.position.set(0, 0, -0.05), this.ghostSpheres.right.rotation.set(0, 0, 0), this.ghostSpheres.right.scale.set(1, 1, 1)));
7869
+ this.isVR && this.ghostSpheres && (this.ghostSpheres.left && this.controller1 && this.ghostSpheres.left.parent === this.controller1 && (this.ghostSpheres.left.position.set(0, 0, -0.07), this.ghostSpheres.left.rotation.set(0, 0, 0), this.ghostSpheres.left.scale.set(1, 1, 1)), this.ghostSpheres.right && this.controller2 && this.ghostSpheres.right.parent === this.controller2 && (this.ghostSpheres.right.position.set(0, 0, -0.07), this.ghostSpheres.right.rotation.set(0, 0, 0), this.ghostSpheres.right.scale.set(1, 1, 1)));
7663
7870
  }
7664
7871
  /**
7665
7872
  * Update method called each frame by the render loop
@@ -7686,27 +7893,38 @@ class Un {
7686
7893
  * @since 1.0.0
7687
7894
  */
7688
7895
  dispose() {
7689
- this.measurementPanel && this.measurementPanel.parentNode && (this.measurementPanel.parentNode.removeChild(this.measurementPanel), this.measurementPanel = null), this.renderer.domElement.removeEventListener("click", this._boundOnMouseClick, !1), this.renderer.domElement.removeEventListener("mousedown", this._boundOnMouseDown, !1), this.renderer.domElement.removeEventListener("mousemove", this._boundOnMouseMove, !1), this.renderer.domElement.removeEventListener("mouseup", this._boundOnMouseUp, !1), this.controller1 && this.controller2 && (this.controller1.removeEventListener("selectstart", this._onVRTriggerDown), this.controller1.removeEventListener("selectend", this._onVRTriggerUp), this.controller2.removeEventListener("selectstart", this._onVRTriggerDown), this.controller2.removeEventListener("selectend", this._onVRTriggerUp), this.controller1.removeEventListener("ybuttondown", this._onVRYButtonDown), this.controller1.removeEventListener("ybuttonup", this._onVRYButtonUp), this.controller2.removeEventListener("ybuttondown", this._onVRYButtonDown), this.controller2.removeEventListener("ybuttonup", this._onVRYButtonUp)), this.clearLegacyDesktopMeasurement(), this.clearVRMeasurement(), this.ghostSpheres && (this.ghostSpheres.left && this.scene.remove(this.ghostSpheres.left), this.ghostSpheres.right && this.scene.remove(this.ghostSpheres.right), this.ghostSpheres = null), this.measurementSprite && this.scene.children.includes(this.measurementSprite) && (this.scene.remove(this.measurementSprite), this.measurementSprite = null), this.connectionLine && this.scene.children.includes(this.connectionLine) && (this.scene.remove(this.connectionLine), this.connectionLine = null), this.measurementSpheres = [], this.isVR = !1, typeof window < "u" && window.measurementSystem === this && (window.measurementSystem = void 0);
7896
+ this.measurementPanel && this.measurementPanel.parentNode && (this.measurementPanel.parentNode.removeChild(this.measurementPanel), this.measurementPanel = null), this.focusAnimation && (cancelAnimationFrame(this.focusAnimation), this.focusAnimation = null), this.controls && this._cancelFocusOnUserInput && (this.controls.removeEventListener("start", this._cancelFocusOnUserInput), this._cancelFocusOnUserInput = null), this.renderer.domElement.removeEventListener("click", this._boundOnMouseClick, !1), this.renderer.domElement.removeEventListener("mousedown", this._boundOnMouseDown, !1), this.renderer.domElement.removeEventListener("mousemove", this._boundOnMouseMove, !1), this.renderer.domElement.removeEventListener("mouseup", this._boundOnMouseUp, !1), this.controller1 && this.controller2 && (this.controller1.removeEventListener("selectstart", this._onVRTriggerDown), this.controller1.removeEventListener("selectend", this._onVRTriggerUp), this.controller2.removeEventListener("selectstart", this._onVRTriggerDown), this.controller2.removeEventListener("selectend", this._onVRTriggerUp), this.controller1.removeEventListener("ybuttondown", this._onVRYButtonDown), this.controller1.removeEventListener("ybuttonup", this._onVRYButtonUp), this.controller2.removeEventListener("ybuttondown", this._onVRYButtonDown), this.controller2.removeEventListener("ybuttonup", this._onVRYButtonUp)), this.clearLegacyDesktopMeasurement(), this.clearVRMeasurement(), this.ghostSpheres && (this.ghostSpheres.left && this.scene.remove(this.ghostSpheres.left), this.ghostSpheres.right && this.scene.remove(this.ghostSpheres.right), this.ghostSpheres = null), this.measurementSprite && this.scene.children.includes(this.measurementSprite) && (this.scene.remove(this.measurementSprite), this.measurementSprite = null), this.connectionLine && this.scene.children.includes(this.connectionLine) && (this.scene.remove(this.connectionLine), this.connectionLine = null), this.measurementSpheres = [], this.isVR = !1, typeof window < "u" && window.measurementSystem === this && (window.measurementSystem = void 0);
7690
7897
  }
7691
7898
  createMeasurementPanel() {
7692
7899
  const e = document.createElement("div");
7693
7900
  e.className = `measurement-panel${this.theme === "light" ? " light-theme" : ""}`, e.addEventListener("click", () => {
7901
+ if (!this.measurementAvailable) {
7902
+ this.updateMeasurementPanel();
7903
+ return;
7904
+ }
7694
7905
  this.renderer && this.renderer.xr && this.renderer.xr.isPresenting ? (this.measurementSystemEnabled = !this.measurementSystemEnabled, this.measurementSystemEnabled ? (this.ghostSpheres.left && (this.ghostSpheres.left.visible = !0), this.ghostSpheres.right && (this.ghostSpheres.right.visible = !0), this.resetGhostSpherePositions()) : (this.clearUnifiedMeasurement(), this.ghostSpheres.left && (this.ghostSpheres.left.visible = !1), this.ghostSpheres.right && (this.ghostSpheres.right.visible = !1)), this.updateMeasurementPanel()) : (this.desktopMeasurementMode = !this.desktopMeasurementMode, this.desktopMeasurementMode || this.clearUnifiedMeasurement(), this.updateMeasurementPanel());
7695
- }), (this.renderer && this.renderer.domElement && this.renderer.domElement.parentElement || document.body).appendChild(e), this.measurementPanel = e;
7906
+ }), (this.uiParent || this.renderer && this.renderer.domElement && this.renderer.domElement.parentElement || document.body).appendChild(e), this.measurementPanel = e;
7696
7907
  }
7697
7908
  updateMeasurementPanel() {
7698
7909
  const e = this.measurementPanel;
7699
7910
  if (!e) return;
7700
7911
  const t = this.renderer && this.renderer.xr && this.renderer.xr.isPresenting, i = this.unifiedMeasurementPoints ? this.unifiedMeasurementPoints.length : 0, s = i === 2, o = t ? this.measurementSystemEnabled : this.desktopMeasurementMode;
7701
7912
  let n;
7702
- if (s && (n = this.unifiedMeasurementPoints[0].position.distanceTo(this.unifiedMeasurementPoints[1].position)), e.classList.remove("disabled", "active", "measured"), !o)
7913
+ if (s && (n = this.unifiedMeasurementPoints[0].position.distanceTo(this.unifiedMeasurementPoints[1].position)), e.classList.remove("disabled", "active", "measured", "unavailable"), e.style.opacity = "", e.style.cursor = "pointer", e.setAttribute("aria-disabled", "false"), e.removeAttribute("title"), !this.measurementAvailable) {
7914
+ e.classList.add("disabled", "unavailable"), e.style.opacity = "0.55", e.style.cursor = "not-allowed", e.setAttribute("aria-disabled", "true"), e.title = "This model is marked as not measurable", e.innerHTML = `
7915
+ <div>MEASURE</div>
7916
+ <div style="font-size: 12px; margin-top: 4px;">Not available</div>
7917
+ `;
7918
+ return;
7919
+ }
7920
+ if (!o)
7703
7921
  e.classList.add("disabled"), e.innerHTML = `
7704
7922
  <div>MEASURE</div>
7705
7923
  <div style="font-size: 12px; margin-top: 4px;">Click to enable</div>
7706
7924
  `;
7707
7925
  else if (s)
7708
7926
  e.classList.add("measured"), e.innerHTML = `
7709
- <div>${n.toFixed(2)}m</div>
7927
+ <div>${this.formatDistance(n)}</div>
7710
7928
  <div style="font-size: 12px; margin-top: 4px;">Click to disable</div>
7711
7929
  `;
7712
7930
  else {
@@ -7733,27 +7951,35 @@ class Un {
7733
7951
  }, 10);
7734
7952
  }
7735
7953
  onMouseClick(e) {
7954
+ if (!this.measurementAvailable)
7955
+ return;
7736
7956
  const t = Date.now(), i = t - this.lastClickTime < 300;
7737
7957
  if (this.lastClickTime = t, this.isDragging || !this.desktopMeasurementMode)
7738
7958
  return;
7739
7959
  this.desktopMeasurementMode && (e.stopPropagation(), e.preventDefault());
7740
- const s = this.renderer.domElement.getBoundingClientRect();
7741
- this.mouse.x = (e.clientX - s.left) / s.width * 2 - 1, this.mouse.y = -((e.clientY - s.top) / s.height) * 2 + 1;
7742
- let o = this.camera;
7960
+ let s = this.camera, o = !1;
7961
+ if (this.getRaycastInfo) {
7962
+ const a = this.getRaycastInfo(e);
7963
+ a && a.mouse && Number.isFinite(a.mouse.x) && Number.isFinite(a.mouse.y) && (a.mouse.isVector2 ? this.mouse.copy(a.mouse) : (this.mouse.x = a.mouse.x, this.mouse.y = a.mouse.y), a.camera && (s = a.camera), o = !0);
7964
+ }
7965
+ if (!o) {
7966
+ const a = this.renderer.domElement.getBoundingClientRect();
7967
+ this.mouse.x = (e.clientX - a.left) / a.width * 2 - 1, this.mouse.y = -((e.clientY - a.top) / a.height) * 2 + 1;
7968
+ }
7743
7969
  if (this.renderer && this.renderer.xr && this.renderer.xr.isPresenting) {
7744
7970
  const a = this.renderer.xr.getCamera();
7745
- a && (o = a);
7971
+ a && (s = a);
7746
7972
  }
7747
- if ((!o || !o.isPerspectiveCamera && !o.isOrthographicCamera) && this.scene && this.scene.children) {
7973
+ if ((!s || !s.isPerspectiveCamera && !s.isOrthographicCamera) && this.scene && this.scene.children) {
7748
7974
  for (const a of this.scene.children)
7749
7975
  if (a.isCamera) {
7750
- o = a;
7976
+ s = a;
7751
7977
  break;
7752
7978
  }
7753
7979
  }
7754
- if ((!o || !o.isPerspectiveCamera && !o.isOrthographicCamera) && typeof window < "u" && window.camera && (window.camera.isPerspectiveCamera || window.camera.isOrthographicCamera) && (o = window.camera), !o || !o.isPerspectiveCamera && !o.isOrthographicCamera && o.type !== "ArrayCamera")
7980
+ if ((!s || !s.isPerspectiveCamera && !s.isOrthographicCamera) && typeof window < "u" && window.camera && (window.camera.isPerspectiveCamera || window.camera.isOrthographicCamera) && (s = window.camera), !s || !s.isPerspectiveCamera && !s.isOrthographicCamera && s.type !== "ArrayCamera")
7755
7981
  return;
7756
- this.raycaster.setFromCamera(this.mouse, o);
7982
+ this.raycaster.setFromCamera(this.mouse, s);
7757
7983
  const n = this._raycastTargets && this._raycastTargets.length > 0 ? this._raycastTargets : [];
7758
7984
  if (n.length === 0)
7759
7985
  return;
@@ -7761,7 +7987,7 @@ class Un {
7761
7987
  if (r.length === 0)
7762
7988
  return;
7763
7989
  const A = r.filter((a) => {
7764
- const l = this.unifiedMeasurementPoints.some((g) => g.sphere === a.object), h = a.object === this.unifiedMeasurementLine, d = this.isMeasurementHelper(a.object);
7990
+ const l = this.unifiedMeasurementPoints.some((u) => u.sphere === a.object), h = a.object === this.unifiedMeasurementLine, d = this.isMeasurementHelper(a.object);
7765
7991
  return !l && !h && !d;
7766
7992
  });
7767
7993
  if (A.length > 0)
@@ -7773,12 +7999,18 @@ class Un {
7773
7999
  }
7774
8000
  }
7775
8001
  focusOnPoint(e) {
7776
- this.focusAnimation && (cancelAnimationFrame(this.focusAnimation), this.focusAnimation = null);
8002
+ if (!e || !this.controls || !this.camera)
8003
+ return;
8004
+ this.focusAnimation && (cancelAnimationFrame(this.focusAnimation), this.focusAnimation = null), this._cancelFocusOnUserInput && (this.controls.removeEventListener("start", this._cancelFocusOnUserInput), this._cancelFocusOnUserInput = null);
7777
8005
  const t = this.controls.target.clone(), i = this.camera.position.clone(), s = i.clone().sub(t), o = e.clone().add(s), n = 1e3, r = performance.now(), A = () => {
7778
- const a = performance.now() - r, l = Math.min(a / n, 1), h = 1 - Math.pow(1 - l, 3);
7779
- this.controls.target.lerpVectors(t, e, h), this.camera.position.lerpVectors(i, o, h), l < 1 ? this.focusAnimation = requestAnimationFrame(A) : this.focusAnimation = null;
8006
+ this.focusAnimation && (cancelAnimationFrame(this.focusAnimation), this.focusAnimation = null), this._cancelFocusOnUserInput && (this.controls.removeEventListener("start", this._cancelFocusOnUserInput), this._cancelFocusOnUserInput = null);
7780
8007
  };
7781
- this.focusAnimation = requestAnimationFrame(A);
8008
+ this._cancelFocusOnUserInput = A, this.controls.addEventListener("start", A, { once: !0 });
8009
+ const a = () => {
8010
+ const l = performance.now() - r, h = Math.min(l / n, 1), d = 1 - Math.pow(1 - h, 3);
8011
+ this.controls.target.lerpVectors(t, e, d), this.camera.position.lerpVectors(i, o, d), h < 1 ? this.focusAnimation = requestAnimationFrame(a) : (this.focusAnimation = null, this._cancelFocusOnUserInput && (this.controls.removeEventListener("start", this._cancelFocusOnUserInput), this._cancelFocusOnUserInput = null));
8012
+ };
8013
+ this.focusAnimation = requestAnimationFrame(a);
7782
8014
  }
7783
8015
  _focusOnPoint(e) {
7784
8016
  if (this.focusAnimation && (cancelAnimationFrame(this.focusAnimation), this.focusAnimation = null), !this.controls || !this.camera) {
@@ -7799,7 +8031,7 @@ class Un {
7799
8031
  if (this.unifiedMeasurementPoints && this.unifiedMeasurementPoints.length === 2) {
7800
8032
  const e = this.unifiedMeasurementPoints[0].position, t = this.unifiedMeasurementPoints[1].position, i = e.distanceTo(t);
7801
8033
  if (this.createMeasurementDisplay(i), this.measurementSprite) {
7802
- const s = new u.Vector3();
8034
+ const s = new g.Vector3();
7803
8035
  s.addVectors(e, t), s.multiplyScalar(0.5);
7804
8036
  const o = Math.max(0.05, Math.min(0.2, i * 0.03));
7805
8037
  s.y += o, this.measurementSprite.position.copy(s), this.scene.children.includes(this.measurementSprite) || this.scene.add(this.measurementSprite);
@@ -7811,12 +8043,13 @@ class Un {
7811
8043
  }
7812
8044
  class Rt {
7813
8045
  constructor(e, t = {}) {
7814
- this.vrManager = e, this.isComfortMode = !1, this._iconRendered = !1, this.options = {
8046
+ this.vrManager = e, this.isComfortMode = !1, this._iconRendered = !1, this.lastToggleAt = 0, this.options = {
7815
8047
  containerId: t.containerId || "modelSelector",
7816
8048
  useInlineLayout: t.useInlineLayout !== !1,
7817
8049
  position: t.position || "bottom-right",
7818
8050
  offsetX: t.offsetX || 20,
7819
8051
  offsetY: t.offsetY || 120,
8052
+ toggleCooldownMs: t.toggleCooldownMs || 180,
7820
8053
  ...t
7821
8054
  }, this.element = null, this.init();
7822
8055
  }
@@ -7832,12 +8065,12 @@ class Rt {
7832
8065
  console.warn("VRComfortGlyph: modeToggleContainer not found, falling back to floating mode"), this.createFloatingElement();
7833
8066
  return;
7834
8067
  }
7835
- this.element = document.createElement("div"), this.element.id = "vrComfortGlyph", this.element.className = "vr-comfort-circle comfort-off", this.renderIcon(), this.element.tabIndex = 0, this.element.role = "button", this.element.title = "Comfort Mode: OFF (Smooth Movement)", this.element.setAttribute("aria-label", "Comfort Mode is OFF - Click to enable");
8068
+ this.element = document.createElement("div"), this.element.id = "vrComfortGlyph", this.element.className = "vr-comfort-circle comfort-off", this.renderIcon(), this.element.tabIndex = 0, this.element.role = "button", this.element.title = "Comfort Mode Off", this.element.setAttribute("aria-label", "Comfort mode off. Click to enable.");
7836
8069
  const t = e.querySelector(".semantic-toggle");
7837
8070
  t ? e.insertBefore(this.element, t.nextSibling) : e.appendChild(this.element), this.updateInlineVisualState();
7838
8071
  }
7839
8072
  createFloatingElement() {
7840
- this.element = document.createElement("div"), this.element.id = "vrComfortGlyph", this.element.className = "vr-comfort-glyph comfort-off", this.renderIcon(), this.element.title = "Comfort Mode: OFF (Smooth Movement)", this.element.tabIndex = 0, this.element.role = "button", this.element.setAttribute("aria-label", "Comfort Mode is OFF - Click to enable comfortable movement");
8073
+ this.element = document.createElement("div"), this.element.id = "vrComfortGlyph", this.element.className = "vr-comfort-glyph comfort-off", this.renderIcon(), this.element.title = "Comfort Mode Off", this.element.tabIndex = 0, this.element.role = "button", this.element.setAttribute("aria-label", "Comfort mode off. Click to enable.");
7841
8074
  const e = this.options.containerId ? document.getElementById(this.options.containerId) : document.body;
7842
8075
  e ? e.appendChild(this.element) : (console.warn("VRComfortGlyph: Container not found, appending to body"), document.body.appendChild(this.element));
7843
8076
  }
@@ -7848,19 +8081,19 @@ class Rt {
7848
8081
  e.id = "vr-comfort-glyph-styles", e.textContent = `
7849
8082
  .vr-comfort-glyph {
7850
8083
  position: absolute;
7851
- width: 36px;
7852
- height: 36px;
8084
+ width: 34px;
8085
+ height: 34px;
7853
8086
  border-radius: 50%;
7854
- background: rgba(0, 0, 0, 0.6);
7855
- border: 2px solid #666;
8087
+ background: rgba(15, 23, 42, 0.58);
8088
+ border: 1px solid rgba(255, 255, 255, 0.22);
7856
8089
  display: flex;
7857
8090
  align-items: center;
7858
8091
  justify-content: center;
7859
8092
  cursor: pointer;
7860
- transition: background-color 120ms ease, border-color 120ms ease, box-shadow 180ms ease, color 120ms ease, filter 180ms ease;
7861
- font-size: 18px;
8093
+ transition: background-color 120ms ease, border-color 120ms ease, box-shadow 140ms ease, color 120ms ease;
8094
+ font-size: 16px;
7862
8095
  z-index: 10000;
7863
- backdrop-filter: blur(10px);
8096
+ backdrop-filter: blur(8px);
7864
8097
  user-select: none;
7865
8098
  -webkit-user-select: none;
7866
8099
  -moz-user-select: none;
@@ -7871,8 +8104,8 @@ class Rt {
7871
8104
  }
7872
8105
 
7873
8106
  .vr-comfort-circle {
7874
- width: 60px;
7875
- height: 60px;
8107
+ width: 54px;
8108
+ height: 54px;
7876
8109
  border-radius: 50%;
7877
8110
  background: rgba(255, 255, 255, 0.06);
7878
8111
  border: 1px solid rgba(255, 255, 255, 0.1);
@@ -7881,9 +8114,9 @@ class Rt {
7881
8114
  align-items: center;
7882
8115
  justify-content: center;
7883
8116
  cursor: pointer;
7884
- transition: background-color 120ms ease, border-color 120ms ease, box-shadow 180ms ease, color 120ms ease, filter 180ms ease;
7885
- font-size: 18px;
7886
- margin-left: 12px;
8117
+ transition: background-color 120ms ease, border-color 120ms ease, box-shadow 140ms ease, color 120ms ease;
8118
+ font-size: 16px;
8119
+ margin-left: 10px;
7887
8120
  position: relative;
7888
8121
  user-select: none;
7889
8122
  -webkit-user-select: none;
@@ -7896,8 +8129,8 @@ class Rt {
7896
8129
  }
7897
8130
 
7898
8131
  .vr-comfort-circle:hover {
7899
- background: rgba(255, 255, 255, 0.1);
7900
- border-color: rgba(255, 255, 255, 0.2);
8132
+ background: rgba(255, 255, 255, 0.09);
8133
+ border-color: rgba(255, 255, 255, 0.18);
7901
8134
  }
7902
8135
 
7903
8136
  .vr-comfort-circle:focus-visible {
@@ -7918,23 +8151,23 @@ class Rt {
7918
8151
  }
7919
8152
 
7920
8153
  .vr-comfort-circle.comfort-off:hover {
7921
- color: rgba(255, 255, 255, 0.7) !important;
7922
- background: rgba(255, 255, 255, 0.1) !important;
7923
- border-color: rgba(255, 255, 255, 0.2) !important;
8154
+ color: rgba(255, 255, 255, 0.68) !important;
8155
+ background: rgba(255, 255, 255, 0.09) !important;
8156
+ border-color: rgba(255, 255, 255, 0.18) !important;
7924
8157
  box-shadow: none !important;
7925
8158
  }
7926
8159
 
7927
8160
  .vr-comfort-circle.comfort-on {
7928
- color: #4ade80 !important;
7929
- background: rgba(74, 222, 128, 0.1) !important;
7930
- border-color: rgba(74, 222, 128, 0.3) !important;
7931
- box-shadow: 0 0 20px rgba(74, 222, 128, 0.1) !important;
8161
+ color: rgba(236, 253, 245, 0.98) !important;
8162
+ background: rgba(74, 222, 128, 0.14) !important;
8163
+ border-color: rgba(74, 222, 128, 0.8) !important;
8164
+ box-shadow: 0 0 0 2px rgba(74, 222, 128, 0.86), 0 6px 18px rgba(2, 6, 23, 0.24) !important;
7932
8165
  }
7933
8166
 
7934
8167
  .vr-comfort-circle.comfort-on:hover {
7935
- background: rgba(74, 222, 128, 0.15) !important;
7936
- border-color: rgba(74, 222, 128, 0.4) !important;
7937
- box-shadow: 0 0 30px rgba(74, 222, 128, 0.15) !important;
8168
+ background: rgba(74, 222, 128, 0.2) !important;
8169
+ border-color: rgba(74, 222, 128, 0.9) !important;
8170
+ box-shadow: 0 0 0 2px rgba(74, 222, 128, 0.92), 0 8px 22px rgba(2, 6, 23, 0.3) !important;
7938
8171
  }
7939
8172
 
7940
8173
  #modeToggleContainer {
@@ -7950,7 +8183,7 @@ class Rt {
7950
8183
  }
7951
8184
 
7952
8185
  .vr-comfort-glyph:hover {
7953
- background: rgba(0, 0, 0, 0.8);
8186
+ background: rgba(15, 23, 42, 0.7);
7954
8187
  }
7955
8188
 
7956
8189
  .vr-comfort-glyph:focus-visible {
@@ -7958,31 +8191,29 @@ class Rt {
7958
8191
  outline-offset: 2px;
7959
8192
  }
7960
8193
  .vr-comfort-glyph.comfort-on:focus-visible { outline-color: #4ade80; }
7961
- .vr-comfort-glyph.comfort-off:focus-visible { outline-color: #666; }
8194
+ .vr-comfort-glyph.comfort-off:focus-visible { outline-color: rgba(255,255,255,0.35); }
7962
8195
 
7963
8196
  .vr-comfort-glyph.comfort-off {
7964
- color: #666;
7965
- border-color: #666;
7966
- background: rgba(0, 0, 0, 0.6);
8197
+ color: rgba(226, 232, 240, 0.55);
8198
+ border-color: rgba(255, 255, 255, 0.22);
8199
+ background: rgba(15, 23, 42, 0.58);
7967
8200
  box-shadow: none;
7968
- filter: none;
7969
8201
  }
7970
8202
 
7971
8203
  .vr-comfort-glyph.comfort-on {
7972
- color: #4ade80;
7973
- border-color: #4ade80;
7974
- background: rgba(74, 222, 128, 0.1);
7975
- box-shadow: 0 0 20px rgba(74, 222, 128, 0.3);
7976
- filter: drop-shadow(0 0 8px rgba(74, 222, 128, 0.4));
8204
+ color: rgba(236, 253, 245, 0.98);
8205
+ border-color: rgba(74, 222, 128, 0.8);
8206
+ background: rgba(74, 222, 128, 0.15);
8207
+ box-shadow: 0 0 0 2px rgba(74, 222, 128, 0.86), 0 6px 20px rgba(2, 6, 23, 0.25);
7977
8208
  }
7978
8209
 
7979
8210
 
7980
8211
  .vr-comfort-emoji {
7981
8212
  display: block;
7982
- font-size: 18px;
8213
+ font-size: 16px;
7983
8214
  line-height: 1;
7984
8215
  transform: translateY(0.5px);
7985
- transition: transform 120ms ease;
8216
+ transition: transform 90ms ease;
7986
8217
  }
7987
8218
  .vr-comfort-circle:active .vr-comfort-emoji,
7988
8219
  .vr-comfort-glyph:active .vr-comfort-emoji {
@@ -8011,10 +8242,10 @@ class Rt {
8011
8242
 
8012
8243
  @media (max-width: 768px) {
8013
8244
  .vr-comfort-circle {
8014
- width: 50px;
8015
- height: 50px;
8016
- font-size: 18px;
8017
- margin-left: 10px;
8245
+ width: 48px;
8246
+ height: 48px;
8247
+ font-size: 16px;
8248
+ margin-left: 8px;
8018
8249
  }
8019
8250
 
8020
8251
  #modeToggleContainer {
@@ -8024,9 +8255,9 @@ class Rt {
8024
8255
 
8025
8256
 
8026
8257
  .vr-comfort-glyph {
8027
- width: 48px !important;
8028
- height: 48px !important;
8029
- font-size: 24px !important;
8258
+ width: 42px !important;
8259
+ height: 42px !important;
8260
+ font-size: 20px !important;
8030
8261
  }
8031
8262
 
8032
8263
  .vr-comfort-glyph.position-bottom-right {
@@ -8060,23 +8291,29 @@ class Rt {
8060
8291
  this.element && (this.options.useInlineLayout ? this.updateInlineVisualState() : this.updateFloatingVisualState());
8061
8292
  }
8062
8293
  updateInlineVisualState() {
8063
- this.element && (this.element.classList.remove("comfort-off", "comfort-on"), this.element.style.removeProperty("background"), this.element.style.removeProperty("border-color"), this.element.style.removeProperty("color"), this.element.style.removeProperty("box-shadow"), this.isComfortMode ? (this.element.classList.add("comfort-on"), this.element.title = "Comfort Mode: ON (Teleport Movement)", this.element.setAttribute("aria-label", "Comfort Mode is ON - Click to disable")) : (this.element.classList.add("comfort-off"), this.element.title = "Comfort Mode: OFF (Smooth Movement)", this.element.setAttribute("aria-label", "Comfort Mode is OFF - Click to enable")));
8294
+ this.element && (this.element.classList.remove("comfort-off", "comfort-on"), this.element.style.removeProperty("background"), this.element.style.removeProperty("border-color"), this.element.style.removeProperty("color"), this.element.style.removeProperty("box-shadow"), this.isComfortMode ? (this.element.classList.add("comfort-on"), this.element.title = "Comfort Mode On", this.element.setAttribute("aria-label", "Comfort mode on. Click to disable.")) : (this.element.classList.add("comfort-off"), this.element.title = "Comfort Mode Off", this.element.setAttribute("aria-label", "Comfort mode off. Click to enable.")));
8064
8295
  }
8065
8296
  updateFloatingVisualState() {
8066
- this.element && (this.updatePosition(), this.element.classList.remove("comfort-off", "comfort-on"), this.isComfortMode ? (this.element.classList.add("comfort-on"), this.element.title = "Comfort Mode: ON (Teleport Movement)", this.element.setAttribute("aria-label", "Comfort Mode is ON - Click to disable")) : (this.element.classList.add("comfort-off"), this.element.title = "Comfort Mode: OFF (Smooth Movement)", this.element.setAttribute("aria-label", "Comfort Mode is OFF - Click to enable comfortable movement")), this.renderIcon());
8297
+ this.element && (this.updatePosition(), this.element.classList.remove("comfort-off", "comfort-on"), this.isComfortMode ? (this.element.classList.add("comfort-on"), this.element.title = "Comfort Mode On", this.element.setAttribute("aria-label", "Comfort mode on. Click to disable.")) : (this.element.classList.add("comfort-off"), this.element.title = "Comfort Mode Off", this.element.setAttribute("aria-label", "Comfort mode off. Click to enable.")), this.renderIcon());
8298
+ }
8299
+ applyComfortMode(e, { emitEvent: t = !0, applyToManager: i = !0 } = {}) {
8300
+ if (this.isComfortMode = e === !0, i && this.vrManager && this.vrManager.setComfortPreset(this.isComfortMode ? "comfort" : "free"), this.updateVisualState(), t && this.element) {
8301
+ const s = new CustomEvent("vrcomfortchange", {
8302
+ detail: {
8303
+ isComfortMode: this.isComfortMode,
8304
+ preset: this.isComfortMode ? "comfort" : "free"
8305
+ }
8306
+ });
8307
+ this.element.dispatchEvent(s);
8308
+ }
8067
8309
  }
8068
8310
  toggle() {
8069
- this.isComfortMode = !this.isComfortMode, this.vrManager && (this.isComfortMode ? this.vrManager.setComfortPreset("comfort") : this.vrManager.setComfortPreset("free")), this.updateVisualState();
8070
- const e = new CustomEvent("vrcomfortchange", {
8071
- detail: {
8072
- isComfortMode: this.isComfortMode,
8073
- preset: this.isComfortMode ? "comfort" : "free"
8074
- }
8075
- });
8076
- this.element.dispatchEvent(e);
8311
+ const e = Date.now();
8312
+ e - this.lastToggleAt < this.options.toggleCooldownMs || (this.lastToggleAt = e, this.applyComfortMode(!this.isComfortMode, { emitEvent: !0, applyToManager: !0 }));
8077
8313
  }
8078
- setComfortMode(e) {
8079
- this.isComfortMode !== e && this.toggle();
8314
+ setComfortMode(e, { emitEvent: t = !0, applyToManager: i = !0 } = {}) {
8315
+ const s = e === !0;
8316
+ this.isComfortMode !== s ? this.applyComfortMode(s, { emitEvent: t, applyToManager: i }) : this.updateVisualState();
8080
8317
  }
8081
8318
  getComfortMode() {
8082
8319
  return this.isComfortMode;
@@ -8104,12 +8341,12 @@ class Rt {
8104
8341
  class Vn {
8105
8342
  constructor(e) {
8106
8343
  this.scene = e, this.particleBounds = {
8107
- min: new u.Vector3(-50, -25, -50),
8108
- max: new u.Vector3(50, 25, 50)
8344
+ min: new g.Vector3(-50, -25, -50),
8345
+ max: new g.Vector3(50, 25, 50)
8109
8346
  }, this.particleCount = 1750, this.densityMultiplier = 1, this.createParticleSystem();
8110
8347
  }
8111
8348
  calculateParticleCount(e) {
8112
- const t = new u.Vector3();
8349
+ const t = new g.Vector3();
8113
8350
  e.getSize(t);
8114
8351
  const s = t.clone().multiplyScalar(2.5), o = s.x * s.y * s.z, n = Math.round(o * 0.01 * this.densityMultiplier);
8115
8352
  return Math.max(100, Math.min(16e3, n));
@@ -8122,16 +8359,16 @@ class Vn {
8122
8359
  this.disable();
8123
8360
  return;
8124
8361
  }
8125
- const t = new u.Box3(this.particleBounds.min, this.particleBounds.max), i = this.calculateParticleCount(t);
8362
+ const t = new g.Box3(this.particleBounds.min, this.particleBounds.max), i = this.calculateParticleCount(t);
8126
8363
  this.particles && (this.scene.remove(this.particles), this.particles.geometry && this.particles.geometry.dispose(), this.particles.material && this.particles.material.dispose(), this.particles = null), this.particleCount = i, this.createParticleSystem(), this.enable();
8127
8364
  }
8128
8365
  createParticleSystem() {
8129
8366
  const e = new Float32Array(this.particleCount * 3), t = new Float32Array(this.particleCount * 3), i = new Float32Array(this.particleCount);
8130
8367
  this.initializeParticleData(e, t, i);
8131
- const s = new u.BufferGeometry(), o = new Float32Array(this.particleCount);
8368
+ const s = new g.BufferGeometry(), o = new Float32Array(this.particleCount);
8132
8369
  for (let n = 0; n < this.particleCount; n++)
8133
8370
  o[n] = n;
8134
- s.setAttribute("position", new u.BufferAttribute(e, 3)), s.setAttribute("originalSize", new u.BufferAttribute(i, 1)), s.setAttribute("velocity", new u.BufferAttribute(t, 3)), s.setAttribute("particleIndex", new u.BufferAttribute(o, 1)), this.originalMaterial = this.createParticleMaterial(), this.particles = new u.Points(s, this.originalMaterial), this.particles.visible = !1, this.scene.add(this.particles);
8371
+ s.setAttribute("position", new g.BufferAttribute(e, 3)), s.setAttribute("originalSize", new g.BufferAttribute(i, 1)), s.setAttribute("velocity", new g.BufferAttribute(t, 3)), s.setAttribute("particleIndex", new g.BufferAttribute(o, 1)), this.originalMaterial = this.createParticleMaterial(), this.particles = new g.Points(s, this.originalMaterial), this.particles.visible = !1, this.scene.add(this.particles);
8135
8372
  }
8136
8373
  /**
8137
8374
  * Initialize particle data arrays
@@ -8154,17 +8391,17 @@ class Vn {
8154
8391
  e.width = e.height = 32;
8155
8392
  const t = e.getContext("2d"), i = t.createRadialGradient(16, 16, 0, 16, 16, 16);
8156
8393
  i.addColorStop(0, "rgba(255, 255, 255, 1)"), i.addColorStop(0.7, "rgba(255, 255, 255, 0.8)"), i.addColorStop(1, "rgba(255, 255, 255, 0)"), t.fillStyle = i, t.fillRect(0, 0, 32, 32);
8157
- const s = new u.CanvasTexture(e);
8158
- return s.needsUpdate = !0, new u.ShaderMaterial({
8394
+ const s = new g.CanvasTexture(e);
8395
+ return s.needsUpdate = !0, new g.ShaderMaterial({
8159
8396
  uniforms: {
8160
8397
  time: { value: 0 },
8161
8398
  pointTexture: { value: s },
8162
- color: { value: new u.Color(16777215) },
8399
+ color: { value: new g.Color(16777215) },
8163
8400
  opacity: { value: 1 },
8164
8401
  size: { value: 2 },
8165
8402
  boundsMin: { value: this.particleBounds.min.clone() },
8166
8403
  boundsMax: { value: this.particleBounds.max.clone() },
8167
- fogColor: { value: new u.Color(268073) },
8404
+ fogColor: { value: new g.Color(268073) },
8168
8405
  fogDensity: { value: 0 }
8169
8406
  },
8170
8407
  vertexShader: `
@@ -8246,7 +8483,7 @@ class Vn {
8246
8483
  `,
8247
8484
  transparent: !0,
8248
8485
  depthWrite: !1,
8249
- blending: u.NormalBlending,
8486
+ blending: g.NormalBlending,
8250
8487
  fog: !1
8251
8488
  });
8252
8489
  }
@@ -8273,9 +8510,9 @@ class Vn {
8273
8510
  */
8274
8511
  updateBounds(e) {
8275
8512
  if (!e) return;
8276
- const t = new u.Box3().setFromObject(e), i = t.getSize(new u.Vector3()), s = t.getCenter(new u.Vector3()), n = i.clone().multiplyScalar(2.5 * 0.5);
8513
+ const t = new g.Box3().setFromObject(e), i = t.getSize(new g.Vector3()), s = t.getCenter(new g.Vector3()), n = i.clone().multiplyScalar(2.5 * 0.5);
8277
8514
  this.particleBounds.min.copy(s).sub(n), this.particleBounds.max.copy(s).add(n);
8278
- const r = this.calculateParticleCount(new u.Box3(this.particleBounds.min, this.particleBounds.max));
8515
+ const r = this.calculateParticleCount(new g.Box3(this.particleBounds.min, this.particleBounds.max));
8279
8516
  Math.abs(r - this.particleCount) > this.particleCount * 0.2 ? (this.particles && (this.scene.remove(this.particles), this.particles.geometry && this.particles.geometry.dispose(), this.particles.material && this.particles.material.dispose(), this.particles = null), this.particleCount = r, this.createParticleSystem()) : this.redistributeParticles();
8280
8517
  }
8281
8518
  /**
@@ -8321,7 +8558,7 @@ class On {
8321
8558
  createSpotlight(e = 25) {
8322
8559
  this.controllerSpotlight && (this.scene.remove(this.controllerSpotlight), this.scene.remove(this.spotlightTarget));
8323
8560
  const t = e * Math.PI / 180, i = (this.isQuest2, 15);
8324
- this.controllerSpotlight = new u.SpotLight(
8561
+ this.controllerSpotlight = new g.SpotLight(
8325
8562
  16777215,
8326
8563
  // Pure white light
8327
8564
  2.5,
@@ -8336,7 +8573,7 @@ class On {
8336
8573
  // Higher decay for realistic underwater attenuation
8337
8574
  ), this.controllerSpotlight.position.set(0, 0, 0), this.controllerSpotlight.visible = !0, this.controllerSpotlight.castShadow = !0;
8338
8575
  const s = this.isQuest2 ? 512 : 1024;
8339
- this.controllerSpotlight.shadow.mapSize.width = s, this.controllerSpotlight.shadow.mapSize.height = s, this.controllerSpotlight.shadow.camera.near = 0.1, this.controllerSpotlight.shadow.camera.far = i, this.controllerSpotlight.shadow.camera.fov = e, this.controllerSpotlight.shadow.bias = -5e-4, this.controllerSpotlight.shadow.normalBias = 0.02, this.controllerSpotlight.shadow.radius = 4, this.controllerSpotlight.shadow.blurSamples = 10, this.scene.add(this.controllerSpotlight), this.spotlightTarget = new u.Object3D(), this.scene.add(this.spotlightTarget), this.controllerSpotlight.target = this.spotlightTarget;
8576
+ this.controllerSpotlight.shadow.mapSize.width = s, this.controllerSpotlight.shadow.mapSize.height = s, this.controllerSpotlight.shadow.camera.near = 0.1, this.controllerSpotlight.shadow.camera.far = i, this.controllerSpotlight.shadow.camera.fov = e, this.controllerSpotlight.shadow.bias = -5e-4, this.controllerSpotlight.shadow.normalBias = 0.02, this.controllerSpotlight.shadow.radius = 4, this.controllerSpotlight.shadow.blurSamples = 10, this.scene.add(this.controllerSpotlight), this.spotlightTarget = new g.Object3D(), this.scene.add(this.spotlightTarget), this.controllerSpotlight.target = this.spotlightTarget;
8340
8577
  }
8341
8578
  enableTorch() {
8342
8579
  this.controllerSpotlight ? this.controllerSpotlight.visible = !0 : console.error("Cannot enable torch - controllerSpotlight is null");
@@ -8355,9 +8592,9 @@ class On {
8355
8592
  e || console.warn("updatePosition called with null controller");
8356
8593
  return;
8357
8594
  }
8358
- const t = new u.Vector3(), i = new u.Quaternion();
8595
+ const t = new g.Vector3(), i = new g.Quaternion();
8359
8596
  e.getWorldPosition(t), e.getWorldQuaternion(i), this.controllerSpotlight.position.copy(t);
8360
- const s = new u.Vector3(0, 0, -1);
8597
+ const s = new g.Vector3(0, 0, -1);
8361
8598
  s.applyQuaternion(i);
8362
8599
  const o = t.clone().add(s.multiplyScalar(2));
8363
8600
  this.spotlightTarget.position.copy(o);
@@ -8365,7 +8602,7 @@ class On {
8365
8602
  updateCameraPosition(e) {
8366
8603
  if (!this.controllerSpotlight || !this.spotlightTarget) return;
8367
8604
  this.controllerSpotlight.position.copy(e.position);
8368
- const t = new u.Vector3(0, 0, -1);
8605
+ const t = new g.Vector3(0, 0, -1);
8369
8606
  t.applyQuaternion(e.quaternion);
8370
8607
  const i = e.position.clone().add(t.multiplyScalar(8));
8371
8608
  this.spotlightTarget.position.copy(i);
@@ -8420,7 +8657,7 @@ class Hn {
8420
8657
  return;
8421
8658
  }
8422
8659
  try {
8423
- this.overheadLight = new u.AmbientLight(16777215, 0.5), this.currentMode = null;
8660
+ this.overheadLight = new g.AmbientLight(16777215, 0.5), this.currentMode = null;
8424
8661
  } catch (e) {
8425
8662
  console.error("Failed to initialize lighting system:", e);
8426
8663
  }
@@ -8428,7 +8665,7 @@ class Hn {
8428
8665
  createSurveyModeLights() {
8429
8666
  if (!(this.isDisposed || !this.scene))
8430
8667
  try {
8431
- this.clearModeDirectionalLight || (this.clearModeDirectionalLight = new u.DirectionalLight(16777215, 1.2), this.clearModeDirectionalLight.position.set(10, 20, 10), this.clearModeDirectionalLight.castShadow = !0, this.clearModeDirectionalLight.shadow.mapSize.width = 2048, this.clearModeDirectionalLight.shadow.mapSize.height = 2048, this.clearModeDirectionalLight.shadow.camera.near = 0.5, this.clearModeDirectionalLight.shadow.camera.far = 100, this.clearModeDirectionalLight.shadow.camera.left = -20, this.clearModeDirectionalLight.shadow.camera.right = 20, this.clearModeDirectionalLight.shadow.camera.top = 20, this.clearModeDirectionalLight.shadow.camera.bottom = -20, this.scene.add(this.clearModeDirectionalLight)), this.clearModeHemisphereLight || (this.clearModeHemisphereLight = new u.HemisphereLight(16777215, 4473924, 0.7), this.scene.add(this.clearModeHemisphereLight)), this.fillLight || (this.fillLight = new u.DirectionalLight(16777215, 0.8), this.fillLight.position.set(-10, 10, -10), this.scene.add(this.fillLight)), this.bottomLight || (this.bottomLight = new u.DirectionalLight(16777215, 0.3), this.bottomLight.position.set(0, -10, 0), this.scene.add(this.bottomLight));
8668
+ this.clearModeDirectionalLight || (this.clearModeDirectionalLight = new g.DirectionalLight(16777215, 1.32), this.clearModeDirectionalLight.position.set(50, 100, 50), this.clearModeDirectionalLight.castShadow = !0, this.clearModeDirectionalLight.shadow.mapSize.width = 2048, this.clearModeDirectionalLight.shadow.mapSize.height = 2048, this.clearModeDirectionalLight.shadow.camera.near = 0.5, this.clearModeDirectionalLight.shadow.camera.far = 500, this.clearModeDirectionalLight.shadow.camera.left = -150, this.clearModeDirectionalLight.shadow.camera.right = 150, this.clearModeDirectionalLight.shadow.camera.top = 150, this.clearModeDirectionalLight.shadow.camera.bottom = -150, this.scene.add(this.clearModeDirectionalLight)), this.clearModeHemisphereLight || (this.clearModeHemisphereLight = new g.HemisphereLight(16777215, 4473924, 0.77), this.scene.add(this.clearModeHemisphereLight)), this.fillLight || (this.fillLight = new g.DirectionalLight(16777215, 0.88), this.fillLight.position.set(-10, 10, -10), this.scene.add(this.fillLight)), this.bottomLight || (this.bottomLight = new g.DirectionalLight(16777215, 0.33), this.bottomLight.position.set(0, -10, 0), this.scene.add(this.bottomLight));
8432
8669
  } catch (e) {
8433
8670
  console.error("Failed to create survey mode lights:", e);
8434
8671
  }
@@ -8437,7 +8674,7 @@ class Hn {
8437
8674
  this.overheadLight && this.scene.children.includes(this.overheadLight) && this.scene.remove(this.overheadLight), this.clearModeDirectionalLight && (this.scene.remove(this.clearModeDirectionalLight), this.clearModeDirectionalLight = null), this.clearModeHemisphereLight && (this.scene.remove(this.clearModeHemisphereLight), this.clearModeHemisphereLight = null), this.fillLight && (this.scene.remove(this.fillLight), this.fillLight = null), this.bottomLight && (this.scene.remove(this.bottomLight), this.bottomLight = null), this.currentMode = "dive";
8438
8675
  }
8439
8676
  enableSurveyMode() {
8440
- this.overheadLight && !this.scene.children.includes(this.overheadLight) && this.scene.add(this.overheadLight), this.overheadLight && (this.overheadLight.intensity = 0.6, this.overheadLight.color.setHex(16777215)), this.createSurveyModeLights(), this.currentMode = "survey";
8677
+ this.overheadLight && !this.scene.children.includes(this.overheadLight) && this.scene.add(this.overheadLight), this.overheadLight && (this.overheadLight.intensity = 0.66, this.overheadLight.color.setHex(16777215)), this.createSurveyModeLights(), this.currentMode = "survey";
8441
8678
  }
8442
8679
  setVRDiveMode() {
8443
8680
  this.overheadLight && this.scene.children.includes(this.overheadLight) && this.scene.remove(this.overheadLight);
@@ -8454,24 +8691,24 @@ class Hn {
8454
8691
  this.pendingAnimations.add(A);
8455
8692
  const a = performance.now(), l = i - t;
8456
8693
  let h, d;
8457
- s !== void 0 && o !== void 0 && (h = new u.Color(s), d = new u.Color(o));
8458
- const g = (p) => {
8694
+ s !== void 0 && o !== void 0 && (h = new g.Color(s), d = new g.Color(o));
8695
+ const u = (p) => {
8459
8696
  if (!this.pendingAnimations.has(A) || this.isDisposed) {
8460
8697
  r && r();
8461
8698
  return;
8462
8699
  }
8463
8700
  try {
8464
- const C = p - a, E = Math.min(C / n, 1), f = 1 - Math.pow(1 - E, 3);
8701
+ const b = p - a, E = Math.min(b / n, 1), f = 1 - Math.pow(1 - E, 3);
8465
8702
  if (!e || this.scene && !this.scene.children.includes(e)) {
8466
8703
  this.pendingAnimations.delete(A), r && r();
8467
8704
  return;
8468
8705
  }
8469
- e.intensity = t + l * f, h && d && e.color && e.color.lerpColors(h, d, f), E < 1 ? requestAnimationFrame(g) : (this.pendingAnimations.delete(A), r && r());
8470
- } catch (C) {
8471
- console.error("Error in lighting animation:", C), this.pendingAnimations.delete(A), r && r();
8706
+ e.intensity = t + l * f, h && d && e.color && e.color.lerpColors(h, d, f), E < 1 ? requestAnimationFrame(u) : (this.pendingAnimations.delete(A), r && r());
8707
+ } catch (b) {
8708
+ console.error("Error in lighting animation:", b), this.pendingAnimations.delete(A), r && r();
8472
8709
  }
8473
8710
  };
8474
- requestAnimationFrame(g);
8711
+ requestAnimationFrame(u);
8475
8712
  }
8476
8713
  cancelActiveAnimations() {
8477
8714
  this.pendingAnimations.clear();
@@ -8492,7 +8729,7 @@ class Hn {
8492
8729
  }
8493
8730
  setSurveyBrightness(e = 1) {
8494
8731
  const t = Math.max(0.5, Math.min(5, e));
8495
- this.overheadLight && (this.overheadLight.intensity = 0.6 * t), this.clearModeDirectionalLight && (this.clearModeDirectionalLight.intensity = 1.2 * t), this.clearModeHemisphereLight && (this.clearModeHemisphereLight.intensity = 0.7 * t), this.fillLight && (this.fillLight.intensity = 0.8 * t), this.bottomLight && (this.bottomLight.intensity = 0.3 * t);
8732
+ this.overheadLight && (this.overheadLight.intensity = 0.66 * t), this.clearModeDirectionalLight && (this.clearModeDirectionalLight.intensity = 1.32 * t), this.clearModeHemisphereLight && (this.clearModeHemisphereLight.intensity = 0.77 * t), this.fillLight && (this.fillLight.intensity = 0.88 * t), this.bottomLight && (this.bottomLight.intensity = 0.33 * t);
8496
8733
  }
8497
8734
  dispose() {
8498
8735
  this.isDisposed = !0, this.cancelActiveAnimations(), requestAnimationFrame(() => {
@@ -8506,18 +8743,20 @@ class Hn {
8506
8743
  }
8507
8744
  class qn {
8508
8745
  constructor(e, t, i) {
8509
- this.scene = e, this.renderer = t, this.camera = i, this.isDiveModeEnabled = !1, this.currentVRMode = null, this.lighting = new Hn(e), this.particles = new Vn(e), this.torch = new On(e), this.isQuest2 = !1, this.isQuest3 = !1, this.detectQuestDevice(), this.applyModeSettings();
8746
+ this.scene = e, this.renderer = t, this.camera = i, this.isDiveModeEnabled = !1, this.currentVRMode = null, this.lighting = new Hn(e), this.particles = new Vn(e), this.torch = new On(e), this.isQuest2 = !1, this.isQuest3 = !1, this._fallbackHandedness = /* @__PURE__ */ new Map(), this.detectQuestDevice(), this.applyModeSettings();
8510
8747
  }
8511
8748
  /**
8512
8749
  * Toggle between dive and survey modes
8513
8750
  */
8514
8751
  toggleDiveMode() {
8515
- this.isDiveModeEnabled = !this.isDiveModeEnabled;
8516
- const e = document.querySelector(".mode-toggle__switch");
8517
- e && (e.checked = this.isDiveModeEnabled), this.applyModeSettings();
8752
+ this.setDiveMode(!this.isDiveModeEnabled);
8518
8753
  }
8519
8754
  setDiveMode(e) {
8520
- this.isDiveModeEnabled !== e && this.toggleDiveMode();
8755
+ if (this.isARSessionActive() && e || this.isDiveModeEnabled === e)
8756
+ return;
8757
+ this.isDiveModeEnabled = e;
8758
+ const t = document.querySelector(".mode-toggle__switch");
8759
+ t && (t.checked = this.isDiveModeEnabled), this.applyModeSettings();
8521
8760
  }
8522
8761
  isDiveMode() {
8523
8762
  return this.isDiveModeEnabled;
@@ -8534,7 +8773,7 @@ class qn {
8534
8773
  * Apply Quest-specific optimizations
8535
8774
  */
8536
8775
  applyQuestOptimizations() {
8537
- this.isQuest2 ? (this.camera.far = 20, this.camera.updateProjectionMatrix(), this.isDiveModeEnabled && (this.scene.fog = new u.FogExp2(268073, 0.084))) : (this.camera.far = 2e3, this.camera.updateProjectionMatrix(), this.isDiveModeEnabled && (this.scene.fog = new u.FogExp2(268073, 0.056)));
8776
+ this.isQuest2 ? (this.camera.far = 20, this.camera.updateProjectionMatrix(), this.isDiveModeEnabled && (this.scene.fog = new g.FogExp2(268073, 0.084))) : (this.camera.far = 2e3, this.camera.updateProjectionMatrix(), this.isDiveModeEnabled && (this.scene.fog = new g.FogExp2(268073, 0.056)));
8538
8777
  }
8539
8778
  /**
8540
8779
  * Apply mode-specific settings for VR vs Desktop
@@ -8546,7 +8785,7 @@ class qn {
8546
8785
  this.scene.fog = null;
8547
8786
  return;
8548
8787
  }
8549
- e ? (this.scene.fog = new u.FogExp2(268073, 0.056), this.lighting.setVRDiveMode(), this.isDiveModeEnabled && this.torch.enableTorch()) : (this.scene.fog = new u.FogExp2(268073, 5e-3), this.lighting.setDesktopDiveMode()), this.particles.updateFog(this.scene.fog);
8788
+ e ? (this.scene.fog = new g.FogExp2(268073, 0.056), this.lighting.setVRDiveMode(), this.isDiveModeEnabled && this.torch.enableTorch()) : (this.scene.fog = new g.FogExp2(268073, 5e-3), this.lighting.setDesktopDiveMode()), this.particles.updateFog(this.scene.fog);
8550
8789
  }
8551
8790
  }
8552
8791
  /**
@@ -8636,30 +8875,58 @@ class qn {
8636
8875
  * Handle VR controller button presses for mode switching
8637
8876
  */
8638
8877
  handleControllerButton(e, t) {
8639
- return t === 4 ? (this.toggleDiveMode(), !0) : !1;
8878
+ return this.isARSessionActive() ? !1 : t === 4 ? (this.toggleDiveMode(), !0) : !1;
8640
8879
  }
8641
8880
  /**
8642
8881
  * Check VR controller buttons for mode switching
8643
8882
  * This replaces the button checking logic that was in the example
8644
8883
  */
8645
8884
  checkVRControllerButtons(e) {
8646
- if (!e || !e.xr) return;
8647
- const t = e.xr.getSession();
8648
- if (t) {
8649
- for (const i of t.inputSources)
8650
- if (i.gamepad && i.handedness) {
8651
- const s = i.gamepad, o = i.handedness;
8652
- [4, 5].forEach((r) => {
8653
- if (s.buttons[r]) {
8654
- const A = s.buttons[r], a = `${o}-${r}`;
8885
+ if (!e || !e.xr || !e.xr.isPresenting || this.isARSessionActive()) return;
8886
+ const t = e.xr.getSession && e.xr.getSession(), i = t && t.inputSources ? Array.from(t.inputSources) : this._getFallbackInputSources();
8887
+ if (!(!i || i.length === 0)) {
8888
+ for (const s of i)
8889
+ if (s.gamepad && s.handedness) {
8890
+ const o = s.gamepad, n = s.handedness;
8891
+ [4, 5].forEach((A) => {
8892
+ if (o.buttons[A]) {
8893
+ const a = o.buttons[A], l = `${n}-${A}`;
8655
8894
  this.buttonStates || (this.buttonStates = /* @__PURE__ */ new Map());
8656
- const l = this.buttonStates.get(a) || !1, h = A.pressed;
8657
- h && !l && this.toggleDiveMode(), this.buttonStates.set(a, h);
8895
+ const h = this.buttonStates.get(l) || !1, d = a.pressed;
8896
+ d && !h && this.toggleDiveMode(), this.buttonStates.set(l, d);
8658
8897
  }
8659
8898
  });
8660
8899
  }
8661
8900
  }
8662
8901
  }
8902
+ _getFallbackInputSources() {
8903
+ if (typeof navigator > "u" || !navigator.getGamepads) return [];
8904
+ const e = navigator.getGamepads();
8905
+ if (!e) return [];
8906
+ const t = [];
8907
+ let i = 0;
8908
+ for (const s of e) {
8909
+ if (!s || !s.buttons) continue;
8910
+ const o = this._resolveHandedness(s, i);
8911
+ if (!o) {
8912
+ i += 1;
8913
+ continue;
8914
+ }
8915
+ t.push({ gamepad: s, handedness: o }), i += 1;
8916
+ }
8917
+ return t;
8918
+ }
8919
+ _resolveHandedness(e, t) {
8920
+ const i = (e.hand || "").toLowerCase();
8921
+ if (i === "left" || i === "right") return i;
8922
+ const s = (e.id || "").toLowerCase();
8923
+ return s.includes("left") ? "left" : s.includes("right") ? "right" : this._fallbackHandedness.has(e.index) ? this._fallbackHandedness.get(e.index) : t === 0 ? (this._fallbackHandedness.set(e.index, "left"), "left") : t === 1 ? (this._fallbackHandedness.set(e.index, "right"), "right") : null;
8924
+ }
8925
+ isARSessionActive() {
8926
+ if (!this.renderer?.xr) return !1;
8927
+ const e = this.renderer.xr.getSession && this.renderer.xr.getSession();
8928
+ return e ? e.mode === "immersive-ar" ? !0 : e.mode === "immersive-vr" ? !1 : e.environmentBlendMode === "alpha-blend" || e.environmentBlendMode === "additive" : !1;
8929
+ }
8663
8930
  /**
8664
8931
  * Dispose of all resources
8665
8932
  */
@@ -8667,7 +8934,115 @@ class qn {
8667
8934
  this.lighting.dispose(), this.particles.dispose(), this.torch.dispose();
8668
8935
  }
8669
8936
  }
8670
- class Kn extends je {
8937
+ class jn extends Te {
8938
+ /**
8939
+ * @param {Object} options
8940
+ * @param {HTMLElement} options.domElement - Element used for pointer lock
8941
+ * @param {THREE.PerspectiveCamera} options.camera - Camera to control
8942
+ * @param {Object} options.controls - OrbitControls instance
8943
+ * @param {THREE.WebGLRenderer} [options.renderer] - Renderer (for XR checks)
8944
+ * @param {boolean} [options.enabled=true] - Enable fly controls
8945
+ * @param {number} [options.baseSpeed=6] - Base movement speed
8946
+ * @param {number} [options.boostSpeed=20] - Boosted speed (shift held)
8947
+ * @param {number} [options.speedScale=100] - Reference size for scaling speed
8948
+ * @param {number} [options.mouseSensitivity=0.002] - Mouse sensitivity
8949
+ * @param {boolean} [options.clickToExit=true] - Exit fly mode on click
8950
+ */
8951
+ constructor(e = {}) {
8952
+ super(), this.domElement = e.domElement || null, this.camera = e.camera || null, this.controls = e.controls || null, this.renderer = e.renderer || null, this.enabled = e.enabled ?? !0, this.baseSpeed = e.baseSpeed ?? 6, this.boostSpeed = e.boostSpeed ?? 20, this.speedScale = e.speedScale ?? 100, this.mouseSensitivity = e.mouseSensitivity ?? 2e-3, this.clickToExit = e.clickToExit ?? !0, this.pointerLocked = !1, this.modelSize = this.speedScale, this.cameraYaw = 0, this.cameraPitch = 0, this.keys = {
8953
+ w: !1,
8954
+ a: !1,
8955
+ s: !1,
8956
+ d: !1,
8957
+ q: !1,
8958
+ e: !1,
8959
+ shift: !1
8960
+ }, this._controlsEnabledBefore = !0, this._onKeyDown = this._onKeyDown.bind(this), this._onKeyUp = this._onKeyUp.bind(this), this._onMouseMove = this._onMouseMove.bind(this), this._onPointerLockChange = this._onPointerLockChange.bind(this), this._onClick = this._onClick.bind(this), this.attach();
8961
+ }
8962
+ attach() {
8963
+ !this.domElement || typeof document > "u" || (document.addEventListener("keydown", this._onKeyDown), document.addEventListener("keyup", this._onKeyUp), document.addEventListener("mousemove", this._onMouseMove), document.addEventListener("pointerlockchange", this._onPointerLockChange), this.clickToExit && this.domElement.addEventListener("click", this._onClick));
8964
+ }
8965
+ dispose() {
8966
+ document.removeEventListener("keydown", this._onKeyDown), document.removeEventListener("keyup", this._onKeyUp), document.removeEventListener("mousemove", this._onMouseMove), document.removeEventListener("pointerlockchange", this._onPointerLockChange), this.domElement && this.clickToExit && this.domElement.removeEventListener("click", this._onClick), this.exitFlyMode();
8967
+ }
8968
+ setEnabled(e) {
8969
+ this.enabled = !!e, this.enabled || this.exitFlyMode();
8970
+ }
8971
+ isActive() {
8972
+ return this.pointerLocked;
8973
+ }
8974
+ enterFlyMode() {
8975
+ !this.enabled || !this.domElement || document.pointerLockElement !== this.domElement && this.domElement.requestPointerLock();
8976
+ }
8977
+ exitFlyMode() {
8978
+ typeof document > "u" || document.pointerLockElement === this.domElement && document.exitPointerLock();
8979
+ }
8980
+ toggleFlyMode() {
8981
+ this.pointerLocked ? this.exitFlyMode() : this.enterFlyMode();
8982
+ }
8983
+ setModelSizeFromObject(e) {
8984
+ if (!e) return;
8985
+ const t = new g.Box3().setFromObject(e);
8986
+ if (t.isEmpty()) return;
8987
+ const i = t.getSize(new g.Vector3()), s = Math.max(i.x, i.y, i.z);
8988
+ s > 0 && Number.isFinite(s) && (this.modelSize = Math.max(1, Math.min(1e4, s)));
8989
+ }
8990
+ update(e) {
8991
+ if (!this.enabled || !this.pointerLocked) return;
8992
+ if (this.renderer?.xr?.isPresenting) {
8993
+ this.exitFlyMode();
8994
+ return;
8995
+ }
8996
+ if (!this.camera) return;
8997
+ const t = this.modelSize / this.speedScale, s = (this.keys.shift ? this.boostSpeed : this.baseSpeed) * t, o = new g.Vector3();
8998
+ this.keys.w && (o.z -= 1), this.keys.s && (o.z += 1), this.keys.a && (o.x -= 1), this.keys.d && (o.x += 1), this.keys.q && (o.y -= 1), this.keys.e && (o.y += 1), o.lengthSq() > 0 && (o.normalize(), o.applyQuaternion(this.camera.quaternion), this.camera.position.addScaledVector(o, s * e), this._syncControlsTarget());
8999
+ }
9000
+ _syncControlsTarget() {
9001
+ if (!this.controls || !this.camera) return;
9002
+ const e = new g.Vector3(0, 0, -5).applyQuaternion(this.camera.quaternion);
9003
+ this.controls.target.copy(this.camera.position).add(e);
9004
+ }
9005
+ _onKeyDown(e) {
9006
+ if (!this.enabled) return;
9007
+ const t = e.target;
9008
+ if (t instanceof HTMLElement) {
9009
+ const s = t.tagName;
9010
+ if (s === "INPUT" || s === "SELECT" || s === "TEXTAREA" || t.isContentEditable)
9011
+ return;
9012
+ }
9013
+ const i = e.key.toLowerCase();
9014
+ if (i in this.keys && (this.keys[i] = !0), e.shiftKey && (this.keys.shift = !0), e.shiftKey && (e.key === "`" || e.key === "~" || e.code === "Backquote")) {
9015
+ e.preventDefault(), this.pointerLocked || this.enterFlyMode();
9016
+ return;
9017
+ }
9018
+ (e.code === "KeyF" || i === "f") && (e.preventDefault(), this.toggleFlyMode());
9019
+ }
9020
+ _onKeyUp(e) {
9021
+ const t = e.key.toLowerCase();
9022
+ t in this.keys && (this.keys[t] = !1), e.shiftKey || (this.keys.shift = !1);
9023
+ }
9024
+ _onMouseMove(e) {
9025
+ if (!this.pointerLocked || !this.camera) return;
9026
+ this.cameraYaw -= e.movementX * this.mouseSensitivity, this.cameraPitch -= e.movementY * this.mouseSensitivity, this.cameraPitch = Math.max(
9027
+ -Math.PI / 2 + 0.01,
9028
+ Math.min(Math.PI / 2 - 0.01, this.cameraPitch)
9029
+ );
9030
+ const t = new g.Euler(this.cameraPitch, this.cameraYaw, 0, "YXZ");
9031
+ this.camera.quaternion.setFromEuler(t), this._syncControlsTarget();
9032
+ }
9033
+ _onPointerLockChange() {
9034
+ const e = this.pointerLocked;
9035
+ if (this.pointerLocked = document.pointerLockElement === this.domElement, this.pointerLocked && !e && this.camera) {
9036
+ const t = new g.Euler().setFromQuaternion(this.camera.quaternion, "YXZ");
9037
+ this.cameraYaw = t.y, this.cameraPitch = t.x;
9038
+ }
9039
+ this.controls && (this.pointerLocked ? (this._controlsEnabledBefore = this.controls.enabled, this.controls.enabled = !1) : this.controls.enabled = this._controlsEnabledBefore), this.emit("fly-mode-change", { active: this.pointerLocked });
9040
+ }
9041
+ _onClick() {
9042
+ this.pointerLocked && this.exitFlyMode();
9043
+ }
9044
+ }
9045
+ class zn extends Te {
8671
9046
  /**
8672
9047
  * Creates a new ModelViewer instance
8673
9048
  *
@@ -8692,8 +9067,11 @@ class Kn extends je {
8692
9067
  showDiveToggle: { type: "boolean", default: !0 },
8693
9068
  enableFullscreen: { type: "boolean", default: !1 },
8694
9069
  enableScreenshot: { type: "boolean", default: !1 },
9070
+ enableFlyControls: { type: "boolean", default: !0 },
9071
+ flyControls: { type: "object", default: {} },
8695
9072
  enableVRAudio: { type: "boolean", default: !1 },
8696
9073
  audioPath: { type: "string", default: "./sound/" },
9074
+ enableAutoRecovery: { type: "boolean", default: !0 },
8697
9075
  viewerConfig: {
8698
9076
  type: "object",
8699
9077
  default: {
@@ -8705,7 +9083,7 @@ class Kn extends je {
8705
9083
  initialModel: { type: "string", default: null },
8706
9084
  initialPositions: { type: "object", default: null }
8707
9085
  };
8708
- this.config = new Ke(i).validate(t), this.options = this.config, this.currentModelKey = null, this.belowViewer = null, this.ui = {}, this.measurementSystem = null, this.comfortGlyph = null, this.diveSystem = null, this.fullscreenButton = null, this.screenshotButton = null, this.lastComfortMode = null, this.isLoading = !1, this.loadingMessage = "", this.loadingModelName = "", this.loadingPercentage = 0, this.lastManualLoadingMessage = "", this.stageOverrideActive = !1, this.vrUpdateLoop = null, typeof window < "u" && (window.modelViewer = this), this.init();
9086
+ this.config = new Ke(i).validate(t), this.options = this.config, this.currentModelKey = null, this.belowViewer = null, this.ui = {}, this.uiRoot = null, this.stereoUiMirror = null, this.stereoUiObserver = null, this.stereoUiSyncQueued = !1, this.stereoUiActive = !1, this.measurementSystem = null, this.comfortGlyph = null, this.diveSystem = null, this.fullscreenButton = null, this.screenshotButton = null, this.flyControls = null, this.lastComfortMode = null, this._vrButtonWasVisible = !1, this.isLoading = !1, this.loadingMessage = "", this.loadingModelName = "", this.loadingPercentage = 0, this.lastManualLoadingMessage = "", this.stageOverrideActive = !1, this.vrUpdateLoop = null, this.lastRequestedModelKey = null, this.recoveryHandlers = null, this.recoveryTimer = null, this.recoveryCooldownMs = 1200, this.lastRecoveryAttemptAt = 0, this.recoveryAttempts = 0, this.maxRecoveryAttempts = 3, this.hadContextLoss = !1, this.isDisposed = !1, typeof window < "u" && (window.modelViewer = this), this.init();
8709
9087
  }
8710
9088
  init() {
8711
9089
  const e = {
@@ -8719,9 +9097,9 @@ class Kn extends je {
8719
9097
  ...this.config.audioPath && { audioPath: this.config.audioPath },
8720
9098
  ...typeof this.config.enableVRAudio < "u" && { enableVRAudio: this.config.enableVRAudio }
8721
9099
  };
8722
- if (this.belowViewer = new _n(this.container, e), this.setupEventForwarding(), this.belowViewer.on("initialized", () => {
8723
- this.setupFocusInteraction(), this._maybeAttachMeasurementSystem(), this._maybeAttachVRComfortGlyph(), this._maybeAttachDiveSystem(), this._maybeAttachScreenshotButton(), this._maybeAttachFullscreenButton();
8724
- }), this.belowViewer.isInitialized && (this.setupFocusInteraction(), this._maybeAttachMeasurementSystem(), this._maybeAttachVRComfortGlyph(), this._maybeAttachDiveSystem(), this._maybeAttachScreenshotButton(), this._maybeAttachFullscreenButton()), Object.keys(this.config.models).length > 0 && (this.createUI(), this.populateDropdown(), this.config.autoLoadFirst)) {
9100
+ if (this.belowViewer = new _n(this.container, e), this.setupEventForwarding(), this.setupRecoveryHandlers(), this.belowViewer.on("initialized", () => {
9101
+ this.setupRecoveryHandlers(), this.setupFocusInteraction(), this._maybeAttachMeasurementSystem(), this._maybeAttachVRComfortGlyph(), this._maybeAttachDiveSystem(), this._maybeAttachScreenshotButton(), this._maybeAttachFullscreenButton(), this._maybeAttachFlyControls();
9102
+ }), this.belowViewer.isInitialized && (this.setupRecoveryHandlers(), this.setupFocusInteraction(), this._maybeAttachMeasurementSystem(), this._maybeAttachVRComfortGlyph(), this._maybeAttachDiveSystem(), this._maybeAttachScreenshotButton(), this._maybeAttachFullscreenButton(), this._maybeAttachFlyControls()), Object.keys(this.config.models).length > 0 && (this.createUI(), this.populateDropdown(), this.config.autoLoadFirst)) {
8725
9103
  const t = Object.keys(this.config.models)[0];
8726
9104
  setTimeout(() => this.loadModel(t), 100);
8727
9105
  }
@@ -8733,6 +9111,8 @@ class Kn extends je {
8733
9111
  camera: this.belowViewer.cameraManager.camera,
8734
9112
  renderer: this.belowViewer.renderer,
8735
9113
  controls: this.belowViewer.cameraManager.controls,
9114
+ uiParent: this.getUiContainer(),
9115
+ getRaycastInfo: (t) => this.getPointerRaycastInfo(t),
8736
9116
  theme: this.config.measurementTheme,
8737
9117
  showMeasurementLabels: this.config.showMeasurementLabels
8738
9118
  });
@@ -8748,30 +9128,68 @@ class Kn extends je {
8748
9128
  t();
8749
9129
  }
8750
9130
  if (this.belowViewer.loadedModels && this.belowViewer.loadedModels.length > 0) {
8751
- const t = this.belowViewer.loadedModels[0].model;
9131
+ const t = this.belowViewer.loadedModels[0].model, i = this.currentModelKey ? this.config.models[this.currentModelKey] : null;
9132
+ this.applyModelMeasurementConfig(i, t);
9133
+ }
9134
+ }
9135
+ isModelMeasurable(e) {
9136
+ return !e || e.measurable !== !1;
9137
+ }
9138
+ applyModelMeasurementConfig(e, t = null) {
9139
+ if (!this.measurementSystem) return;
9140
+ const i = this.isModelMeasurable(e);
9141
+ if (typeof this.measurementSystem.setMeasurementAvailability == "function" ? this.measurementSystem.setMeasurementAvailability(i) : (this.measurementSystem.clearUnifiedMeasurement(), this.measurementSystem.clearLegacyVRMeasurement(), this.measurementSystem.clearLegacyDesktopMeasurement(), this.measurementSystem.desktopMeasurementMode = !1, this.measurementSystem.measurementSystemEnabled = i, this.measurementSystem.updateMeasurementPanel()), this.measurementSystem.ghostSpheres) {
9142
+ const s = i && this.measurementSystem.isVR;
9143
+ this.measurementSystem.ghostSpheres.left && (this.measurementSystem.ghostSpheres.left.visible = s), this.measurementSystem.ghostSpheres.right && (this.measurementSystem.ghostSpheres.right.visible = s);
9144
+ }
9145
+ if (i && t) {
8752
9146
  this.measurementSystem.setRaycastTargets(t);
9147
+ return;
8753
9148
  }
9149
+ this.measurementSystem.setRaycastTargets([]);
8754
9150
  }
8755
9151
  async _maybeAttachVRComfortGlyph() {
8756
- if (!(!this.config.enableVRComfortGlyph || this.comfortGlyph) && this.belowViewer.vrManager && this.belowViewer.vrManager.vrCore && (await this.belowViewer.vrManager.vrCore.checkVRSupported(), !!this.belowViewer.vrManager.vrCore.isVRSupported)) {
8757
- if (this.comfortGlyph = new Rt(this.belowViewer.vrManager, {
8758
- position: "bottom-right",
8759
- offsetX: 20,
8760
- offsetY: 70
8761
- }), this.lastComfortMode = this.comfortGlyph.isComfortMode, this.comfortGlyph.element.addEventListener("vrcomfortchange", (e) => {
8762
- this.lastComfortMode = e.detail.isComfortMode;
8763
- }), this.belowViewer.vrManager && this.belowViewer.vrManager.vrCore) {
8764
- const e = this.belowViewer.vrManager.vrCore.onSessionStart;
8765
- this.belowViewer.vrManager.vrCore.onSessionStart = async () => {
8766
- e && await e(), this.lastComfortMode !== null && setTimeout(() => {
8767
- this.lastComfortMode ? this.belowViewer.vrManager.setComfortPreset("comfort") : this.belowViewer.vrManager.setComfortPreset("free"), this.comfortGlyph.setComfortMode(this.lastComfortMode);
8768
- }, 50);
8769
- };
8770
- }
8771
- document.addEventListener("keydown", (e) => {
8772
- e.code === "KeyC" && (e.ctrlKey || e.metaKey) && (e.preventDefault(), this.comfortGlyph && this.comfortGlyph.toggle());
8773
- }), window.addEventListener("beforeunload", () => this.comfortGlyph && this.comfortGlyph.dispose());
9152
+ if (!this.config.enableVRComfortGlyph || this.comfortGlyph || !this.belowViewer.vrManager || !this.belowViewer.vrManager.vrCore || (await this.belowViewer.vrManager.vrCore.checkVRSupported(), !this.belowViewer.vrManager.vrCore.isVRSupported)) return;
9153
+ this.comfortGlyph = new Rt(this.belowViewer.vrManager, {
9154
+ position: "bottom-right",
9155
+ offsetX: 20,
9156
+ offsetY: 70
9157
+ });
9158
+ const e = this.belowViewer.getVRComfortSettings ? this.belowViewer.getVRComfortSettings() : null, t = e ? e.locomotionMode === "teleport" && e.reducedMotion === !0 : !1, i = typeof this.lastComfortMode == "boolean" ? this.lastComfortMode : t;
9159
+ if (this.lastComfortMode = i, this.comfortGlyph.setComfortMode(i, {
9160
+ emitEvent: !1,
9161
+ applyToManager: !1
9162
+ }), this.comfortGlyph.element.addEventListener("vrcomfortchange", (s) => {
9163
+ this.lastComfortMode = s.detail.isComfortMode;
9164
+ }), this.belowViewer.vrManager) {
9165
+ const s = this.belowViewer.vrManager.onComfortModeChange;
9166
+ this.belowViewer.vrManager.onComfortModeChange = (o) => {
9167
+ s && s(o);
9168
+ const n = o && typeof o.enabled == "boolean" ? o.enabled : this.belowViewer.vrManager.isComfortModeEnabled();
9169
+ this.lastComfortMode = n, this.comfortGlyph && this.comfortGlyph.setComfortMode(n, {
9170
+ emitEvent: !1,
9171
+ applyToManager: !1
9172
+ }), this.emit("comfort-mode-change", {
9173
+ enabled: n,
9174
+ inVR: this.belowViewer.vrManager.isVRPresenting,
9175
+ preset: n ? "comfort" : "free"
9176
+ });
9177
+ };
9178
+ }
9179
+ if (this.belowViewer.vrManager && this.belowViewer.vrManager.vrCore) {
9180
+ const s = this.belowViewer.vrManager.vrCore.onSessionStart;
9181
+ this.belowViewer.vrManager.vrCore.onSessionStart = async () => {
9182
+ s && await s(), this.lastComfortMode !== null && setTimeout(() => {
9183
+ this.lastComfortMode ? this.belowViewer.vrManager.setComfortPreset("comfort") : this.belowViewer.vrManager.setComfortPreset("free"), this.comfortGlyph.setComfortMode(this.lastComfortMode, {
9184
+ emitEvent: !1,
9185
+ applyToManager: !1
9186
+ });
9187
+ }, 50);
9188
+ };
8774
9189
  }
9190
+ document.addEventListener("keydown", (s) => {
9191
+ s.code === "KeyC" && (s.ctrlKey || s.metaKey) && (s.preventDefault(), this.comfortGlyph && this.comfortGlyph.toggle());
9192
+ }), window.addEventListener("beforeunload", () => this.comfortGlyph && this.comfortGlyph.dispose());
8775
9193
  }
8776
9194
  _maybeAttachDiveSystem() {
8777
9195
  if (!this.config.enableDiveSystem || this.diveSystem) return;
@@ -8781,14 +9199,23 @@ class Kn extends je {
8781
9199
  this.belowViewer.cameraManager.camera
8782
9200
  ), setTimeout(() => {
8783
9201
  this.diveSystem.initializeToggleSwitch();
8784
- }, 100);
9202
+ }, 100), document.addEventListener("keydown", (t) => {
9203
+ if (t.code === "KeyZ" && !t.ctrlKey && !t.metaKey && !t.altKey) {
9204
+ if (this.belowViewer?.arManager?.isActive?.())
9205
+ return;
9206
+ t.preventDefault(), this.diveSystem && this.diveSystem.toggleDiveMode();
9207
+ }
9208
+ t.code === "KeyH" && !t.ctrlKey && !t.metaKey && !t.altKey && (t.preventDefault(), this.takeScreenshot());
9209
+ });
8785
9210
  const e = (t) => {
8786
9211
  if (this.diveSystem) {
8787
9212
  const i = performance.now();
8788
9213
  this.diveSystem.update(i, t), this.belowViewer.vrManager && this.diveSystem.updateTorchFromVRManager(this.belowViewer.vrManager), this.belowViewer.renderer.xr.isPresenting || this.diveSystem.torch.updateCameraPosition(this.belowViewer.cameraManager.camera);
8789
9214
  }
8790
9215
  };
8791
- this.belowViewer.onAfterRender ? this.belowViewer.onAfterRender(e) : this.belowViewer.on("before-render", e), this.on("model-loaded", (t) => {
9216
+ this.belowViewer.onAfterRender ? this.belowViewer.onAfterRender(e) : this.belowViewer.on("before-render", e), this.belowViewer.on("ar-session-start", () => {
9217
+ this.diveSystem && this.diveSystem.setDiveMode(!1);
9218
+ }), this.on("model-loaded", (t) => {
8792
9219
  this.diveSystem && t.model && this.diveSystem.updateParticleBounds(t.model);
8793
9220
  }), typeof window < "u" && (window.diveSystem = this.diveSystem);
8794
9221
  }
@@ -8800,14 +9227,118 @@ class Kn extends je {
8800
9227
  <circle cx="12" cy="13" r="4"></circle>
8801
9228
  </svg>`, e.tabIndex = 0, e.title = "Save Screenshot", e.setAttribute("aria-label", "Save Screenshot"), e.addEventListener("click", () => this.takeScreenshot()), e.addEventListener("keydown", (t) => {
8802
9229
  (t.key === "Enter" || t.key === " ") && (t.preventDefault(), this.takeScreenshot());
8803
- }), this.container.appendChild(e), this.screenshotButton = e, this.ui.screenshot = e;
9230
+ }), this.getUiContainer().appendChild(e), this.screenshotButton = e, this.ui.screenshot = e;
8804
9231
  }
8805
9232
  _maybeAttachFullscreenButton() {
8806
9233
  if (!this.config.enableFullscreen || this.fullscreenButton) return;
8807
9234
  const e = document.createElement("div");
8808
9235
  e.id = "fullscreenButton", e.className = "fullscreen-button", this.config.measurementTheme === "light" && e.classList.add("light-theme"), this.config.enableMeasurement || e.classList.add("no-measurement"), e.textContent = "⛶", e.tabIndex = 0, e.title = "Enter Fullscreen", e.setAttribute("aria-label", "Enter Fullscreen"), e.addEventListener("click", () => this.toggleFullscreen()), e.addEventListener("keydown", (t) => {
8809
9236
  (t.key === "Enter" || t.key === " ") && (t.preventDefault(), this.toggleFullscreen());
8810
- }), this.container.appendChild(e), this.fullscreenButton = e, this.ui.fullscreen = e, this._onFullscreenChange = () => this.updateFullscreenButton(), document.addEventListener("fullscreenchange", this._onFullscreenChange), this.updateFullscreenButton();
9237
+ }), this.getUiContainer().appendChild(e), this.fullscreenButton = e, this.ui.fullscreen = e, this._onFullscreenChange = () => this.updateFullscreenButton(), document.addEventListener("fullscreenchange", this._onFullscreenChange), this.updateFullscreenButton();
9238
+ }
9239
+ _maybeAttachFlyControls() {
9240
+ if (!this.config.enableFlyControls || this.flyControls || !this.belowViewer?.cameraManager || !this.belowViewer?.renderer) return;
9241
+ this.flyControls = new jn({
9242
+ domElement: this.belowViewer.renderer.domElement,
9243
+ camera: this.belowViewer.cameraManager.camera,
9244
+ controls: this.belowViewer.cameraManager.controls,
9245
+ renderer: this.belowViewer.renderer,
9246
+ ...this.config.flyControls
9247
+ }), this._ensureFlyModeIndicator(), this.flyControls.on("fly-mode-change", (t) => {
9248
+ this.emit("fly-mode-change", t), this.ui.flyIndicator && this.ui.flyIndicator.classList.toggle("visible", t.active), this._handleVRButtonVisibility(t.active);
9249
+ });
9250
+ const e = (t) => {
9251
+ this.flyControls && this.flyControls.update(t);
9252
+ };
9253
+ this.belowViewer.onAfterRender ? this.belowViewer.onAfterRender(e) : this.belowViewer.on("before-render", e);
9254
+ }
9255
+ _ensureFlyModeIndicator() {
9256
+ if (this.ui.flyIndicator || typeof document > "u") return;
9257
+ const e = document.getElementById("flyModeIndicator");
9258
+ if (e) {
9259
+ this.ui.flyIndicator = e;
9260
+ return;
9261
+ }
9262
+ const t = document.createElement("div");
9263
+ t.className = "fly-mode-indicator";
9264
+ const i = this.flyControls?.clickToExit ? "Click to exit or press Esc" : "Press Esc to exit";
9265
+ t.innerHTML = `
9266
+ <div class="crosshair"></div>
9267
+ <div class="hint">
9268
+ <kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd> Move
9269
+ <kbd>Q</kbd><kbd>E</kbd> Up/Down
9270
+ <kbd>Shift</kbd> Fast<br>
9271
+ <span class="fly-exit">${i}</span>
9272
+ </div>
9273
+ `, this.container.appendChild(t), this.ui.flyIndicator = t;
9274
+ }
9275
+ _handleVRButtonVisibility(e) {
9276
+ const t = this.belowViewer?.vrManager?.vrCore?.vrButton;
9277
+ t && (e ? window.getComputedStyle(t).visibility !== "hidden" && (this._vrButtonWasVisible = !0, t.style.setProperty("visibility", "hidden", "important"), t.style.setProperty("opacity", "0", "important"), t.style.setProperty("pointer-events", "none", "important")) : this._vrButtonWasVisible && (t.style.setProperty("visibility", "visible", "important"), t.style.setProperty("opacity", "1", "important"), t.style.setProperty("pointer-events", "auto", "important"), this._vrButtonWasVisible = !1));
9278
+ }
9279
+ setupRecoveryHandlers() {
9280
+ if (this.recoveryHandlers || !this.config.enableAutoRecovery || typeof window > "u" || typeof document > "u") return;
9281
+ const e = this.belowViewer?.renderer?.domElement;
9282
+ if (!e) return;
9283
+ const t = () => {
9284
+ document.hidden || this.queueRecovery("visibility-change", { forceReload: this.hadContextLoss });
9285
+ }, i = () => {
9286
+ this.queueRecovery("window-focus", { forceReload: !1 });
9287
+ }, s = (n) => {
9288
+ n && typeof n.preventDefault == "function" && n.preventDefault(), this.hadContextLoss = !0;
9289
+ }, o = () => {
9290
+ this.queueRecovery("context-restored", { forceReload: !0, delayMs: 120 });
9291
+ };
9292
+ document.addEventListener("visibilitychange", t), window.addEventListener("focus", i), e.addEventListener("webglcontextlost", s, !1), e.addEventListener("webglcontextrestored", o, !1), this.recoveryHandlers = {
9293
+ canvas: e,
9294
+ onVisibilityChange: t,
9295
+ onWindowFocus: i,
9296
+ onContextLost: s,
9297
+ onContextRestored: o
9298
+ };
9299
+ }
9300
+ queueRecovery(e, { forceReload: t = !1, delayMs: i = 200 } = {}) {
9301
+ this.isDisposed || !this.config.enableAutoRecovery || (this.recoveryTimer && (clearTimeout(this.recoveryTimer), this.recoveryTimer = null), this.recoveryTimer = setTimeout(() => {
9302
+ this.recoveryTimer = null, this.tryRecoverFromInterruption(e, { forceReload: t });
9303
+ }, i));
9304
+ }
9305
+ async tryRecoverFromInterruption(e, { forceReload: t = !1 } = {}) {
9306
+ if (this.isDisposed || !this.config.enableAutoRecovery || typeof document < "u" && document.hidden) return;
9307
+ if (this.isLoading) {
9308
+ this.queueRecovery(e, { forceReload: !0, delayMs: 600 });
9309
+ return;
9310
+ }
9311
+ const i = Date.now();
9312
+ if (i - this.lastRecoveryAttemptAt < this.recoveryCooldownMs)
9313
+ return;
9314
+ this.lastRecoveryAttemptAt = i;
9315
+ const s = this.belowViewer?.getLoadedModels?.()?.length || 0;
9316
+ if (!(t || this.hadContextLoss || s === 0)) {
9317
+ this.forceRefreshFrame();
9318
+ return;
9319
+ }
9320
+ const n = Object.keys(this.config.models)[0], r = this.currentModelKey || this.lastRequestedModelKey || n;
9321
+ if (!r || !this.config.models[r]) {
9322
+ this.forceRefreshFrame();
9323
+ return;
9324
+ }
9325
+ if (this.recoveryAttempts += 1, this.updateStatus("Recovering viewer..."), await this.loadModel(r), (this.belowViewer?.getLoadedModels?.()?.length || 0) > 0) {
9326
+ this.hadContextLoss = !1, this.recoveryAttempts = 0, this.forceRefreshFrame(), this.emit("viewer-recovered", { reason: e, modelKey: r });
9327
+ return;
9328
+ }
9329
+ this.recoveryAttempts < this.maxRecoveryAttempts ? this.queueRecovery(e, {
9330
+ forceReload: !0,
9331
+ delayMs: 400 + this.recoveryAttempts * 300
9332
+ }) : this.updateStatus("Recovery failed. Try selecting the model again.");
9333
+ }
9334
+ forceRefreshFrame() {
9335
+ const e = this.belowViewer?.renderer, t = this.belowViewer?.sceneManager?.scene, i = this.belowViewer?.cameraManager?.camera;
9336
+ if (!(!e || !t || !i))
9337
+ try {
9338
+ const s = e.xr?.isPresenting;
9339
+ this.belowViewer?.stereoEnabled && !s && this.belowViewer?.stereoMode === "sbs" && typeof this.belowViewer.renderSbsStereo == "function" ? this.belowViewer.renderSbsStereo() : e.render(t, i);
9340
+ } catch {
9341
+ }
8811
9342
  }
8812
9343
  toggleFullscreen() {
8813
9344
  if (this.isFullscreen()) {
@@ -8881,7 +9412,7 @@ class Kn extends je {
8881
9412
  }), this.belowViewer.on("vr-movement-start", (e) => this.emit("vr-movement-start", e)), this.belowViewer.on("vr-movement-stop", (e) => this.emit("vr-movement-stop", e)), this.belowViewer.on("vr-movement-update", (e) => this.emit("vr-movement-update", e));
8882
9413
  }
8883
9414
  onVRSessionStart() {
8884
- if (this.ui.info && (this.ui.info.style.display = "none"), this.ui.selector && (this.ui.selector.style.pointerEvents = "none", this.ui.selector.style.opacity = "0.5"), this.isLoading && this.updateVRLoadingIndicator(), !this.vrUpdateLoop) {
9415
+ if (this.flyControls && this.flyControls.exitFlyMode(), this.ui.info && (this.ui.info.style.display = "none"), this.ui.selector && (this.ui.selector.style.pointerEvents = "none", this.ui.selector.style.opacity = "0.5"), this.isLoading && this.updateVRLoadingIndicator(), !this.vrUpdateLoop) {
8885
9416
  let e = 0;
8886
9417
  const t = (i) => {
8887
9418
  this.belowViewer && this.belowViewer.renderer && this.belowViewer.renderer.xr && this.belowViewer.renderer.xr.isPresenting ? (i - e > 100 && (this.vrLoadingSprite && this.belowViewer.sceneManager.scene.children.includes(this.vrLoadingSprite) && this.isLoading && this.positionVRLoadingSprite(), e = i), this.vrUpdateLoop = requestAnimationFrame(t)) : this.vrUpdateLoop = null;
@@ -8908,16 +9439,16 @@ class Kn extends je {
8908
9439
  s = !1, o.x = h.clientX, o.y = h.clientY;
8909
9440
  }, A = (h) => {
8910
9441
  if (!s) {
8911
- const d = Math.abs(h.clientX - o.x), g = Math.abs(h.clientY - o.y);
8912
- (d > n || g > n) && (s = !0);
9442
+ const d = Math.abs(h.clientX - o.x), u = Math.abs(h.clientY - o.y);
9443
+ (d > n || u > n) && (s = !0);
8913
9444
  }
8914
9445
  }, a = () => {
8915
9446
  setTimeout(() => {
8916
9447
  s = !1;
8917
9448
  }, 10);
8918
9449
  }, l = (h) => {
8919
- const d = Date.now(), g = d - i < t;
8920
- i = d, !(this.belowViewer.renderer.xr?.isPresenting || s) && g && this.focusOnPoint(h);
9450
+ const d = Date.now(), u = d - i < t;
9451
+ i = d, !(this.belowViewer.renderer.xr?.isPresenting || s) && (this.measurementSystem && this.measurementSystem.desktopMeasurementMode || u && this.focusOnPoint(h));
8921
9452
  };
8922
9453
  e.addEventListener("mousedown", r), e.addEventListener("mousemove", A), e.addEventListener("mouseup", a), e.addEventListener("click", l), this.focusEventHandlers = {
8923
9454
  onMouseDown: r,
@@ -8926,27 +9457,48 @@ class Kn extends je {
8926
9457
  onMouseClick: l
8927
9458
  };
8928
9459
  }
9460
+ getPointerRaycastInfo(e) {
9461
+ if (!e || typeof e.clientX != "number" || typeof e.clientY != "number" || !this.belowViewer || !this.belowViewer.renderer || !this.belowViewer.cameraManager || this.belowViewer.renderer.xr?.isPresenting)
9462
+ return null;
9463
+ const i = this.belowViewer.renderer.domElement.getBoundingClientRect();
9464
+ if (!i.width || !i.height)
9465
+ return null;
9466
+ const s = e.clientX - i.left, o = e.clientY - i.top;
9467
+ if (!Number.isFinite(s) || !Number.isFinite(o))
9468
+ return null;
9469
+ const n = this.belowViewer.cameraManager.getCamera();
9470
+ let r = n, A = s / i.width * 2 - 1;
9471
+ const a = -(o / i.height * 2 - 1), l = this.belowViewer.getStereoSettings?.();
9472
+ if (l?.enabled === !0 && l?.mode === "sbs" && this.belowViewer.stereoCamera) {
9473
+ const h = this.belowViewer.stereoCamera, d = i.width / 2, u = s <= d, p = u ? d : i.width - d, b = u ? s : s - d;
9474
+ p > 0 && (A = b / p * 2 - 1), h.aspect = i.height > 0 ? d / i.height : 1, h.update(n), r = u ? h.cameraL : h.cameraR;
9475
+ }
9476
+ return {
9477
+ mouse: { x: A, y: a },
9478
+ camera: r
9479
+ };
9480
+ }
8929
9481
  focusOnPoint(e) {
8930
- const i = this.belowViewer.renderer.domElement.getBoundingClientRect(), s = {
8931
- x: (e.clientX - i.left) / i.width * 2 - 1,
8932
- y: -((e.clientY - i.top) / i.height) * 2 + 1
8933
- }, o = new u.Raycaster(), n = this.belowViewer.cameraManager.getCamera();
8934
- o.setFromCamera(s, n);
8935
- let r = [];
9482
+ const t = this.getPointerRaycastInfo(e), i = t?.mouse, s = t?.camera;
9483
+ if (!i || !s)
9484
+ return;
9485
+ const o = new g.Raycaster();
9486
+ o.setFromCamera(i, s);
9487
+ let n = [];
8936
9488
  if (this.measurementSystem && this.measurementSystem._raycastTargets && this.measurementSystem._raycastTargets.length > 0)
8937
- r = this.measurementSystem._raycastTargets;
9489
+ n = this.measurementSystem._raycastTargets;
8938
9490
  else {
8939
- const a = this.belowViewer.sceneManager.getScene();
8940
- r = [], a.traverse((l) => {
8941
- l.isMesh && l.geometry && !this.isMeasurementHelper(l) && r.push(l);
9491
+ const A = this.belowViewer.sceneManager.getScene();
9492
+ n = [], A.traverse((a) => {
9493
+ a.isMesh && a.geometry && !this.isMeasurementHelper(a) && n.push(a);
8942
9494
  });
8943
9495
  }
8944
- if (r.length === 0)
9496
+ if (n.length === 0)
8945
9497
  return;
8946
- const A = o.intersectObjects(r, !0);
8947
- if (A.length > 0) {
8948
- const a = A[0].point;
8949
- this.belowViewer.cameraManager.focusOn(a), this.emit("focus", { point: a, intersect: A[0] });
9498
+ const r = o.intersectObjects(n, !0);
9499
+ if (r.length > 0) {
9500
+ const A = r[0].point;
9501
+ this.belowViewer.cameraManager.focusOn(A), this.emit("focus", { point: A, intersect: r[0] });
8950
9502
  }
8951
9503
  }
8952
9504
  isMeasurementHelper(e) {
@@ -8961,14 +9513,72 @@ class Kn extends je {
8961
9513
  return !!(typeof e.name == "string" && (e.name.startsWith("MeasurementHelper") || e.name.includes("measurement") || e.name.includes("ghost")));
8962
9514
  }
8963
9515
  createUI() {
8964
- this.container === document.body ? document.documentElement.classList.add("below-viewer") : this.container.classList.add("below-viewer-container");
9516
+ this.container === document.body ? document.documentElement.classList.add("below-viewer") : this.container.classList.add("below-viewer-container"), this.ensureUiRoot();
8965
9517
  const e = Object.keys(this.config.models).length;
8966
9518
  e > 1 && !this.ui.dropdown && this.createModelSelector(), this.config.enableDiveSystem && this.config.showDiveToggle && e <= 1 && !this.ui.diveToggle && this.createDiveModeToggle(), this.config.showInfo && !this.ui.info && this.createInfoPanel(), this.config.showLoadingIndicator && !this.ui.loading && this.createLoadingIndicator(), this.config.showStatus && !this.ui.status && this.createStatusIndicator(), this.ui.dropdown && this.ui.dropdown.addEventListener("change", (t) => {
8967
9519
  t.target.value && this.loadModel(t.target.value);
8968
9520
  });
8969
9521
  }
9522
+ ensureUiRoot() {
9523
+ if (this.uiRoot)
9524
+ return this.uiRoot;
9525
+ const e = document.createElement("div");
9526
+ return e.className = "below-ui-root", this.container.appendChild(e), this.uiRoot = e, this.applyStereoUiState(), e;
9527
+ }
9528
+ getUiContainer() {
9529
+ return this.ensureUiRoot();
9530
+ }
9531
+ applyStereoUiState() {
9532
+ const e = this.belowViewer?.getStereoSettings?.(), t = e?.enabled === !0 && e?.mode === "sbs";
9533
+ this.uiRoot && (t ? this.enableStereoUi() : this.disableStereoUi());
9534
+ }
9535
+ updateStereoUiState() {
9536
+ this.applyStereoUiState();
9537
+ }
9538
+ enableStereoUi() {
9539
+ if (this.stereoUiActive) {
9540
+ this.scheduleStereoUiSync();
9541
+ return;
9542
+ }
9543
+ if (this.stereoUiActive = !0, this.uiRoot.classList.add("below-ui-root--stereo-left"), !this.stereoUiMirror) {
9544
+ const e = document.createElement("div");
9545
+ e.className = "below-ui-root below-ui-root--stereo-right", e.setAttribute("aria-hidden", "true"), e.setAttribute("inert", ""), e.tabIndex = -1, e.style.pointerEvents = "none", this.container.appendChild(e), this.stereoUiMirror = e;
9546
+ }
9547
+ this.scheduleStereoUiSync(), !this.stereoUiObserver && typeof MutationObserver < "u" && (this.stereoUiObserver = new MutationObserver(() => this.scheduleStereoUiSync()), this.stereoUiObserver.observe(this.uiRoot, {
9548
+ childList: !0,
9549
+ attributes: !0,
9550
+ characterData: !0,
9551
+ subtree: !0
9552
+ }));
9553
+ }
9554
+ disableStereoUi() {
9555
+ this.stereoUiActive && (this.stereoUiActive = !1, this.uiRoot.classList.remove("below-ui-root--stereo-left"), this.stereoUiObserver && (this.stereoUiObserver.disconnect(), this.stereoUiObserver = null), this.stereoUiMirror && (this.stereoUiMirror.remove(), this.stereoUiMirror = null));
9556
+ }
9557
+ scheduleStereoUiSync() {
9558
+ if (this.stereoUiSyncQueued || !this.stereoUiMirror)
9559
+ return;
9560
+ this.stereoUiSyncQueued = !0, (typeof requestAnimationFrame == "function" ? requestAnimationFrame : (t) => setTimeout(t, 0))(() => {
9561
+ this.stereoUiSyncQueued = !1, this.syncStereoUiMirror();
9562
+ });
9563
+ }
9564
+ syncStereoUiMirror() {
9565
+ if (!(!this.stereoUiMirror || !this.uiRoot)) {
9566
+ this.stereoUiMirror.innerHTML = "";
9567
+ for (const e of this.uiRoot.childNodes) {
9568
+ const t = e.cloneNode(!0);
9569
+ this.stripStereoCloneIds(t), this.stereoUiMirror.appendChild(t);
9570
+ }
9571
+ }
9572
+ }
9573
+ stripStereoCloneIds(e) {
9574
+ if (!(!e || e.nodeType !== 1)) {
9575
+ e.hasAttribute("id") && e.removeAttribute("id"), e.hasAttribute("for") && e.removeAttribute("for");
9576
+ for (const t of e.children)
9577
+ this.stripStereoCloneIds(t);
9578
+ }
9579
+ }
8970
9580
  createModelSelector() {
8971
- const e = this.container, t = e.querySelector(".model-selector");
9581
+ const e = this.getUiContainer(), t = e.querySelector(".model-selector");
8972
9582
  t && t.parentElement && t.remove();
8973
9583
  const i = document.createElement("div");
8974
9584
  i.className = "model-selector below-panel", e.appendChild(i);
@@ -8990,16 +9600,16 @@ class Kn extends je {
8990
9600
  h.className = "toggle-text", h.textContent = "Survey", a.appendChild(l), a.appendChild(h);
8991
9601
  const d = document.createElement("div");
8992
9602
  d.className = "toggle-option right";
8993
- const g = document.createElement("div");
8994
- g.className = "toggle-icon", g.textContent = "🌊";
9603
+ const u = document.createElement("div");
9604
+ u.className = "toggle-icon", u.textContent = "🌊";
8995
9605
  const p = document.createElement("div");
8996
- p.className = "toggle-text", p.textContent = "Dive", d.appendChild(g), d.appendChild(p), n.appendChild(a), n.appendChild(d), o.appendChild(n), i.appendChild(o);
9606
+ p.className = "toggle-text", p.textContent = "Dive", d.appendChild(u), d.appendChild(p), n.appendChild(a), n.appendChild(d), o.appendChild(n), i.appendChild(o);
8997
9607
  }
8998
9608
  this.ui.dropdown = s, this.ui.selector = i;
8999
9609
  }
9000
9610
  createDiveModeToggle() {
9001
9611
  const e = document.createElement("div");
9002
- e.className = "dive-mode-toggle-container", e.style.position = "fixed", e.style.top = "20px", e.style.right = "20px", e.style.zIndex = "1000";
9612
+ e.className = "dive-mode-toggle-container", e.style.position = "absolute", e.style.top = "20px", e.style.right = "20px", e.style.zIndex = "1000";
9003
9613
  const t = document.createElement("div");
9004
9614
  t.className = "semantic-toggle";
9005
9615
  const i = document.createElement("input");
@@ -9017,7 +9627,7 @@ class Kn extends je {
9017
9627
  const a = document.createElement("div");
9018
9628
  a.className = "toggle-icon", a.textContent = "🌊";
9019
9629
  const l = document.createElement("div");
9020
- l.className = "toggle-text", l.textContent = "Dive", A.appendChild(a), A.appendChild(l), t.appendChild(o), t.appendChild(A), e.appendChild(t), this.container.appendChild(e), this.ui.diveToggle = e;
9630
+ l.className = "toggle-text", l.textContent = "Dive", A.appendChild(a), A.appendChild(l), t.appendChild(o), t.appendChild(A), e.appendChild(t), this.getUiContainer().appendChild(e), this.ui.diveToggle = e;
9021
9631
  }
9022
9632
  createLoadingIndicator() {
9023
9633
  const e = document.createElement("div");
@@ -9032,7 +9642,7 @@ class Kn extends je {
9032
9642
  <div class="loading-model-name">Loading Model</div>
9033
9643
  <div class="loading-status">Initializing...</div>
9034
9644
  </div>
9035
- `, this.container.appendChild(e), this.ui.loading = e;
9645
+ `, this.getUiContainer().appendChild(e), this.ui.loading = e;
9036
9646
  }
9037
9647
  /**
9038
9648
  * Create VR loading indicator as a canvas-based sprite
@@ -9043,27 +9653,27 @@ class Kn extends je {
9043
9653
  this.vrLoadingCanvas || (this.vrLoadingCanvas = document.createElement("canvas")), (this.vrLoadingCanvas.width !== r || this.vrLoadingCanvas.height !== A) && (this.vrLoadingCanvas.width = r, this.vrLoadingCanvas.height = A);
9044
9654
  const a = this.vrLoadingCanvas.getContext("2d");
9045
9655
  a.setTransform(1, 0, 0, 1, 0, 0), a.clearRect(0, 0, r, A), a.save(), a.scale(s, s);
9046
- const l = o / 2, h = n / 2, d = 25, g = h - 40;
9047
- if (a.shadowColor = "rgba(0, 0, 0, 0.8)", a.shadowBlur = 3, a.strokeStyle = "rgba(255, 255, 255, 0.3)", a.lineWidth = 3, a.beginPath(), a.arc(l, g, d, 0, Math.PI * 2), a.stroke(), a.shadowColor = "transparent", a.shadowBlur = 0, i > 0) {
9656
+ const l = o / 2, h = n / 2, d = 25, u = h - 40;
9657
+ if (a.shadowColor = "rgba(0, 0, 0, 0.8)", a.shadowBlur = 3, a.strokeStyle = "rgba(255, 255, 255, 0.3)", a.lineWidth = 3, a.beginPath(), a.arc(l, u, d, 0, Math.PI * 2), a.stroke(), a.shadowColor = "transparent", a.shadowBlur = 0, i > 0) {
9048
9658
  const p = i / 100 * Math.PI * 2;
9049
- a.strokeStyle = "#ffffff", a.lineWidth = 3, a.beginPath(), a.arc(l, g, d, -Math.PI / 2, -Math.PI / 2 + p), a.stroke();
9659
+ a.strokeStyle = "#ffffff", a.lineWidth = 3, a.beginPath(), a.arc(l, u, d, -Math.PI / 2, -Math.PI / 2 + p), a.stroke();
9050
9660
  }
9051
- if (a.fillStyle = "white", a.font = '600 16px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', a.textAlign = "center", a.textBaseline = "middle", a.shadowColor = "rgba(0, 0, 0, 0.8)", a.shadowBlur = 2, a.shadowOffsetX = 1, a.shadowOffsetY = 1, a.fillText(`${Math.round(i)}%`, l, g), t && (a.fillStyle = "white", a.font = '600 28px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', a.textAlign = "center", a.textBaseline = "middle", a.shadowColor = "rgba(0, 0, 0, 0.8)", a.shadowBlur = 4, a.shadowOffsetX = 1, a.shadowOffsetY = 1, a.fillText(t, l, h + 20)), a.fillStyle = "rgba(255, 255, 255, 0.9)", a.font = '400 20px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', a.shadowColor = "rgba(0, 0, 0, 0.8)", a.shadowBlur = 3, a.shadowOffsetX = 1, a.shadowOffsetY = 1, a.fillText(e, l, h + 50), a.restore(), this.vrLoadingTexture ? this.vrLoadingTexture.needsUpdate = !0 : (this.vrLoadingTexture = new u.CanvasTexture(this.vrLoadingCanvas), this.vrLoadingTexture.minFilter = u.LinearFilter, this.vrLoadingTexture.magFilter = u.LinearFilter), !this.vrLoadingSprite) {
9052
- const p = new u.SpriteMaterial({
9661
+ if (a.fillStyle = "white", a.font = '600 16px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', a.textAlign = "center", a.textBaseline = "middle", a.shadowColor = "rgba(0, 0, 0, 0.8)", a.shadowBlur = 2, a.shadowOffsetX = 1, a.shadowOffsetY = 1, a.fillText(`${Math.round(i)}%`, l, u), t && (a.fillStyle = "white", a.font = '600 28px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', a.textAlign = "center", a.textBaseline = "middle", a.shadowColor = "rgba(0, 0, 0, 0.8)", a.shadowBlur = 4, a.shadowOffsetX = 1, a.shadowOffsetY = 1, a.fillText(t, l, h + 20)), a.fillStyle = "rgba(255, 255, 255, 0.9)", a.font = '400 20px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', a.shadowColor = "rgba(0, 0, 0, 0.8)", a.shadowBlur = 3, a.shadowOffsetX = 1, a.shadowOffsetY = 1, a.fillText(e, l, h + 50), a.restore(), this.vrLoadingTexture ? this.vrLoadingTexture.needsUpdate = !0 : (this.vrLoadingTexture = new g.CanvasTexture(this.vrLoadingCanvas), this.vrLoadingTexture.minFilter = g.LinearFilter, this.vrLoadingTexture.magFilter = g.LinearFilter), !this.vrLoadingSprite) {
9662
+ const p = new g.SpriteMaterial({
9053
9663
  map: this.vrLoadingTexture,
9054
9664
  depthTest: !1,
9055
9665
  depthWrite: !1,
9056
9666
  transparent: !0
9057
9667
  });
9058
- this.vrLoadingSprite = new u.Sprite(p);
9059
- const C = 0.7, E = o / n;
9060
- this.vrLoadingSprite.scale.set(C * E, C, 1);
9668
+ this.vrLoadingSprite = new g.Sprite(p);
9669
+ const b = 0.7, E = o / n;
9670
+ this.vrLoadingSprite.scale.set(b * E, b, 1);
9061
9671
  }
9062
9672
  return this.vrLoadingSprite;
9063
9673
  }
9064
9674
  createStatusIndicator() {
9065
9675
  const e = document.createElement("div");
9066
- e.id = "status", e.className = "status below-status", e.style.display = "none", this.container.appendChild(e), this.ui.status = e;
9676
+ e.id = "status", e.className = "status below-status", e.style.display = "none", this.getUiContainer().appendChild(e), this.ui.status = e;
9067
9677
  }
9068
9678
  createInfoPanel() {
9069
9679
  const e = document.createElement("div");
@@ -9074,7 +9684,7 @@ class Kn extends je {
9074
9684
  i.id = "infoControls", i.className = "info-panel__controls", i.innerHTML = `
9075
9685
  <strong>Desktop:</strong> Drag to rotate • Scroll to zoom<br>
9076
9686
  <strong>Mobile:</strong> Touch and drag to explore
9077
- `, e.appendChild(t), e.appendChild(i), this.container.appendChild(e), this.ui.info = e;
9687
+ `, e.appendChild(t), e.appendChild(i), this.getUiContainer().appendChild(e), this.ui.info = e;
9078
9688
  }
9079
9689
  populateDropdown() {
9080
9690
  if (!this.ui.dropdown) return;
@@ -9108,7 +9718,7 @@ class Kn extends je {
9108
9718
  console.error("Model not found:", e);
9109
9719
  return;
9110
9720
  }
9111
- this.currentModelKey = e, this.ui.dropdown && (this.ui.dropdown.value = e), this.showLoading("Preparing to load...", t.name || e), this.belowViewer?.getLoadedModels()?.length > 0 && this.setManualLoadingMessage("Cleaning up previous model..."), document.title = `BelowJS – ${t.name || e}`;
9721
+ this.lastRequestedModelKey = e, this.currentModelKey = e, this.hadContextLoss = !1, this.recoveryTimer && (clearTimeout(this.recoveryTimer), this.recoveryTimer = null), this.ui.dropdown && (this.ui.dropdown.value = e), this.showLoading("Preparing to load...", t.name || e), this.belowViewer?.getLoadedModels()?.length > 0 && this.setManualLoadingMessage("Cleaning up previous model..."), document.title = `BelowJS – ${t.name || e}`;
9112
9722
  try {
9113
9723
  this.measurementSystem && (this.measurementSystem.clearUnifiedMeasurement(), this.measurementSystem.clearLegacyVRMeasurement(), this.measurementSystem.clearLegacyDesktopMeasurement()), this.belowViewer.clearModels(), this.belowViewer.vrManager && (this.belowViewer.vrManager.stopMovement(), this.belowViewer.vrManager.resetTeleportState()), await new Promise((n) => setTimeout(n, 50));
9114
9724
  const o = await this.belowViewer.loadModel(t.url, {
@@ -9117,9 +9727,9 @@ class Kn extends je {
9117
9727
  initialPositions: t.initialPositions
9118
9728
  // Pass VR/desktop positions
9119
9729
  });
9120
- o && (this.applyInitialPositions(t, o), this.hideLoading(), this.updateStatus(`Loaded: ${t.name || e}`), this.measurementSystem && this.measurementSystem.setRaycastTargets(o), this.modelReady = !0, this.emit("model-switched", { modelKey: e, model: o, config: t }), this.emit("modelLoaded", { modelKey: e, model: o, config: t }));
9730
+ o ? (this.applyInitialPositions(t, o), this.hideLoading(), this.updateStatus(`Loaded: ${t.name || e}`), this.applyModelMeasurementConfig(t, o), this.modelReady = !0, this.recoveryAttempts = 0, this.emit("model-switched", { modelKey: e, model: o, config: t }), this.emit("modelLoaded", { modelKey: e, model: o, config: t })) : this.currentModelKey === e && this.queueRecovery("empty-load-result", { forceReload: !0, delayMs: 350 });
9121
9731
  } catch (o) {
9122
- o.message !== "Loading cancelled" && (console.error("Failed to load model:", o), this.hideLoading(), this.updateStatus(`Error loading ${t.name || e}`), this.measurementSystem && this.measurementSystem.setRaycastTargets([]));
9732
+ o.message !== "Loading cancelled" && (console.error("Failed to load model:", o), this.hideLoading(), this.updateStatus(`Error loading ${t.name || e}`), this.applyModelMeasurementConfig(t, null), this.currentModelKey === e && (typeof document > "u" || !document.hidden) && this.queueRecovery("model-load-error", { forceReload: !0, delayMs: 500 }));
9123
9733
  }
9124
9734
  }
9125
9735
  applyInitialPositions(e, t) {
@@ -9201,11 +9811,11 @@ class Kn extends je {
9201
9811
  positionVRLoadingSprite() {
9202
9812
  if (!this.vrLoadingSprite || !this.belowViewer || !this.belowViewer.cameraManager)
9203
9813
  return;
9204
- const e = this.belowViewer.cameraManager.camera, t = 2, i = new u.Vector3();
9814
+ const e = this.belowViewer.cameraManager.camera, t = 2, i = new g.Vector3();
9205
9815
  e.getWorldDirection(i);
9206
- const s = new u.Vector3();
9816
+ const s = new g.Vector3();
9207
9817
  e.getWorldPosition(s);
9208
- const o = new u.Vector3();
9818
+ const o = new g.Vector3();
9209
9819
  o.copy(s), o.add(i.multiplyScalar(t)), this.vrLoadingSprite.position.copy(o), this.vrLoadingSprite.lookAt(s);
9210
9820
  }
9211
9821
  updateStatus(e) {
@@ -9225,7 +9835,8 @@ class Kn extends je {
9225
9835
  }
9226
9836
  }
9227
9837
  onModelLoaded({ model: e }) {
9228
- this.measurementSystem && this.measurementSystem.setRaycastTargets(e);
9838
+ const t = this.currentModelKey ? this.config.models[this.currentModelKey] : null;
9839
+ this.applyModelMeasurementConfig(t, e), this.flyControls && this.flyControls.setModelSizeFromObject(e);
9229
9840
  }
9230
9841
  onModelLoadError({ error: e }) {
9231
9842
  this.hideLoading(), this.updateStatus(`Failed to load model: ${e.message}`);
@@ -9337,6 +9948,48 @@ class Kn extends je {
9337
9948
  }
9338
9949
  }
9339
9950
  }
9951
+ /**
9952
+ * Enable or disable fly controls.
9953
+ *
9954
+ * @method setFlyControlsEnabled
9955
+ * @param {boolean} enabled - Whether fly controls should be enabled
9956
+ */
9957
+ setFlyControlsEnabled(e) {
9958
+ this.flyControls && this.flyControls.setEnabled(e);
9959
+ }
9960
+ /**
9961
+ * Enter fly mode (pointer lock).
9962
+ *
9963
+ * @method enterFlyMode
9964
+ */
9965
+ enterFlyMode() {
9966
+ this.flyControls && this.flyControls.enterFlyMode();
9967
+ }
9968
+ /**
9969
+ * Exit fly mode (pointer lock).
9970
+ *
9971
+ * @method exitFlyMode
9972
+ */
9973
+ exitFlyMode() {
9974
+ this.flyControls && this.flyControls.exitFlyMode();
9975
+ }
9976
+ /**
9977
+ * Toggle fly mode (pointer lock).
9978
+ *
9979
+ * @method toggleFlyMode
9980
+ */
9981
+ toggleFlyMode() {
9982
+ this.flyControls && this.flyControls.toggleFlyMode();
9983
+ }
9984
+ /**
9985
+ * Check if fly mode is currently active.
9986
+ *
9987
+ * @method isFlyModeActive
9988
+ * @returns {boolean} True if fly mode is active
9989
+ */
9990
+ isFlyModeActive() {
9991
+ return this.flyControls ? this.flyControls.isActive() : !1;
9992
+ }
9340
9993
  /**
9341
9994
  * Set VR comfort settings for motion sickness reduction
9342
9995
  *
@@ -9362,8 +10015,48 @@ class Kn extends je {
9362
10015
  return this.belowViewer.setVRComfortSettings(e);
9363
10016
  }
9364
10017
  setVRComfortPreset(e) {
9365
- if (this.belowViewer && this.belowViewer.setVRComfortPreset)
9366
- return this.belowViewer.setVRComfortPreset(e);
10018
+ const t = e === "comfort", i = e === "free", s = this.belowViewer && this.belowViewer.setVRComfortPreset ? this.belowViewer.setVRComfortPreset(e) : !1;
10019
+ return (t || i) && (this.lastComfortMode = t, this.comfortGlyph && this.comfortGlyph.setComfortMode(t, {
10020
+ emitEvent: !1,
10021
+ applyToManager: !1
10022
+ })), s;
10023
+ }
10024
+ /**
10025
+ * Enable or disable comfort mode.
10026
+ *
10027
+ * Works both inside and outside active VR sessions.
10028
+ *
10029
+ * @param {boolean} enabled
10030
+ * @returns {boolean}
10031
+ */
10032
+ setComfortMode(e) {
10033
+ const t = e === !0, i = this.belowViewer && this.belowViewer.setVRComfortMode ? this.belowViewer.setVRComfortMode(t) : !1;
10034
+ return this.lastComfortMode = t, this.comfortGlyph && this.comfortGlyph.setComfortMode(t, {
10035
+ emitEvent: !1,
10036
+ applyToManager: !1
10037
+ }), i;
10038
+ }
10039
+ /**
10040
+ * Toggle comfort mode.
10041
+ *
10042
+ * Works both inside and outside active VR sessions.
10043
+ *
10044
+ * @returns {boolean} New comfort mode state
10045
+ */
10046
+ toggleComfortMode() {
10047
+ const e = !this.getComfortMode();
10048
+ return this.setComfortMode(e), e;
10049
+ }
10050
+ /**
10051
+ * Check current comfort mode state.
10052
+ *
10053
+ * @returns {boolean}
10054
+ */
10055
+ getComfortMode() {
10056
+ if (typeof this.lastComfortMode == "boolean")
10057
+ return this.lastComfortMode;
10058
+ const e = this.getVRComfortSettings();
10059
+ return e ? e.locomotionMode === "teleport" && e.reducedMotion === !0 : !1;
9367
10060
  }
9368
10061
  /**
9369
10062
  * Get current VR comfort settings
@@ -9380,6 +10073,38 @@ class Kn extends je {
9380
10073
  getVRComfortSettings() {
9381
10074
  return this.belowViewer && this.belowViewer.getVRComfortSettings ? this.belowViewer.getVRComfortSettings() : null;
9382
10075
  }
10076
+ /**
10077
+ * Enable or disable SBS stereo rendering.
10078
+ *
10079
+ * @param {boolean} enabled - Whether stereo rendering is enabled.
10080
+ */
10081
+ setStereoEnabled(e) {
10082
+ this.belowViewer && this.belowViewer.setStereoEnabled && this.belowViewer.setStereoEnabled(e), this.updateStereoUiState();
10083
+ }
10084
+ /**
10085
+ * Adjust the SBS stereo eye separation.
10086
+ *
10087
+ * @param {number} eyeSeparation - Eye separation in meters.
10088
+ */
10089
+ setStereoEyeSeparation(e) {
10090
+ this.belowViewer && this.belowViewer.setStereoEyeSeparation && this.belowViewer.setStereoEyeSeparation(e);
10091
+ }
10092
+ /**
10093
+ * Set the stereo mode (currently only 'sbs').
10094
+ *
10095
+ * @param {string} mode - Stereo mode string.
10096
+ */
10097
+ setStereoMode(e) {
10098
+ this.belowViewer && this.belowViewer.setStereoMode && this.belowViewer.setStereoMode(e), this.updateStereoUiState();
10099
+ }
10100
+ /**
10101
+ * Get current stereo settings.
10102
+ *
10103
+ * @returns {{enabled: boolean, mode: string, eyeSeparation: number}|null}
10104
+ */
10105
+ getStereoSettings() {
10106
+ return this.belowViewer && this.belowViewer.getStereoSettings ? this.belowViewer.getStereoSettings() : null;
10107
+ }
9383
10108
  /**
9384
10109
  * Clean up and dispose of all resources
9385
10110
  *
@@ -9396,23 +10121,28 @@ class Kn extends je {
9396
10121
  * @since 1.0.0
9397
10122
  */
9398
10123
  dispose() {
10124
+ if (this.isDisposed = !0, this.recoveryTimer && (clearTimeout(this.recoveryTimer), this.recoveryTimer = null), this.recoveryHandlers) {
10125
+ const { canvas: e, onVisibilityChange: t, onWindowFocus: i, onContextLost: s, onContextRestored: o } = this.recoveryHandlers;
10126
+ typeof document < "u" && t && document.removeEventListener("visibilitychange", t), typeof window < "u" && i && window.removeEventListener("focus", i), e && s && e.removeEventListener("webglcontextlost", s, !1), e && o && e.removeEventListener("webglcontextrestored", o, !1), this.recoveryHandlers = null;
10127
+ }
9399
10128
  if (typeof window < "u" && window.modelViewer === this && (window.modelViewer = null), this.focusEventHandlers && this.belowViewer?.renderer?.domElement) {
9400
10129
  const e = this.belowViewer.renderer.domElement;
9401
10130
  e.removeEventListener("mousedown", this.focusEventHandlers.onMouseDown), e.removeEventListener("mousemove", this.focusEventHandlers.onMouseMove), e.removeEventListener("mouseup", this.focusEventHandlers.onMouseUp), e.removeEventListener("click", this.focusEventHandlers.onMouseClick), this.focusEventHandlers = null;
9402
10131
  }
9403
- this.measurementSystem && (this.measurementSystem.dispose(), this.measurementSystem = null), this.comfortGlyph && (this.comfortGlyph.dispose(), this.comfortGlyph = null), this.diveSystem && (this.diveSystem.dispose(), this.diveSystem = null, typeof window < "u" && window.diveSystem === this.diveSystem && (window.diveSystem = null)), this.fullscreenButton && (this.fullscreenButton.remove(), this.fullscreenButton = null, document.removeEventListener("fullscreenchange", this._onFullscreenChange)), this.screenshotButton && (this.screenshotButton.remove(), this.screenshotButton = null), this.belowViewer && this.belowViewer.dispose(), this.removeAllListeners();
10132
+ this.measurementSystem && (this.measurementSystem.dispose(), this.measurementSystem = null), this.comfortGlyph && (this.comfortGlyph.dispose(), this.comfortGlyph = null), this.diveSystem && (this.diveSystem.dispose(), this.diveSystem = null, typeof window < "u" && window.diveSystem === this.diveSystem && (window.diveSystem = null)), this.fullscreenButton && (this.fullscreenButton.remove(), this.fullscreenButton = null, document.removeEventListener("fullscreenchange", this._onFullscreenChange)), this.screenshotButton && (this.screenshotButton.remove(), this.screenshotButton = null), this.stereoUiObserver && (this.stereoUiObserver.disconnect(), this.stereoUiObserver = null), this.stereoUiMirror && (this.stereoUiMirror.remove(), this.stereoUiMirror = null), this.belowViewer && this.belowViewer.dispose(), this.removeAllListeners();
9404
10133
  }
9405
10134
  }
9406
10135
  export {
9407
10136
  _n as BelowViewer,
9408
10137
  Ws as Camera,
9409
10138
  Ke as ConfigValidator,
9410
- je as EventSystem,
10139
+ Te as EventSystem,
10140
+ jn as FlyControls,
9411
10141
  Ai as Line2,
9412
10142
  It as LineGeometry,
9413
- Ve as LineMaterial,
10143
+ Oe as LineMaterial,
9414
10144
  O as ModelLoader,
9415
- Kn as ModelViewer,
9416
- ks as Scene,
10145
+ zn as ModelViewer,
10146
+ Fs as Scene,
9417
10147
  Mn as VRManager
9418
10148
  };