@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.cjs CHANGED
@@ -2641,6 +2641,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2641
2641
  const { camera, gl } = (0, import_fiber.useThree)();
2642
2642
  const xrSession = (0, import_xr.useXR)((state) => state.session);
2643
2643
  const xrSessionRef = (0, import_react3.useRef)(xrSession);
2644
+ const pointerRevisionRef = (0, import_react3.useRef)(0);
2644
2645
  const viewRef = (0, import_react3.useRef)({ ...initialView });
2645
2646
  const targetViewRef = (0, import_react3.useRef)({ ...initialView });
2646
2647
  const initialViewRef = (0, import_react3.useRef)({ ...initialView });
@@ -2735,6 +2736,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2735
2736
  };
2736
2737
  const acquireInteractionLock = () => {
2737
2738
  cancelNavigation();
2739
+ pointerRevisionRef.current += 1;
2738
2740
  interactionLockCountRef.current += 1;
2739
2741
  stopVelocity();
2740
2742
  if (mouseActiveRef.current) {
@@ -2766,6 +2768,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2766
2768
  legacyFovRef.current.maxFov
2767
2769
  );
2768
2770
  if (JSON.stringify(next) === JSON.stringify(limitsRef.current)) return;
2771
+ pointerRevisionRef.current += 1;
2769
2772
  limitsRef.current = next;
2770
2773
  cancelNavigation();
2771
2774
  stopVelocity();
@@ -2781,6 +2784,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2781
2784
  };
