@ericchen1990/pano-view 3.6.0 → 3.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2587,6 +2587,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2587
2587
  const { camera, gl } = useThree();
2588
2588
  const xrSession = useXR((state) => state.session);
2589
2589
  const xrSessionRef = useRef(xrSession);
2590
+ const pointerRevisionRef = useRef(0);
2590
2591
  const viewRef = useRef({ ...initialView });
2591
2592
  const targetViewRef = useRef({ ...initialView });
2592
2593
  const initialViewRef = useRef({ ...initialView });
@@ -2681,6 +2682,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2681
2682
  };
2682
2683
  const acquireInteractionLock = () => {
2683
2684
  cancelNavigation();
2685
+ pointerRevisionRef.current += 1;
2684
2686
  interactionLockCountRef.current += 1;
2685
2687
  stopVelocity();
2686
2688
  if (mouseActiveRef.current) {
@@ -2712,6 +2714,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2712
2714
  legacyFovRef.current.maxFov
2713
2715
  );
2714
2716
  if (JSON.stringify(next) === JSON.stringify(limitsRef.current)) return;
2717
+ pointerRevisionRef.current += 1;
2715
2718
  limitsRef.current = next;
2716
2719
  cancelNavigation();
2717
2720
  stopVelocity();
@@ -2727,6 +2730,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2727
2730
  };