2782
2785
  const setView = (view, setOptions) => {
2783
2786
  cancelNavigation();
2787
+ pointerRevisionRef.current += 1;
2784
2788
  const nextView = hardConstrainView(view);
2785
2789
  if (gyroActiveRef.current) {
2786
2790
  gyroOffsetRef.current = {
@@ -2800,6 +2804,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2800
2804
  if (xrSessionRef.current != null || gyroActiveRef.current || interactionLockCountRef.current > 0) {
2801
2805
  return Promise.resolve({ status: "cancelled" });
2802
2806
  }
2807
+ pointerRevisionRef.current += 1;
2803
2808
  const from = { ...viewRef.current };
2804
2809
  const safeTargetInput = {
2805
2810
  yaw: targetInput.yaw !== void 0 && Number.isFinite(targetInput.yaw) ? targetInput.yaw : from.yaw,
@@ -2864,19 +2869,24 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2864
2869
  return false;
2865
2870
  }
2866
2871
  const current = targetViewRef.current;
2872
+ const origin = !gyroActiveRef.current ? applyOptions?.pointerOrigin : void 0;
2873
+ const reference = origin ?? current;
2867
2874
  const gyroMode = gyroTouchModeRef.current;
2868
2875
  const gyroControlsView = gyroActiveRef.current;
2869
2876
  const appliesTouchMode = gyroControlsView && applyOptions?.source === "touch";
2870
2877
  const acceptsYaw = !appliesTouchMode || gyroMode === "horizontaloffset" || gyroMode === "full";
2871
2878
  const acceptsPitch = !appliesTouchMode || gyroMode === "full";
2872
- const nextYaw = acceptsYaw && delta.yaw !== void 0 && Number.isFinite(delta.yaw) ? applyLimitedYawDelta(current.yaw, delta.yaw, limitsRef.current.yaw) : current.yaw;
2873
- const nextPitch = acceptsPitch && delta.pitch !== void 0 && Number.isFinite(delta.pitch) ? current.pitch + delta.pitch : current.pitch;
2879
+ const nextYaw = acceptsYaw && delta.yaw !== void 0 && Number.isFinite(delta.yaw) ? applyLimitedYawDelta(reference.yaw, delta.yaw, limitsRef.current.yaw) : current.yaw;
2880
+ const nextPitch = acceptsPitch && delta.pitch !== void 0 && Number.isFinite(delta.pitch) ? reference.pitch + delta.pitch : current.pitch;
2874
2881
  const nextFov = delta.fov !== void 0 && Number.isFinite(delta.fov) ? current.fov + delta.fov : current.fov;
2875
2882
  targetViewRef.current = softConstrainView({
2876
2883
  yaw: nextYaw,
2877
2884
  pitch: nextPitch,
2878
2885
  fov: nextFov
2879
2886
  });
2887
+ if (origin) {
2888
+ viewRef.current = { ...viewRef.current, yaw: targetViewRef.current.yaw, pitch: targetViewRef.current.pitch };
2889
+ }
2880
2890
  if (gyroControlsView) {
2881
2891
  if (acceptsYaw && delta.yaw !== void 0 && Number.isFinite(delta.yaw)) {
2882
2892
  gyroOffsetRef.current.yaw = shortestYawDelta(gyroPoseRef.current.yaw, targetViewRef.current.yaw);
@@ -2892,10 +2902,10 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2892
2902
  const elapsed = previousAt === null ? 1 / 60 : Math.max((now - previousAt) / 1e3, 1 / 120);
2893
2903
  lastVelocitySampleAtRef.current = now;
2894
2904
  if (delta.yaw !== void 0 && Number.isFinite(delta.yaw)) {
2895
- yawVelocityRef.current = delta.yaw / elapsed;
2905
+ yawVelocityRef.current = limitedYawDelta(current.yaw, targetViewRef.current.yaw, limitsRef.current.yaw) / elapsed;
2896
2906
  }
2897
2907
  if (delta.pitch !== void 0 && Number.isFinite(delta.pitch)) {
2898
- pitchVelocityRef.current = delta.pitch / elapsed;
2908
+ pitchVelocityRef.current = (targetViewRef.current.pitch - current.pitch) / elapsed;
2899
2909
  }
2900
2910
  if (delta.fov !== void 0 && Number.isFinite(delta.fov)) {
2901
2911
  zoomVelocityRef.current = clamp(delta.fov / elapsed, -180, 180);
@@ -2909,6 +2919,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2909
2919
  ref,
2910
2920
  () => ({
2911
2921
  getView: () => ({ ...viewRef.current }),
2922
+ getPointerDragState: () => ({ revision: pointerRevisionRef.current, anchored: !gyroActiveRef.current && xrSessionRef.current == null }),
2912
2923
  setSceneViewLimits: (limits) => {
2913
2924
  sceneLimitsRef.current = parseViewLimits(limits);
2914
2925
  refreshLimits();
@@ -2948,6 +2959,9 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2948
2959
  }
2949
2960
  syncInteracting();
2950
2961
  if (active && !wasActive) {
2962
+ if (!gyroActiveRef.current) {
2963
+ targetViewRef.current = { ...targetViewRef.current, yaw: viewRef.current.yaw, pitch: viewRef.current.pitch };
2964
+ }
2951
2965
  eventBusRef.current.emit("viewinteractionstart", { source });
2952
2966
  } else if (!active && wasActive) {
2953
2967
  eventBusRef.current.emit("viewinteractionend", { source });
@@ -2967,6 +2981,7 @@ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRun
2967
2981
  isInteractionLocked: () => interactionLockCountRef.current > 0,
2968
2982
  isUserInteracting,
2969
2983
  setGyroActive: (active) => {
2984
+ if (gyroActiveRef.current !== active) pointerRevisionRef.current += 1;
2970
2985
  if (active) {
2971
2986
  cancelNavigation();
2972
2987
  }
@@ -3716,6 +3731,149 @@ function KeyboardControls({
3716
3731
  // src/mouse-controls.tsx
3717
3732
  var import_fiber4 = require("@react-three/fiber");
3718
3733
  var import_react9 = require("react");
3734
+
3735
+ // src/pointer-drag.ts
3736
+ var import_three2 = require("three");
3737
+ var DEFAULT_POINTER_DRAG_SPEED = 0.35;
3738
+ var POINTER_FOLLOW_TIME_SECONDS = 0.01;
3739
+ var PointerDragAnchor = class {
3740
+ constructor(start, origin, rect, projection) {
3741
+ this.start = start;
3742
+ this.origin = origin;
3743
+ this.rect = rect;
3744
+ this.projection = projection;
3745
+ this.local = new import_three2.Vector3();
3746
+ this.rotation = new import_three2.Euler(0, 0, 0, "YXZ");
3747
+ this.anchor = this.ray(start).clone().applyEuler(this.rotation.set(
3748
+ import_three2.MathUtils.degToRad(origin.pitch),
3749
+ import_three2.MathUtils.degToRad(-origin.yaw),
3750
+ 0,
3751
+ "YXZ"
3752
+ ));
3753
+ }
3754
+ ray(point) {
3755
+ return this.local.set(
3756
+ (point.x - this.rect.left) / Math.max(this.rect.width, 1) * 2 - 1,
3757
+ 1 - (point.y - this.rect.top) / Math.max(this.rect.height, 1) * 2,
3758
+ 0.5
3759
+ ).applyMatrix4(this.projection.projectionMatrixInverse).normalize();
3760
+ }
3761
+ solve(point, speed = DEFAULT_POINTER_DRAG_SPEED, invert = false) {
3762
+ const multiplier = (Number.isFinite(speed) && speed >= 0 ? speed : DEFAULT_POINTER_DRAG_SPEED) / DEFAULT_POINTER_DRAG_SPEED * (invert ? -1 : 1);
3763
+ if (multiplier === 0) return { yaw: 0, pitch: 0 };
3764
+ const ray = this.ray({
3765
+ x: this.start.x + (point.x - this.start.x) * multiplier,
3766
+ y: this.start.y + (point.y - this.start.y) * multiplier
3767
+ });
3768
+ const latitude = Math.asin(import_three2.MathUtils.clamp(this.anchor.y / Math.max(Math.hypot(ray.y, ray.z), 1e-12), -1, 1));
3769
+ const offset = Math.atan2(ray.y, -ray.z);
3770
+ const originPitch = import_three2.MathUtils.degToRad(this.origin.pitch);
3771
+ const candidates = [latitude - offset, Math.PI - latitude - offset, -Math.PI - latitude - offset];
3772
+ let pitch = candidates[0];
3773
+ let distance = Infinity;
3774
+ for (const candidate of candidates) {
3775
+ const bounded = import_three2.MathUtils.clamp(candidate, -Math.PI / 2, Math.PI / 2);
3776
+ const nextDistance = Math.abs(candidate - bounded) * 10 + Math.abs(bounded - originPitch);
3777
+ if (nextDistance < distance) {
3778
+ pitch = bounded;
3779
+ distance = nextDistance;
3780
+ }
3781
+ }
3782
+ const z = Math.sin(pitch) * ray.y + Math.cos(pitch) * ray.z;
3783
+ const yaw = import_three2.MathUtils.radToDeg(Math.atan2(this.anchor.x, -this.anchor.z) - Math.atan2(ray.x, -z));
3784
+ return { yaw: normalizeViewYaw(yaw - this.origin.yaw), pitch: import_three2.MathUtils.radToDeg(pitch) - this.origin.pitch };
3785
+ }
3786
+ };
3787
+ function createPointerDrag(camera, element, runtime, source) {
3788
+ let anchor;
3789
+ let revision = -1;
3790
+ let projectionKey = "";
3791
+ let pending;
3792
+ let displayed;
3793
+ let lastPoint;
3794
+ let fresh = false;
3795
+ let lastFrameDelta = 1 / 60;
3796
+ const key = (rect) => `${rect.left},${rect.top},${rect.width},${rect.height},${camera.projectionMatrix.elements.join(",")}`;
3797
+ const start = (point) => {
3798
+ const handle = runtime();
3799
+ displayed = { ...point };
3800
+ lastPoint = { ...point };
3801
+ pending = void 0;
3802
+ revision = handle?.getPointerDragState().revision ?? -1;
3803
+ anchor = void 0;
3804
+ if (!(camera instanceof import_three2.PerspectiveCamera) || !handle?.getPointerDragState().anchored) return;
3805
+ const rect = element.getBoundingClientRect();
3806
+ projectionKey = key(rect);
3807
+ anchor = new PointerDragAnchor(point, handle.getView(), rect, camera.clone());
3808
+ };
3809
+ const apply = (point, previous, speed, invert, recordVelocity) => {
3810
+ const handle = runtime();
3811
+ if (!handle) return;
3812
+ const rect = element.getBoundingClientRect();
3813
+ if (anchor && key(rect) !== projectionKey) {
3814
+ const queued = pending;
3815
+ start(displayed ?? previous);
3816
+ pending = queued;
3817
+ }
3818
+ if (anchor) {
3819
+ handle.applyViewDelta(anchor.solve(point, speed, invert), {
3820
+ pointerOrigin: anchor.origin,
3821
+ recordVelocity,
3822
+ source
3823
+ });
3824
+ } else {
3825
+ handle.applyViewDelta({
3826
+ yaw: -(point.x - previous.x) * 360 * speed / Math.max(rect.width, 1) * (invert ? -1 : 1),
3827
+ pitch: (point.y - previous.y) * 180 * speed / Math.max(rect.height, 1) * (invert ? -1 : 1)
3828
+ }, { recordVelocity, source });
3829
+ }
3830
+ };
3831
+ return {
3832
+ start,
3833
+ valid: () => revision === (runtime()?.getPointerDragState().revision ?? -1) && !runtime()?.isInteractionLocked(),
3834
+ clear: () => {
3835
+ anchor = void 0;
3836
+ revision = -1;
3837
+ pending = void 0;
3838
+ displayed = void 0;
3839
+ },
3840
+ suspend: () => {
3841
+ anchor = void 0;
3842
+ pending = void 0;
3843
+ displayed = void 0;
3844
+ },
3845
+ move(point, previous, speed, invert) {
3846
+ fresh = true;
3847
+ pending = { point, previous: lastPoint ?? previous, speed, invert };
3848
+ },
3849
+ flush(deltaSeconds = lastFrameDelta, immediate = false) {
3850
+ lastFrameDelta = deltaSeconds;
3851
+ if (!pending) return;
3852
+ const sample = pending;
3853
+ if (!anchor || immediate) {
3854
+ pending = void 0;
3855
+ apply(sample.point, sample.previous, sample.speed, sample.invert, fresh);
3856
+ fresh = false;
3857
+ lastPoint = sample.point;
3858
+ displayed = sample.point;
3859
+ return;
3860
+ }
3861
+ const previousDisplay = displayed ?? sample.previous;
3862
+ const dx = sample.point.x - previousDisplay.x;
3863
+ const dy = sample.point.y - previousDisplay.y;
3864
+ const distance = Math.hypot(dx, dy);
3865
+ const ratio = distance > 0.01 ? POINTER_FOLLOW_TIME_SECONDS / (POINTER_FOLLOW_TIME_SECONDS + deltaSeconds) : 0;
3866
+ const point = { x: sample.point.x - dx * ratio, y: sample.point.y - dy * ratio };
3867
+ apply(point, sample.previous, sample.speed, sample.invert, fresh);
3868
+ fresh = false;
3869
+ lastPoint = sample.point;
3870
+ displayed = point;
3871
+ if (ratio === 0) pending = void 0;
3872
+ }
3873
+ };
3874
+ }
3875
+
3876
+ // src/mouse-controls.tsx
3719
3877
  var DEFAULT_ROTATE_SPEED2 = 0.35;
3720
3878
  var DEFAULT_ZOOM_SPEED2 = 0.08;
3721
3879
  var BUTTON_FLAG = {
@@ -3741,7 +3899,9 @@ function MouseControls({
3741
3899
  }) {
3742
3900
  useClaimControlChannel("mouse");
3743
3901
  const controlsRef = (0, import_react9.useContext)(PanoramaViewContext);
3744
- const { gl } = (0, import_fiber4.useThree)();
3902
+ const { gl, camera } = (0, import_fiber4.useThree)();
3903
+ const validateDragRef = (0, import_react9.useRef)(void 0);
3904
+ (0, import_fiber4.useFrame)((_, delta) => validateDragRef.current?.(delta), -1);
3745
3905
  const pointersRef = (0, import_react9.useRef)(
3746
3906
  /* @__PURE__ */ new Map()
3747
3907
  );
@@ -3764,6 +3924,7 @@ function MouseControls({
3764
3924
  };
3765
3925
  (0, import_react9.useEffect)(() => {
3766
3926
  const element = gl.domElement;
3927
+ const drag = createPointerDrag(camera, element, () => controlsRef.current, "mouse");
3767
3928
  const allowedButtons = resolveButtons(buttons);
3768
3929
  const clearPointers = () => {
3769
3930
  for (const pointerId of pointersRef.current.keys()) {
@@ -3772,8 +3933,13 @@ function MouseControls({
3772
3933
  }
3773
3934
  }
3774
3935
  pointersRef.current.clear();
3936
+ drag.clear();
3775
3937
  controlsRef.current?.setPointerActive("mouse", false, { cancelled: true });
3776
3938
  };
3939
+ validateDragRef.current = (delta) => {
3940
+ if (pointersRef.current.size && !drag.valid()) clearPointers();
3941
+ else drag.flush(delta);
3942
+ };
3777
3943
  if (!enabled) {
3778
3944
  clearPointers();
3779
3945
  return;
@@ -3804,6 +3970,7 @@ function MouseControls({
3804
3970
  });
3805
3971
  element.setPointerCapture?.(event.pointerId);
3806
3972
  syncActive();
3973
+ drag.start({ x: event.clientX, y: event.clientY });
3807
3974
  };
3808
3975
  const onPointerMove = (event) => {
3809
3976
  if (!isMouseLike(event)) {
@@ -3823,24 +3990,16 @@ function MouseControls({
3823
3990
  at: performance.now()
3824
3991
  };
3825
3992
  pointersRef.current.set(event.pointerId, next);
3826
- const rect = element.getBoundingClientRect();
3827
- const speed = resolveSpeed2(
3828
- optionsRef.current.rotateSpeed,
3829
- DEFAULT_ROTATE_SPEED2
3830
- );
3831
- const sign = optionsRef.current.invert ? -1 : 1;
3832
- const deltaYaw = sign * -(next.x - previous.x) * 360 * speed / Math.max(rect.width, 1);
3833
- const deltaPitch = sign * (next.y - previous.y) * 180 * speed / Math.max(rect.height, 1);
3834
- controlsRef.current?.applyViewDelta(
3835
- { yaw: deltaYaw, pitch: deltaPitch },
3836
- { recordVelocity: true, source: "mouse" }
3837
- );
3993
+ const speed = resolveSpeed2(optionsRef.current.rotateSpeed, DEFAULT_ROTATE_SPEED2);
3994
+ drag.move(next, previous, speed, optionsRef.current.invert);
3838
3995
  };
3839
3996
  const releasePointer = (event) => {
3840
3997
  if (!pointersRef.current.has(event.pointerId)) {
3841
3998
  return;
3842
3999
  }
4000
+ if (event.type === "pointerup") drag.flush();
3843
4001
  pointersRef.current.delete(event.pointerId);
4002
+ drag.clear();
3844
4003
  if (element.hasPointerCapture?.(event.pointerId)) {
3845
4004
  element.releasePointerCapture?.(event.pointerId);
3846
4005
  }
@@ -3876,6 +4035,7 @@ function MouseControls({
3876
4035
  element.addEventListener("lostpointercapture", releasePointer);
3877
4036
  element.addEventListener("wheel", onWheel, { passive: false });
3878
4037
  return () => {
4038
+ validateDragRef.current = void 0;
3879
4039
  element.removeEventListener("pointerdown", onPointerDown);
3880
4040
  element.removeEventListener("pointermove", onPointerMove);
3881
4041
  element.removeEventListener("pointerup", releasePointer);
@@ -3884,7 +4044,7 @@ function MouseControls({
3884
4044
  element.removeEventListener("wheel", onWheel);
3885
4045
  clearPointers();
3886
4046
  };
3887
- }, [buttons, controlsRef, enabled, gl]);
4047
+ }, [buttons, controlsRef, enabled, gl, camera]);
3888
4048
  return null;
3889
4049
  }
3890
4050
 
@@ -5299,10 +5459,10 @@ function usePanoOverlayHost(isFullscreen) {
5299
5459
  // src/panorama-event-surface.tsx
5300
5460
  var import_fiber7 = require("@react-three/fiber");
5301
5461
  var import_react16 = require("react");
5302
- var import_three3 = require("three");
5462
+ var import_three4 = require("three");
5303
5463
 
5304
5464
  // src/hotspot/coordinates.ts
5305
- var import_three2 = require("three");
5465
+ var import_three3 = require("three");
5306
5466
 
5307
5467
  // src/hotspot/types.ts
5308
5468
  var MAX_HOTSPOT_PITCH = 90;
@@ -5325,13 +5485,13 @@ function normalizePanoYaw(yaw) {
5325
5485
  if (!Number.isFinite(yaw)) {
5326
5486
  return 0;
5327
5487
  }
5328
- return import_three2.MathUtils.euclideanModulo(yaw + 180, 360) - 180;
5488
+ return import_three3.MathUtils.euclideanModulo(yaw + 180, 360) - 180;
5329
5489
  }
5330
5490
  function clampPanoPitch(pitch) {
5331
5491
  if (!Number.isFinite(pitch)) {
5332
5492
  return 0;
5333
5493
  }
5334
- const clamped = import_three2.MathUtils.clamp(
5494
+ const clamped = import_three3.MathUtils.clamp(
5335
5495
  pitch,
5336
5496
  -MAX_HOTSPOT_PITCH,
5337
5497
  MAX_HOTSPOT_PITCH
@@ -5348,10 +5508,10 @@ function normalizePanoPosition(position) {
5348
5508
  function panoPositionToVector3(position, radius = 1) {
5349
5509
  const normalized = normalizePanoPosition(position);
5350
5510
  const safeRadius = Number.isFinite(radius) ? Math.max(0, radius) : 1;
5351
- const yaw = import_three2.MathUtils.degToRad(normalized.yaw);
5352
- const pitch = import_three2.MathUtils.degToRad(normalized.pitch);
5511
+ const yaw = import_three3.MathUtils.degToRad(normalized.yaw);
5512
+ const pitch = import_three3.MathUtils.degToRad(normalized.pitch);
5353
5513
  const cosPitch = Math.cos(pitch);
5354
- return new import_three2.Vector3(
5514
+ return new import_three3.Vector3(
5355
5515
  cosPitch * Math.sin(yaw) * safeRadius,
5356
5516
  Math.sin(pitch) * safeRadius,
5357
5517
  -cosPitch * Math.cos(yaw) * safeRadius
@@ -5363,9 +5523,9 @@ function vector3ToPanoPosition(vector) {
5363
5523
  return { yaw: 0, pitch: 0 };
5364
5524
  }
5365
5525
  return normalizePanoPosition({
5366
- yaw: import_three2.MathUtils.radToDeg(Math.atan2(vector.x, -vector.z)),
5367
- pitch: import_three2.MathUtils.radToDeg(
5368
- Math.asin(import_three2.MathUtils.clamp(vector.y / length, -1, 1))
5526
+ yaw: import_three3.MathUtils.radToDeg(Math.atan2(vector.x, -vector.z)),
5527
+ pitch: import_three3.MathUtils.radToDeg(
5528
+ Math.asin(import_three3.MathUtils.clamp(vector.y / length, -1, 1))
5369
5529
  )
5370
5530
  });
5371
5531
  }
@@ -5398,9 +5558,9 @@ function PanoramaEventSurface() {
5398
5558
  return;
5399
5559
  }
5400
5560
  const element = gl.domElement;
5401
- const ndc = new import_three3.Vector2();
5402
- const raycaster = new import_three3.Raycaster();
5403
- const direction = new import_three3.Vector3();
5561
+ const ndc = new import_three4.Vector2();
5562
+ const raycaster = new import_three4.Raycaster();
5563
+ const direction = new import_three4.Vector3();
5404
5564
  const handleContextMenu = (nativeEvent) => {
5405
5565
  const rect = element.getBoundingClientRect();
5406
5566
  if (rect.width <= 0 || rect.height <= 0) {
@@ -5452,7 +5612,7 @@ function PanoramaEventSurface() {
5452
5612
  depthTest: false,
5453
5613
  depthWrite: false,
5454
5614
  opacity: 0,
5455
- side: import_three3.BackSide,
5615
+ side: import_three4.BackSide,
5456
5616
  transparent: true
5457
5617
  }
5458
5618
  )
@@ -5496,7 +5656,9 @@ function TouchControls({
5496
5656
  }) {
5497
5657
  useClaimControlChannel("touch");
5498
5658
  const controlsRef = (0, import_react18.useContext)(PanoramaViewContext);
5499
- const { gl } = (0, import_fiber8.useThree)();
5659
+ const { gl, camera } = (0, import_fiber8.useThree)();
5660
+ const validateDragRef = (0, import_react18.useRef)(void 0);
5661
+ (0, import_fiber8.useFrame)((_, delta) => validateDragRef.current?.(delta), -1);
5500
5662
  const pointersRef = (0, import_react18.useRef)(/* @__PURE__ */ new Map());
5501
5663
  const pinchDistanceRef = (0, import_react18.useRef)(null);
5502
5664
  const optionsRef = (0, import_react18.useRef)({ rotateSpeed, invert, pinchZoom });
@@ -5506,6 +5668,7 @@ function TouchControls({
5506
5668
  optionsRef.current = { rotateSpeed, invert, pinchZoom };
5507
5669
  (0, import_react18.useEffect)(() => {
5508
5670
  const element = gl.domElement;
5671
+ const drag = createPointerDrag(camera, element, () => controlsRef.current, "touch");
5509
5672
  const clearPointers = () => {
5510
5673
  for (const pointerId of pointersRef.current.keys()) {
5511
5674
  if (element.hasPointerCapture?.(pointerId)) {
@@ -5513,9 +5676,14 @@ function TouchControls({
5513
5676
  }
5514
5677
  }
5515
5678
  pointersRef.current.clear();
5679
+ drag.clear();
5516
5680
  pinchDistanceRef.current = null;
5517
5681
  controlsRef.current?.setPointerActive("touch", false, { cancelled: true });
5518
5682
  };
5683
+ validateDragRef.current = (delta) => {
5684
+ if (pointersRef.current.size && !drag.valid()) clearPointers();
5685
+ else drag.flush(delta);
5686
+ };
5519
5687
  if (!enabled) {
5520
5688
  clearPointers();
5521
5689
  return;
@@ -5542,7 +5710,9 @@ function TouchControls({
5542
5710
  });
5543
5711
  element.setPointerCapture?.(event.pointerId);
5544
5712
  syncActive();
5545
- if (pointersRef.current.size === 2) {
5713
+ drag.start({ x: event.clientX, y: event.clientY });
5714
+ if (pointersRef.current.size >= 2) {
5715
+ drag.suspend();
5546
5716
  const [first, second] = Array.from(pointersRef.current.values());
5547
5717
  pinchDistanceRef.current = pointerDistance(first, second);
5548
5718
  }
@@ -5567,6 +5737,7 @@ function TouchControls({
5567
5737
  pointersRef.current.set(event.pointerId, next);
5568
5738
  const pointers = Array.from(pointersRef.current.values());
5569
5739
  if (pointers.length >= 2) {
5740
+ drag.suspend();
5570
5741
  if (!optionsRef.current.pinchZoom) {
5571
5742
  return;
5572
5743
  }
@@ -5585,24 +5756,16 @@ function TouchControls({
5585
5756
  }
5586
5757
  return;
5587
5758
  }
5588
- const rect = element.getBoundingClientRect();
5589
- const speed = resolveSpeed3(
5590
- optionsRef.current.rotateSpeed,
5591
- DEFAULT_ROTATE_SPEED3
5592
- );
5593
- const sign = optionsRef.current.invert ? -1 : 1;
5594
- const deltaYaw = sign * -(next.x - previous.x) * 360 * speed / Math.max(rect.width, 1);
5595
- const deltaPitch = sign * (next.y - previous.y) * 180 * speed / Math.max(rect.height, 1);
5596
- controlsRef.current?.applyViewDelta(
5597
- { yaw: deltaYaw, pitch: deltaPitch },
5598
- { recordVelocity: true, source: "touch" }
5599
- );
5759
+ const speed = resolveSpeed3(optionsRef.current.rotateSpeed, DEFAULT_ROTATE_SPEED3);
5760
+ drag.move(next, previous, speed, optionsRef.current.invert);
5600
5761
  };
5601
5762
  const releasePointer = (event) => {
5602
5763
  if (!pointersRef.current.has(event.pointerId)) {
5603
5764
  return;
5604
5765
  }
5766
+ if (event.type === "pointerup") drag.flush();
5605
5767
  pointersRef.current.delete(event.pointerId);
5768
+ drag.clear();
5606
5769
  if (element.hasPointerCapture?.(event.pointerId)) {
5607
5770
  element.releasePointerCapture?.(event.pointerId);
5608
5771
  }
@@ -5610,6 +5773,8 @@ function TouchControls({
5610
5773
  pinchDistanceRef.current = null;
5611
5774
  }
5612
5775
  syncActive(event.type !== "pointerup");
5776
+ const remaining = pointersRef.current.values().next().value;
5777
+ if (remaining) drag.start(remaining);
5613
5778
  };
5614
5779
  element.addEventListener("pointerdown", onPointerDown);
5615
5780
  element.addEventListener("pointermove", onPointerMove);
@@ -5617,6 +5782,7 @@ function TouchControls({
5617
5782
  element.addEventListener("pointercancel", releasePointer);
5618
5783
  element.addEventListener("lostpointercapture", releasePointer);
5619
5784
  return () => {
5785
+ validateDragRef.current = void 0;
5620
5786
  element.removeEventListener("pointerdown", onPointerDown);
5621
5787
  element.removeEventListener("pointermove", onPointerMove);
5622
5788
  element.removeEventListener("pointerup", releasePointer);
@@ -5624,7 +5790,7 @@ function TouchControls({
5624
5790
  element.removeEventListener("lostpointercapture", releasePointer);
5625
5791
  clearPointers();
5626
5792
  };
5627
- }, [controlsRef, enabled, gl]);
5793
+ }, [controlsRef, enabled, gl, camera]);
5628
5794
  return null;
5629
5795
  }
5630
5796
 
@@ -7247,12 +7413,12 @@ function WebVRChromeBridge({ host }) {
7247
7413
  }
7248
7414
 
7249
7415
  // src/webvr/stereo-view.ts
7250
- var import_three4 = require("three");
7251
- var PROJECT = new import_three4.Vector3();
7416
+ var import_three5 = require("three");
7417
+ var PROJECT = new import_three5.Vector3();
7252
7418
  function createWebVRStereoView() {
7253
7419
  return {
7254
7420
  active: false,
7255
- stereo: new import_three4.StereoCamera()
7421
+ stereo: new import_three5.StereoCamera()
7256
7422
  };
7257
7423
  }
7258
7424
  function isFallbackStereoMode(mode) {
@@ -7276,11 +7442,11 @@ function projectStereoHtmlPosition(el, camera, size, eye) {
7276
7442
  var import_fiber9 = require("@react-three/fiber");
7277
7443
  var import_xr2 = require("@react-three/xr");
7278
7444
  var import_react26 = require("react");
7279
- var import_three5 = require("three");
7445
+ var import_three6 = require("three");
7280
7446
  var import_jsx_runtime11 = require("react/jsx-runtime");
7281
7447
  function PanoramaXROrigin() {
7282
7448
  const originRef = (0, import_react26.useRef)(null);
7283
- const localHeadPositionRef = (0, import_react26.useRef)(new import_three5.Vector3());
7449
+ const localHeadPositionRef = (0, import_react26.useRef)(new import_three6.Vector3());
7284
7450
  const session2 = (0, import_xr2.useXR)((state) => state.session);
7285
7451
  const gl = (0, import_fiber9.useThree)((state) => state.gl);
7286
7452
  (0, import_fiber9.useFrame)(() => {
@@ -8030,7 +8196,7 @@ var import_react51 = require("react");
8030
8196
  // src/scenes.tsx
8031
8197
  var import_fiber18 = require("@react-three/fiber");
8032
8198
  var import_react38 = require("react");
8033
- var import_three19 = require("three");
8199
+ var import_three20 = require("three");
8034
8200
 
8035
8201
  // src/scene-detail.tsx
8036
8202
  var import_react28 = require("react");
@@ -8102,12 +8268,12 @@ function isSnapshotTransition(preset) {
8102
8268
  // src/scene-transitions/snapshot-hold.tsx
8103
8269
  var import_fiber11 = require("@react-three/fiber");
8104
8270
  var import_react29 = require("react");
8105
- var import_three8 = require("three");
8271
+ var import_three9 = require("three");
8106
8272
 
8107
8273
  // src/scene-transitions/overlay-utils.ts
8108
- var import_three6 = require("three");
8274
+ var import_three7 = require("three");
8109
8275
  var OVERLAY_RENDER_ORDER = 1e4;
8110
- var FULLSCREEN_PLANE = new import_three6.PlaneGeometry(1, 1);
8276
+ var FULLSCREEN_PLANE = new import_three7.PlaneGeometry(1, 1);
8111
8277
  function isPerspectiveCamera(camera) {
8112
8278
  return camera.isPerspectiveCamera === true;
8113
8279
  }
@@ -8126,7 +8292,7 @@ function overlayProgress(elapsedTime, duration, startTime) {
8126
8292
  }
8127
8293
 
8128
8294
  // src/scene-transitions/snapshot-shaders.ts
8129
- var import_three7 = require("three");
8295
+ var import_three8 = require("three");
8130
8296
 
8131
8297
  // src/scene-transitions/glsl.ts
8132
8298
  var GLSL_COMMON = `
@@ -8418,15 +8584,15 @@ var SNAPSHOT_FRAGMENT_SHADERS = {
8418
8584
  `)
8419
8585
  };
8420
8586
  function createSnapshotMaterial(preset, texture) {
8421
- return new import_three7.ShaderMaterial({
8587
+ return new import_three8.ShaderMaterial({
8422
8588
  transparent: true,
8423
8589
  depthTest: false,
8424
8590
  depthWrite: false,
8425
- side: import_three7.DoubleSide,
8591
+ side: import_three8.DoubleSide,
8426
8592
  uniforms: {
8427
8593
  map: { value: texture },
8428
8594
  progress: { value: 0 },
8429
- resolution: { value: new import_three7.Vector2(1, 1) }
8595
+ resolution: { value: new import_three8.Vector2(1, 1) }
8430
8596
  },
8431
8597
  vertexShader: SNAPSHOT_VERTEX_SHADER,
8432
8598
  fragmentShader: SNAPSHOT_FRAGMENT_SHADERS[preset]
@@ -8438,7 +8604,7 @@ var import_jsx_runtime13 = require("react/jsx-runtime");
8438
8604
  function SnapshotHold({ snapshot }) {
8439
8605
  const { camera, gl } = (0, import_fiber11.useThree)();
8440
8606
  const meshRef = (0, import_react29.useRef)(null);
8441
- const directionRef = (0, import_react29.useRef)(new import_three8.Vector3());
8607
+ const directionRef = (0, import_react29.useRef)(new import_three9.Vector3());
8442
8608
  const material = (0, import_react29.useMemo)(
8443
8609
  () => createSnapshotMaterial("crossfade", snapshot.texture),
8444
8610
  [snapshot.texture]
@@ -8522,7 +8688,7 @@ function phaseAfterSnapshot(preset, hold) {
8522
8688
  // src/scene-transitions/particle-overlay.tsx
8523
8689
  var import_fiber12 = require("@react-three/fiber");
8524
8690
  var import_react30 = require("react");
8525
- var import_three9 = require("three");
8691
+ var import_three10 = require("three");
8526
8692
  var import_jsx_runtime14 = require("react/jsx-runtime");
8527
8693
  var PARTICLE_GRID = 48;
8528
8694
  var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
@@ -8576,8 +8742,8 @@ var PARTICLE_FRAGMENT_SHADER = `
8576
8742
  }
8577
8743
  `;
8578
8744
  function createParticleGeometry() {
8579
- const quad = new import_three9.PlaneGeometry(1, 1);
8580
- const geometry = new import_three9.InstancedBufferGeometry();
8745
+ const quad = new import_three10.PlaneGeometry(1, 1);
8746
+ const geometry = new import_three10.InstancedBufferGeometry();
8581
8747
  if (quad.index) {
8582
8748
  geometry.setIndex(quad.index.clone());
8583
8749
  }
@@ -8587,7 +8753,7 @@ function createParticleGeometry() {
8587
8753
  for (let i = 0; i < PARTICLE_COUNT; i += 1) {
8588
8754
  indexes[i] = i;
8589
8755
  }
8590
- geometry.setAttribute("instanceIndex", new import_three9.InstancedBufferAttribute(indexes, 1));
8756
+ geometry.setAttribute("instanceIndex", new import_three10.InstancedBufferAttribute(indexes, 1));
8591
8757
  geometry.instanceCount = PARTICLE_COUNT;
8592
8758
  quad.dispose();
8593
8759
  return geometry;
@@ -8603,18 +8769,18 @@ function ParticleOverlay({
8603
8769
  const meshRef = (0, import_react30.useRef)(null);
8604
8770
  const startRef = (0, import_react30.useRef)(null);
8605
8771
  const finishedRef = (0, import_react30.useRef)(false);
8606
- const directionRef = (0, import_react30.useRef)(new import_three9.Vector3());
8772
+ const directionRef = (0, import_react30.useRef)(new import_three10.Vector3());
8607
8773
  const geometry = (0, import_react30.useMemo)(() => createParticleGeometry(), []);
8608
8774
  const material = (0, import_react30.useMemo)(
8609
- () => new import_three9.ShaderMaterial({
8775
+ () => new import_three10.ShaderMaterial({
8610
8776
  transparent: true,
8611
8777
  depthTest: false,
8612
8778
  depthWrite: false,
8613
- side: import_three9.DoubleSide,
8779
+ side: import_three10.DoubleSide,
8614
8780
  uniforms: {
8615
8781
  map: { value: snapshot.texture },
8616
8782
  progress: { value: 0 },
8617
- grid: { value: new import_three9.Vector2(PARTICLE_GRID, PARTICLE_GRID) }
8783
+ grid: { value: new import_three10.Vector2(PARTICLE_GRID, PARTICLE_GRID) }
8618
8784
  },
8619
8785
  vertexShader: PARTICLE_VERTEX_SHADER,
8620
8786
  fragmentShader: PARTICLE_FRAGMENT_SHADER
@@ -8660,7 +8826,7 @@ function ParticleOverlay({
8660
8826
  // src/scene-transitions/snapshot-overlay.tsx
8661
8827
  var import_fiber13 = require("@react-three/fiber");
8662
8828
  var import_react31 = require("react");
8663
- var import_three10 = require("three");
8829
+ var import_three11 = require("three");
8664
8830
  var import_jsx_runtime15 = require("react/jsx-runtime");
8665
8831
  function SnapshotOverlay({
8666
8832
  snapshot,
@@ -8673,7 +8839,7 @@ function SnapshotOverlay({
8673
8839
  const meshRef = (0, import_react31.useRef)(null);
8674
8840
  const startRef = (0, import_react31.useRef)(null);
8675
8841
  const finishedRef = (0, import_react31.useRef)(false);
8676
- const directionRef = (0, import_react31.useRef)(new import_three10.Vector3());
8842
+ const directionRef = (0, import_react31.useRef)(new import_three11.Vector3());
8677
8843
  const material = (0, import_react31.useMemo)(() => {
8678
8844
  if (!isSnapshotTransition(transition.preset)) {
8679
8845
  return null;
@@ -8764,11 +8930,11 @@ function TransitionOverlay(props) {
8764
8930
  // src/sphere.tsx
8765
8931
  var import_fiber14 = require("@react-three/fiber");
8766
8932
  var import_react33 = require("react");
8767
- var import_three12 = require("three");
8933
+ var import_three13 = require("three");
8768
8934
 
8769
8935
  // src/pano-filter/pano-basic-material.tsx
8770
8936
  var import_react32 = require("react");
8771
- var import_three11 = require("three");
8937
+ var import_three12 = require("three");
8772
8938
 
8773
8939
  // src/pano-filter/shaders.ts
8774
8940
  var GLSL_FILTER_COMMON = `
@@ -8935,7 +9101,7 @@ function injectPanoColorMatrixShader(shader) {
8935
9101
  var import_jsx_runtime17 = require("react/jsx-runtime");
8936
9102
  function matrixUniforms(matrix) {
8937
9103
  return {
8938
- matrix: new import_three11.Matrix4().set(
9104
+ matrix: new import_three12.Matrix4().set(
8939
9105
  matrix[0],
8940
9106
  matrix[1],
8941
9107
  matrix[2],
@@ -8953,7 +9119,7 @@ function matrixUniforms(matrix) {
8953
9119
  matrix[17],
8954
9120
  matrix[18]
8955
9121
  ),
8956
- offset: new import_three11.Vector4(matrix[4], matrix[9], matrix[14], matrix[19])
9122
+ offset: new import_three12.Vector4(matrix[4], matrix[9], matrix[14], matrix[19])
8957
9123
  };
8958
9124
  }
8959
9125
  function PanoBasicMaterial({
@@ -9024,7 +9190,7 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9024
9190
  return;
9025
9191
  }
9026
9192
  let active = true;
9027
- const loader = new import_three12.TextureLoader();
9193
+ const loader = new import_three13.TextureLoader();
9028
9194
  setTexture(null);
9029
9195
  loader.load(
9030
9196
  url,
@@ -9033,13 +9199,13 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9033
9199
  loadedTexture.dispose();
9034
9200
  return;
9035
9201
  }
9036
- loadedTexture.colorSpace = import_three12.SRGBColorSpace;
9037
- loadedTexture.wrapS = import_three12.RepeatWrapping;
9202
+ loadedTexture.colorSpace = import_three13.SRGBColorSpace;
9203
+ loadedTexture.wrapS = import_three13.RepeatWrapping;
9038
9204
  loadedTexture.repeat.x = -1;
9039
9205
  loadedTexture.offset.x = 1;
9040
9206
  loadedTexture.anisotropy = anisotropy;
9041
- loadedTexture.magFilter = import_three12.LinearFilter;
9042
- loadedTexture.minFilter = generateMipmaps ? import_three12.LinearMipmapLinearFilter : import_three12.LinearFilter;
9207
+ loadedTexture.magFilter = import_three13.LinearFilter;
9208
+ loadedTexture.minFilter = generateMipmaps ? import_three13.LinearMipmapLinearFilter : import_three13.LinearFilter;
9043
9209
  loadedTexture.generateMipmaps = generateMipmaps;
9044
9210
  loadedTexture.needsUpdate = true;
9045
9211
  setTexture(loadedTexture);
@@ -9123,7 +9289,7 @@ function Sphere({
9123
9289
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
9124
9290
  "mesh",
9125
9291
  {
9126
- rotation: [0, import_three12.MathUtils.degToRad(90 + yawOffset2), 0],
9292
+ rotation: [0, import_three13.MathUtils.degToRad(90 + yawOffset2), 0],
9127
9293
  visible,
9128
9294
  children: [
9129
9295
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
@@ -9131,7 +9297,7 @@ function Sphere({
9131
9297
  PanoBasicMaterial,
9132
9298
  {
9133
9299
  map: displayTexture,
9134
- side: import_three12.BackSide,
9300
+ side: import_three13.BackSide,
9135
9301
  toneMapped: false
9136
9302
  }
9137
9303
  )
@@ -9143,10 +9309,10 @@ function Sphere({
9143
9309
  // src/sphere-tile/sphere-tile.tsx
9144
9310
  var import_fiber16 = require("@react-three/fiber");
9145
9311
  var import_react36 = require("react");
9146
- var import_three16 = require("three");
9312
+ var import_three17 = require("three");
9147
9313
 
9148
9314
  // src/tile/texture-manager.ts
9149
- var import_three13 = require("three");
9315
+ var import_three14 = require("three");
9150
9316
  var EMPTY_TEXTURE_SNAPSHOT = {
9151
9317
  status: "idle",
9152
9318
  texture: null,
@@ -9154,7 +9320,7 @@ var EMPTY_TEXTURE_SNAPSHOT = {
9154
9320
  };
9155
9321
  var TileTextureManager = class {
9156
9322
  constructor(options) {
9157
- this.loader = new import_three13.TextureLoader();
9323
+ this.loader = new import_three14.TextureLoader();
9158
9324
  this.entries = /* @__PURE__ */ new Map();
9159
9325
  this.queue = [];
9160
9326
  this.activeLoads = 0;
@@ -9326,11 +9492,11 @@ var TileTextureManager = class {
9326
9492
  }
9327
9493
  }
9328
9494
  configureTexture(texture) {
9329
- texture.colorSpace = import_three13.SRGBColorSpace;
9330
- texture.wrapS = import_three13.ClampToEdgeWrapping;
9331
- texture.wrapT = import_three13.ClampToEdgeWrapping;
9332
- texture.magFilter = import_three13.LinearFilter;
9333
- texture.minFilter = import_three13.LinearFilter;
9495
+ texture.colorSpace = import_three14.SRGBColorSpace;
9496
+ texture.wrapS = import_three14.ClampToEdgeWrapping;
9497
+ texture.wrapT = import_three14.ClampToEdgeWrapping;
9498
+ texture.magFilter = import_three14.LinearFilter;
9499
+ texture.minFilter = import_three14.LinearFilter;
9334
9500
  texture.generateMipmaps = false;
9335
9501
  texture.anisotropy = Math.min(4, this.options.anisotropy);
9336
9502
  texture.needsUpdate = true;
@@ -9403,7 +9569,7 @@ function useSharedTileTextureManager() {
9403
9569
 
9404
9570
  // src/tile/texture-hooks.ts
9405
9571
  var import_react35 = require("react");
9406
- var import_three14 = require("three");
9572
+ var import_three15 = require("three");
9407
9573
  function usePreviewTexture(url, anisotropy, onError) {
9408
9574
  const [texture, setTexture] = (0, import_react35.useState)(null);
9409
9575
  const onErrorRef = (0, import_react35.useRef)(onError);
@@ -9414,7 +9580,7 @@ function usePreviewTexture(url, anisotropy, onError) {
9414
9580
  return;
9415
9581
  }
9416
9582
  let active = true;
9417
- const loader = new import_three14.TextureLoader();
9583
+ const loader = new import_three15.TextureLoader();
9418
9584
  setTexture(null);
9419
9585
  loader.load(
9420
9586
  url,
@@ -9423,11 +9589,11 @@ function usePreviewTexture(url, anisotropy, onError) {
9423
9589
  loadedTexture.dispose();
9424
9590
  return;
9425
9591
  }
9426
- loadedTexture.colorSpace = import_three14.SRGBColorSpace;
9427
- loadedTexture.wrapS = import_three14.ClampToEdgeWrapping;
9428
- loadedTexture.wrapT = import_three14.ClampToEdgeWrapping;
9429
- loadedTexture.magFilter = import_three14.LinearFilter;
9430
- loadedTexture.minFilter = import_three14.LinearFilter;
9592
+ loadedTexture.colorSpace = import_three15.SRGBColorSpace;
9593
+ loadedTexture.wrapS = import_three15.ClampToEdgeWrapping;
9594
+ loadedTexture.wrapT = import_three15.ClampToEdgeWrapping;
9595
+ loadedTexture.magFilter = import_three15.LinearFilter;
9596
+ loadedTexture.minFilter = import_three15.LinearFilter;
9431
9597
  loadedTexture.generateMipmaps = false;
9432
9598
  loadedTexture.anisotropy = Math.min(4, anisotropy);
9433
9599
  loadedTexture.needsUpdate = true;
@@ -9476,7 +9642,7 @@ function useManagedTexture(manager, key, url, address) {
9476
9642
  }
9477
9643
 
9478
9644
  // src/sphere-tile/layout.ts
9479
- var import_three15 = require("three");
9645
+ var import_three16 = require("three");
9480
9646
  function positiveInteger2(value, name) {
9481
9647
  if (!Number.isSafeInteger(value) || value <= 0) {
9482
9648
  throw new Error(`${name} must be a positive safe integer`);
@@ -9547,9 +9713,9 @@ function sphereTileRange(address) {
9547
9713
  };
9548
9714
  }
9549
9715
  function spherePoint(u, v, yawOffset2 = 0, radius = DEFAULT_PANORAMA_RADIUS) {
9550
- const yaw = (u - 0.5) * Math.PI * 2 + import_three15.MathUtils.degToRad(yawOffset2);
9716
+ const yaw = (u - 0.5) * Math.PI * 2 + import_three16.MathUtils.degToRad(yawOffset2);
9551
9717
  const pitch = (0.5 - v) * Math.PI;
9552
- return new import_three15.Vector3(
9718
+ return new import_three16.Vector3(
9553
9719
  Math.sin(yaw) * Math.cos(pitch) * radius,
9554
9720
  Math.sin(pitch) * radius,
9555
9721
  -Math.cos(yaw) * Math.cos(pitch) * radius
@@ -9563,7 +9729,7 @@ function sphereTileBounds(address, yawOffset2) {
9563
9729
  if (u > left && u < right) us.push(u);
9564
9730
  }
9565
9731
  const vs = top < 0.5 && bottom > 0.5 ? [top, 0.5, bottom] : [top, bottom];
9566
- return new import_three15.Box3().setFromPoints(
9732
+ return new import_three16.Box3().setFromPoints(
9567
9733
  us.flatMap((u) => vs.map((v) => spherePoint(u, v, yawOffset2)))
9568
9734
  );
9569
9735
  }
@@ -9589,9 +9755,9 @@ function sphereTileGeometry(address, yawOffset2, radius = DEFAULT_PANORAMA_RADIU
9589
9755
  }
9590
9756
  }
9591
9757
  }
9592
- const geometry = new import_three15.BufferGeometry();
9593
- geometry.setAttribute("position", new import_three15.Float32BufferAttribute(positions, 3));
9594
- geometry.setAttribute("uv", new import_three15.Float32BufferAttribute(uvs, 2));
9758
+ const geometry = new import_three16.BufferGeometry();
9759
+ geometry.setAttribute("position", new import_three16.Float32BufferAttribute(positions, 3));
9760
+ geometry.setAttribute("uv", new import_three16.Float32BufferAttribute(uvs, 2));
9595
9761
  geometry.setIndex(indices);
9596
9762
  geometry.computeBoundingSphere();
9597
9763
  return geometry;
@@ -9637,7 +9803,7 @@ function SpherePatch({
9637
9803
  PanoBasicMaterial,
9638
9804
  {
9639
9805
  map: texture,
9640
- side: import_three16.BackSide,
9806
+ side: import_three17.BackSide,
9641
9807
  depthTest: false,
9642
9808
  depthWrite: false,
9643
9809
  toneMapped: false
@@ -9779,9 +9945,9 @@ function SphereTileSource({
9779
9945
  const targetKeysRef = (0, import_react36.useRef)([]);
9780
9946
  const scratch = (0, import_react36.useMemo)(
9781
9947
  () => ({
9782
- camera: new import_three16.PerspectiveCamera(),
9783
- frustum: new import_three16.Frustum(),
9784
- matrix: new import_three16.Matrix4(),
9948
+ camera: new import_three17.PerspectiveCamera(),
9949
+ frustum: new import_three17.Frustum(),
9950
+ matrix: new import_three17.Matrix4(),
9785
9951
  quaternion: camera.quaternion.clone(),
9786
9952
  fov: NaN,
9787
9953
  width: 0,
@@ -9796,7 +9962,7 @@ function SphereTileSource({
9796
9962
  [camera, candidates]
9797
9963
  );
9798
9964
  (0, import_fiber16.useFrame)(() => {
9799
- if (!(camera instanceof import_three16.PerspectiveCamera)) return;
9965
+ if (!(camera instanceof import_three17.PerspectiveCamera)) return;
9800
9966
  const now = performance.now(), dpr = gl.getPixelRatio();
9801
9967
  const managerChanged = scratch.manager !== manager;
9802
9968
  const loadModeChanged = scratch.loadMode !== loadMode;
@@ -9900,10 +10066,10 @@ function SphereTile({ multires, ...props }) {
9900
10066
  // src/tile/tile.tsx
9901
10067
  var import_fiber17 = require("@react-three/fiber");
9902
10068
  var import_react37 = require("react");
9903
- var import_three18 = require("three");
10069
+ var import_three19 = require("three");
9904
10070
 
9905
10071
  // src/tile/face-layout.ts
9906
- var import_three17 = require("three");
10072
+ var import_three18 = require("three");
9907
10073
  var CUBE_FACES = ["f", "r", "b", "l", "u", "d"];
9908
10074
  var PREVIEW_FACE_ORDER = ["l", "f", "r", "b", "u", "d"];
9909
10075
  var CUBE_RADIUS = DEFAULT_PANORAMA_RADIUS;
@@ -9954,8 +10120,8 @@ function getFaceQuaternion(face) {
9954
10120
  return cached;
9955
10121
  }
9956
10122
  const transform = getFaceTransform(face);
9957
- const quaternion = new import_three17.Quaternion().setFromEuler(
9958
- new import_three17.Euler(...transform.rotation, "XYZ")
10123
+ const quaternion = new import_three18.Quaternion().setFromEuler(
10124
+ new import_three18.Euler(...transform.rotation, "XYZ")
9959
10125
  );
9960
10126
  faceQuaternionCache.set(face, quaternion);
9961
10127
  return quaternion;
@@ -9966,17 +10132,17 @@ function getTileBoundingBox(address, radius = CUBE_RADIUS) {
9966
10132
  const halfWidth = local.width / 2;
9967
10133
  const halfHeight = local.height / 2;
9968
10134
  const quaternion = getFaceQuaternion(address.face);
9969
- const position = new import_three17.Vector3(...transform.position);
10135
+ const position = new import_three18.Vector3(...transform.position);
9970
10136
  const corners = [
9971
- new import_three17.Vector3(local.x - halfWidth, local.y - halfHeight, 0),
9972
- new import_three17.Vector3(local.x + halfWidth, local.y - halfHeight, 0),
9973
- new import_three17.Vector3(local.x - halfWidth, local.y + halfHeight, 0),
9974
- new import_three17.Vector3(local.x + halfWidth, local.y + halfHeight, 0)
10137
+ new import_three18.Vector3(local.x - halfWidth, local.y - halfHeight, 0),
10138
+ new import_three18.Vector3(local.x + halfWidth, local.y - halfHeight, 0),
10139
+ new import_three18.Vector3(local.x - halfWidth, local.y + halfHeight, 0),
10140
+ new import_three18.Vector3(local.x + halfWidth, local.y + halfHeight, 0)
9975
10141
  ];
9976
10142
  for (const corner of corners) {
9977
10143
  corner.applyQuaternion(quaternion).add(position);
9978
10144
  }
9979
- return new import_three17.Box3().setFromPoints(corners);
10145
+ return new import_three18.Box3().setFromPoints(corners);
9980
10146
  }
9981
10147
  function makeTileAddress(face, level, faceSize, tileSize, col, row) {
9982
10148
  const left = (col - 1) * tileSize;
@@ -10046,14 +10212,14 @@ function decideTileLodUpdate(input) {
10046
10212
  }
10047
10213
  var VISIBILITY_FOV_PADDING_DEGREES = 8;
10048
10214
  var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
10049
- var SHARED_TILE_GEOMETRY = new import_three18.PlaneGeometry(1, 1);
10215
+ var SHARED_TILE_GEOMETRY = new import_three19.PlaneGeometry(1, 1);
10050
10216
  function PreviewFace({
10051
10217
  face,
10052
10218
  texture,
10053
10219
  faceOrder
10054
10220
  }) {
10055
10221
  const geometry = (0, import_react37.useMemo)(() => {
10056
- const nextGeometry = new import_three18.PlaneGeometry(
10222
+ const nextGeometry = new import_three19.PlaneGeometry(
10057
10223
  PREVIEW_RADIUS * 2,
10058
10224
  PREVIEW_RADIUS * 2
10059
10225
  );
@@ -10245,8 +10411,8 @@ function parentAddresses(child, parentLevel, parentFaceSize, tileSize) {
10245
10411
  return addresses;
10246
10412
  }
10247
10413
  function centerFacingAddress(candidates, camera) {
10248
- const direction = camera.getWorldDirection(new import_three18.Vector3());
10249
- const center = new import_three18.Vector3();
10414
+ const direction = camera.getWorldDirection(new import_three19.Vector3());
10415
+ const center = new import_three19.Vector3();
10250
10416
  let bestCandidate = candidates[0];
10251
10417
  let bestAlignment = -Infinity;
10252
10418
  for (const candidate of candidates) {
@@ -10391,9 +10557,9 @@ function Tile({
10391
10557
  const lastVisibilityQuaternionRef = (0, import_react37.useRef)(camera.quaternion.clone());
10392
10558
  const lastVisibilityFovRef = (0, import_react37.useRef)(Number.NaN);
10393
10559
  const lastViewportRef = (0, import_react37.useRef)({ width: 0, height: 0, dpr: 0 });
10394
- const frustumRef = (0, import_react37.useRef)(new import_three18.Frustum());
10395
- const projectionMatrixRef = (0, import_react37.useRef)(new import_three18.Matrix4());
10396
- const visibilityCameraRef = (0, import_react37.useRef)(new import_three18.PerspectiveCamera());
10560
+ const frustumRef = (0, import_react37.useRef)(new import_three19.Frustum());
10561
+ const projectionMatrixRef = (0, import_react37.useRef)(new import_three19.Matrix4());
10562
+ const visibilityCameraRef = (0, import_react37.useRef)(new import_three19.PerspectiveCamera());
10397
10563
  const trackedLoadModeRef = (0, import_react37.useRef)(loadMode);
10398
10564
  const targetKeysRef = (0, import_react37.useRef)([]);
10399
10565
  const detailTokenRef = (0, import_react37.useRef)("");
@@ -10421,7 +10587,7 @@ function Tile({
10421
10587
  }
10422
10588
  };
10423
10589
  (0, import_fiber17.useFrame)(() => {
10424
- if (!(camera instanceof import_three18.PerspectiveCamera)) {
10590
+ if (!(camera instanceof import_three19.PerspectiveCamera)) {
10425
10591
  return;
10426
10592
  }
10427
10593
  if (loadMode === "preview") {
@@ -10601,14 +10767,14 @@ function SnapshotCapture({
10601
10767
  const scale = Math.min(1, Math.sqrt(maxPixels / (sourceWidth * sourceHeight)));
10602
10768
  const width = Math.max(1, Math.floor(sourceWidth * scale));
10603
10769
  const height = Math.max(1, Math.floor(sourceHeight * scale));
10604
- const nextTarget = new import_three19.WebGLRenderTarget(width, height, {
10770
+ const nextTarget = new import_three20.WebGLRenderTarget(width, height, {
10605
10771
  depthBuffer: false,
10606
10772
  stencilBuffer: false
10607
10773
  });
10608
- nextTarget.texture.colorSpace = import_three19.LinearSRGBColorSpace;
10774
+ nextTarget.texture.colorSpace = import_three20.LinearSRGBColorSpace;
10609
10775
  nextTarget.texture.generateMipmaps = false;
10610
- nextTarget.texture.minFilter = import_three19.LinearFilter;
10611
- nextTarget.texture.magFilter = import_three19.LinearFilter;
10776
+ nextTarget.texture.minFilter = import_three20.LinearFilter;
10777
+ nextTarget.texture.magFilter = import_three20.LinearFilter;
10612
10778
  const previousTarget = gl.getRenderTarget();
10613
10779
  gl.setRenderTarget(nextTarget);
10614
10780
  gl.clear();
@@ -11158,12 +11324,12 @@ function Scenes({
11158
11324
  // src/hotspot/image-hotspot.tsx
11159
11325
  var import_fiber22 = require("@react-three/fiber");
11160
11326
  var import_react43 = require("react");
11161
- var import_three25 = require("three");
11327
+ var import_three26 = require("three");
11162
11328
 
11163
11329
  // src/hotspot/hotspot-anchor.tsx
11164
11330
  var import_fiber21 = require("@react-three/fiber");
11165
11331
  var import_react42 = require("react");
11166
- var import_three23 = require("three");
11332
+ var import_three24 = require("three");
11167
11333
 
11168
11334
  // src/hotspot/hotspot-tooltip.tsx
11169
11335
  var import_react40 = require("react");
@@ -11172,7 +11338,7 @@ var import_react40 = require("react");
11172
11338
  var import_fiber19 = require("@react-three/fiber");
11173
11339
  var import_react39 = require("react");
11174
11340
  var import_client = require("react-dom/client");
11175
- var import_three20 = require("three");
11341
+ var import_three21 = require("three");
11176
11342
  var import_jsx_runtime23 = require("react/jsx-runtime");
11177
11343
  function useFallbackStereoView() {
11178
11344
  const runtime = (0, import_react39.useContext)(WebVRRuntimeContext);
@@ -11195,7 +11361,7 @@ function ProjectedHtml({
11195
11361
  const { camera, gl, events, size } = (0, import_fiber19.useThree)();
11196
11362
  const group = (0, import_react39.useRef)(null);
11197
11363
  const overlay = (0, import_react39.useRef)(null);
11198
- const scratch = (0, import_react39.useRef)(new import_three20.Vector3());
11364
+ const scratch = (0, import_react39.useRef)(new import_three21.Vector3());
11199
11365
  const target = events.connected || gl.domElement.parentElement;
11200
11366
  const updatePosition = () => {
11201
11367
  const anchor = group.current;
@@ -11395,18 +11561,18 @@ function HotspotTooltip({
11395
11561
  }
11396
11562
 
11397
11563
  // src/hotspot/transform.ts
11398
- var import_three21 = require("three");
11399
- var LOCAL_FORWARD = new import_three21.Vector3(0, 0, 1);
11400
- var CAMERA_POSITION = new import_three21.Vector3();
11564
+ var import_three22 = require("three");
11565
+ var LOCAL_FORWARD = new import_three22.Vector3(0, 0, 1);
11566
+ var CAMERA_POSITION = new import_three22.Vector3();
11401
11567
  function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight, distance) {
11402
11568
  if (orientation2 === "billboard") {
11403
11569
  group.quaternion.copy(camera.quaternion);
11404
11570
  } else {
11405
11571
  group.quaternion.copy(surfaceQuaternion3);
11406
11572
  }
11407
- group.rotateOnAxis(LOCAL_FORWARD, import_three21.MathUtils.degToRad(-rotation));
11408
- let scaleFactor = scaleMode === "fixed" && camera instanceof import_three21.PerspectiveCamera ? fixedScaleFactor(camera.fov, referenceFov) : 1;
11409
- if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof import_three21.PerspectiveCamera) {
11573
+ group.rotateOnAxis(LOCAL_FORWARD, import_three22.MathUtils.degToRad(-rotation));
11574
+ let scaleFactor = scaleMode === "fixed" && camera instanceof import_three22.PerspectiveCamera ? fixedScaleFactor(camera.fov, referenceFov) : 1;
11575
+ if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof import_three22.PerspectiveCamera) {
11410
11576
  group.updateWorldMatrix(true, false);
11411
11577
  CAMERA_POSITION.setFromMatrixPosition(group.matrixWorld).applyMatrix4(
11412
11578
  camera.matrixWorldInverse
@@ -11421,17 +11587,17 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
11421
11587
  group.updateMatrixWorld();
11422
11588
  }
11423
11589
  function fixedScaleFactor(cameraFov, referenceFov) {
11424
- const safeReferenceFov = import_three21.MathUtils.clamp(referenceFov, 1, 179);
11425
- return Math.tan(import_three21.MathUtils.degToRad(cameraFov) / 2) / Math.tan(import_three21.MathUtils.degToRad(safeReferenceFov) / 2);
11590
+ const safeReferenceFov = import_three22.MathUtils.clamp(referenceFov, 1, 179);
11591
+ return Math.tan(import_three22.MathUtils.degToRad(cameraFov) / 2) / Math.tan(import_three22.MathUtils.degToRad(safeReferenceFov) / 2);
11426
11592
  }
11427
11593
 
11428
11594
  // src/hotspot/hotspot-stroke-line.tsx
11429
11595
  var import_drei = require("@react-three/drei");
11430
11596
  var import_fiber20 = require("@react-three/fiber");
11431
11597
  var import_react41 = require("react");
11432
- var import_three22 = require("three");
11598
+ var import_three23 = require("three");
11433
11599
  var import_jsx_runtime25 = require("react/jsx-runtime");
11434
- var LINE_WORLD_POSITION = new import_three22.Vector3();
11600
+ var LINE_WORLD_POSITION = new import_three23.Vector3();
11435
11601
  function applyScreenSpaceDashScale(object, camera, viewportHeight) {
11436
11602
  const material = object?.material;
11437
11603
  if (!object || typeof material?.dashScale !== "number") {
@@ -11439,8 +11605,8 @@ function applyScreenSpaceDashScale(object, camera, viewportHeight) {
11439
11605
  }
11440
11606
  object.getWorldPosition(LINE_WORLD_POSITION);
11441
11607
  const depth = Math.max(camera.position.distanceTo(LINE_WORLD_POSITION), 1);
11442
- const fov = camera instanceof import_three22.PerspectiveCamera ? camera.fov : 75;
11443
- material.dashScale = viewportHeight / (2 * Math.tan(import_three22.MathUtils.degToRad(fov) * 0.5) * depth);
11608
+ const fov = camera instanceof import_three23.PerspectiveCamera ? camera.fov : 75;
11609
+ material.dashScale = viewportHeight / (2 * Math.tan(import_three23.MathUtils.degToRad(fov) * 0.5) * depth);
11444
11610
  }
11445
11611
  function resolveDash(dashSize, gapSize) {
11446
11612
  if (dashSize === void 0 || !Number.isFinite(dashSize) || dashSize <= 0) {
@@ -11513,27 +11679,27 @@ var SELECTION_BORDER_POINTS = [
11513
11679
  [-0.5, 0.5, 1e-3],
11514
11680
  [-0.5, -0.5, 1e-3]
11515
11681
  ];
11516
- var TOOLTIP_WORLD_BOX = new import_three23.Box3();
11517
- var TOOLTIP_LOCAL_BOX = new import_three23.Box3();
11518
- var TOOLTIP_CORNER = new import_three23.Vector3();
11519
- var TOOLTIP_INVERSE = new import_three23.Matrix4();
11520
- var TOOLTIP_WORLD_CORNER = new import_three23.Vector3();
11521
- var TOOLTIP_PROJECTED = new import_three23.Vector3();
11522
- var TOOLTIP_RAY_ORIGIN = new import_three23.Vector3();
11523
- var TOOLTIP_RAY_FAR = new import_three23.Vector3();
11524
- var TOOLTIP_RAY_DIRECTION = new import_three23.Vector3();
11525
- var TOOLTIP_RAY = new import_three23.Ray();
11526
- var TOOLTIP_PLANE = new import_three23.Plane();
11527
- var TOOLTIP_INTERSECTION = new import_three23.Vector3();
11528
- var TOOLTIP_PLANE_NORMAL = new import_three23.Vector3();
11529
- var TOOLTIP_PLANE_POINT = new import_three23.Vector3();
11682
+ var TOOLTIP_WORLD_BOX = new import_three24.Box3();
11683
+ var TOOLTIP_LOCAL_BOX = new import_three24.Box3();
11684
+ var TOOLTIP_CORNER = new import_three24.Vector3();
11685
+ var TOOLTIP_INVERSE = new import_three24.Matrix4();
11686
+ var TOOLTIP_WORLD_CORNER = new import_three24.Vector3();
11687
+ var TOOLTIP_PROJECTED = new import_three24.Vector3();
11688
+ var TOOLTIP_RAY_ORIGIN = new import_three24.Vector3();
11689
+ var TOOLTIP_RAY_FAR = new import_three24.Vector3();
11690
+ var TOOLTIP_RAY_DIRECTION = new import_three24.Vector3();
11691
+ var TOOLTIP_RAY = new import_three24.Ray();
11692
+ var TOOLTIP_PLANE = new import_three24.Plane();
11693
+ var TOOLTIP_INTERSECTION = new import_three24.Vector3();
11694
+ var TOOLTIP_PLANE_NORMAL = new import_three24.Vector3();
11695
+ var TOOLTIP_PLANE_POINT = new import_three24.Vector3();
11530
11696
  var HOTSPOT_MODE_RENDERING = {
11531
11697
  surface: { orientation: "surface", placement: "surface" },
11532
11698
  billboard: { orientation: "billboard", placement: "floating" }
11533
11699
  };
11534
11700
  function angularSizeToWorldSize(size, radius) {
11535
- const safeSize = Number.isFinite(size) ? import_three23.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
11536
- return 2 * radius * Math.tan(import_three23.MathUtils.degToRad(safeSize) / 2);
11701
+ const safeSize = Number.isFinite(size) ? import_three24.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
11702
+ return 2 * radius * Math.tan(import_three24.MathUtils.degToRad(safeSize) / 2);
11537
11703
  }
11538
11704
  function resolveScale(scale) {
11539
11705
  return Number.isFinite(scale) && scale > 0 ? scale : 1;
@@ -11546,39 +11712,39 @@ function resolveDistance(placement, distance, width, height) {
11546
11712
  if (!Number.isFinite(distance)) {
11547
11713
  return DEFAULT_FLOATING_DISTANCE;
11548
11714
  }
11549
- return import_three23.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
11715
+ return import_three24.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
11550
11716
  }
11551
11717
  function maximumHotspotDistance(width, height) {
11552
- const safeWidth = import_three23.MathUtils.clamp(
11718
+ const safeWidth = import_three24.MathUtils.clamp(
11553
11719
  Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
11554
11720
  MIN_ANGULAR_SIZE,
11555
11721
  MAX_ANGULAR_SIZE
11556
11722
  );
11557
- const safeHeight = import_three23.MathUtils.clamp(
11723
+ const safeHeight = import_three24.MathUtils.clamp(
11558
11724
  Math.abs(Number.isFinite(height) ? height : MIN_ANGULAR_SIZE),
11559
11725
  MIN_ANGULAR_SIZE,
11560
11726
  MAX_ANGULAR_SIZE
11561
11727
  );
11562
11728
  const cornerFactor = Math.hypot(
11563
11729
  1,
11564
- Math.tan(import_three23.MathUtils.degToRad(safeWidth) / 2),
11565
- Math.tan(import_three23.MathUtils.degToRad(safeHeight) / 2)
11730
+ Math.tan(import_three24.MathUtils.degToRad(safeWidth) / 2),
11731
+ Math.tan(import_three24.MathUtils.degToRad(safeHeight) / 2)
11566
11732
  );
11567
11733
  return (PANORAMA_RADIUS - PANORAMA_SURFACE_INSET) / cornerFactor;
11568
11734
  }
11569
11735
  function createSurfaceQuaternion(position) {
11570
11736
  const outward = panoPositionToVector3(position).normalize();
11571
11737
  const inward = outward.clone().negate();
11572
- const pitch = import_three23.MathUtils.degToRad(position.pitch);
11573
- const yaw = import_three23.MathUtils.degToRad(position.yaw);
11574
- const localUp = new import_three23.Vector3(
11738
+ const pitch = import_three24.MathUtils.degToRad(position.pitch);
11739
+ const yaw = import_three24.MathUtils.degToRad(position.yaw);
11740
+ const localUp = new import_three24.Vector3(
11575
11741
  -Math.sin(pitch) * Math.sin(yaw),
11576
11742
  Math.cos(pitch),
11577
11743
  Math.sin(pitch) * Math.cos(yaw)
11578
11744
  ).normalize();
11579
11745
  const localRight = localUp.clone().cross(inward).normalize();
11580
- const basis = new import_three23.Matrix4().makeBasis(localRight, localUp, inward);
11581
- return new import_three23.Quaternion().setFromRotationMatrix(basis);
11746
+ const basis = new import_three24.Matrix4().makeBasis(localRight, localUp, inward);
11747
+ return new import_three24.Quaternion().setFromRotationMatrix(basis);
11582
11748
  }
11583
11749
  function makeInteractionEvent(id, position, event) {
11584
11750
  return {
@@ -11591,7 +11757,7 @@ function makeInteractionEvent(id, position, event) {
11591
11757
  function angularDistance(a, b) {
11592
11758
  const aVector = panoPositionToVector3(a);
11593
11759
  const bVector = panoPositionToVector3(b);
11594
- return import_three23.MathUtils.radToDeg(aVector.angleTo(bVector));
11760
+ return import_three24.MathUtils.radToDeg(aVector.angleTo(bVector));
11595
11761
  }
11596
11762
  function isTooltipOpen(trigger, hovered, focused, pinned) {
11597
11763
  switch (trigger) {
@@ -11868,8 +12034,8 @@ function HotspotAnchor({
11868
12034
  const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
11869
12035
  const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
11870
12036
  const focusGeometry = (0, import_react42.useMemo)(() => {
11871
- const planeGeometry = new import_three23.PlaneGeometry(1, 1);
11872
- const geometry = new import_three23.EdgesGeometry(planeGeometry);
12037
+ const planeGeometry = new import_three24.PlaneGeometry(1, 1);
12038
+ const geometry = new import_three24.EdgesGeometry(planeGeometry);
11873
12039
  planeGeometry.dispose();
11874
12040
  return geometry;
11875
12041
  }, []);
@@ -12185,10 +12351,10 @@ function HotspotAnchor({
12185
12351
  }
12186
12352
 
12187
12353
  // src/hotspot/hotspot-plane.tsx
12188
- var import_three24 = require("three");
12354
+ var import_three25 = require("three");
12189
12355
  var import_jsx_runtime27 = require("react/jsx-runtime");
12190
12356
  var HOTSPOT_ALPHA_CUTOFF = 0.05;
12191
- var SAMPLE_UV = new import_three24.Vector2();
12357
+ var SAMPLE_UV = new import_three25.Vector2();
12192
12358
  var RAYCAST_HITS = [];
12193
12359
  var IMAGE_DATA_CACHE = /* @__PURE__ */ new WeakMap();
12194
12360
  function clampOpacity(opacity) {
@@ -12262,8 +12428,8 @@ function sampleTextureAlpha(texture, u, v) {
12262
12428
  }
12263
12429
  function hotspotPlaneRaycast(raycaster, intersects2) {
12264
12430
  const material = Array.isArray(this.material) ? this.material[0] : this.material;
12265
- if (!(material instanceof import_three24.MeshBasicMaterial)) {
12266
- import_three24.Mesh.prototype.raycast.call(this, raycaster, intersects2);
12431
+ if (!(material instanceof import_three25.MeshBasicMaterial)) {
12432
+ import_three25.Mesh.prototype.raycast.call(this, raycaster, intersects2);
12267
12433
  return;
12268
12434
  }
12269
12435
  const cutoff = Math.max(material.alphaTest, HOTSPOT_ALPHA_CUTOFF);
@@ -12271,7 +12437,7 @@ function hotspotPlaneRaycast(raycaster, intersects2) {
12271
12437
  return;
12272
12438
  }
12273
12439
  RAYCAST_HITS.length = 0;
12274
- import_three24.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
12440
+ import_three25.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
12275
12441
  const map = material.map;
12276
12442
  for (const hit of RAYCAST_HITS) {
12277
12443
  if (!map || !hit.uv) {
@@ -12297,7 +12463,7 @@ function HotspotPlane({
12297
12463
  alphaTest: HOTSPOT_ALPHA_CUTOFF,
12298
12464
  map,
12299
12465
  opacity: map ? clampOpacity(opacity) : 0,
12300
- side: import_three24.DoubleSide,
12466
+ side: import_three25.DoubleSide,
12301
12467
  toneMapped: false,
12302
12468
  transparent: true
12303
12469
  }
@@ -12322,7 +12488,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
12322
12488
  active = false;
12323
12489
  };
12324
12490
  }
12325
- const loader = new import_three25.TextureLoader();
12491
+ const loader = new import_three26.TextureLoader();
12326
12492
  loader.load(
12327
12493
  src,
12328
12494
  (loadedTexture) => {
@@ -12330,11 +12496,11 @@ function useHotspotImageTexture(src, onLoad, onError) {
12330
12496
  loadedTexture.dispose();
12331
12497
  return;
12332
12498
  }
12333
- loadedTexture.colorSpace = import_three25.SRGBColorSpace;
12334
- loadedTexture.wrapS = import_three25.ClampToEdgeWrapping;
12335
- loadedTexture.wrapT = import_three25.ClampToEdgeWrapping;
12336
- loadedTexture.magFilter = import_three25.LinearFilter;
12337
- loadedTexture.minFilter = import_three25.LinearMipmapLinearFilter;
12499
+ loadedTexture.colorSpace = import_three26.SRGBColorSpace;
12500
+ loadedTexture.wrapS = import_three26.ClampToEdgeWrapping;
12501
+ loadedTexture.wrapT = import_three26.ClampToEdgeWrapping;
12502
+ loadedTexture.magFilter = import_three26.LinearFilter;
12503
+ loadedTexture.minFilter = import_three26.LinearMipmapLinearFilter;
12338
12504
  loadedTexture.generateMipmaps = true;
12339
12505
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
12340
12506
  loadedTexture.needsUpdate = true;
@@ -12375,7 +12541,7 @@ function ImageHotspot({
12375
12541
 
12376
12542
  // src/hotspot/graphic-hotspot.tsx
12377
12543
  var import_react44 = require("react");
12378
- var import_three26 = require("three");
12544
+ var import_three27 = require("three");
12379
12545
  var import_jsx_runtime29 = require("react/jsx-runtime");
12380
12546
  var GRAPHIC_TEXTURE_SIZE = 512;
12381
12547
  function resolveStrokeWidth(value) {
@@ -12554,12 +12720,12 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
12554
12720
  throw new Error("Canvas 2D is unavailable for this graphic hotspot.");
12555
12721
  }
12556
12722
  drawGraphic(context, graphic, aspectWidth, aspectHeight);
12557
- const texture = new import_three26.CanvasTexture(canvas);
12558
- texture.colorSpace = import_three26.SRGBColorSpace;
12559
- texture.wrapS = import_three26.ClampToEdgeWrapping;
12560
- texture.wrapT = import_three26.ClampToEdgeWrapping;
12561
- texture.magFilter = import_three26.LinearFilter;
12562
- texture.minFilter = import_three26.LinearMipmapLinearFilter;
12723
+ const texture = new import_three27.CanvasTexture(canvas);
12724
+ texture.colorSpace = import_three27.SRGBColorSpace;
12725
+ texture.wrapS = import_three27.ClampToEdgeWrapping;
12726
+ texture.wrapT = import_three27.ClampToEdgeWrapping;
12727
+ texture.magFilter = import_three27.LinearFilter;
12728
+ texture.minFilter = import_three27.LinearMipmapLinearFilter;
12563
12729
  texture.generateMipmaps = true;
12564
12730
  texture.needsUpdate = true;
12565
12731
  return texture;
@@ -12610,7 +12776,7 @@ function GraphicHotspot(props) {
12610
12776
  // src/hotspot/sequence-hotspot.tsx
12611
12777
  var import_fiber23 = require("@react-three/fiber");
12612
12778
  var import_react45 = require("react");
12613
- var import_three27 = require("three");
12779
+ var import_three28 = require("three");
12614
12780
  var import_jsx_runtime30 = require("react/jsx-runtime");
12615
12781
  var DEFAULT_SEQUENCE_FPS = 12;
12616
12782
  function resolveFps(value) {
@@ -12640,7 +12806,7 @@ function useSpriteTexture({
12640
12806
  active = false;
12641
12807
  };
12642
12808
  }
12643
- const loader = new import_three27.TextureLoader();
12809
+ const loader = new import_three28.TextureLoader();
12644
12810
  loader.load(
12645
12811
  src,
12646
12812
  (loadedTexture) => {
@@ -12648,11 +12814,11 @@ function useSpriteTexture({
12648
12814
  loadedTexture.dispose();
12649
12815
  return;
12650
12816
  }
12651
- loadedTexture.colorSpace = import_three27.SRGBColorSpace;
12652
- loadedTexture.wrapS = import_three27.ClampToEdgeWrapping;
12653
- loadedTexture.wrapT = import_three27.ClampToEdgeWrapping;
12654
- loadedTexture.magFilter = import_three27.LinearFilter;
12655
- loadedTexture.minFilter = import_three27.LinearMipmapLinearFilter;
12817
+ loadedTexture.colorSpace = import_three28.SRGBColorSpace;
12818
+ loadedTexture.wrapS = import_three28.ClampToEdgeWrapping;
12819
+ loadedTexture.wrapT = import_three28.ClampToEdgeWrapping;
12820
+ loadedTexture.magFilter = import_three28.LinearFilter;
12821
+ loadedTexture.minFilter = import_three28.LinearMipmapLinearFilter;
12656
12822
  loadedTexture.generateMipmaps = true;
12657
12823
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
12658
12824
  loadedTexture.needsUpdate = true;
@@ -12793,7 +12959,7 @@ function SequenceHotspot({
12793
12959
  // src/hotspot/video-hotspot.tsx
12794
12960
  var import_fiber24 = require("@react-three/fiber");
12795
12961
  var import_react46 = require("react");
12796
- var import_three28 = require("three");
12962
+ var import_three29 = require("three");
12797
12963
 
12798
12964
  // src/video/inline-playback.ts
12799
12965
  var INLINE_VIDEO_ATTRIBUTES = [
@@ -12866,7 +13032,7 @@ function usePosterTexture(id, poster, onError) {
12866
13032
  active = false;
12867
13033
  };
12868
13034
  }
12869
- const loader = new import_three28.TextureLoader();
13035
+ const loader = new import_three29.TextureLoader();
12870
13036
  loader.load(
12871
13037
  poster,
12872
13038
  (loadedTexture) => {
@@ -12874,11 +13040,11 @@ function usePosterTexture(id, poster, onError) {
12874
13040
  loadedTexture.dispose();
12875
13041
  return;
12876
13042
  }
12877
- loadedTexture.colorSpace = import_three28.SRGBColorSpace;
12878
- loadedTexture.wrapS = import_three28.ClampToEdgeWrapping;
12879
- loadedTexture.wrapT = import_three28.ClampToEdgeWrapping;
12880
- loadedTexture.magFilter = import_three28.LinearFilter;
12881
- loadedTexture.minFilter = import_three28.LinearMipmapLinearFilter;
13043
+ loadedTexture.colorSpace = import_three29.SRGBColorSpace;
13044
+ loadedTexture.wrapS = import_three29.ClampToEdgeWrapping;
13045
+ loadedTexture.wrapT = import_three29.ClampToEdgeWrapping;
13046
+ loadedTexture.magFilter = import_three29.LinearFilter;
13047
+ loadedTexture.minFilter = import_three29.LinearMipmapLinearFilter;
12882
13048
  loadedTexture.generateMipmaps = true;
12883
13049
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
12884
13050
  loadedTexture.needsUpdate = true;
@@ -12933,12 +13099,12 @@ function useVideoResource({
12933
13099
  }
12934
13100
  applyInlineVideoPlayback(video, playsInline ?? true);
12935
13101
  video.poster = poster ?? "";
12936
- const texture = new import_three28.VideoTexture(video);
12937
- texture.colorSpace = import_three28.SRGBColorSpace;
12938
- texture.wrapS = import_three28.ClampToEdgeWrapping;
12939
- texture.wrapT = import_three28.ClampToEdgeWrapping;
12940
- texture.magFilter = import_three28.LinearFilter;
12941
- texture.minFilter = import_three28.LinearFilter;
13102
+ const texture = new import_three29.VideoTexture(video);
13103
+ texture.colorSpace = import_three29.SRGBColorSpace;
13104
+ texture.wrapS = import_three29.ClampToEdgeWrapping;
13105
+ texture.wrapT = import_three29.ClampToEdgeWrapping;
13106
+ texture.magFilter = import_three29.LinearFilter;
13107
+ texture.minFilter = import_three29.LinearFilter;
12942
13108
  texture.generateMipmaps = false;
12943
13109
  const notifyState = (state) => {
12944
13110
  if (active) {
@@ -13077,13 +13243,13 @@ function VideoHotspot({
13077
13243
  // src/hotspot/audio-hotspot.tsx
13078
13244
  var import_fiber25 = require("@react-three/fiber");
13079
13245
  var import_react47 = require("react");
13080
- var import_three30 = require("three");
13246
+ var import_three31 = require("three");
13081
13247
 
13082
13248
  // src/hotspot/audio-spatial.ts
13083
- var import_three29 = require("three");
13084
- var LOOK_DIR = new import_three29.Vector3();
13085
- var SOURCE_DIR = new import_three29.Vector3();
13086
- var RIGHT_DIR = new import_three29.Vector3();
13249
+ var import_three30 = require("three");
13250
+ var LOOK_DIR = new import_three30.Vector3();
13251
+ var SOURCE_DIR = new import_three30.Vector3();
13252
+ var RIGHT_DIR = new import_three30.Vector3();
13087
13253
  function clampAudioVolume(volume) {
13088
13254
  if (!Number.isFinite(volume)) {
13089
13255
  return 1;
@@ -13108,11 +13274,11 @@ function lookRangeGain(angleDegrees, range) {
13108
13274
  function audioSpatialFromView(camera, position, range) {
13109
13275
  camera.getWorldDirection(LOOK_DIR);
13110
13276
  SOURCE_DIR.copy(panoPositionToVector3(position)).normalize();
13111
- const angleDegrees = import_three29.MathUtils.radToDeg(
13112
- Math.acos(import_three29.MathUtils.clamp(LOOK_DIR.dot(SOURCE_DIR), -1, 1))
13277
+ const angleDegrees = import_three30.MathUtils.radToDeg(
13278
+ Math.acos(import_three30.MathUtils.clamp(LOOK_DIR.dot(SOURCE_DIR), -1, 1))
13113
13279
  );
13114
13280
  RIGHT_DIR.set(1, 0, 0).applyQuaternion(camera.quaternion);
13115
- const pan = import_three29.MathUtils.clamp(
13281
+ const pan = import_three30.MathUtils.clamp(
13116
13282
  Math.atan2(SOURCE_DIR.dot(RIGHT_DIR), SOURCE_DIR.dot(LOOK_DIR)) / (Math.PI / 2),
13117
13283
  -1,
13118
13284
  1
@@ -13177,12 +13343,12 @@ function createSpeakerTexture(state) {
13177
13343
  return exhaustive;
13178
13344
  }
13179
13345
  }
13180
- const texture = new import_three30.CanvasTexture(canvas);
13181
- texture.colorSpace = import_three30.SRGBColorSpace;
13182
- texture.wrapS = import_three30.ClampToEdgeWrapping;
13183
- texture.wrapT = import_three30.ClampToEdgeWrapping;
13184
- texture.magFilter = import_three30.LinearFilter;
13185
- texture.minFilter = import_three30.LinearMipmapLinearFilter;
13346
+ const texture = new import_three31.CanvasTexture(canvas);
13347
+ texture.colorSpace = import_three31.SRGBColorSpace;
13348
+ texture.wrapS = import_three31.ClampToEdgeWrapping;
13349
+ texture.wrapT = import_three31.ClampToEdgeWrapping;
13350
+ texture.magFilter = import_three31.LinearFilter;
13351
+ texture.minFilter = import_three31.LinearMipmapLinearFilter;
13186
13352
  texture.generateMipmaps = true;
13187
13353
  texture.needsUpdate = true;
13188
13354
  return texture;
@@ -13217,7 +13383,7 @@ function useIconTexture(icon, enabled, onError, id) {
13217
13383
  active = false;
13218
13384
  };
13219
13385
  }
13220
- const loader = new import_three30.TextureLoader();
13386
+ const loader = new import_three31.TextureLoader();
13221
13387
  loader.load(
13222
13388
  icon,
13223
13389
  (loadedTexture) => {
@@ -13225,11 +13391,11 @@ function useIconTexture(icon, enabled, onError, id) {
13225
13391
  loadedTexture.dispose();
13226
13392
  return;
13227
13393
  }
13228
- loadedTexture.colorSpace = import_three30.SRGBColorSpace;
13229
- loadedTexture.wrapS = import_three30.ClampToEdgeWrapping;
13230
- loadedTexture.wrapT = import_three30.ClampToEdgeWrapping;
13231
- loadedTexture.magFilter = import_three30.LinearFilter;
13232
- loadedTexture.minFilter = import_three30.LinearMipmapLinearFilter;
13394
+ loadedTexture.colorSpace = import_three31.SRGBColorSpace;
13395
+ loadedTexture.wrapS = import_three31.ClampToEdgeWrapping;
13396
+ loadedTexture.wrapT = import_three31.ClampToEdgeWrapping;
13397
+ loadedTexture.magFilter = import_three31.LinearFilter;
13398
+ loadedTexture.minFilter = import_three31.LinearMipmapLinearFilter;
13233
13399
  loadedTexture.generateMipmaps = true;
13234
13400
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
13235
13401
  loadedTexture.needsUpdate = true;
@@ -13420,7 +13586,7 @@ function AudioHotspot({
13420
13586
  // src/hotspot/text-hotspot.tsx
13421
13587
  var import_react48 = require("react");
13422
13588
  var import_fiber26 = require("@react-three/fiber");
13423
- var import_three31 = require("three");
13589
+ var import_three32 = require("three");
13424
13590
  var import_jsx_runtime33 = require("react/jsx-runtime");
13425
13591
  var TEXT_TEXTURE_LONG_SIDE = 1024;
13426
13592
  var TEXT_RASTER_SUPERSAMPLE = 2;
@@ -13492,7 +13658,7 @@ function projectedDevicePixels(angleDeg, fovDeg, viewportHeight) {
13492
13658
  }
13493
13659
  const fov = Math.min(179, Math.max(1, resolvePositive(fovDeg, DEFAULT_REFERENCE_FOV2)));
13494
13660
  const angle = Math.min(179, Math.max(0.01, Math.abs(angleDeg)));
13495
- return Math.tan(import_three31.MathUtils.degToRad(angle) / 2) / Math.tan(import_three31.MathUtils.degToRad(fov) / 2) * viewportHeight;
13661
+ return Math.tan(import_three32.MathUtils.degToRad(angle) / 2) / Math.tan(import_three32.MathUtils.degToRad(fov) / 2) * viewportHeight;
13496
13662
  }
13497
13663
  function snapRasterLongSide(screenLong, layoutLong) {
13498
13664
  if (!(screenLong > 0)) {
@@ -13677,12 +13843,12 @@ function createTextTexture(text, width, height, style, rasterLong) {
13677
13843
  fontSize: resolvePositive(style.fontSize, DEFAULT_FONT_SIZE) * scale,
13678
13844
  strokeWidth: Number.isFinite(style.strokeWidth) ? style.strokeWidth * scale : style.strokeWidth
13679
13845
  });
13680
- const texture = new import_three31.CanvasTexture(canvas);
13681
- texture.colorSpace = import_three31.SRGBColorSpace;
13682
- texture.wrapS = import_three31.ClampToEdgeWrapping;
13683
- texture.wrapT = import_three31.ClampToEdgeWrapping;
13684
- texture.magFilter = import_three31.LinearFilter;
13685
- texture.minFilter = import_three31.LinearFilter;
13846
+ const texture = new import_three32.CanvasTexture(canvas);
13847
+ texture.colorSpace = import_three32.SRGBColorSpace;
13848
+ texture.wrapS = import_three32.ClampToEdgeWrapping;
13849
+ texture.wrapT = import_three32.ClampToEdgeWrapping;
13850
+ texture.magFilter = import_three32.LinearFilter;
13851
+ texture.minFilter = import_three32.LinearFilter;
13686
13852
  texture.generateMipmaps = false;
13687
13853
  texture.needsUpdate = true;
13688
13854
  return texture;
@@ -13694,7 +13860,7 @@ function useRasterLongSide(width, height, scale, scaleMode, referenceFov) {
13694
13860
  const measure = () => {
13695
13861
  const pixelRatio = getPixelRatio();
13696
13862
  const viewportHeight = size.height * (Number.isFinite(pixelRatio) && pixelRatio > 0 ? pixelRatio : 1);
13697
- const cameraFov = camera instanceof import_three31.PerspectiveCamera ? camera.fov : DEFAULT_REFERENCE_FOV2;
13863
+ const cameraFov = camera instanceof import_three32.PerspectiveCamera ? camera.fov : DEFAULT_REFERENCE_FOV2;
13698
13864
  const screenLong = Math.max(
13699
13865
  projectedDevicePixels(
13700
13866
  width * resolveScale2(scale),
@@ -13846,7 +14012,7 @@ function TextHotspot({
13846
14012
 
13847
14013
  // src/hotspot/iframe-hotspot.tsx
13848
14014
  var import_drei2 = require("@react-three/drei");
13849
- var import_three32 = require("three");
14015
+ var import_three33 = require("three");
13850
14016
  var import_jsx_runtime34 = require("react/jsx-runtime");
13851
14017
  var IFRAME_LONG_SIDE = 800;
13852
14018
  var CSS3D_DISTANCE_FACTOR = 400;
@@ -13920,7 +14086,7 @@ function IframeHotspot({
13920
14086
  {
13921
14087
  depthWrite: false,
13922
14088
  opacity: 0,
13923
- side: import_three32.DoubleSide,
14089
+ side: import_three33.DoubleSide,
13924
14090
  toneMapped: false,
13925
14091
  transparent: true
13926
14092
  }
@@ -13964,7 +14130,7 @@ function IframeHotspot({
13964
14130
 
13965
14131
  // src/hotspot/polygon-hotspot.tsx
13966
14132
  var import_react49 = require("react");
13967
- var import_three33 = require("three");
14133
+ var import_three34 = require("three");
13968
14134
  var import_jsx_runtime35 = require("react/jsx-runtime");
13969
14135
  var POLYGON_RADIUS = 990;
13970
14136
  var MAX_FILL_SEGMENT_DEGREES = 7;
@@ -14000,7 +14166,7 @@ function intersects(a, b, c, d) {
14000
14166
  }
14001
14167
  function hasSelfIntersection(vertices) {
14002
14168
  const points = vertices.map(
14003
- (vertex) => new import_three33.Vector2(vertex.unwrappedYaw, vertex.pitch)
14169
+ (vertex) => new import_three34.Vector2(vertex.unwrappedYaw, vertex.pitch)
14004
14170
  );
14005
14171
  for (let index = 0; index < points.length; index += 1) {
14006
14172
  const nextIndex = (index + 1) % points.length;
@@ -14037,7 +14203,7 @@ function polygonContainsDirection(vertices, direction) {
14037
14203
  }
14038
14204
  function fitsHemisphere(vertices) {
14039
14205
  const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
14040
- const candidates = [new import_three33.Vector3()];
14206
+ const candidates = [new import_three34.Vector3()];
14041
14207
  for (const direction of directions) {
14042
14208
  candidates[0].add(direction);
14043
14209
  candidates.push(direction.clone());
@@ -14061,7 +14227,7 @@ function validatePolygonVertices(vertices) {
14061
14227
  if (hasSelfIntersection(unwrapped)) {
14062
14228
  issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
14063
14229
  }
14064
- if (polygonContainsDirection(normalized, new import_three33.Vector3(0, 1, 0)) || polygonContainsDirection(normalized, new import_three33.Vector3(0, -1, 0))) {
14230
+ if (polygonContainsDirection(normalized, new import_three34.Vector3(0, 1, 0)) || polygonContainsDirection(normalized, new import_three34.Vector3(0, -1, 0))) {
14065
14231
  issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
14066
14232
  }
14067
14233
  if (!fitsHemisphere(normalized)) {
@@ -14072,7 +14238,7 @@ function validatePolygonVertices(vertices) {
14072
14238
  function polygonCenter(vertices) {
14073
14239
  const sum = vertices.reduce(
14074
14240
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14075
- new import_three33.Vector3()
14241
+ new import_three34.Vector3()
14076
14242
  );
14077
14243
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14078
14244
  }
@@ -14081,20 +14247,20 @@ function surfaceQuaternion(position) {
14081
14247
  const inward = outward.clone().negate();
14082
14248
  const pitch = position.pitch * Math.PI / 180;
14083
14249
  const yaw = position.yaw * Math.PI / 180;
14084
- const localUp = new import_three33.Vector3(
14250
+ const localUp = new import_three34.Vector3(
14085
14251
  -Math.sin(pitch) * Math.sin(yaw),
14086
14252
  Math.cos(pitch),
14087
14253
  Math.sin(pitch) * Math.cos(yaw)
14088
14254
  ).normalize();
14089
- return new import_three33.Quaternion().setFromRotationMatrix(
14090
- new import_three33.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14255
+ return new import_three34.Quaternion().setFromRotationMatrix(
14256
+ new import_three34.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14091
14257
  );
14092
14258
  }
14093
14259
  function makeWorldToLocal(center) {
14094
- return new import_three33.Matrix4().compose(
14260
+ return new import_three34.Matrix4().compose(
14095
14261
  panoPositionToVector3(center, POLYGON_RADIUS),
14096
14262
  surfaceQuaternion(center),
14097
- new import_three33.Vector3(1, 1, 1)
14263
+ new import_three34.Vector3(1, 1, 1)
14098
14264
  ).invert();
14099
14265
  }
14100
14266
  function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
@@ -14149,8 +14315,8 @@ function addSubdividedTriangle(positions, indices, a, b, c, worldToLocal, steps)
14149
14315
  }
14150
14316
  function makeFillGeometry(vertices, center) {
14151
14317
  const unwrapped = unwrapPolygonVertices(vertices);
14152
- const contour = unwrapped.map((vertex) => new import_three33.Vector2(vertex.unwrappedYaw, vertex.pitch));
14153
- const triangles = import_three33.ShapeUtils.triangulateShape(contour, []);
14318
+ const contour = unwrapped.map((vertex) => new import_three34.Vector2(vertex.unwrappedYaw, vertex.pitch));
14319
+ const triangles = import_three34.ShapeUtils.triangulateShape(contour, []);
14154
14320
  const positions = [];
14155
14321
  const indices = [];
14156
14322
  const worldToLocal = makeWorldToLocal(center);
@@ -14166,7 +14332,7 @@ function makeFillGeometry(vertices, center) {
14166
14332
  steps
14167
14333
  );
14168
14334
  }
14169
- return new import_three33.BufferGeometry().setAttribute("position", new import_three33.Float32BufferAttribute(positions, 3)).setIndex(indices);
14335
+ return new import_three34.BufferGeometry().setAttribute("position", new import_three34.Float32BufferAttribute(positions, 3)).setIndex(indices);
14170
14336
  }
14171
14337
  function makeStrokePositions(vertices, center) {
14172
14338
  const points = [];
@@ -14296,7 +14462,7 @@ function PolygonHotspot({
14296
14462
  color: fill,
14297
14463
  depthWrite: false,
14298
14464
  opacity: Math.max(0, Math.min(fillOpacity, 1)),
14299
- side: import_three33.DoubleSide,
14465
+ side: import_three34.DoubleSide,
14300
14466
  transparent: true
14301
14467
  }
14302
14468
  ) }),
@@ -14319,7 +14485,7 @@ function PolygonHotspot({
14319
14485
 
14320
14486
  // src/hotspot/polyline-hotspot.tsx
14321
14487
  var import_react50 = require("react");
14322
- var import_three34 = require("three");
14488
+ var import_three35 = require("three");
14323
14489
  var import_jsx_runtime36 = require("react/jsx-runtime");
14324
14490
  var POLYLINE_RADIUS = 990;
14325
14491
  var MAX_SEGMENT_DEGREES = 7;
@@ -14345,29 +14511,29 @@ function unwrapVertices(vertices) {
14345
14511
  function polylineCenter(vertices) {
14346
14512
  const sum = vertices.reduce(
14347
14513
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14348
- new import_three34.Vector3()
14514
+ new import_three35.Vector3()
14349
14515
  );
14350
14516
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14351
14517
  }
14352
14518
  function surfaceQuaternion2(position) {
14353
14519
  const outward = panoPositionToVector3(position).normalize();
14354
14520
  const inward = outward.clone().negate();
14355
- const pitch = import_three34.MathUtils.degToRad(position.pitch);
14356
- const yaw = import_three34.MathUtils.degToRad(position.yaw);
14357
- const localUp = new import_three34.Vector3(
14521
+ const pitch = import_three35.MathUtils.degToRad(position.pitch);
14522
+ const yaw = import_three35.MathUtils.degToRad(position.yaw);
14523
+ const localUp = new import_three35.Vector3(
14358
14524
  -Math.sin(pitch) * Math.sin(yaw),
14359
14525
  Math.cos(pitch),
14360
14526
  Math.sin(pitch) * Math.cos(yaw)
14361
14527
  ).normalize();
14362
- return new import_three34.Quaternion().setFromRotationMatrix(
14363
- new import_three34.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14528
+ return new import_three35.Quaternion().setFromRotationMatrix(
14529
+ new import_three35.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14364
14530
  );
14365
14531
  }
14366
14532
  function makeWorldToLocal2(center) {
14367
- return new import_three34.Matrix4().compose(
14533
+ return new import_three35.Matrix4().compose(
14368
14534
  panoPositionToVector3(center, POLYLINE_RADIUS),
14369
14535
  surfaceQuaternion2(center),
14370
- new import_three34.Vector3(1, 1, 1)
14536
+ new import_three35.Vector3(1, 1, 1)
14371
14537
  ).invert();
14372
14538
  }
14373
14539
  function subdivisionSteps(vertices) {
@@ -14382,7 +14548,7 @@ function subdivisionSteps(vertices) {
14382
14548
  }
14383
14549
  return Math.min(
14384
14550
  8,
14385
- Math.max(1, Math.ceil(import_three34.MathUtils.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
14551
+ Math.max(1, Math.ceil(import_three35.MathUtils.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
14386
14552
  );
14387
14553
  }
14388
14554
  function makeLinePositions(vertices, center) {
@@ -15149,12 +15315,12 @@ var import_fiber27 = require("@react-three/fiber");
15149
15315
  var import_react54 = require("react");
15150
15316
 
15151
15317
  // src/gyro-orientation.ts
15152
- var import_three35 = require("three");
15153
- var DEVICE_FORWARD_CORRECTION = new import_three35.Quaternion().setFromAxisAngle(
15154
- new import_three35.Vector3(1, 0, 0),
15318
+ var import_three36 = require("three");
15319
+ var DEVICE_FORWARD_CORRECTION = new import_three36.Quaternion().setFromAxisAngle(
15320
+ new import_three36.Vector3(1, 0, 0),
15155
15321
  -Math.PI / 2
15156
15322
  );
15157
- var SCREEN_AXIS = new import_three35.Vector3(0, 0, 1);
15323
+ var SCREEN_AXIS = new import_three36.Vector3(0, 0, 1);
15158
15324
  function getScreenOrientationAngle() {
15159
15325
  if (typeof window === "undefined") {
15160
15326
  return 0;
@@ -15168,31 +15334,31 @@ function getScreenOrientationAngle() {
15168
15334
  }
15169
15335
  function deviceOrientationToQuaternion(sample, screenOrientation) {
15170
15336
  const alpha = Number.isFinite(sample.compassHeading) ? 360 - sample.compassHeading : sample.alpha;
15171
- const deviceEuler = new import_three35.Euler(
15172
- import_three35.MathUtils.degToRad(sample.beta),
15173
- import_three35.MathUtils.degToRad(alpha),
15174
- import_three35.MathUtils.degToRad(-sample.gamma),
15337
+ const deviceEuler = new import_three36.Euler(
15338
+ import_three36.MathUtils.degToRad(sample.beta),
15339
+ import_three36.MathUtils.degToRad(alpha),
15340
+ import_three36.MathUtils.degToRad(-sample.gamma),
15175
15341
  "YXZ"
15176
15342
  );
15177
- const screenCorrection = new import_three35.Quaternion().setFromAxisAngle(
15343
+ const screenCorrection = new import_three36.Quaternion().setFromAxisAngle(
15178
15344
  SCREEN_AXIS,
15179
- -import_three35.MathUtils.degToRad(screenOrientation)
15345
+ -import_three36.MathUtils.degToRad(screenOrientation)
15180
15346
  );
15181
- return new import_three35.Quaternion().setFromEuler(deviceEuler).multiply(DEVICE_FORWARD_CORRECTION).multiply(screenCorrection).normalize();
15347
+ return new import_three36.Quaternion().setFromEuler(deviceEuler).multiply(DEVICE_FORWARD_CORRECTION).multiply(screenCorrection).normalize();
15182
15348
  }
15183
15349
  function quaternionToGyroPose(quaternion) {
15184
- const euler = new import_three35.Euler().setFromQuaternion(quaternion, "YXZ");
15350
+ const euler = new import_three36.Euler().setFromQuaternion(quaternion, "YXZ");
15185
15351
  return {
15186
- yaw: import_three35.MathUtils.radToDeg(-euler.y),
15187
- pitch: import_three35.MathUtils.radToDeg(euler.x),
15188
- roll: import_three35.MathUtils.radToDeg(euler.z)
15352
+ yaw: import_three36.MathUtils.radToDeg(-euler.y),
15353
+ pitch: import_three36.MathUtils.radToDeg(euler.x),
15354
+ roll: import_three36.MathUtils.radToDeg(euler.z)
15189
15355
  };
15190
15356
  }
15191
15357
  function createRelativeCalibration(deviceQuaternion, yaw, pitch) {
15192
- const targetQuaternion = new import_three35.Quaternion().setFromEuler(
15193
- new import_three35.Euler(
15194
- import_three35.MathUtils.degToRad(pitch),
15195
- import_three35.MathUtils.degToRad(-yaw),
15358
+ const targetQuaternion = new import_three36.Quaternion().setFromEuler(
15359
+ new import_three36.Euler(
15360
+ import_three36.MathUtils.degToRad(pitch),
15361
+ import_three36.MathUtils.degToRad(-yaw),
15196
15362
  0,
15197
15363
  "YXZ"
15198
15364
  )
@@ -15623,9 +15789,9 @@ async function detectWebVRCapabilities() {
15623
15789
  // src/webvr/reticle.tsx
15624
15790
  var import_fiber28 = require("@react-three/fiber");
15625
15791
  var import_react55 = require("react");
15626
- var import_three36 = require("three");
15792
+ var import_three37 = require("three");
15627
15793
  var import_jsx_runtime38 = require("react/jsx-runtime");
15628
- var CENTER_NDC = new import_three36.Vector2(0, 0);
15794
+ var CENTER_NDC = new import_three37.Vector2(0, 0);
15629
15795
  var HUD_DISTANCE = 2;
15630
15796
  var RETICLE_SCALE = 1;
15631
15797
  var RETICLE_RENDER_ORDER = 1e5;
@@ -15710,8 +15876,8 @@ function WebVRReticle({
15710
15876
  }) {
15711
15877
  const groupRef = (0, import_react55.useRef)(null);
15712
15878
  const ringMeshRef = (0, import_react55.useRef)(null);
15713
- const directionRef = (0, import_react55.useRef)(new import_three36.Vector3());
15714
- const raycasterRef = (0, import_react55.useRef)(new import_three36.Raycaster());
15879
+ const directionRef = (0, import_react55.useRef)(new import_three37.Vector3());
15880
+ const raycasterRef = (0, import_react55.useRef)(new import_three37.Raycaster());
15715
15881
  const hoveredRef = (0, import_react55.useRef)(null);
15716
15882
  const dwellRef = (0, import_react55.useRef)(0);
15717
15883
  const clickedRef = (0, import_react55.useRef)(false);
@@ -15862,7 +16028,7 @@ function WebVRReticle({
15862
16028
  color: "#ffffff",
15863
16029
  depthTest: false,
15864
16030
  depthWrite: false,
15865
- side: import_three36.DoubleSide,
16031
+ side: import_three37.DoubleSide,
15866
16032
  toneMapped: false,
15867
16033
  transparent: true
15868
16034
  }
@@ -15878,7 +16044,7 @@ function WebVRReticle({
15878
16044
  // src/webvr/stereo.tsx
15879
16045
  var import_fiber29 = require("@react-three/fiber");
15880
16046
  var import_react56 = require("react");
15881
- var import_three37 = require("three");
16047
+ var import_three38 = require("three");
15882
16048
  var vertexShader = `
15883
16049
  varying vec2 vUv;
15884
16050
  void main() {
@@ -15903,26 +16069,26 @@ void main() {
15903
16069
  }
15904
16070
  `;
15905
16071
  function createDistortionResources() {
15906
- const target = new import_three37.WebGLRenderTarget(1, 1, {
16072
+ const target = new import_three38.WebGLRenderTarget(1, 1, {
15907
16073
  depthBuffer: true,
15908
16074
  stencilBuffer: false
15909
16075
  });
15910
- const geometry = new import_three37.PlaneGeometry(2, 2);
15911
- const material = new import_three37.ShaderMaterial({
16076
+ const geometry = new import_three38.PlaneGeometry(2, 2);
16077
+ const material = new import_three38.ShaderMaterial({
15912
16078
  depthTest: false,
15913
16079
  depthWrite: false,
15914
16080
  fragmentShader,
15915
16081
  uniforms: {
15916
- distortion: { value: new import_three37.Vector2() },
16082
+ distortion: { value: new import_three38.Vector2() },
15917
16083
  sourceTexture: { value: target.texture }
15918
16084
  },
15919
16085
  vertexShader
15920
16086
  });
15921
- const mesh = new import_three37.Mesh(geometry, material);
15922
- const scene = new import_three37.Scene();
16087
+ const mesh = new import_three38.Mesh(geometry, material);
16088
+ const scene = new import_three38.Scene();
15923
16089
  scene.add(mesh);
15924
16090
  return {
15925
- camera: new import_three37.OrthographicCamera(-1, 1, 1, -1, 0, 1),
16091
+ camera: new import_three38.OrthographicCamera(-1, 1, 1, -1, 0, 1),
15926
16092
  geometry,
15927
16093
  material,
15928
16094
  mesh,
@@ -15955,15 +16121,15 @@ function WebVRStereoRenderer({
15955
16121
  const runtime = (0, import_react56.useContext)(WebVRRuntimeContext);
15956
16122
  const fallbackStereoRef = (0, import_react56.useRef)(null);
15957
16123
  if (!fallbackStereoRef.current) {
15958
- fallbackStereoRef.current = new import_three37.StereoCamera();
16124
+ fallbackStereoRef.current = new import_three38.StereoCamera();
15959
16125
  }
15960
16126
  const stereo = runtime?.stereoView.stereo ?? fallbackStereoRef.current;
15961
16127
  const stereoRef = (0, import_react56.useRef)(stereo);
15962
16128
  stereoRef.current = stereo;
15963
16129
  const resources = (0, import_react56.useMemo)(createDistortionResources, []);
15964
- const drawingSizeRef = (0, import_react56.useRef)(new import_three37.Vector2());
15965
- const viewportRef = (0, import_react56.useRef)(new import_three37.Vector4());
15966
- const scissorRef = (0, import_react56.useRef)(new import_three37.Vector4());
16130
+ const drawingSizeRef = (0, import_react56.useRef)(new import_three38.Vector2());
16131
+ const viewportRef = (0, import_react56.useRef)(new import_three38.Vector4());
16132
+ const scissorRef = (0, import_react56.useRef)(new import_three38.Vector4());
15967
16133
  const originalFovRef = (0, import_react56.useRef)(null);
15968
16134
  const stereoActiveRef = (0, import_react56.useRef)(false);
15969
16135
  const profileRef = (0, import_react56.useRef)(profile);
@@ -15981,7 +16147,7 @@ function WebVRStereoRenderer({
15981
16147
  (0, import_react56.useEffect)(() => {
15982
16148
  const originalRender = gl.render.bind(gl);
15983
16149
  gl.render = (sceneToRender, cameraToRender) => {
15984
- if (!stereoActiveRef.current || !(cameraToRender instanceof import_three37.PerspectiveCamera)) {
16150
+ if (!stereoActiveRef.current || !(cameraToRender instanceof import_three38.PerspectiveCamera)) {
15985
16151
  originalRender(sceneToRender, cameraToRender);
15986
16152
  return;
15987
16153
  }
@@ -16056,7 +16222,7 @@ function WebVRStereoRenderer({
16056
16222
  if (runtime) {
16057
16223
  runtime.stereoView.active = fallback;
16058
16224
  }
16059
- if (fallback && camera instanceof import_three37.PerspectiveCamera) {
16225
+ if (fallback && camera instanceof import_three38.PerspectiveCamera) {
16060
16226
  syncStereoCameras(
16061
16227
  stereoRef.current,
16062
16228
  camera,
@@ -16067,7 +16233,7 @@ function WebVRStereoRenderer({
16067
16233
  );
16068
16234
  return;
16069
16235
  }
16070
- if (originalFovRef.current !== null && camera instanceof import_three37.PerspectiveCamera) {
16236
+ if (originalFovRef.current !== null && camera instanceof import_three38.PerspectiveCamera) {
16071
16237
  camera.fov = originalFovRef.current;
16072
16238
  camera.updateProjectionMatrix();
16073
16239
  originalFovRef.current = null;
@@ -16749,7 +16915,7 @@ function usePanoViewer() {
16749
16915
  // src/video/pano-video.tsx
16750
16916
  var import_fiber31 = require("@react-three/fiber");
16751
16917
  var import_react61 = require("react");
16752
- var import_three38 = require("three");
16918
+ var import_three39 = require("three");
16753
16919
  var import_jsx_runtime40 = require("react/jsx-runtime");
16754
16920
  var EMPTY_TRACKS = [];
16755
16921
  var EMPTY_RATES = DEFAULT_PANO_VIDEO_PLAYBACK_RATES;
@@ -16826,8 +16992,8 @@ function findTextTrack(video, tracks, trackId) {
16826
16992
  return list.length > 0 ? list[0] : null;
16827
16993
  }
16828
16994
  function applyEquirectangularLayout(texture, anisotropy) {
16829
- texture.colorSpace = import_three38.SRGBColorSpace;
16830
- texture.wrapS = import_three38.RepeatWrapping;
16995
+ texture.colorSpace = import_three39.SRGBColorSpace;
16996
+ texture.wrapS = import_three39.RepeatWrapping;
16831
16997
  texture.repeat.x = -1;
16832
16998
  texture.offset.x = 1;
16833
16999
  texture.anisotropy = anisotropy;
@@ -16846,7 +17012,7 @@ function usePosterTexture2(poster, onError) {
16846
17012
  active = false;
16847
17013
  };
16848
17014
  }
16849
- const loader = new import_three38.TextureLoader();
17015
+ const loader = new import_three39.TextureLoader();
16850
17016
  loader.load(
16851
17017
  poster,
16852
17018
  (loadedTexture) => {
@@ -16858,9 +17024,9 @@ function usePosterTexture2(poster, onError) {
16858
17024
  loadedTexture,
16859
17025
  gl.capabilities.getMaxAnisotropy()
16860
17026
  );
16861
- loadedTexture.wrapT = import_three38.RepeatWrapping;
16862
- loadedTexture.magFilter = import_three38.LinearFilter;
16863
- loadedTexture.minFilter = import_three38.LinearMipmapLinearFilter;
17027
+ loadedTexture.wrapT = import_three39.RepeatWrapping;
17028
+ loadedTexture.magFilter = import_three39.LinearFilter;
17029
+ loadedTexture.minFilter = import_three39.LinearMipmapLinearFilter;
16864
17030
  loadedTexture.generateMipmaps = true;
16865
17031
  setTexture(loadedTexture);
16866
17032
  },
@@ -17014,10 +17180,10 @@ function PanoVideo({
17014
17180
  video.muted = true;
17015
17181
  applyInlineVideoPlayback(video, true);
17016
17182
  video.preload = "metadata";
17017
- const texture = new import_three38.VideoTexture(video);
17183
+ const texture = new import_three39.VideoTexture(video);
17018
17184
  applyEquirectangularLayout(texture, 1);
17019
- texture.magFilter = import_three38.LinearFilter;
17020
- texture.minFilter = import_three38.LinearFilter;
17185
+ texture.magFilter = import_three39.LinearFilter;
17186
+ texture.minFilter = import_three39.LinearFilter;
17021
17187
  texture.generateMipmaps = false;
17022
17188
  return { video, texture };
17023
17189
  }, []);
@@ -17453,7 +17619,7 @@ function PanoVideo({
17453
17619
  activeTexture ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
17454
17620
  "mesh",
17455
17621
  {
17456
- rotation: [0, import_three38.MathUtils.degToRad(90 + yawOffset2), 0],
17622
+ rotation: [0, import_three39.MathUtils.degToRad(90 + yawOffset2), 0],
17457
17623
  visible,
17458
17624
  children: [
17459
17625
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
@@ -17461,7 +17627,7 @@ function PanoVideo({
17461
17627
  PanoBasicMaterial,
17462
17628
  {
17463
17629
  map: activeTexture,
17464
- side: import_three38.BackSide,
17630
+ side: import_three39.BackSide,
17465
17631
  toneMapped: false
17466
17632
  }
17467
17633
  )