2728
2731
  const setView = (view, setOptions) => {
2729
2732
  cancelNavigation();
2733
+ pointerRevisionRef.current += 1;
2730
2734
  const nextView = hardConstrainView(view);
2731
2735
  if (gyroActiveRef.current) {
2732
2736
  gyroOffsetRef.current = {
@@ -2746,6 +2750,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2746
2750
  if (xrSessionRef.current != null || gyroActiveRef.current || interactionLockCountRef.current > 0) {
2747
2751
  return Promise.resolve({ status: "cancelled" });
2748
2752
  }
2753
+ pointerRevisionRef.current += 1;
2749
2754
  const from = { ...viewRef.current };
2750
2755
  const safeTargetInput = {
2751
2756
  yaw: targetInput.yaw !== void 0 && Number.isFinite(targetInput.yaw) ? targetInput.yaw : from.yaw,
@@ -2810,19 +2815,24 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2810
2815
  return false;
2811
2816
  }
2812
2817
  const current = targetViewRef.current;
2818
+ const origin = !gyroActiveRef.current ? applyOptions?.pointerOrigin : void 0;
2819
+ const reference = origin ?? current;
2813
2820
  const gyroMode = gyroTouchModeRef.current;
2814
2821
  const gyroControlsView = gyroActiveRef.current;
2815
2822
  const appliesTouchMode = gyroControlsView && applyOptions?.source === "touch";
2816
2823
  const acceptsYaw = !appliesTouchMode || gyroMode === "horizontaloffset" || gyroMode === "full";
2817
2824
  const acceptsPitch = !appliesTouchMode || gyroMode === "full";
2818
- const nextYaw = acceptsYaw && delta.yaw !== void 0 && Number.isFinite(delta.yaw) ? applyLimitedYawDelta(current.yaw, delta.yaw, limitsRef.current.yaw) : current.yaw;
2819
- const nextPitch = acceptsPitch && delta.pitch !== void 0 && Number.isFinite(delta.pitch) ? current.pitch + delta.pitch : current.pitch;
2825
+ const nextYaw = acceptsYaw && delta.yaw !== void 0 && Number.isFinite(delta.yaw) ? applyLimitedYawDelta(reference.yaw, delta.yaw, limitsRef.current.yaw) : current.yaw;
2826
+ const nextPitch = acceptsPitch && delta.pitch !== void 0 && Number.isFinite(delta.pitch) ? reference.pitch + delta.pitch : current.pitch;
2820
2827
  const nextFov = delta.fov !== void 0 && Number.isFinite(delta.fov) ? current.fov + delta.fov : current.fov;
2821
2828
  targetViewRef.current = softConstrainView({
2822
2829
  yaw: nextYaw,
2823
2830
  pitch: nextPitch,
2824
2831
  fov: nextFov
2825
2832
  });
2833
+ if (origin) {
2834
+ viewRef.current = { ...viewRef.current, yaw: targetViewRef.current.yaw, pitch: targetViewRef.current.pitch };
2835
+ }
2826
2836
  if (gyroControlsView) {
2827
2837
  if (acceptsYaw && delta.yaw !== void 0 && Number.isFinite(delta.yaw)) {
2828
2838
  gyroOffsetRef.current.yaw = shortestYawDelta(gyroPoseRef.current.yaw, targetViewRef.current.yaw);
@@ -2838,10 +2848,10 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2838
2848
  const elapsed = previousAt === null ? 1 / 60 : Math.max((now - previousAt) / 1e3, 1 / 120);
2839
2849
  lastVelocitySampleAtRef.current = now;
2840
2850
  if (delta.yaw !== void 0 && Number.isFinite(delta.yaw)) {
2841
- yawVelocityRef.current = delta.yaw / elapsed;
2851
+ yawVelocityRef.current = limitedYawDelta(current.yaw, targetViewRef.current.yaw, limitsRef.current.yaw) / elapsed;
2842
2852
  }
2843
2853
  if (delta.pitch !== void 0 && Number.isFinite(delta.pitch)) {
2844
- pitchVelocityRef.current = delta.pitch / elapsed;
2854
+ pitchVelocityRef.current = (targetViewRef.current.pitch - current.pitch) / elapsed;
2845
2855
  }
2846
2856
  if (delta.fov !== void 0 && Number.isFinite(delta.fov)) {
2847
2857
  zoomVelocityRef.current = clamp(delta.fov / elapsed, -180, 180);
@@ -2855,6 +2865,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2855
2865
  ref,
2856
2866
  () => ({
2857
2867
  getView: () => ({ ...viewRef.current }),
2868
+ getPointerDragState: () => ({ revision: pointerRevisionRef.current, anchored: !gyroActiveRef.current && xrSessionRef.current == null }),
2858
2869
  setSceneViewLimits: (limits) => {
2859
2870
  sceneLimitsRef.current = parseViewLimits(limits);
2860
2871
  refreshLimits();
@@ -2894,6 +2905,9 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2894
2905
  }
2895
2906
  syncInteracting();
2896
2907
  if (active && !wasActive) {
2908
+ if (!gyroActiveRef.current) {
2909
+ targetViewRef.current = { ...targetViewRef.current, yaw: viewRef.current.yaw, pitch: viewRef.current.pitch };
2910
+ }
2897
2911
  eventBusRef.current.emit("viewinteractionstart", { source });
2898
2912
  } else if (!active && wasActive) {
2899
2913
  eventBusRef.current.emit("viewinteractionend", { source });
@@ -2913,6 +2927,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2913
2927
  isInteractionLocked: () => interactionLockCountRef.current > 0,
2914
2928
  isUserInteracting,
2915
2929
  setGyroActive: (active) => {
2930
+ if (gyroActiveRef.current !== active) pointerRevisionRef.current += 1;
2916
2931
  if (active) {
2917
2932
  cancelNavigation();
2918
2933
  }
@@ -3668,8 +3683,151 @@ function KeyboardControls({
3668
3683
  }
3669
3684
 
3670
3685
  // src/mouse-controls.tsx
3671
- import { useThree as useThree3 } from "@react-three/fiber";
3686
+ import { useFrame as useFrame4, useThree as useThree3 } from "@react-three/fiber";
3672
3687
  import { useContext as useContext5, useEffect as useEffect5, useRef as useRef5 } from "react";
3688
+
3689
+ // src/pointer-drag.ts
3690
+ import { Euler as Euler2, MathUtils as MathUtils2, PerspectiveCamera as PerspectiveCamera2, Vector3 } from "three";
3691
+ var DEFAULT_POINTER_DRAG_SPEED = 0.35;
3692
+ var POINTER_FOLLOW_TIME_SECONDS = 0.01;
3693
+ var PointerDragAnchor = class {
3694
+ constructor(start, origin, rect, projection) {
3695
+ this.start = start;
3696
+ this.origin = origin;
3697
+ this.rect = rect;
3698
+ this.projection = projection;
3699
+ this.local = new Vector3();
3700
+ this.rotation = new Euler2(0, 0, 0, "YXZ");
3701
+ this.anchor = this.ray(start).clone().applyEuler(this.rotation.set(
3702
+ MathUtils2.degToRad(origin.pitch),
3703
+ MathUtils2.degToRad(-origin.yaw),
3704
+ 0,
3705
+ "YXZ"
3706
+ ));
3707
+ }
3708
+ ray(point) {
3709
+ return this.local.set(
3710
+ (point.x - this.rect.left) / Math.max(this.rect.width, 1) * 2 - 1,
3711
+ 1 - (point.y - this.rect.top) / Math.max(this.rect.height, 1) * 2,
3712
+ 0.5
3713
+ ).applyMatrix4(this.projection.projectionMatrixInverse).normalize();
3714
+ }
3715
+ solve(point, speed = DEFAULT_POINTER_DRAG_SPEED, invert = false) {
3716
+ const multiplier = (Number.isFinite(speed) && speed >= 0 ? speed : DEFAULT_POINTER_DRAG_SPEED) / DEFAULT_POINTER_DRAG_SPEED * (invert ? -1 : 1);
3717
+ if (multiplier === 0) return { yaw: 0, pitch: 0 };
3718
+ const ray = this.ray({
3719
+ x: this.start.x + (point.x - this.start.x) * multiplier,
3720
+ y: this.start.y + (point.y - this.start.y) * multiplier
3721
+ });
3722
+ const latitude = Math.asin(MathUtils2.clamp(this.anchor.y / Math.max(Math.hypot(ray.y, ray.z), 1e-12), -1, 1));
3723
+ const offset = Math.atan2(ray.y, -ray.z);
3724
+ const originPitch = MathUtils2.degToRad(this.origin.pitch);
3725
+ const candidates = [latitude - offset, Math.PI - latitude - offset, -Math.PI - latitude - offset];
3726
+ let pitch = candidates[0];
3727
+ let distance = Infinity;
3728
+ for (const candidate of candidates) {
3729
+ const bounded = MathUtils2.clamp(candidate, -Math.PI / 2, Math.PI / 2);
3730
+ const nextDistance = Math.abs(candidate - bounded) * 10 + Math.abs(bounded - originPitch);
3731
+ if (nextDistance < distance) {
3732
+ pitch = bounded;
3733
+ distance = nextDistance;
3734
+ }
3735
+ }
3736
+ const z = Math.sin(pitch) * ray.y + Math.cos(pitch) * ray.z;
3737
+ const yaw = MathUtils2.radToDeg(Math.atan2(this.anchor.x, -this.anchor.z) - Math.atan2(ray.x, -z));
3738
+ return { yaw: normalizeViewYaw(yaw - this.origin.yaw), pitch: MathUtils2.radToDeg(pitch) - this.origin.pitch };
3739
+ }
3740
+ };
3741
+ function createPointerDrag(camera, element, runtime, source) {
3742
+ let anchor;
3743
+ let revision = -1;
3744
+ let projectionKey = "";
3745
+ let pending;
3746
+ let displayed;
3747
+ let lastPoint;
3748
+ let fresh = false;
3749
+ let lastFrameDelta = 1 / 60;
3750
+ const key = (rect) => `${rect.left},${rect.top},${rect.width},${rect.height},${camera.projectionMatrix.elements.join(",")}`;
3751
+ const start = (point) => {
3752
+ const handle = runtime();
3753
+ displayed = { ...point };
3754
+ lastPoint = { ...point };
3755
+ pending = void 0;
3756
+ revision = handle?.getPointerDragState().revision ?? -1;
3757
+ anchor = void 0;
3758
+ if (!(camera instanceof PerspectiveCamera2) || !handle?.getPointerDragState().anchored) return;
3759
+ const rect = element.getBoundingClientRect();
3760
+ projectionKey = key(rect);
3761
+ anchor = new PointerDragAnchor(point, handle.getView(), rect, camera.clone());
3762
+ };
3763
+ const apply = (point, previous, speed, invert, recordVelocity) => {
3764
+ const handle = runtime();
3765
+ if (!handle) return;
3766
+ const rect = element.getBoundingClientRect();
3767
+ if (anchor && key(rect) !== projectionKey) {
3768
+ const queued = pending;
3769
+ start(displayed ?? previous);
3770
+ pending = queued;
3771
+ }
3772
+ if (anchor) {
3773
+ handle.applyViewDelta(anchor.solve(point, speed, invert), {
3774
+ pointerOrigin: anchor.origin,
3775
+ recordVelocity,
3776
+ source
3777
+ });
3778
+ } else {
3779
+ handle.applyViewDelta({
3780
+ yaw: -(point.x - previous.x) * 360 * speed / Math.max(rect.width, 1) * (invert ? -1 : 1),
3781
+ pitch: (point.y - previous.y) * 180 * speed / Math.max(rect.height, 1) * (invert ? -1 : 1)
3782
+ }, { recordVelocity, source });
3783
+ }
3784
+ };
3785
+ return {
3786
+ start,
3787
+ valid: () => revision === (runtime()?.getPointerDragState().revision ?? -1) && !runtime()?.isInteractionLocked(),
3788
+ clear: () => {
3789
+ anchor = void 0;
3790
+ revision = -1;
3791
+ pending = void 0;
3792
+ displayed = void 0;
3793
+ },
3794
+ suspend: () => {
3795
+ anchor = void 0;
3796
+ pending = void 0;
3797
+ displayed = void 0;
3798
+ },
3799
+ move(point, previous, speed, invert) {
3800
+ fresh = true;
3801
+ pending = { point, previous: lastPoint ?? previous, speed, invert };
3802
+ },
3803
+ flush(deltaSeconds = lastFrameDelta, immediate = false) {
3804
+ lastFrameDelta = deltaSeconds;
3805
+ if (!pending) return;
3806
+ const sample = pending;
3807
+ if (!anchor || immediate) {
3808
+ pending = void 0;
3809
+ apply(sample.point, sample.previous, sample.speed, sample.invert, fresh);
3810
+ fresh = false;
3811
+ lastPoint = sample.point;
3812
+ displayed = sample.point;
3813
+ return;
3814
+ }
3815
+ const previousDisplay = displayed ?? sample.previous;
3816
+ const dx = sample.point.x - previousDisplay.x;
3817
+ const dy = sample.point.y - previousDisplay.y;
3818
+ const distance = Math.hypot(dx, dy);
3819
+ const ratio = distance > 0.01 ? POINTER_FOLLOW_TIME_SECONDS / (POINTER_FOLLOW_TIME_SECONDS + deltaSeconds) : 0;
3820
+ const point = { x: sample.point.x - dx * ratio, y: sample.point.y - dy * ratio };
3821
+ apply(point, sample.previous, sample.speed, sample.invert, fresh);
3822
+ fresh = false;
3823
+ lastPoint = sample.point;
3824
+ displayed = point;
3825
+ if (ratio === 0) pending = void 0;
3826
+ }
3827
+ };
3828
+ }
3829
+
3830
+ // src/mouse-controls.tsx
3673
3831
  var DEFAULT_ROTATE_SPEED2 = 0.35;
3674
3832
  var DEFAULT_ZOOM_SPEED2 = 0.08;
3675
3833
  var BUTTON_FLAG = {
@@ -3695,7 +3853,9 @@ function MouseControls({
3695
3853
  }) {
3696
3854
  useClaimControlChannel("mouse");
3697
3855
  const controlsRef = useContext5(PanoramaViewContext);
3698
- const { gl } = useThree3();
3856
+ const { gl, camera } = useThree3();
3857
+ const validateDragRef = useRef5(void 0);
3858
+ useFrame4((_, delta) => validateDragRef.current?.(delta), -1);
3699
3859
  const pointersRef = useRef5(
3700
3860
  /* @__PURE__ */ new Map()
3701
3861
  );
@@ -3718,6 +3878,7 @@ function MouseControls({
3718
3878
  };
3719
3879
  useEffect5(() => {
3720
3880
  const element = gl.domElement;
3881
+ const drag = createPointerDrag(camera, element, () => controlsRef.current, "mouse");
3721
3882
  const allowedButtons = resolveButtons(buttons);
3722
3883
  const clearPointers = () => {
3723
3884
  for (const pointerId of pointersRef.current.keys()) {
@@ -3726,8 +3887,13 @@ function MouseControls({
3726
3887
  }
3727
3888
  }
3728
3889
  pointersRef.current.clear();
3890
+ drag.clear();
3729
3891
  controlsRef.current?.setPointerActive("mouse", false, { cancelled: true });
3730
3892
  };
3893
+ validateDragRef.current = (delta) => {
3894
+ if (pointersRef.current.size && !drag.valid()) clearPointers();
3895
+ else drag.flush(delta);
3896
+ };
3731
3897
  if (!enabled) {
3732
3898
  clearPointers();
3733
3899
  return;
@@ -3758,6 +3924,7 @@ function MouseControls({
3758
3924
  });
3759
3925
  element.setPointerCapture?.(event.pointerId);
3760
3926
  syncActive();
3927
+ drag.start({ x: event.clientX, y: event.clientY });
3761
3928
  };
3762
3929
  const onPointerMove = (event) => {
3763
3930
  if (!isMouseLike(event)) {
@@ -3777,24 +3944,16 @@ function MouseControls({
3777
3944
  at: performance.now()
3778
3945
  };
3779
3946
  pointersRef.current.set(event.pointerId, next);
3780
- const rect = element.getBoundingClientRect();
3781
- const speed = resolveSpeed2(
3782
- optionsRef.current.rotateSpeed,
3783
- DEFAULT_ROTATE_SPEED2
3784
- );
3785
- const sign = optionsRef.current.invert ? -1 : 1;
3786
- const deltaYaw = sign * -(next.x - previous.x) * 360 * speed / Math.max(rect.width, 1);
3787
- const deltaPitch = sign * (next.y - previous.y) * 180 * speed / Math.max(rect.height, 1);
3788
- controlsRef.current?.applyViewDelta(
3789
- { yaw: deltaYaw, pitch: deltaPitch },
3790
- { recordVelocity: true, source: "mouse" }
3791
- );
3947
+ const speed = resolveSpeed2(optionsRef.current.rotateSpeed, DEFAULT_ROTATE_SPEED2);
3948
+ drag.move(next, previous, speed, optionsRef.current.invert);
3792
3949
  };
3793
3950
  const releasePointer = (event) => {
3794
3951
  if (!pointersRef.current.has(event.pointerId)) {
3795
3952
  return;
3796
3953
  }
3954
+ if (event.type === "pointerup") drag.flush();
3797
3955
  pointersRef.current.delete(event.pointerId);
3956
+ drag.clear();
3798
3957
  if (element.hasPointerCapture?.(event.pointerId)) {
3799
3958
  element.releasePointerCapture?.(event.pointerId);
3800
3959
  }
@@ -3830,6 +3989,7 @@ function MouseControls({
3830
3989
  element.addEventListener("lostpointercapture", releasePointer);
3831
3990
  element.addEventListener("wheel", onWheel, { passive: false });
3832
3991
  return () => {
3992
+ validateDragRef.current = void 0;
3833
3993
  element.removeEventListener("pointerdown", onPointerDown);
3834
3994
  element.removeEventListener("pointermove", onPointerMove);
3835
3995
  element.removeEventListener("pointerup", releasePointer);
@@ -3838,7 +3998,7 @@ function MouseControls({
3838
3998
  element.removeEventListener("wheel", onWheel);
3839
3999
  clearPointers();
3840
4000
  };
3841
- }, [buttons, controlsRef, enabled, gl]);
4001
+ }, [buttons, controlsRef, enabled, gl, camera]);
3842
4002
  return null;
3843
4003
  }
3844
4004
 
@@ -4863,7 +5023,7 @@ function PanoCursorController({
4863
5023
  }
4864
5024
 
4865
5025
  // src/pano-events.tsx
4866
- import { useFrame as useFrame4, useThree as useThree5 } from "@react-three/fiber";
5026
+ import { useFrame as useFrame5, useThree as useThree5 } from "@react-three/fiber";
4867
5027
  import { useContext as useContext10, useEffect as useEffect9, useRef as useRef9 } from "react";
4868
5028
  var DEFAULT_IDLE_TIME_MS = 2e3;
4869
5029
  function resolveIdleTime(value) {
@@ -5118,7 +5278,7 @@ function usePanoEvents({
5118
5278
  observer.disconnect();
5119
5279
  };
5120
5280
  }, [gl]);
5121
- useFrame4((_, deltaSeconds) => {
5281
+ useFrame5((_, deltaSeconds) => {
5122
5282
  const interacting = controlsRef.current?.isUserInteracting() ?? false;
5123
5283
  if (interacting) {
5124
5284
  idleElapsedRef.current = 0;
@@ -5276,10 +5436,10 @@ function usePanoOverlayHost(isFullscreen) {
5276
5436
  // src/panorama-event-surface.tsx
5277
5437
  import { useThree as useThree6 } from "@react-three/fiber";
5278
5438
  import { useContext as useContext12, useEffect as useEffect10 } from "react";
5279
- import { BackSide, Raycaster, Vector2, Vector3 as Vector32 } from "three";
5439
+ import { BackSide, Raycaster, Vector2, Vector3 as Vector33 } from "three";
5280
5440
 
5281
5441
  // src/hotspot/coordinates.ts
5282
- import { MathUtils as MathUtils2, Vector3 } from "three";
5442
+ import { MathUtils as MathUtils3, Vector3 as Vector32 } from "three";
5283
5443
 
5284
5444
  // src/hotspot/types.ts
5285
5445
  var MAX_HOTSPOT_PITCH = 90;
@@ -5302,13 +5462,13 @@ function normalizePanoYaw(yaw) {
5302
5462
  if (!Number.isFinite(yaw)) {
5303
5463
  return 0;
5304
5464
  }
5305
- return MathUtils2.euclideanModulo(yaw + 180, 360) - 180;
5465
+ return MathUtils3.euclideanModulo(yaw + 180, 360) - 180;
5306
5466
  }
5307
5467
  function clampPanoPitch(pitch) {
5308
5468
  if (!Number.isFinite(pitch)) {
5309
5469
  return 0;
5310
5470
  }
5311
- const clamped = MathUtils2.clamp(
5471
+ const clamped = MathUtils3.clamp(
5312
5472
  pitch,
5313
5473
  -MAX_HOTSPOT_PITCH,
5314
5474
  MAX_HOTSPOT_PITCH
@@ -5325,10 +5485,10 @@ function normalizePanoPosition(position) {
5325
5485
  function panoPositionToVector3(position, radius = 1) {
5326
5486
  const normalized = normalizePanoPosition(position);
5327
5487
  const safeRadius = Number.isFinite(radius) ? Math.max(0, radius) : 1;
5328
- const yaw = MathUtils2.degToRad(normalized.yaw);
5329
- const pitch = MathUtils2.degToRad(normalized.pitch);
5488
+ const yaw = MathUtils3.degToRad(normalized.yaw);
5489
+ const pitch = MathUtils3.degToRad(normalized.pitch);
5330
5490
  const cosPitch = Math.cos(pitch);
5331
- return new Vector3(
5491
+ return new Vector32(
5332
5492
  cosPitch * Math.sin(yaw) * safeRadius,
5333
5493
  Math.sin(pitch) * safeRadius,
5334
5494
  -cosPitch * Math.cos(yaw) * safeRadius
@@ -5340,9 +5500,9 @@ function vector3ToPanoPosition(vector) {
5340
5500
  return { yaw: 0, pitch: 0 };
5341
5501
  }
5342
5502
  return normalizePanoPosition({
5343
- yaw: MathUtils2.radToDeg(Math.atan2(vector.x, -vector.z)),
5344
- pitch: MathUtils2.radToDeg(
5345
- Math.asin(MathUtils2.clamp(vector.y / length, -1, 1))
5503
+ yaw: MathUtils3.radToDeg(Math.atan2(vector.x, -vector.z)),
5504
+ pitch: MathUtils3.radToDeg(
5505
+ Math.asin(MathUtils3.clamp(vector.y / length, -1, 1))
5346
5506
  )
5347
5507
  });
5348
5508
  }
@@ -5377,7 +5537,7 @@ function PanoramaEventSurface() {
5377
5537
  const element = gl.domElement;
5378
5538
  const ndc = new Vector2();
5379
5539
  const raycaster = new Raycaster();
5380
- const direction = new Vector32();
5540
+ const direction = new Vector33();
5381
5541
  const handleContextMenu = (nativeEvent) => {
5382
5542
  const rect = element.getBoundingClientRect();
5383
5543
  if (rect.width <= 0 || rect.height <= 0) {
@@ -5456,7 +5616,7 @@ function notifyScenesHost(host) {
5456
5616
  }
5457
5617
 
5458
5618
  // src/touch-controls.tsx
5459
- import { useThree as useThree7 } from "@react-three/fiber";
5619
+ import { useFrame as useFrame6, useThree as useThree7 } from "@react-three/fiber";
5460
5620
  import { useContext as useContext13, useEffect as useEffect11, useRef as useRef10 } from "react";
5461
5621
  var DEFAULT_ROTATE_SPEED3 = 0.35;
5462
5622
  function resolveSpeed3(value, fallback) {
@@ -5473,7 +5633,9 @@ function TouchControls({
5473
5633
  }) {
5474
5634
  useClaimControlChannel("touch");
5475
5635
  const controlsRef = useContext13(PanoramaViewContext);
5476
- const { gl } = useThree7();
5636
+ const { gl, camera } = useThree7();
5637
+ const validateDragRef = useRef10(void 0);
5638
+ useFrame6((_, delta) => validateDragRef.current?.(delta), -1);
5477
5639
  const pointersRef = useRef10(/* @__PURE__ */ new Map());
5478
5640
  const pinchDistanceRef = useRef10(null);
5479
5641
  const optionsRef = useRef10({ rotateSpeed, invert, pinchZoom });
@@ -5483,6 +5645,7 @@ function TouchControls({
5483
5645
  optionsRef.current = { rotateSpeed, invert, pinchZoom };
5484
5646
  useEffect11(() => {
5485
5647
  const element = gl.domElement;
5648
+ const drag = createPointerDrag(camera, element, () => controlsRef.current, "touch");
5486
5649
  const clearPointers = () => {
5487
5650
  for (const pointerId of pointersRef.current.keys()) {
5488
5651
  if (element.hasPointerCapture?.(pointerId)) {
@@ -5490,9 +5653,14 @@ function TouchControls({
5490
5653
  }
5491
5654
  }
5492
5655
  pointersRef.current.clear();
5656
+ drag.clear();
5493
5657
  pinchDistanceRef.current = null;
5494
5658
  controlsRef.current?.setPointerActive("touch", false, { cancelled: true });
5495
5659
  };
5660
+ validateDragRef.current = (delta) => {
5661
+ if (pointersRef.current.size && !drag.valid()) clearPointers();
5662
+ else drag.flush(delta);
5663
+ };
5496
5664
  if (!enabled) {
5497
5665
  clearPointers();
5498
5666
  return;
@@ -5519,7 +5687,9 @@ function TouchControls({
5519
5687
  });
5520
5688
  element.setPointerCapture?.(event.pointerId);
5521
5689
  syncActive();
5522
- if (pointersRef.current.size === 2) {
5690
+ drag.start({ x: event.clientX, y: event.clientY });
5691
+ if (pointersRef.current.size >= 2) {
5692
+ drag.suspend();
5523
5693
  const [first, second] = Array.from(pointersRef.current.values());
5524
5694
  pinchDistanceRef.current = pointerDistance(first, second);
5525
5695
  }
@@ -5544,6 +5714,7 @@ function TouchControls({
5544
5714
  pointersRef.current.set(event.pointerId, next);
5545
5715
  const pointers = Array.from(pointersRef.current.values());
5546
5716
  if (pointers.length >= 2) {
5717
+ drag.suspend();
5547
5718
  if (!optionsRef.current.pinchZoom) {
5548
5719
  return;
5549
5720
  }
@@ -5562,24 +5733,16 @@ function TouchControls({
5562
5733
  }
5563
5734
  return;
5564
5735
  }
5565
- const rect = element.getBoundingClientRect();
5566
- const speed = resolveSpeed3(
5567
- optionsRef.current.rotateSpeed,
5568
- DEFAULT_ROTATE_SPEED3
5569
- );
5570
- const sign = optionsRef.current.invert ? -1 : 1;
5571
- const deltaYaw = sign * -(next.x - previous.x) * 360 * speed / Math.max(rect.width, 1);
5572
- const deltaPitch = sign * (next.y - previous.y) * 180 * speed / Math.max(rect.height, 1);
5573
- controlsRef.current?.applyViewDelta(
5574
- { yaw: deltaYaw, pitch: deltaPitch },
5575
- { recordVelocity: true, source: "touch" }
5576
- );
5736
+ const speed = resolveSpeed3(optionsRef.current.rotateSpeed, DEFAULT_ROTATE_SPEED3);
5737
+ drag.move(next, previous, speed, optionsRef.current.invert);
5577
5738
  };
5578
5739
  const releasePointer = (event) => {
5579
5740
  if (!pointersRef.current.has(event.pointerId)) {
5580
5741
  return;
5581
5742
  }
5743
+ if (event.type === "pointerup") drag.flush();
5582
5744
  pointersRef.current.delete(event.pointerId);
5745
+ drag.clear();
5583
5746
  if (element.hasPointerCapture?.(event.pointerId)) {
5584
5747
  element.releasePointerCapture?.(event.pointerId);
5585
5748
  }
@@ -5587,6 +5750,8 @@ function TouchControls({
5587
5750
  pinchDistanceRef.current = null;
5588
5751
  }
5589
5752
  syncActive(event.type !== "pointerup");
5753
+ const remaining = pointersRef.current.values().next().value;
5754
+ if (remaining) drag.start(remaining);
5590
5755
  };
5591
5756
  element.addEventListener("pointerdown", onPointerDown);
5592
5757
  element.addEventListener("pointermove", onPointerMove);
@@ -5594,6 +5759,7 @@ function TouchControls({
5594
5759
  element.addEventListener("pointercancel", releasePointer);
5595
5760
  element.addEventListener("lostpointercapture", releasePointer);
5596
5761
  return () => {
5762
+ validateDragRef.current = void 0;
5597
5763
  element.removeEventListener("pointerdown", onPointerDown);
5598
5764
  element.removeEventListener("pointermove", onPointerMove);
5599
5765
  element.removeEventListener("pointerup", releasePointer);
@@ -5601,7 +5767,7 @@ function TouchControls({
5601
5767
  element.removeEventListener("lostpointercapture", releasePointer);
5602
5768
  clearPointers();
5603
5769
  };
5604
- }, [controlsRef, enabled, gl]);
5770
+ }, [controlsRef, enabled, gl, camera]);
5605
5771
  return null;
5606
5772
  }
5607
5773
 
@@ -7233,8 +7399,8 @@ function WebVRChromeBridge({ host }) {
7233
7399
  }
7234
7400
 
7235
7401
  // src/webvr/stereo-view.ts
7236
- import { StereoCamera, Vector3 as Vector33 } from "three";
7237
- var PROJECT = new Vector33();
7402
+ import { StereoCamera, Vector3 as Vector34 } from "three";
7403
+ var PROJECT = new Vector34();
7238
7404
  function createWebVRStereoView() {
7239
7405
  return {
7240
7406
  active: false,
@@ -7259,17 +7425,17 @@ function projectStereoHtmlPosition(el, camera, size, eye) {
7259
7425
  }
7260
7426
 
7261
7427
  // src/webvr/xr-origin.tsx
7262
- import { useFrame as useFrame5, useThree as useThree8 } from "@react-three/fiber";
7428
+ import { useFrame as useFrame7, useThree as useThree8 } from "@react-three/fiber";
7263
7429
  import { useXR as useXR2, XROrigin } from "@react-three/xr";
7264
7430
  import { useRef as useRef12 } from "react";
7265
- import { Vector3 as Vector34 } from "three";
7431
+ import { Vector3 as Vector35 } from "three";
7266
7432
  import { jsx as jsx11 } from "react/jsx-runtime";
7267
7433
  function PanoramaXROrigin() {
7268
7434
  const originRef = useRef12(null);
7269
- const localHeadPositionRef = useRef12(new Vector34());
7435
+ const localHeadPositionRef = useRef12(new Vector35());
7270
7436
  const session2 = useXR2((state) => state.session);
7271
7437
  const gl = useThree8((state) => state.gl);
7272
- useFrame5(() => {
7438
+ useFrame7(() => {
7273
7439
  const origin = originRef.current;
7274
7440
  if (!session2 || !origin || !gl.xr.isPresenting) {
7275
7441
  return;
@@ -8018,7 +8184,7 @@ import {
8018
8184
  } from "react";
8019
8185
 
8020
8186
  // src/scenes.tsx
8021
- import { useFrame as useFrame11, useThree as useThree16 } from "@react-three/fiber";
8187
+ import { useFrame as useFrame13, useThree as useThree16 } from "@react-three/fiber";
8022
8188
  import {
8023
8189
  Fragment as Fragment4,
8024
8190
  useCallback as useCallback8,
@@ -8102,9 +8268,9 @@ function isSnapshotTransition(preset) {
8102
8268
  }
8103
8269
 
8104
8270
  // src/scene-transitions/snapshot-hold.tsx
8105
- import { useFrame as useFrame6, useThree as useThree9 } from "@react-three/fiber";
8271
+ import { useFrame as useFrame8, useThree as useThree9 } from "@react-three/fiber";
8106
8272
  import { useEffect as useEffect14, useMemo as useMemo9, useRef as useRef14 } from "react";
8107
- import { Vector3 as Vector36 } from "three";
8273
+ import { Vector3 as Vector37 } from "three";
8108
8274
 
8109
8275
  // src/scene-transitions/overlay-utils.ts
8110
8276
  import { PlaneGeometry } from "three";
@@ -8440,13 +8606,13 @@ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
8440
8606
  function SnapshotHold({ snapshot }) {
8441
8607
  const { camera, gl } = useThree9();
8442
8608
  const meshRef = useRef14(null);
8443
- const directionRef = useRef14(new Vector36());
8609
+ const directionRef = useRef14(new Vector37());
8444
8610
  const material = useMemo9(
8445
8611
  () => createSnapshotMaterial("crossfade", snapshot.texture),
8446
8612
  [snapshot.texture]
8447
8613
  );
8448
8614
  useEffect14(() => () => material.dispose(), [material]);
8449
- useFrame6(() => {
8615
+ useFrame8(() => {
8450
8616
  const mesh = meshRef.current;
8451
8617
  if (!mesh || !isPerspectiveCamera(camera)) {
8452
8618
  return;
@@ -8522,7 +8688,7 @@ function phaseAfterSnapshot(preset, hold) {
8522
8688
  }
8523
8689
 
8524
8690
  // src/scene-transitions/particle-overlay.tsx
8525
- import { useFrame as useFrame7, useThree as useThree10 } from "@react-three/fiber";
8691
+ import { useFrame as useFrame9, useThree as useThree10 } from "@react-three/fiber";
8526
8692
  import { useEffect as useEffect15, useMemo as useMemo10, useRef as useRef15 } from "react";
8527
8693
  import {
8528
8694
  DoubleSide as DoubleSide2,
@@ -8531,7 +8697,7 @@ import {
8531
8697
  PlaneGeometry as PlaneGeometry2,
8532
8698
  ShaderMaterial as ShaderMaterial2,
8533
8699
  Vector2 as Vector23,
8534
- Vector3 as Vector37
8700
+ Vector3 as Vector38
8535
8701
  } from "three";
8536
8702
  import { jsx as jsx14 } from "react/jsx-runtime";
8537
8703
  var PARTICLE_GRID = 48;
@@ -8613,7 +8779,7 @@ function ParticleOverlay({
8613
8779
  const meshRef = useRef15(null);
8614
8780
  const startRef = useRef15(null);
8615
8781
  const finishedRef = useRef15(false);
8616
- const directionRef = useRef15(new Vector37());
8782
+ const directionRef = useRef15(new Vector38());
8617
8783
  const geometry = useMemo10(() => createParticleGeometry(), []);
8618
8784
  const material = useMemo10(
8619
8785
  () => new ShaderMaterial2({
@@ -8638,7 +8804,7 @@ function ParticleOverlay({
8638
8804
  finishedRef.current = false;
8639
8805
  material.uniforms.progress.value = 0;
8640
8806
  }, [material, runId]);
8641
- useFrame7((state) => {
8807
+ useFrame9((state) => {
8642
8808
  const mesh = meshRef.current;
8643
8809
  if (!mesh || !isPerspectiveCamera(camera)) {
8644
8810
  return;
@@ -8668,9 +8834,9 @@ function ParticleOverlay({
8668
8834
  }
8669
8835
 
8670
8836
  // src/scene-transitions/snapshot-overlay.tsx
8671
- import { useFrame as useFrame8, useThree as useThree11 } from "@react-three/fiber";
8837
+ import { useFrame as useFrame10, useThree as useThree11 } from "@react-three/fiber";
8672
8838
  import { useEffect as useEffect16, useMemo as useMemo11, useRef as useRef16 } from "react";
8673
- import { Vector3 as Vector38 } from "three";
8839
+ import { Vector3 as Vector39 } from "three";
8674
8840
  import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
8675
8841
  function SnapshotOverlay({
8676
8842
  snapshot,
@@ -8683,7 +8849,7 @@ function SnapshotOverlay({
8683
8849
  const meshRef = useRef16(null);
8684
8850
  const startRef = useRef16(null);
8685
8851
  const finishedRef = useRef16(false);
8686
- const directionRef = useRef16(new Vector38());
8852
+ const directionRef = useRef16(new Vector39());
8687
8853
  const material = useMemo11(() => {
8688
8854
  if (!isSnapshotTransition(transition.preset)) {
8689
8855
  return null;
@@ -8698,7 +8864,7 @@ function SnapshotOverlay({
8698
8864
  material.uniforms.progress.value = 0;
8699
8865
  }
8700
8866
  }, [material, runId]);
8701
- useFrame8((state) => {
8867
+ useFrame10((state) => {
8702
8868
  const mesh = meshRef.current;
8703
8869
  if (!mesh || !material || !isPerspectiveCamera(camera)) {
8704
8870
  return;
@@ -8778,7 +8944,7 @@ import {
8778
8944
  BackSide as BackSide2,
8779
8945
  LinearFilter,
8780
8946
  LinearMipmapLinearFilter,
8781
- MathUtils as MathUtils3,
8947
+ MathUtils as MathUtils4,
8782
8948
  RepeatWrapping,
8783
8949
  SRGBColorSpace,
8784
8950
  TextureLoader
@@ -9144,7 +9310,7 @@ function Sphere({
9144
9310
  return /* @__PURE__ */ jsxs9(
9145
9311
  "mesh",
9146
9312
  {
9147
- rotation: [0, MathUtils3.degToRad(90 + yawOffset2), 0],
9313
+ rotation: [0, MathUtils4.degToRad(90 + yawOffset2), 0],
9148
9314
  visible,
9149
9315
  children: [
9150
9316
  /* @__PURE__ */ jsx18("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
@@ -9162,9 +9328,9 @@ function Sphere({
9162
9328
  }
9163
9329
 
9164
9330
  // src/sphere-tile/sphere-tile.tsx
9165
- import { useFrame as useFrame9, useThree as useThree14 } from "@react-three/fiber";
9331
+ import { useFrame as useFrame11, useThree as useThree14 } from "@react-three/fiber";
9166
9332
  import { memo, useCallback as useCallback7, useEffect as useEffect20, useMemo as useMemo15, useRef as useRef20, useState as useState9 } from "react";
9167
- import { BackSide as BackSide3, Frustum, Matrix4 as Matrix42, PerspectiveCamera as PerspectiveCamera3 } from "three";
9333
+ import { BackSide as BackSide3, Frustum, Matrix4 as Matrix42, PerspectiveCamera as PerspectiveCamera4 } from "three";
9168
9334
 
9169
9335
  // src/tile/texture-manager.ts
9170
9336
  import {
@@ -9516,8 +9682,8 @@ import {
9516
9682
  Box3,
9517
9683
  BufferGeometry,
9518
9684
  Float32BufferAttribute,
9519
- MathUtils as MathUtils4,
9520
- Vector3 as Vector39
9685
+ MathUtils as MathUtils5,
9686
+ Vector3 as Vector310
9521
9687
  } from "three";
9522
9688
  function positiveInteger2(value, name) {
9523
9689
  if (!Number.isSafeInteger(value) || value <= 0) {
@@ -9589,9 +9755,9 @@ function sphereTileRange(address) {
9589
9755
  };
9590
9756
  }
9591
9757
  function spherePoint(u, v, yawOffset2 = 0, radius = DEFAULT_PANORAMA_RADIUS) {
9592
- const yaw = (u - 0.5) * Math.PI * 2 + MathUtils4.degToRad(yawOffset2);
9758
+ const yaw = (u - 0.5) * Math.PI * 2 + MathUtils5.degToRad(yawOffset2);
9593
9759
  const pitch = (0.5 - v) * Math.PI;
9594
- return new Vector39(
9760
+ return new Vector310(
9595
9761
  Math.sin(yaw) * Math.cos(pitch) * radius,
9596
9762
  Math.sin(pitch) * radius,
9597
9763
  -Math.cos(yaw) * Math.cos(pitch) * radius
@@ -9821,7 +9987,7 @@ function SphereTileSource({
9821
9987
  const targetKeysRef = useRef20([]);
9822
9988
  const scratch = useMemo15(
9823
9989
  () => ({
9824
- camera: new PerspectiveCamera3(),
9990
+ camera: new PerspectiveCamera4(),
9825
9991
  frustum: new Frustum(),
9826
9992
  matrix: new Matrix42(),
9827
9993
  quaternion: camera.quaternion.clone(),
@@ -9837,8 +10003,8 @@ function SphereTileSource({
9837
10003
  }),
9838
10004
  [camera, candidates]
9839
10005
  );
9840
- useFrame9(() => {
9841
- if (!(camera instanceof PerspectiveCamera3)) return;
10006
+ useFrame11(() => {
10007
+ if (!(camera instanceof PerspectiveCamera4)) return;
9842
10008
  const now = performance.now(), dpr = gl.getPixelRatio();
9843
10009
  const managerChanged = scratch.manager !== manager;
9844
10010
  const loadModeChanged = scratch.loadMode !== loadMode;
@@ -9940,22 +10106,22 @@ function SphereTile({ multires, ...props }) {
9940
10106
  }
9941
10107
 
9942
10108
  // src/tile/tile.tsx
9943
- import { useFrame as useFrame10, useThree as useThree15 } from "@react-three/fiber";
10109
+ import { useFrame as useFrame12, useThree as useThree15 } from "@react-three/fiber";
9944
10110
  import { memo as memo2, useEffect as useEffect21, useMemo as useMemo16, useRef as useRef21, useState as useState10 } from "react";
9945
10111
  import {
9946
10112
  Frustum as Frustum2,
9947
10113
  Matrix4 as Matrix43,
9948
10114
  PlaneGeometry as PlaneGeometry3,
9949
- PerspectiveCamera as PerspectiveCamera4,
9950
- Vector3 as Vector311
10115
+ PerspectiveCamera as PerspectiveCamera5,
10116
+ Vector3 as Vector312
9951
10117
  } from "three";
9952
10118
 
9953
10119
  // src/tile/face-layout.ts
9954
10120
  import {
9955
10121
  Box3 as Box32,
9956
- Euler as Euler2,
10122
+ Euler as Euler3,
9957
10123
  Quaternion,
9958
- Vector3 as Vector310
10124
+ Vector3 as Vector311
9959
10125
  } from "three";
9960
10126
  var CUBE_FACES = ["f", "r", "b", "l", "u", "d"];
9961
10127
  var PREVIEW_FACE_ORDER = ["l", "f", "r", "b", "u", "d"];
@@ -10008,7 +10174,7 @@ function getFaceQuaternion(face) {
10008
10174
  }
10009
10175
  const transform = getFaceTransform(face);
10010
10176
  const quaternion = new Quaternion().setFromEuler(
10011
- new Euler2(...transform.rotation, "XYZ")
10177
+ new Euler3(...transform.rotation, "XYZ")
10012
10178
  );
10013
10179
  faceQuaternionCache.set(face, quaternion);
10014
10180
  return quaternion;
@@ -10019,12 +10185,12 @@ function getTileBoundingBox(address, radius = CUBE_RADIUS) {
10019
10185
  const halfWidth = local.width / 2;
10020
10186
  const halfHeight = local.height / 2;
10021
10187
  const quaternion = getFaceQuaternion(address.face);
10022
- const position = new Vector310(...transform.position);
10188
+ const position = new Vector311(...transform.position);
10023
10189
  const corners = [
10024
- new Vector310(local.x - halfWidth, local.y - halfHeight, 0),
10025
- new Vector310(local.x + halfWidth, local.y - halfHeight, 0),
10026
- new Vector310(local.x - halfWidth, local.y + halfHeight, 0),
10027
- new Vector310(local.x + halfWidth, local.y + halfHeight, 0)
10190
+ new Vector311(local.x - halfWidth, local.y - halfHeight, 0),
10191
+ new Vector311(local.x + halfWidth, local.y - halfHeight, 0),
10192
+ new Vector311(local.x - halfWidth, local.y + halfHeight, 0),
10193
+ new Vector311(local.x + halfWidth, local.y + halfHeight, 0)
10028
10194
  ];
10029
10195
  for (const corner of corners) {
10030
10196
  corner.applyQuaternion(quaternion).add(position);
@@ -10298,8 +10464,8 @@ function parentAddresses(child, parentLevel, parentFaceSize, tileSize) {
10298
10464
  return addresses;
10299
10465
  }
10300
10466
  function centerFacingAddress(candidates, camera) {
10301
- const direction = camera.getWorldDirection(new Vector311());
10302
- const center = new Vector311();
10467
+ const direction = camera.getWorldDirection(new Vector312());
10468
+ const center = new Vector312();
10303
10469
  let bestCandidate = candidates[0];
10304
10470
  let bestAlignment = -Infinity;
10305
10471
  for (const candidate of candidates) {
@@ -10446,7 +10612,7 @@ function Tile({
10446
10612
  const lastViewportRef = useRef21({ width: 0, height: 0, dpr: 0 });
10447
10613
  const frustumRef = useRef21(new Frustum2());
10448
10614
  const projectionMatrixRef = useRef21(new Matrix43());
10449
- const visibilityCameraRef = useRef21(new PerspectiveCamera4());
10615
+ const visibilityCameraRef = useRef21(new PerspectiveCamera5());
10450
10616
  const trackedLoadModeRef = useRef21(loadMode);
10451
10617
  const targetKeysRef = useRef21([]);
10452
10618
  const detailTokenRef = useRef21("");
@@ -10473,8 +10639,8 @@ function Tile({
10473
10639
  setLayers(nextLayers);
10474
10640
  }
10475
10641
  };
10476
- useFrame10(() => {
10477
- if (!(camera instanceof PerspectiveCamera4)) {
10642
+ useFrame12(() => {
10643
+ if (!(camera instanceof PerspectiveCamera5)) {
10478
10644
  return;
10479
10645
  }
10480
10646
  if (loadMode === "preview") {
@@ -10644,7 +10810,7 @@ function SnapshotCapture({
10644
10810
  },
10645
10811
  []
10646
10812
  );
10647
- useFrame11(() => {
10813
+ useFrame13(() => {
10648
10814
  if (requestId === 0 || requestId === capturedRequestRef.current) {
10649
10815
  return;
10650
10816
  }
@@ -11220,7 +11386,7 @@ import {
11220
11386
  } from "three";
11221
11387
 
11222
11388
  // src/hotspot/hotspot-anchor.tsx
11223
- import { useFrame as useFrame14, useThree as useThree19 } from "@react-three/fiber";
11389
+ import { useFrame as useFrame16, useThree as useThree19 } from "@react-three/fiber";
11224
11390
  import {
11225
11391
  useContext as useContext21,
11226
11392
  useEffect as useEffect24,
@@ -11232,20 +11398,20 @@ import {
11232
11398
  import {
11233
11399
  Box3 as Box34,
11234
11400
  EdgesGeometry,
11235
- MathUtils as MathUtils7,
11401
+ MathUtils as MathUtils8,
11236
11402
  Matrix4 as Matrix44,
11237
11403
  Plane,
11238
11404
  PlaneGeometry as PlaneGeometry4,
11239
11405
  Quaternion as Quaternion3,
11240
11406
  Ray,
11241
- Vector3 as Vector315
11407
+ Vector3 as Vector316
11242
11408
  } from "three";
11243
11409
 
11244
11410
  // src/hotspot/hotspot-tooltip.tsx
11245
11411
  import { useEffect as useEffect23, useMemo as useMemo18, useState as useState12 } from "react";
11246
11412
 
11247
11413
  // src/webvr/stereo-html.tsx
11248
- import { useFrame as useFrame12, useThree as useThree17 } from "@react-three/fiber";
11414
+ import { useFrame as useFrame14, useThree as useThree17 } from "@react-three/fiber";
11249
11415
  import {
11250
11416
  useContext as useContext20,
11251
11417
  useLayoutEffect as useLayoutEffect5,
@@ -11253,7 +11419,7 @@ import {
11253
11419
  useSyncExternalStore as useSyncExternalStore7
11254
11420
  } from "react";
11255
11421
  import { createRoot } from "react-dom/client";
11256
- import { Vector3 as Vector312 } from "three";
11422
+ import { Vector3 as Vector313 } from "three";
11257
11423
  import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
11258
11424
  function useFallbackStereoView() {
11259
11425
  const runtime = useContext20(WebVRRuntimeContext);
@@ -11276,7 +11442,7 @@ function ProjectedHtml({
11276
11442
  const { camera, gl, events, size } = useThree17();
11277
11443
  const group = useRef23(null);
11278
11444
  const overlay = useRef23(null);
11279
- const scratch = useRef23(new Vector312());
11445
+ const scratch = useRef23(new Vector313());
11280
11446
  const target = events.connected || gl.domElement.parentElement;
11281
11447
  const updatePosition = () => {
11282
11448
  const anchor = group.current;
@@ -11335,7 +11501,7 @@ function ProjectedHtml({
11335
11501
  );
11336
11502
  updatePosition();
11337
11503
  });
11338
- useFrame12(updatePosition);
11504
+ useFrame14(updatePosition);
11339
11505
  return /* @__PURE__ */ jsx23("group", { ref: group });
11340
11506
  }
11341
11507
  function PanoHtml(props) {
@@ -11477,21 +11643,21 @@ function HotspotTooltip({
11477
11643
 
11478
11644
  // src/hotspot/transform.ts
11479
11645
  import {
11480
- MathUtils as MathUtils5,
11481
- PerspectiveCamera as PerspectiveCamera5,
11482
- Vector3 as Vector313
11646
+ MathUtils as MathUtils6,
11647
+ PerspectiveCamera as PerspectiveCamera6,
11648
+ Vector3 as Vector314
11483
11649
  } from "three";
11484
- var LOCAL_FORWARD = new Vector313(0, 0, 1);
11485
- var CAMERA_POSITION = new Vector313();
11650
+ var LOCAL_FORWARD = new Vector314(0, 0, 1);
11651
+ var CAMERA_POSITION = new Vector314();
11486
11652
  function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight, distance) {
11487
11653
  if (orientation2 === "billboard") {
11488
11654
  group.quaternion.copy(camera.quaternion);
11489
11655
  } else {
11490
11656
  group.quaternion.copy(surfaceQuaternion3);
11491
11657
  }
11492
- group.rotateOnAxis(LOCAL_FORWARD, MathUtils5.degToRad(-rotation));
11493
- let scaleFactor = scaleMode === "fixed" && camera instanceof PerspectiveCamera5 ? fixedScaleFactor(camera.fov, referenceFov) : 1;
11494
- if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof PerspectiveCamera5) {
11658
+ group.rotateOnAxis(LOCAL_FORWARD, MathUtils6.degToRad(-rotation));
11659
+ let scaleFactor = scaleMode === "fixed" && camera instanceof PerspectiveCamera6 ? fixedScaleFactor(camera.fov, referenceFov) : 1;
11660
+ if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof PerspectiveCamera6) {
11495
11661
  group.updateWorldMatrix(true, false);
11496
11662
  CAMERA_POSITION.setFromMatrixPosition(group.matrixWorld).applyMatrix4(
11497
11663
  camera.matrixWorldInverse
@@ -11506,21 +11672,21 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
11506
11672
  group.updateMatrixWorld();
11507
11673
  }
11508
11674
  function fixedScaleFactor(cameraFov, referenceFov) {
11509
- const safeReferenceFov = MathUtils5.clamp(referenceFov, 1, 179);
11510
- return Math.tan(MathUtils5.degToRad(cameraFov) / 2) / Math.tan(MathUtils5.degToRad(safeReferenceFov) / 2);
11675
+ const safeReferenceFov = MathUtils6.clamp(referenceFov, 1, 179);
11676
+ return Math.tan(MathUtils6.degToRad(cameraFov) / 2) / Math.tan(MathUtils6.degToRad(safeReferenceFov) / 2);
11511
11677
  }
11512
11678
 
11513
11679
  // src/hotspot/hotspot-stroke-line.tsx
11514
11680
  import { Line } from "@react-three/drei";
11515
- import { useFrame as useFrame13, useThree as useThree18 } from "@react-three/fiber";
11681
+ import { useFrame as useFrame15, useThree as useThree18 } from "@react-three/fiber";
11516
11682
  import { useLayoutEffect as useLayoutEffect6, useRef as useRef24 } from "react";
11517
11683
  import {
11518
- MathUtils as MathUtils6,
11519
- PerspectiveCamera as PerspectiveCamera6,
11520
- Vector3 as Vector314
11684
+ MathUtils as MathUtils7,
11685
+ PerspectiveCamera as PerspectiveCamera7,
11686
+ Vector3 as Vector315
11521
11687
  } from "three";
11522
11688
  import { jsx as jsx25 } from "react/jsx-runtime";
11523
- var LINE_WORLD_POSITION = new Vector314();
11689
+ var LINE_WORLD_POSITION = new Vector315();
11524
11690
  function applyScreenSpaceDashScale(object, camera, viewportHeight) {
11525
11691
  const material = object?.material;
11526
11692
  if (!object || typeof material?.dashScale !== "number") {
@@ -11528,8 +11694,8 @@ function applyScreenSpaceDashScale(object, camera, viewportHeight) {
11528
11694
  }
11529
11695
  object.getWorldPosition(LINE_WORLD_POSITION);
11530
11696
  const depth = Math.max(camera.position.distanceTo(LINE_WORLD_POSITION), 1);
11531
- const fov = camera instanceof PerspectiveCamera6 ? camera.fov : 75;
11532
- material.dashScale = viewportHeight / (2 * Math.tan(MathUtils6.degToRad(fov) * 0.5) * depth);
11697
+ const fov = camera instanceof PerspectiveCamera7 ? camera.fov : 75;
11698
+ material.dashScale = viewportHeight / (2 * Math.tan(MathUtils7.degToRad(fov) * 0.5) * depth);
11533
11699
  }
11534
11700
  function resolveDash(dashSize, gapSize) {
11535
11701
  if (dashSize === void 0 || !Number.isFinite(dashSize) || dashSize <= 0) {
@@ -11559,7 +11725,7 @@ function HotspotStrokeLine({
11559
11725
  }
11560
11726
  applyScreenSpaceDashScale(lineRef.current, camera, size.height);
11561
11727
  }, [camera, dash.dashed, dash.dashSize, dash.gapSize, size.height]);
11562
- useFrame13((state) => {
11728
+ useFrame15((state) => {
11563
11729
  if (!dash.dashed) {
11564
11730
  return;
11565
11731
  }
@@ -11604,25 +11770,25 @@ var SELECTION_BORDER_POINTS = [
11604
11770
  ];
11605
11771
  var TOOLTIP_WORLD_BOX = new Box34();
11606
11772
  var TOOLTIP_LOCAL_BOX = new Box34();
11607
- var TOOLTIP_CORNER = new Vector315();
11773
+ var TOOLTIP_CORNER = new Vector316();
11608
11774
  var TOOLTIP_INVERSE = new Matrix44();
11609
- var TOOLTIP_WORLD_CORNER = new Vector315();
11610
- var TOOLTIP_PROJECTED = new Vector315();
11611
- var TOOLTIP_RAY_ORIGIN = new Vector315();
11612
- var TOOLTIP_RAY_FAR = new Vector315();
11613
- var TOOLTIP_RAY_DIRECTION = new Vector315();
11775
+ var TOOLTIP_WORLD_CORNER = new Vector316();
11776
+ var TOOLTIP_PROJECTED = new Vector316();
11777
+ var TOOLTIP_RAY_ORIGIN = new Vector316();
11778
+ var TOOLTIP_RAY_FAR = new Vector316();
11779
+ var TOOLTIP_RAY_DIRECTION = new Vector316();
11614
11780
  var TOOLTIP_RAY = new Ray();
11615
11781
  var TOOLTIP_PLANE = new Plane();
11616
- var TOOLTIP_INTERSECTION = new Vector315();
11617
- var TOOLTIP_PLANE_NORMAL = new Vector315();
11618
- var TOOLTIP_PLANE_POINT = new Vector315();
11782
+ var TOOLTIP_INTERSECTION = new Vector316();
11783
+ var TOOLTIP_PLANE_NORMAL = new Vector316();
11784
+ var TOOLTIP_PLANE_POINT = new Vector316();
11619
11785
  var HOTSPOT_MODE_RENDERING = {
11620
11786
  surface: { orientation: "surface", placement: "surface" },
11621
11787
  billboard: { orientation: "billboard", placement: "floating" }
11622
11788
  };
11623
11789
  function angularSizeToWorldSize(size, radius) {
11624
- const safeSize = Number.isFinite(size) ? MathUtils7.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
11625
- return 2 * radius * Math.tan(MathUtils7.degToRad(safeSize) / 2);
11790
+ const safeSize = Number.isFinite(size) ? MathUtils8.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
11791
+ return 2 * radius * Math.tan(MathUtils8.degToRad(safeSize) / 2);
11626
11792
  }
11627
11793
  function resolveScale(scale) {
11628
11794
  return Number.isFinite(scale) && scale > 0 ? scale : 1;
@@ -11635,32 +11801,32 @@ function resolveDistance(placement, distance, width, height) {
11635
11801
  if (!Number.isFinite(distance)) {
11636
11802
  return DEFAULT_FLOATING_DISTANCE;
11637
11803
  }
11638
- return MathUtils7.clamp(Math.abs(distance), 0.1, maximumDistance);
11804
+ return MathUtils8.clamp(Math.abs(distance), 0.1, maximumDistance);
11639
11805
  }
11640
11806
  function maximumHotspotDistance(width, height) {
11641
- const safeWidth = MathUtils7.clamp(
11807
+ const safeWidth = MathUtils8.clamp(
11642
11808
  Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
11643
11809
  MIN_ANGULAR_SIZE,
11644
11810
  MAX_ANGULAR_SIZE
11645
11811
  );
11646
- const safeHeight = MathUtils7.clamp(
11812
+ const safeHeight = MathUtils8.clamp(
11647
11813
  Math.abs(Number.isFinite(height) ? height : MIN_ANGULAR_SIZE),
11648
11814
  MIN_ANGULAR_SIZE,
11649
11815
  MAX_ANGULAR_SIZE
11650
11816
  );
11651
11817
  const cornerFactor = Math.hypot(
11652
11818
  1,
11653
- Math.tan(MathUtils7.degToRad(safeWidth) / 2),
11654
- Math.tan(MathUtils7.degToRad(safeHeight) / 2)
11819
+ Math.tan(MathUtils8.degToRad(safeWidth) / 2),
11820
+ Math.tan(MathUtils8.degToRad(safeHeight) / 2)
11655
11821
  );
11656
11822
  return (PANORAMA_RADIUS - PANORAMA_SURFACE_INSET) / cornerFactor;
11657
11823
  }
11658
11824
  function createSurfaceQuaternion(position) {
11659
11825
  const outward = panoPositionToVector3(position).normalize();
11660
11826
  const inward = outward.clone().negate();
11661
- const pitch = MathUtils7.degToRad(position.pitch);
11662
- const yaw = MathUtils7.degToRad(position.yaw);
11663
- const localUp = new Vector315(
11827
+ const pitch = MathUtils8.degToRad(position.pitch);
11828
+ const yaw = MathUtils8.degToRad(position.yaw);
11829
+ const localUp = new Vector316(
11664
11830
  -Math.sin(pitch) * Math.sin(yaw),
11665
11831
  Math.cos(pitch),
11666
11832
  Math.sin(pitch) * Math.cos(yaw)
@@ -11680,7 +11846,7 @@ function makeInteractionEvent(id, position, event) {
11680
11846
  function angularDistance(a, b) {
11681
11847
  const aVector = panoPositionToVector3(a);
11682
11848
  const bVector = panoPositionToVector3(b);
11683
- return MathUtils7.radToDeg(aVector.angleTo(bVector));
11849
+ return MathUtils8.radToDeg(aVector.angleTo(bVector));
11684
11850
  }
11685
11851
  function isTooltipOpen(trigger, hovered, focused, pinned) {
11686
11852
  switch (trigger) {
@@ -12093,7 +12259,7 @@ function HotspotAnchor({
12093
12259
  worldHeight,
12094
12260
  worldWidth
12095
12261
  ]);
12096
- useFrame14((state) => {
12262
+ useFrame16((state) => {
12097
12263
  const group = groupRef.current;
12098
12264
  if (!group) {
12099
12265
  return;
@@ -12708,7 +12874,7 @@ function GraphicHotspot(props) {
12708
12874
  }
12709
12875
 
12710
12876
  // src/hotspot/sequence-hotspot.tsx
12711
- import { useFrame as useFrame15, useThree as useThree21 } from "@react-three/fiber";
12877
+ import { useFrame as useFrame17, useThree as useThree21 } from "@react-three/fiber";
12712
12878
  import { useEffect as useEffect27, useRef as useRef28, useState as useState16 } from "react";
12713
12879
  import {
12714
12880
  ClampToEdgeWrapping as ClampToEdgeWrapping5,
@@ -12863,7 +13029,7 @@ function SequenceHotspot({
12863
13029
  onPlaybackStateChangeRef.current?.(nextState);
12864
13030
  }
12865
13031
  }, [playing, texture]);
12866
- useFrame15((_, deltaSeconds) => {
13032
+ useFrame17((_, deltaSeconds) => {
12867
13033
  if (!texture || !playing || endedRef.current) {
12868
13034
  return;
12869
13035
  }
@@ -13188,7 +13354,7 @@ function VideoHotspot({
13188
13354
  }
13189
13355
 
13190
13356
  // src/hotspot/audio-hotspot.tsx
13191
- import { useFrame as useFrame16, useThree as useThree23 } from "@react-three/fiber";
13357
+ import { useFrame as useFrame18, useThree as useThree23 } from "@react-three/fiber";
13192
13358
  import { useEffect as useEffect29, useRef as useRef30, useState as useState18 } from "react";
13193
13359
  import {
13194
13360
  CanvasTexture as CanvasTexture2,
@@ -13200,10 +13366,10 @@ import {
13200
13366
  } from "three";
13201
13367
 
13202
13368
  // src/hotspot/audio-spatial.ts
13203
- import { MathUtils as MathUtils8, Vector3 as Vector316 } from "three";
13204
- var LOOK_DIR = new Vector316();
13205
- var SOURCE_DIR = new Vector316();
13206
- var RIGHT_DIR = new Vector316();
13369
+ import { MathUtils as MathUtils9, Vector3 as Vector317 } from "three";
13370
+ var LOOK_DIR = new Vector317();
13371
+ var SOURCE_DIR = new Vector317();
13372
+ var RIGHT_DIR = new Vector317();
13207
13373
  function clampAudioVolume(volume) {
13208
13374
  if (!Number.isFinite(volume)) {
13209
13375
  return 1;
@@ -13228,11 +13394,11 @@ function lookRangeGain(angleDegrees, range) {
13228
13394
  function audioSpatialFromView(camera, position, range) {
13229
13395
  camera.getWorldDirection(LOOK_DIR);
13230
13396
  SOURCE_DIR.copy(panoPositionToVector3(position)).normalize();
13231
- const angleDegrees = MathUtils8.radToDeg(
13232
- Math.acos(MathUtils8.clamp(LOOK_DIR.dot(SOURCE_DIR), -1, 1))
13397
+ const angleDegrees = MathUtils9.radToDeg(
13398
+ Math.acos(MathUtils9.clamp(LOOK_DIR.dot(SOURCE_DIR), -1, 1))
13233
13399
  );
13234
13400
  RIGHT_DIR.set(1, 0, 0).applyQuaternion(camera.quaternion);
13235
- const pan = MathUtils8.clamp(
13401
+ const pan = MathUtils9.clamp(
13236
13402
  Math.atan2(SOURCE_DIR.dot(RIGHT_DIR), SOURCE_DIR.dot(LOOK_DIR)) / (Math.PI / 2),
13237
13403
  -1,
13238
13404
  1
@@ -13521,7 +13687,7 @@ function AudioHotspot({
13521
13687
  document.removeEventListener("visibilitychange", handleVisibility);
13522
13688
  };
13523
13689
  }, [howl, pauseWhenHidden]);
13524
- useFrame16(() => {
13690
+ useFrame18(() => {
13525
13691
  if (!howl) {
13526
13692
  return;
13527
13693
  }
@@ -13539,13 +13705,13 @@ function AudioHotspot({
13539
13705
 
13540
13706
  // src/hotspot/text-hotspot.tsx
13541
13707
  import { useEffect as useEffect30, useRef as useRef31, useState as useState19 } from "react";
13542
- import { useFrame as useFrame17, useThree as useThree24 } from "@react-three/fiber";
13708
+ import { useFrame as useFrame19, useThree as useThree24 } from "@react-three/fiber";
13543
13709
  import {
13544
13710
  CanvasTexture as CanvasTexture3,
13545
13711
  ClampToEdgeWrapping as ClampToEdgeWrapping8,
13546
13712
  LinearFilter as LinearFilter10,
13547
- MathUtils as MathUtils9,
13548
- PerspectiveCamera as PerspectiveCamera7,
13713
+ MathUtils as MathUtils10,
13714
+ PerspectiveCamera as PerspectiveCamera8,
13549
13715
  SRGBColorSpace as SRGBColorSpace9
13550
13716
  } from "three";
13551
13717
  import { jsx as jsx33 } from "react/jsx-runtime";
@@ -13619,7 +13785,7 @@ function projectedDevicePixels(angleDeg, fovDeg, viewportHeight) {
13619
13785
  }
13620
13786
  const fov = Math.min(179, Math.max(1, resolvePositive(fovDeg, DEFAULT_REFERENCE_FOV2)));
13621
13787
  const angle = Math.min(179, Math.max(0.01, Math.abs(angleDeg)));
13622
- return Math.tan(MathUtils9.degToRad(angle) / 2) / Math.tan(MathUtils9.degToRad(fov) / 2) * viewportHeight;
13788
+ return Math.tan(MathUtils10.degToRad(angle) / 2) / Math.tan(MathUtils10.degToRad(fov) / 2) * viewportHeight;
13623
13789
  }
13624
13790
  function snapRasterLongSide(screenLong, layoutLong) {
13625
13791
  if (!(screenLong > 0)) {
@@ -13821,7 +13987,7 @@ function useRasterLongSide(width, height, scale, scaleMode, referenceFov) {
13821
13987
  const measure = () => {
13822
13988
  const pixelRatio = getPixelRatio();
13823
13989
  const viewportHeight = size.height * (Number.isFinite(pixelRatio) && pixelRatio > 0 ? pixelRatio : 1);
13824
- const cameraFov = camera instanceof PerspectiveCamera7 ? camera.fov : DEFAULT_REFERENCE_FOV2;
13990
+ const cameraFov = camera instanceof PerspectiveCamera8 ? camera.fov : DEFAULT_REFERENCE_FOV2;
13825
13991
  const screenLong = Math.max(
13826
13992
  projectedDevicePixels(
13827
13993
  width * resolveScale2(scale),
@@ -13845,7 +14011,7 @@ function useRasterLongSide(width, height, scale, scaleMode, referenceFov) {
13845
14011
  if (measured !== rasterLong) {
13846
14012
  setRasterLong(measured);
13847
14013
  }
13848
- useFrame17(() => {
14014
+ useFrame19(() => {
13849
14015
  const next = measure();
13850
14016
  setRasterLong((current) => current === next ? current : next);
13851
14017
  });
@@ -14099,7 +14265,7 @@ import {
14099
14265
  Quaternion as Quaternion4,
14100
14266
  ShapeUtils,
14101
14267
  Vector2 as Vector25,
14102
- Vector3 as Vector317
14268
+ Vector3 as Vector318
14103
14269
  } from "three";
14104
14270
  import { jsx as jsx35, jsxs as jsxs18 } from "react/jsx-runtime";
14105
14271
  var POLYGON_RADIUS = 990;
@@ -14173,7 +14339,7 @@ function polygonContainsDirection(vertices, direction) {
14173
14339
  }
14174
14340
  function fitsHemisphere(vertices) {
14175
14341
  const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
14176
- const candidates = [new Vector317()];
14342
+ const candidates = [new Vector318()];
14177
14343
  for (const direction of directions) {
14178
14344
  candidates[0].add(direction);
14179
14345
  candidates.push(direction.clone());
@@ -14197,7 +14363,7 @@ function validatePolygonVertices(vertices) {
14197
14363
  if (hasSelfIntersection(unwrapped)) {
14198
14364
  issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
14199
14365
  }
14200
- if (polygonContainsDirection(normalized, new Vector317(0, 1, 0)) || polygonContainsDirection(normalized, new Vector317(0, -1, 0))) {
14366
+ if (polygonContainsDirection(normalized, new Vector318(0, 1, 0)) || polygonContainsDirection(normalized, new Vector318(0, -1, 0))) {
14201
14367
  issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
14202
14368
  }
14203
14369
  if (!fitsHemisphere(normalized)) {
@@ -14208,7 +14374,7 @@ function validatePolygonVertices(vertices) {
14208
14374
  function polygonCenter(vertices) {
14209
14375
  const sum = vertices.reduce(
14210
14376
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14211
- new Vector317()
14377
+ new Vector318()
14212
14378
  );
14213
14379
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14214
14380
  }
@@ -14217,7 +14383,7 @@ function surfaceQuaternion(position) {
14217
14383
  const inward = outward.clone().negate();
14218
14384
  const pitch = position.pitch * Math.PI / 180;
14219
14385
  const yaw = position.yaw * Math.PI / 180;
14220
- const localUp = new Vector317(
14386
+ const localUp = new Vector318(
14221
14387
  -Math.sin(pitch) * Math.sin(yaw),
14222
14388
  Math.cos(pitch),
14223
14389
  Math.sin(pitch) * Math.cos(yaw)
@@ -14230,7 +14396,7 @@ function makeWorldToLocal(center) {
14230
14396
  return new Matrix45().compose(
14231
14397
  panoPositionToVector3(center, POLYGON_RADIUS),
14232
14398
  surfaceQuaternion(center),
14233
- new Vector317(1, 1, 1)
14399
+ new Vector318(1, 1, 1)
14234
14400
  ).invert();
14235
14401
  }
14236
14402
  function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
@@ -14456,10 +14622,10 @@ function PolygonHotspot({
14456
14622
  // src/hotspot/polyline-hotspot.tsx
14457
14623
  import { useEffect as useEffect32, useMemo as useMemo21, useRef as useRef33 } from "react";
14458
14624
  import {
14459
- MathUtils as MathUtils10,
14625
+ MathUtils as MathUtils11,
14460
14626
  Matrix4 as Matrix46,
14461
14627
  Quaternion as Quaternion5,
14462
- Vector3 as Vector318
14628
+ Vector3 as Vector319
14463
14629
  } from "three";
14464
14630
  import { jsx as jsx36 } from "react/jsx-runtime";
14465
14631
  var POLYLINE_RADIUS = 990;
@@ -14486,16 +14652,16 @@ function unwrapVertices(vertices) {
14486
14652
  function polylineCenter(vertices) {
14487
14653
  const sum = vertices.reduce(
14488
14654
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14489
- new Vector318()
14655
+ new Vector319()
14490
14656
  );
14491
14657
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14492
14658
  }
14493
14659
  function surfaceQuaternion2(position) {
14494
14660
  const outward = panoPositionToVector3(position).normalize();
14495
14661
  const inward = outward.clone().negate();
14496
- const pitch = MathUtils10.degToRad(position.pitch);
14497
- const yaw = MathUtils10.degToRad(position.yaw);
14498
- const localUp = new Vector318(
14662
+ const pitch = MathUtils11.degToRad(position.pitch);
14663
+ const yaw = MathUtils11.degToRad(position.yaw);
14664
+ const localUp = new Vector319(
14499
14665
  -Math.sin(pitch) * Math.sin(yaw),
14500
14666
  Math.cos(pitch),
14501
14667
  Math.sin(pitch) * Math.cos(yaw)
@@ -14508,7 +14674,7 @@ function makeWorldToLocal2(center) {
14508
14674
  return new Matrix46().compose(
14509
14675
  panoPositionToVector3(center, POLYLINE_RADIUS),
14510
14676
  surfaceQuaternion2(center),
14511
- new Vector318(1, 1, 1)
14677
+ new Vector319(1, 1, 1)
14512
14678
  ).invert();
14513
14679
  }
14514
14680
  function subdivisionSteps(vertices) {
@@ -14523,7 +14689,7 @@ function subdivisionSteps(vertices) {
14523
14689
  }
14524
14690
  return Math.min(
14525
14691
  8,
14526
- Math.max(1, Math.ceil(MathUtils10.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
14692
+ Math.max(1, Math.ceil(MathUtils11.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
14527
14693
  );
14528
14694
  }
14529
14695
  function makeLinePositions(vertices, center) {
@@ -15286,7 +15452,7 @@ function PanoFilter({
15286
15452
  }
15287
15453
 
15288
15454
  // src/gyro.tsx
15289
- import { useFrame as useFrame18, useThree as useThree25 } from "@react-three/fiber";
15455
+ import { useFrame as useFrame20, useThree as useThree25 } from "@react-three/fiber";
15290
15456
  import {
15291
15457
  forwardRef as forwardRef3,
15292
15458
  useCallback as useCallback9,
@@ -15298,12 +15464,12 @@ import {
15298
15464
  } from "react";
15299
15465
 
15300
15466
  // src/gyro-orientation.ts
15301
- import { Euler as Euler3, MathUtils as MathUtils11, Quaternion as Quaternion6, Vector3 as Vector319 } from "three";
15467
+ import { Euler as Euler4, MathUtils as MathUtils12, Quaternion as Quaternion6, Vector3 as Vector320 } from "three";
15302
15468
  var DEVICE_FORWARD_CORRECTION = new Quaternion6().setFromAxisAngle(
15303
- new Vector319(1, 0, 0),
15469
+ new Vector320(1, 0, 0),
15304
15470
  -Math.PI / 2
15305
15471
  );
15306
- var SCREEN_AXIS = new Vector319(0, 0, 1);
15472
+ var SCREEN_AXIS = new Vector320(0, 0, 1);
15307
15473
  function getScreenOrientationAngle() {
15308
15474
  if (typeof window === "undefined") {
15309
15475
  return 0;
@@ -15317,31 +15483,31 @@ function getScreenOrientationAngle() {
15317
15483
  }
15318
15484
  function deviceOrientationToQuaternion(sample, screenOrientation) {
15319
15485
  const alpha = Number.isFinite(sample.compassHeading) ? 360 - sample.compassHeading : sample.alpha;
15320
- const deviceEuler = new Euler3(
15321
- MathUtils11.degToRad(sample.beta),
15322
- MathUtils11.degToRad(alpha),
15323
- MathUtils11.degToRad(-sample.gamma),
15486
+ const deviceEuler = new Euler4(
15487
+ MathUtils12.degToRad(sample.beta),
15488
+ MathUtils12.degToRad(alpha),
15489
+ MathUtils12.degToRad(-sample.gamma),
15324
15490
  "YXZ"
15325
15491
  );
15326
15492
  const screenCorrection = new Quaternion6().setFromAxisAngle(
15327
15493
  SCREEN_AXIS,
15328
- -MathUtils11.degToRad(screenOrientation)
15494
+ -MathUtils12.degToRad(screenOrientation)
15329
15495
  );
15330
15496
  return new Quaternion6().setFromEuler(deviceEuler).multiply(DEVICE_FORWARD_CORRECTION).multiply(screenCorrection).normalize();
15331
15497
  }
15332
15498
  function quaternionToGyroPose(quaternion) {
15333
- const euler = new Euler3().setFromQuaternion(quaternion, "YXZ");
15499
+ const euler = new Euler4().setFromQuaternion(quaternion, "YXZ");
15334
15500
  return {
15335
- yaw: MathUtils11.radToDeg(-euler.y),
15336
- pitch: MathUtils11.radToDeg(euler.x),
15337
- roll: MathUtils11.radToDeg(euler.z)
15501
+ yaw: MathUtils12.radToDeg(-euler.y),
15502
+ pitch: MathUtils12.radToDeg(euler.x),
15503
+ roll: MathUtils12.radToDeg(euler.z)
15338
15504
  };
15339
15505
  }
15340
15506
  function createRelativeCalibration(deviceQuaternion, yaw, pitch) {
15341
15507
  const targetQuaternion = new Quaternion6().setFromEuler(
15342
- new Euler3(
15343
- MathUtils11.degToRad(pitch),
15344
- MathUtils11.degToRad(-yaw),
15508
+ new Euler4(
15509
+ MathUtils12.degToRad(pitch),
15510
+ MathUtils12.degToRad(-yaw),
15345
15511
  0,
15346
15512
  "YXZ"
15347
15513
  )
@@ -15686,7 +15852,7 @@ var Gyro = forwardRef3(function Gyro2({
15686
15852
  internallyDisabled,
15687
15853
  requestPermission
15688
15854
  ]);
15689
- useFrame18((_, deltaSeconds) => {
15855
+ useFrame20((_, deltaSeconds) => {
15690
15856
  const rawQuaternion = rawQuaternionRef.current;
15691
15857
  if (!activeRef.current || !rawQuaternion) {
15692
15858
  return;
@@ -15779,13 +15945,13 @@ async function detectWebVRCapabilities() {
15779
15945
  }
15780
15946
 
15781
15947
  // src/webvr/reticle.tsx
15782
- import { useFrame as useFrame19, useThree as useThree26 } from "@react-three/fiber";
15948
+ import { useFrame as useFrame21, useThree as useThree26 } from "@react-three/fiber";
15783
15949
  import { useRef as useRef36 } from "react";
15784
15950
  import {
15785
15951
  DoubleSide as DoubleSide6,
15786
15952
  Raycaster as Raycaster3,
15787
15953
  Vector2 as Vector26,
15788
- Vector3 as Vector320
15954
+ Vector3 as Vector321
15789
15955
  } from "three";
15790
15956
  import { jsx as jsx38, jsxs as jsxs19 } from "react/jsx-runtime";
15791
15957
  var CENTER_NDC = new Vector26(0, 0);
@@ -15873,13 +16039,13 @@ function WebVRReticle({
15873
16039
  }) {
15874
16040
  const groupRef = useRef36(null);
15875
16041
  const ringMeshRef = useRef36(null);
15876
- const directionRef = useRef36(new Vector320());
16042
+ const directionRef = useRef36(new Vector321());
15877
16043
  const raycasterRef = useRef36(new Raycaster3());
15878
16044
  const hoveredRef = useRef36(null);
15879
16045
  const dwellRef = useRef36(0);
15880
16046
  const clickedRef = useRef36(false);
15881
16047
  const { camera, gl, scene } = useThree26();
15882
- useFrame19((_, deltaSeconds) => {
16048
+ useFrame21((_, deltaSeconds) => {
15883
16049
  const group = groupRef.current;
15884
16050
  const ringMesh = ringMeshRef.current;
15885
16051
  if (!visible || !group) {
@@ -16039,12 +16205,12 @@ function WebVRReticle({
16039
16205
  }
16040
16206
 
16041
16207
  // src/webvr/stereo.tsx
16042
- import { useFrame as useFrame20, useThree as useThree27 } from "@react-three/fiber";
16208
+ import { useFrame as useFrame22, useThree as useThree27 } from "@react-three/fiber";
16043
16209
  import { useContext as useContext26, useEffect as useEffect36, useMemo as useMemo25, useRef as useRef37 } from "react";
16044
16210
  import {
16045
16211
  Mesh as Mesh6,
16046
16212
  OrthographicCamera,
16047
- PerspectiveCamera as PerspectiveCamera8,
16213
+ PerspectiveCamera as PerspectiveCamera9,
16048
16214
  PlaneGeometry as PlaneGeometry5,
16049
16215
  Scene,
16050
16216
  ShaderMaterial as ShaderMaterial3,
@@ -16155,7 +16321,7 @@ function WebVRStereoRenderer({
16155
16321
  useEffect36(() => {
16156
16322
  const originalRender = gl.render.bind(gl);
16157
16323
  gl.render = (sceneToRender, cameraToRender) => {
16158
- if (!stereoActiveRef.current || !(cameraToRender instanceof PerspectiveCamera8)) {
16324
+ if (!stereoActiveRef.current || !(cameraToRender instanceof PerspectiveCamera9)) {
16159
16325
  originalRender(sceneToRender, cameraToRender);
16160
16326
  return;
16161
16327
  }
@@ -16224,13 +16390,13 @@ function WebVRStereoRenderer({
16224
16390
  },
16225
16391
  [runtime]
16226
16392
  );
16227
- useFrame20(() => {
16393
+ useFrame22(() => {
16228
16394
  const fallback = isFallbackStereoMode(mode);
16229
16395
  stereoActiveRef.current = fallback;
16230
16396
  if (runtime) {
16231
16397
  runtime.stereoView.active = fallback;
16232
16398
  }
16233
- if (fallback && camera instanceof PerspectiveCamera8) {
16399
+ if (fallback && camera instanceof PerspectiveCamera9) {
16234
16400
  syncStereoCameras(
16235
16401
  stereoRef.current,
16236
16402
  camera,
@@ -16241,7 +16407,7 @@ function WebVRStereoRenderer({
16241
16407
  );
16242
16408
  return;
16243
16409
  }
16244
- if (originalFovRef.current !== null && camera instanceof PerspectiveCamera8) {
16410
+ if (originalFovRef.current !== null && camera instanceof PerspectiveCamera9) {
16245
16411
  camera.fov = originalFovRef.current;
16246
16412
  camera.updateProjectionMatrix();
16247
16413
  originalFovRef.current = null;
@@ -16935,7 +17101,7 @@ import {
16935
17101
  BackSide as BackSide4,
16936
17102
  LinearFilter as LinearFilter11,
16937
17103
  LinearMipmapLinearFilter as LinearMipmapLinearFilter7,
16938
- MathUtils as MathUtils12,
17104
+ MathUtils as MathUtils13,
16939
17105
  RepeatWrapping as RepeatWrapping2,
16940
17106
  SRGBColorSpace as SRGBColorSpace10,
16941
17107
  TextureLoader as TextureLoader8,
@@ -17644,7 +17810,7 @@ function PanoVideo({
17644
17810
  activeTexture ? /* @__PURE__ */ jsxs21(
17645
17811
  "mesh",
17646
17812
  {
17647
- rotation: [0, MathUtils12.degToRad(90 + yawOffset2), 0],
17813
+ rotation: [0, MathUtils13.degToRad(90 + yawOffset2), 0],
17648
17814
  visible,
17649
17815
  children: [
17650
17816
  /* @__PURE__ */ jsx40("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),