@react-three/drei 11.0.0-alpha.5 → 11.0.0-alpha.6

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/core/index.mjs CHANGED
@@ -2,9 +2,8 @@ import * as React from 'react';
2
2
  import { forwardRef, useImperativeHandle, useMemo, useEffect, useCallback, useRef, useLayoutEffect, useState, Fragment, createContext, useContext } from 'react';
3
3
  import { useThree, useFrame, extend, createPortal, useInstanceHandle, context as context$9, useLoader, applyProps, addEffect, addAfterEffect } from '@react-three/fiber';
4
4
  import * as THREE from 'three';
5
- import { REVISION, WebGLRenderTarget, Frustum, Matrix4, Vector3, Vector4, Vector2, Color, InstancedInterleavedBuffer, InterleavedBufferAttribute, WebGLCubeRenderTarget, HalfFloatType, CubeCamera as CubeCamera$1, EventDispatcher, Euler, Quaternion, MathUtils, TextureLoader, Texture as Texture$1, MeshLambertMaterial, DynamicDrawUsage, CatmullRomCurve3, CubicBezierCurve3, QuadraticBezierCurve3, Shape as Shape$1, Object3D, CanvasTexture, DoubleSide, PerspectiveCamera as PerspectiveCamera$1, OrthographicCamera as OrthographicCamera$1, AudioListener, AudioLoader, AnimationMixer, BufferAttribute, Box3, Sphere as Sphere$1, InstancedBufferAttribute, DepthTexture, DepthFormat, UnsignedShortType, CubeTextureLoader, DefaultLoadingManager, Ray, Raycaster, Camera, CubeReflectionMapping, EquirectangularReflectionMapping, Scene, RepeatWrapping } from 'three';
5
+ import { REVISION, WebGLRenderTarget, Frustum, Matrix4, Vector3, Vector4, Vector2, Color, InstancedInterleavedBuffer, InterleavedBufferAttribute, WebGLCubeRenderTarget, HalfFloatType, CubeCamera as CubeCamera$1, EventDispatcher, Euler, Quaternion, MathUtils, TextureLoader, Texture as Texture$1, MeshLambertMaterial, DynamicDrawUsage, CatmullRomCurve3, CubicBezierCurve3, QuadraticBezierCurve3, Shape as Shape$1, Object3D, CanvasTexture, PerspectiveCamera as PerspectiveCamera$1, OrthographicCamera as OrthographicCamera$1, AudioListener, AudioLoader, AnimationMixer, BufferAttribute, Box3, Sphere as Sphere$1, InstancedBufferAttribute, DoubleSide, DepthTexture, DepthFormat, UnsignedShortType, CubeTextureLoader, DefaultLoadingManager, Ray, Raycaster, Camera, CubeReflectionMapping, EquirectangularReflectionMapping, Scene, RepeatWrapping } from 'three';
6
6
  import { ArcballControls as ArcballControls$1 } from 'three/examples/jsm/controls/ArcballControls.js';
7
- import { useGesture } from '@use-gesture/react';
8
7
  import { FirstPersonControls as FirstPersonControls$1 } from 'three/examples/jsm/controls/FirstPersonControls.js';
9
8
  import { FlyControls as FlyControls$1 } from 'three/examples/jsm/controls/FlyControls.js';
10
9
  import { create as create$1 } from 'zustand';
@@ -13,6 +12,7 @@ import { MapControls as MapControls$1 } from 'three/examples/jsm/controls/MapCon
13
12
  import { misc, easing } from 'maath';
14
13
  import { OrbitControls as OrbitControls$1 } from 'three/addons/controls/OrbitControls.js';
15
14
  import { PointerLockControls as PointerLockControls$1 } from 'three/examples/jsm/controls/PointerLockControls.js';
15
+ import { useGesture } from '@use-gesture/react';
16
16
  import * as ReactDOM from 'react-dom/client';
17
17
  import { TrackballControls as TrackballControls$1 } from 'three/examples/jsm/controls/TrackballControls.js';
18
18
  import { SimplexNoise } from 'three/examples/jsm/math/SimplexNoise.js';
@@ -31,7 +31,6 @@ import { TransformControls as TransformControls$1 } from 'three/examples/jsm/con
31
31
  import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils.js';
32
32
  import { MeshSurfaceSampler } from 'three/examples/jsm/math/MeshSurfaceSampler.js';
33
33
  import { SVGLoader } from 'three/examples/jsm/loaders/SVGLoader.js';
34
- import { Events } from 'hls.js';
35
34
  import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
36
35
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
37
36
  import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
@@ -1172,11 +1171,11 @@ const DeviceOrientationControls = /* @__PURE__ */ React.forwardRef(
1172
1171
  );
1173
1172
 
1174
1173
  const initialModelPosition = /* @__PURE__ */ new THREE.Vector3();
1175
- const mousePosition2D = /* @__PURE__ */ new THREE.Vector2();
1176
1174
  const mousePosition3D = /* @__PURE__ */ new THREE.Vector3();
1177
1175
  const dragOffset = /* @__PURE__ */ new THREE.Vector3();
1178
1176
  const dragPlaneNormal = /* @__PURE__ */ new THREE.Vector3();
1179
1177
  const dragPlane = /* @__PURE__ */ new THREE.Plane();
1178
+ const startPointerPos = /* @__PURE__ */ new THREE.Vector3();
1180
1179
  const DragControls = React.forwardRef(
1181
1180
  ({
1182
1181
  autoTransform = true,
@@ -1192,90 +1191,132 @@ const DragControls = React.forwardRef(
1192
1191
  ...props
1193
1192
  }, fRef) => {
1194
1193
  const defaultControls = useThree((state) => state.controls);
1195
- const { camera, size, raycaster, invalidate } = useThree();
1194
+ const { camera, invalidate } = useThree();
1196
1195
  const ref = React.useRef(null);
1197
- const bind = useGesture(
1198
- {
1199
- onHover: ({ hovering }) => onHover && onHover(hovering ?? false),
1200
- onDragStart: ({ event }) => {
1201
- if (defaultControls) defaultControls.enabled = false;
1202
- const { point } = event;
1203
- ref.current.matrix.decompose(initialModelPosition, new THREE.Quaternion(), new THREE.Vector3());
1204
- mousePosition3D.copy(point);
1205
- dragOffset.copy(mousePosition3D).sub(initialModelPosition);
1206
- onDragStart && onDragStart(initialModelPosition);
1207
- invalidate();
1208
- },
1209
- onDrag: ({ xy: [dragX, dragY], intentional, event }) => {
1210
- if (!intentional) return;
1211
- if (dragConfig && dragConfig.preventOverlap) event.preventDefault();
1212
- const normalizedMouseX = (dragX - size.left) / size.width * 2 - 1;
1213
- const normalizedMouseY = -((dragY - size.top) / size.height) * 2 + 1;
1214
- mousePosition2D.set(normalizedMouseX, normalizedMouseY);
1215
- raycaster.setFromCamera(mousePosition2D, camera);
1216
- if (!axisLock) {
1217
- camera.getWorldDirection(dragPlaneNormal).negate();
1218
- } else {
1219
- switch (axisLock) {
1220
- case "x":
1221
- dragPlaneNormal.set(1, 0, 0);
1222
- break;
1223
- case "y":
1224
- dragPlaneNormal.set(0, 1, 0);
1225
- break;
1226
- case "z":
1227
- dragPlaneNormal.set(0, 0, 1);
1228
- break;
1229
- }
1230
- }
1231
- dragPlane.setFromNormalAndCoplanarPoint(dragPlaneNormal, mousePosition3D);
1232
- raycaster.ray.intersectPlane(dragPlane, mousePosition3D);
1233
- const previousLocalMatrix = ref.current.matrix.clone();
1234
- const previousWorldMatrix = ref.current.matrixWorld.clone();
1235
- const intendedNewPosition = new THREE.Vector3(
1236
- mousePosition3D.x - dragOffset.x,
1237
- mousePosition3D.y - dragOffset.y,
1238
- mousePosition3D.z - dragOffset.z
1239
- );
1240
- if (dragLimits) {
1241
- intendedNewPosition.x = dragLimits[0] ? Math.max(Math.min(intendedNewPosition.x, dragLimits[0][1]), dragLimits[0][0]) : intendedNewPosition.x;
1242
- intendedNewPosition.y = dragLimits[1] ? Math.max(Math.min(intendedNewPosition.y, dragLimits[1][1]), dragLimits[1][0]) : intendedNewPosition.y;
1243
- intendedNewPosition.z = dragLimits[2] ? Math.max(Math.min(intendedNewPosition.z, dragLimits[2][1]), dragLimits[2][0]) : intendedNewPosition.z;
1244
- }
1245
- if (autoTransform) {
1246
- ref.current.matrix.setPosition(intendedNewPosition);
1247
- const deltaLocalMatrix = ref.current.matrix.clone().multiply(previousLocalMatrix.invert());
1248
- const deltaWorldMatrix = ref.current.matrix.clone().multiply(previousWorldMatrix.invert());
1249
- onDrag && onDrag(ref.current.matrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
1250
- } else {
1251
- const tempMatrix = new THREE.Matrix4().copy(ref.current.matrix);
1252
- tempMatrix.setPosition(intendedNewPosition);
1253
- const deltaLocalMatrix = tempMatrix.clone().multiply(previousLocalMatrix.invert());
1254
- const deltaWorldMatrix = tempMatrix.clone().multiply(previousWorldMatrix.invert());
1255
- onDrag && onDrag(tempMatrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
1196
+ const dragState = React.useRef({
1197
+ active: false,
1198
+ intentional: false,
1199
+ // Has moved past threshold
1200
+ pointerId: -1
1201
+ });
1202
+ const threshold = dragConfig?.threshold ?? 0;
1203
+ const filterTaps = dragConfig?.filterTaps ?? true;
1204
+ const handlePointerDown = React.useCallback(
1205
+ (event) => {
1206
+ event.stopPropagation();
1207
+ event.target.setPointerCapture(event.pointerId);
1208
+ dragState.current.active = true;
1209
+ dragState.current.intentional = threshold === 0;
1210
+ dragState.current.pointerId = event.pointerId;
1211
+ if (defaultControls) defaultControls.enabled = false;
1212
+ ref.current.matrix.decompose(initialModelPosition, new THREE.Quaternion(), new THREE.Vector3());
1213
+ mousePosition3D.copy(event.point);
1214
+ startPointerPos.copy(event.point);
1215
+ dragOffset.copy(mousePosition3D).sub(initialModelPosition);
1216
+ if (!axisLock) {
1217
+ camera.getWorldDirection(dragPlaneNormal).negate();
1218
+ } else {
1219
+ switch (axisLock) {
1220
+ case "x":
1221
+ dragPlaneNormal.set(1, 0, 0);
1222
+ break;
1223
+ case "y":
1224
+ dragPlaneNormal.set(0, 1, 0);
1225
+ break;
1226
+ case "z":
1227
+ dragPlaneNormal.set(0, 0, 1);
1228
+ break;
1256
1229
  }
1257
- invalidate();
1258
- },
1259
- onDragEnd: () => {
1260
- if (defaultControls) defaultControls.enabled = true;
1261
- onDragEnd && onDragEnd();
1262
- invalidate();
1263
1230
  }
1231
+ dragPlane.setFromNormalAndCoplanarPoint(dragPlaneNormal, mousePosition3D);
1232
+ if (dragState.current.intentional) {
1233
+ onDragStart && onDragStart(initialModelPosition);
1234
+ }
1235
+ invalidate();
1264
1236
  },
1265
- {
1266
- drag: {
1267
- filterTaps: true,
1268
- threshold: 1,
1269
- ...typeof dragConfig === "object" ? dragConfig : {}
1237
+ [defaultControls, camera, axisLock, threshold, onDragStart, invalidate]
1238
+ );
1239
+ const handlePointerMove = React.useCallback(
1240
+ (event) => {
1241
+ if (!dragState.current.active || event.pointerId !== dragState.current.pointerId) return;
1242
+ const intersection = event.ray.intersectPlane(dragPlane, mousePosition3D);
1243
+ if (!intersection) return;
1244
+ if (!dragState.current.intentional) {
1245
+ const distance = mousePosition3D.distanceTo(startPointerPos);
1246
+ if (distance < threshold) return;
1247
+ dragState.current.intentional = true;
1248
+ onDragStart && onDragStart(initialModelPosition);
1270
1249
  }
1271
- }
1250
+ const previousLocalMatrix = ref.current.matrix.clone();
1251
+ const previousWorldMatrix = ref.current.matrixWorld.clone();
1252
+ const intendedNewPosition = new THREE.Vector3(
1253
+ mousePosition3D.x - dragOffset.x,
1254
+ mousePosition3D.y - dragOffset.y,
1255
+ mousePosition3D.z - dragOffset.z
1256
+ );
1257
+ if (dragLimits) {
1258
+ intendedNewPosition.x = dragLimits[0] ? Math.max(Math.min(intendedNewPosition.x, dragLimits[0][1]), dragLimits[0][0]) : intendedNewPosition.x;
1259
+ intendedNewPosition.y = dragLimits[1] ? Math.max(Math.min(intendedNewPosition.y, dragLimits[1][1]), dragLimits[1][0]) : intendedNewPosition.y;
1260
+ intendedNewPosition.z = dragLimits[2] ? Math.max(Math.min(intendedNewPosition.z, dragLimits[2][1]), dragLimits[2][0]) : intendedNewPosition.z;
1261
+ }
1262
+ if (autoTransform) {
1263
+ ref.current.matrix.setPosition(intendedNewPosition);
1264
+ const deltaLocalMatrix = ref.current.matrix.clone().multiply(previousLocalMatrix.invert());
1265
+ const deltaWorldMatrix = ref.current.matrix.clone().multiply(previousWorldMatrix.invert());
1266
+ onDrag && onDrag(ref.current.matrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
1267
+ } else {
1268
+ const tempMatrix = new THREE.Matrix4().copy(ref.current.matrix);
1269
+ tempMatrix.setPosition(intendedNewPosition);
1270
+ const deltaLocalMatrix = tempMatrix.clone().multiply(previousLocalMatrix.invert());
1271
+ const deltaWorldMatrix = tempMatrix.clone().multiply(previousWorldMatrix.invert());
1272
+ onDrag && onDrag(tempMatrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
1273
+ }
1274
+ invalidate();
1275
+ },
1276
+ [autoTransform, dragLimits, threshold, onDragStart, onDrag, invalidate]
1272
1277
  );
1278
+ const handlePointerUp = React.useCallback(
1279
+ (event) => {
1280
+ if (!dragState.current.active || event.pointerId !== dragState.current.pointerId) return;
1281
+ event.target.releasePointerCapture(event.pointerId);
1282
+ const wasIntentional = dragState.current.intentional;
1283
+ dragState.current.active = false;
1284
+ dragState.current.intentional = false;
1285
+ dragState.current.pointerId = -1;
1286
+ if (defaultControls) defaultControls.enabled = true;
1287
+ if (wasIntentional || !filterTaps) {
1288
+ onDragEnd && onDragEnd();
1289
+ }
1290
+ invalidate();
1291
+ },
1292
+ [defaultControls, filterTaps, onDragEnd, invalidate]
1293
+ );
1294
+ const handlePointerEnter = React.useCallback(() => {
1295
+ onHover && onHover(true);
1296
+ }, [onHover]);
1297
+ const handlePointerLeave = React.useCallback(() => {
1298
+ onHover && onHover(false);
1299
+ }, [onHover]);
1273
1300
  React.useImperativeHandle(fRef, () => ref.current, []);
1274
1301
  React.useLayoutEffect(() => {
1275
1302
  if (!matrix) return;
1276
1303
  ref.current.matrix = matrix;
1277
1304
  }, [matrix]);
1278
- return /* @__PURE__ */ React.createElement("group", { ref, ...bind(), matrix, matrixAutoUpdate: false, ...props }, children);
1305
+ return /* @__PURE__ */ React.createElement(
1306
+ "group",
1307
+ {
1308
+ ref,
1309
+ onPointerDown: handlePointerDown,
1310
+ onPointerMove: handlePointerMove,
1311
+ onPointerUp: handlePointerUp,
1312
+ onPointerEnter: handlePointerEnter,
1313
+ onPointerLeave: handlePointerLeave,
1314
+ matrix,
1315
+ matrixAutoUpdate: false,
1316
+ ...props
1317
+ },
1318
+ children
1319
+ );
1279
1320
  }
1280
1321
  );
1281
1322
 
@@ -1393,7 +1434,7 @@ function KeyboardControls({ map, children, onChange, domElement }) {
1393
1434
  source.removeEventListener("keyup", upHandler);
1394
1435
  window.removeEventListener("blur", blurHandler);
1395
1436
  };
1396
- }, [domElement, key]);
1437
+ }, [domElement, key, onChange]);
1397
1438
  return /* @__PURE__ */ React.createElement(context$8.Provider, { value: api, children });
1398
1439
  }
1399
1440
  function useKeyboardControls(sel) {
@@ -1415,20 +1456,28 @@ const MapControls = /* @__PURE__ */ React.forwardRef((props = { enableDamping: t
1415
1456
  const controls = React.useMemo(() => new MapControls$1(explCamera), [explCamera]);
1416
1457
  React.useEffect(() => {
1417
1458
  controls.connect(explDomElement);
1459
+ return () => void controls.dispose();
1460
+ }, [explDomElement, controls]);
1461
+ React.useEffect(() => {
1418
1462
  const callback = (e) => {
1419
1463
  invalidate();
1420
1464
  if (onChange) onChange(e);
1421
1465
  };
1466
+ const onStartCb = (e) => {
1467
+ if (onStart) onStart(e);
1468
+ };
1469
+ const onEndCb = (e) => {
1470
+ if (onEnd) onEnd(e);
1471
+ };
1422
1472
  controls.addEventListener("change", callback);
1423
- if (onStart) controls.addEventListener("start", onStart);
1424
- if (onEnd) controls.addEventListener("end", onEnd);
1473
+ controls.addEventListener("start", onStartCb);
1474
+ controls.addEventListener("end", onEndCb);
1425
1475
  return () => {
1426
- controls.dispose();
1476
+ controls.removeEventListener("start", onStartCb);
1477
+ controls.removeEventListener("end", onEndCb);
1427
1478
  controls.removeEventListener("change", callback);
1428
- if (onStart) controls.removeEventListener("start", onStart);
1429
- if (onEnd) controls.removeEventListener("end", onEnd);
1430
1479
  };
1431
- }, [onChange, onStart, onEnd, controls, invalidate, explDomElement]);
1480
+ }, [onChange, onStart, onEnd, controls, invalidate]);
1432
1481
  React.useEffect(() => {
1433
1482
  if (makeDefault) {
1434
1483
  const old = get().controls;
@@ -1436,7 +1485,9 @@ const MapControls = /* @__PURE__ */ React.forwardRef((props = { enableDamping: t
1436
1485
  return () => set({ controls: old });
1437
1486
  }
1438
1487
  }, [makeDefault, controls]);
1439
- useFrame(() => controls.update(), -1);
1488
+ useFrame(() => {
1489
+ if (controls.enabled) controls.update();
1490
+ }, -1);
1440
1491
  return /* @__PURE__ */ React.createElement("primitive", { ref, object: controls, enableDamping: true, ...rest });
1441
1492
  });
1442
1493
 
@@ -1562,20 +1613,16 @@ const OrbitControls = /* @__PURE__ */ React.forwardRef(
1562
1613
  onEnd,
1563
1614
  ...restProps
1564
1615
  }, ref) => {
1565
- const invalidate = useThree((state) => state.invalidate);
1566
- const defaultCamera = useThree((state) => state.camera);
1567
- const gl = useThree((state) => state.gl);
1568
- const events = useThree((state) => state.events);
1569
- const setEvents = useThree((state) => state.setEvents);
1570
- const set = useThree((state) => state.set);
1571
- const get = useThree((state) => state.get);
1572
- const performance = useThree((state) => state.performance);
1616
+ const { invalidate, camera: defaultCamera, renderer, events, setEvents, set, get, performance } = useThree();
1573
1617
  const explCamera = camera || defaultCamera;
1574
- const explDomElement = domElement || events.connected || gl.domElement;
1618
+ const explDomElement = domElement || events.connected || renderer.domElement;
1575
1619
  const controls = React.useMemo(() => new OrbitControls$1(explCamera), [explCamera]);
1576
- useFrame(() => {
1577
- if (controls.enabled) controls.update();
1578
- }, -1);
1620
+ useFrame(
1621
+ () => {
1622
+ if (controls.enabled) controls.update();
1623
+ },
1624
+ { before: "update" }
1625
+ );
1579
1626
  React.useEffect(() => {
1580
1627
  if (keyEvents) {
1581
1628
  controls.connect(keyEvents === true ? explDomElement : keyEvents);
@@ -1689,9 +1736,8 @@ function PresentationControls({
1689
1736
  azimuth = [-Infinity, Infinity],
1690
1737
  damping = 0.25
1691
1738
  }) {
1692
- const events = useThree((state) => state.events);
1693
- const gl = useThree((state) => state.gl);
1694
- const explDomElement = domElement || events.connected || gl.domElement;
1739
+ const { events, renderer, invalidate } = useThree();
1740
+ const explDomElement = domElement || events.connected || renderer.domElement;
1695
1741
  const { size } = useThree();
1696
1742
  const rPolar = React.useMemo(
1697
1743
  () => [rotation[0] + polar[0], rotation[0] + polar[1]],
@@ -1708,18 +1754,20 @@ function PresentationControls({
1708
1754
  React.useEffect(() => {
1709
1755
  if (global && cursor && enabled) {
1710
1756
  explDomElement.style.cursor = "grab";
1711
- gl.domElement.style.cursor = "";
1757
+ renderer.domElement.style.cursor = "";
1712
1758
  return () => {
1713
1759
  explDomElement.style.cursor = "default";
1714
- gl.domElement.style.cursor = "default";
1760
+ renderer.domElement.style.cursor = "default";
1715
1761
  };
1716
1762
  }
1717
1763
  }, [global, cursor, explDomElement, enabled]);
1718
1764
  const [animation] = React.useState({ scale: 1, rotation: rInitial, damping });
1719
1765
  const ref = React.useRef(null);
1720
1766
  useFrame((state, delta) => {
1721
- easing.damp3(ref.current.scale, animation.scale, animation.damping, delta);
1722
- easing.dampE(ref.current.rotation, animation.rotation, animation.damping, delta);
1767
+ let changed = false;
1768
+ changed ||= easing.damp3(ref.current.scale, animation.scale, animation.damping, delta);
1769
+ changed ||= easing.dampE(ref.current.rotation, animation.rotation, animation.damping, delta);
1770
+ if (changed) state.invalidate();
1723
1771
  });
1724
1772
  const bind = useGesture(
1725
1773
  {
@@ -1727,6 +1775,7 @@ function PresentationControls({
1727
1775
  if (cursor && !global && enabled) explDomElement.style.cursor = last ? "auto" : "grab";
1728
1776
  },
1729
1777
  onDrag: ({ down, delta: [x, y], memo: [oldY, oldX] = animation.rotation || rInitial }) => {
1778
+ invalidate();
1730
1779
  if (!enabled) return [y, x];
1731
1780
  if (cursor) explDomElement.style.cursor = down ? "grabbing" : "grab";
1732
1781
  x = MathUtils.clamp(oldX + x / size.width * Math.PI * speed, ...rAzimuth);
@@ -1735,9 +1784,12 @@ function PresentationControls({
1735
1784
  animation.rotation = snap && !down ? rInitial : [y, x, 0];
1736
1785
  animation.damping = snap && !down && typeof snap !== "boolean" ? snap : damping;
1737
1786
  return [y, x];
1787
+ },
1788
+ onDragEnd: () => {
1789
+ invalidate();
1738
1790
  }
1739
1791
  },
1740
- { target: global ? explDomElement : void 0 }
1792
+ { target: global ? explDomElement : void 0, enabled }
1741
1793
  );
1742
1794
  return /* @__PURE__ */ React.createElement("group", { ref, ...bind?.() }, children);
1743
1795
  }
@@ -1746,6 +1798,10 @@ function roundToPixelRatio(value) {
1746
1798
  const ratio = window.devicePixelRatio || 1;
1747
1799
  return Math.round(value * ratio) / ratio;
1748
1800
  }
1801
+ function getMaxAnisotropy(renderer) {
1802
+ const r = renderer;
1803
+ return r?.getMaxAnisotropy?.() ?? r?.capabilities?.getMaxAnisotropy?.() ?? 1;
1804
+ }
1749
1805
 
1750
1806
  const context$7 = /* @__PURE__ */ React.createContext(null);
1751
1807
  const rootCache = /* @__PURE__ */ new WeakMap();
@@ -1772,6 +1828,7 @@ function ScrollControls({
1772
1828
  const [fixed] = React.useState(() => document.createElement("div"));
1773
1829
  const target = gl.domElement.parentNode;
1774
1830
  const scroll = React.useRef(0);
1831
+ const disableScrollUpdate = React.useRef(false);
1775
1832
  const state = React.useMemo(() => {
1776
1833
  const state2 = {
1777
1834
  el,
@@ -1853,16 +1910,20 @@ function ScrollControls({
1853
1910
  const scrollLength = el[horizontal ? "scrollWidth" : "scrollHeight"];
1854
1911
  const scrollThreshold = scrollLength - containerLength;
1855
1912
  let current = 0;
1856
- let disableScroll = true;
1913
+ let disableScroll = false;
1857
1914
  let firstRun = true;
1858
1915
  const onScroll = () => {
1859
1916
  if (!enabled || firstRun) return;
1917
+ if (disableScrollUpdate.current) {
1918
+ disableScrollUpdate.current = false;
1919
+ return;
1920
+ }
1860
1921
  invalidate();
1861
1922
  current = el[horizontal ? "scrollLeft" : "scrollTop"];
1862
1923
  scroll.current = current / scrollThreshold;
1863
1924
  if (infinite) {
1864
1925
  if (!disableScroll) {
1865
- if (current >= scrollThreshold) {
1926
+ if (current >= scrollThreshold - 1) {
1866
1927
  const damp = 1 - state.offset;
1867
1928
  el[horizontal ? "scrollLeft" : "scrollTop"] = 1;
1868
1929
  scroll.current = state.offset = -damp;
@@ -1879,11 +1940,34 @@ function ScrollControls({
1879
1940
  };
1880
1941
  el.addEventListener("scroll", onScroll, { passive: true });
1881
1942
  requestAnimationFrame(() => firstRun = false);
1882
- const onWheel = (e) => el.scrollLeft += e.deltaY / 2;
1883
- if (horizontal) el.addEventListener("wheel", onWheel, { passive: true });
1943
+ const onResize = () => {
1944
+ if (!el) return;
1945
+ const scrollLength2 = el[horizontal ? "scrollWidth" : "scrollHeight"];
1946
+ const containerLength2 = el[horizontal ? "clientWidth" : "clientHeight"];
1947
+ disableScrollUpdate.current = true;
1948
+ el[horizontal ? "scrollLeft" : "scrollTop"] = state.offset * (scrollLength2 - containerLength2);
1949
+ };
1950
+ const onWheel = (e) => {
1951
+ if (horizontal) {
1952
+ const previous = el.scrollLeft;
1953
+ el.scrollLeft += e.deltaY / 2;
1954
+ if (infinite && previous === el.scrollLeft) {
1955
+ onScroll();
1956
+ }
1957
+ } else if (infinite) {
1958
+ if (el.scrollTop <= 1 && e.deltaY < 0) {
1959
+ onScroll();
1960
+ } else if (el.scrollTop >= el.scrollHeight - el.clientHeight - 1 && e.deltaY > 0) {
1961
+ onScroll();
1962
+ }
1963
+ }
1964
+ };
1965
+ if (horizontal || infinite) el.addEventListener("wheel", onWheel, { passive: true });
1966
+ if (horizontal) window.addEventListener("resize", onResize);
1884
1967
  return () => {
1885
1968
  el.removeEventListener("scroll", onScroll);
1886
- if (horizontal) el.removeEventListener("wheel", onWheel);
1969
+ if (horizontal || infinite) el.removeEventListener("wheel", onWheel);
1970
+ if (horizontal) window.removeEventListener("resize", onResize);
1887
1971
  };
1888
1972
  }
1889
1973
  }, [el, events, size, infinite, state, invalidate, horizontal, enabled]);
@@ -2300,10 +2384,10 @@ const CloudInstance = /* @__PURE__ */ React.forwardRef(
2300
2384
  return /* @__PURE__ */ React.createElement("group", { ref, ...props });
2301
2385
  }
2302
2386
  );
2303
- const Cloud = /* @__PURE__ */ React.forwardRef((props, fref) => {
2387
+ const Cloud = /* @__PURE__ */ React.forwardRef(({ materialFactory, ...props }, fref) => {
2304
2388
  const parent = React.useContext(context$6);
2305
2389
  if (parent) return /* @__PURE__ */ React.createElement(CloudInstance, { ref: fref, ...props });
2306
- return /* @__PURE__ */ React.createElement(Clouds, null, /* @__PURE__ */ React.createElement(CloudInstance, { ref: fref, ...props }));
2390
+ return /* @__PURE__ */ React.createElement(Clouds, { materialFactory }, /* @__PURE__ */ React.createElement(CloudInstance, { ref: fref, ...props }));
2307
2391
  });
2308
2392
 
2309
2393
  const CatmullRomLine = /* @__PURE__ */ React.forwardRef(function CatmullRomLine2({
@@ -2825,7 +2909,7 @@ const Text3D = /* @__PURE__ */ React.forwardRef(
2825
2909
  return {
2826
2910
  font,
2827
2911
  size,
2828
- height,
2912
+ depth: height,
2829
2913
  bevelThickness,
2830
2914
  bevelSize,
2831
2915
  bevelEnabled,
@@ -3008,7 +3092,7 @@ const FaceMaterial = ({
3008
3092
  "meshBasicMaterial",
3009
3093
  {
3010
3094
  map: texture,
3011
- "map-anisotropy": renderer.getMaxAnisotropy() || 1,
3095
+ "map-anisotropy": getMaxAnisotropy(renderer),
3012
3096
  attach: `material-${index}`,
3013
3097
  color: hover ? hoverColor : "white",
3014
3098
  transparent: true,
@@ -3119,7 +3203,7 @@ function AxisHead({
3119
3203
  "spriteMaterial",
3120
3204
  {
3121
3205
  map: texture,
3122
- "map-anisotropy": renderer.getMaxAnisotropy() || 1,
3206
+ "map-anisotropy": getMaxAnisotropy(renderer),
3123
3207
  alphaTest: 0.3,
3124
3208
  opacity: label ? 1 : 0.75,
3125
3209
  toneMapped: false
@@ -3264,6 +3348,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
3264
3348
  }, ref) => {
3265
3349
  const { gl, camera, scene, size, raycaster, events, viewport } = useThree();
3266
3350
  const forceEven = useThree((state) => state.internal.forceEven);
3351
+ const { frustum } = useThree();
3267
3352
  const [el] = React.useState(() => document.createElement(as));
3268
3353
  const root = React.useRef(null);
3269
3354
  const group = React.useRef(null);
@@ -3293,22 +3378,18 @@ const Html = /* @__PURE__ */ React.forwardRef(
3293
3378
  if (group.current) {
3294
3379
  if (!root.current) {
3295
3380
  root.current = ReactDOM.createRoot(el);
3296
- }
3297
- scene.updateMatrixWorld();
3298
- if (transform) {
3299
- el.style.cssText = `position:absolute;top:0;left:0;pointer-events:none;overflow:hidden;`;
3300
- } else {
3301
- el.style.cssText = `position:absolute;top:0;left:0;transform:translate3d(0,-9999px,0);transform-origin:0 0;`;
3381
+ scene.updateMatrixWorld();
3382
+ if (transform) {
3383
+ el.style.cssText = `position:absolute;top:0;left:0;pointer-events:none;overflow:hidden;`;
3384
+ } else {
3385
+ el.style.cssText = `position:absolute;top:0;left:0;transform:translate3d(0,-9999px,0);transform-origin:0 0;`;
3386
+ }
3302
3387
  }
3303
3388
  if (target) {
3304
3389
  if (prepend) target.prepend(el);
3305
3390
  else target.appendChild(el);
3306
3391
  }
3307
3392
  return () => {
3308
- if (root.current) {
3309
- root.current.unmount();
3310
- root.current = null;
3311
- }
3312
3393
  if (target && target.contains(el)) {
3313
3394
  target.removeChild(el);
3314
3395
  }
@@ -3442,8 +3523,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
3442
3523
  if (transformOuterRef.current) {
3443
3524
  const el2 = transformOuterRef.current.children[0];
3444
3525
  if (el2?.clientWidth && el2?.clientHeight) {
3445
- const { isOrthographicCamera } = camera;
3446
- if (isOrthographicCamera || geometry) {
3526
+ if (geometry) {
3447
3527
  if (props.scale) {
3448
3528
  if (!Array.isArray(props.scale)) {
3449
3529
  occlusionMeshRef.current.scale.setScalar(1 / props.scale);
@@ -3475,64 +3555,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
3475
3555
  }
3476
3556
  }
3477
3557
  });
3478
- const shaders = React.useMemo(
3479
- () => ({
3480
- vertexShader: !transform ? (
3481
- /* glsl */
3482
- `
3483
- /*
3484
- This shader is from the THREE's SpriteMaterial.
3485
- We need to turn the backing plane into a Sprite
3486
- (make it always face the camera) if "transfrom"
3487
- is false.
3488
- */
3489
- #include <common>
3490
-
3491
- void main() {
3492
- vec2 center = vec2(0., 1.);
3493
- float rotation = 0.0;
3494
-
3495
- // This is somewhat arbitrary, but it seems to work well
3496
- // Need to figure out how to derive this dynamically if it even matters
3497
- float size = 0.03;
3498
-
3499
- vec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );
3500
- vec2 scale;
3501
- scale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );
3502
- scale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );
3503
-
3504
- bool isPerspective = isPerspectiveMatrix( projectionMatrix );
3505
- if ( isPerspective ) scale *= - mvPosition.z;
3506
-
3507
- vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale * size;
3508
- vec2 rotatedPosition;
3509
- rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;
3510
- rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;
3511
- mvPosition.xy += rotatedPosition;
3512
-
3513
- gl_Position = projectionMatrix * mvPosition;
3514
- }
3515
- `
3516
- ) : void 0,
3517
- fragmentShader: (
3518
- /* glsl */
3519
- `
3520
- void main() {
3521
- gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
3522
- }
3523
- `
3524
- )
3525
- }),
3526
- [transform]
3527
- );
3528
- return /* @__PURE__ */ React.createElement("group", { ...props, ref: group }, occlude && !isRayCastOcclusion && /* @__PURE__ */ React.createElement("mesh", { castShadow, receiveShadow, ref: occlusionMeshRef }, geometry || /* @__PURE__ */ React.createElement("planeGeometry", null), material || /* @__PURE__ */ React.createElement(
3529
- "shaderMaterial",
3530
- {
3531
- side: DoubleSide,
3532
- vertexShader: shaders.vertexShader,
3533
- fragmentShader: shaders.fragmentShader
3534
- }
3535
- )));
3558
+ return /* @__PURE__ */ React.createElement("group", { ...props, ref: group }, occlude && !isRayCastOcclusion && /* @__PURE__ */ React.createElement("mesh", { castShadow, receiveShadow, ref: occlusionMeshRef }, geometry || /* @__PURE__ */ React.createElement("planeGeometry", null), material));
3536
3559
  }
3537
3560
  );
3538
3561
 
@@ -4385,6 +4408,7 @@ const mW = /* @__PURE__ */ new THREE.Matrix4();
4385
4408
  const mL = /* @__PURE__ */ new THREE.Matrix4();
4386
4409
  const mL0Inv = /* @__PURE__ */ new THREE.Matrix4();
4387
4410
  const mdL = /* @__PURE__ */ new THREE.Matrix4();
4411
+ const mdW = /* @__PURE__ */ new THREE.Matrix4();
4388
4412
  const mG = /* @__PURE__ */ new THREE.Matrix4();
4389
4413
  const bb = /* @__PURE__ */ new THREE.Box3();
4390
4414
  const bbObj = /* @__PURE__ */ new THREE.Box3();
@@ -4499,7 +4523,8 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
4499
4523
  onDragStart && onDragStart(props2);
4500
4524
  invalidate();
4501
4525
  },
4502
- onDrag: (mdW) => {
4526
+ onDrag: (mdW_) => {
4527
+ mdW.copy(mdW_);
4503
4528
  mP.copy(parentRef.current.matrixWorld);
4504
4529
  mPInv.copy(mP).invert();
4505
4530
  mW.copy(mW0).premultiply(mdW);
@@ -4511,12 +4536,12 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
4511
4536
  }
4512
4537
  const target = resolveObject(object);
4513
4538
  if (target) target.matrix.copy(mL);
4514
- onDrag && onDrag(mL, mdL, mW, mdW);
4539
+ onDrag && onDrag({ local: mL, deltaLocal: mdL, world: mW, deltaWorld: mdW });
4515
4540
  invalidate();
4516
4541
  },
4517
4542
  onDragEnd: () => {
4518
4543
  dragState.current = null;
4519
- if (onDragEnd) onDragEnd();
4544
+ if (onDragEnd) onDragEnd({ local: mL, deltaLocal: mdL, world: mW, deltaWorld: mdW });
4520
4545
  invalidate();
4521
4546
  },
4522
4547
  onHover: (props2) => {
@@ -4627,7 +4652,9 @@ const TransformControls = /* @__PURE__ */ React.forwardRef(
4627
4652
  const group = React.useRef(null);
4628
4653
  React.useLayoutEffect(() => {
4629
4654
  if (object) {
4630
- controls.attach(object instanceof THREE.Object3D ? object : object.current);
4655
+ controls.attach(
4656
+ object instanceof THREE.Object3D ? object : object.current
4657
+ );
4631
4658
  } else if (group.current instanceof THREE.Object3D) {
4632
4659
  controls.attach(group.current);
4633
4660
  }
@@ -4723,7 +4750,7 @@ const PointMaterial = /* @__PURE__ */ React.forwardRef((props, ref) => {
4723
4750
  return /* @__PURE__ */ React.createElement("primitive", { ...props, object: material, ref, attach: "material" });
4724
4751
  });
4725
4752
 
4726
- const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, loop = true, autoplay, ...props }, ref) => {
4753
+ const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, loop = false, autoplay, ...props }, ref) => {
4727
4754
  const sound = React.useRef(null);
4728
4755
  React.useImperativeHandle(ref, () => sound.current, []);
4729
4756
  const camera = useThree(({ camera: camera2 }) => camera2);
@@ -4735,7 +4762,9 @@ const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, l
4735
4762
  _sound.setBuffer(Array.isArray(buffer) ? buffer[0] : buffer);
4736
4763
  _sound.setRefDistance(distance);
4737
4764
  _sound.setLoop(loop);
4738
- if (autoplay && !_sound.isPlaying) _sound.play();
4765
+ if (autoplay && !_sound.isPlaying) {
4766
+ _sound.play();
4767
+ }
4739
4768
  }
4740
4769
  }, [buffer, camera, distance, loop]);
4741
4770
  React.useEffect(() => {
@@ -4804,7 +4833,6 @@ const tempMatrix = /* @__PURE__ */ new THREE.Matrix4();
4804
4833
  const translation = /* @__PURE__ */ new THREE.Vector3();
4805
4834
  const rotation = /* @__PURE__ */ new THREE.Quaternion();
4806
4835
  const scale = /* @__PURE__ */ new THREE.Vector3();
4807
- const isInstancedBufferAttribute = (attr) => attr.isInstancedBufferAttribute;
4808
4836
  const Instance = /* @__PURE__ */ React.forwardRef(({ context, children, ...props }, ref) => {
4809
4837
  React.useMemo(() => extend({ PositionMesh }), []);
4810
4838
  const group = React.useRef(null);
@@ -4824,24 +4852,20 @@ const Instances = /* @__PURE__ */ React.forwardRef(({ context, children, range,
4824
4852
  const parentRef = React.useRef(null);
4825
4853
  React.useImperativeHandle(ref, () => parentRef.current, []);
4826
4854
  const [instances, setInstances] = React.useState([]);
4855
+ const boundsDirty = React.useRef(true);
4827
4856
  const [[matrices, colors]] = React.useState(() => {
4828
4857
  const mArray = new Float32Array(limit * 16);
4829
4858
  for (let i = 0; i < limit; i++) tempMatrix.identity().toArray(mArray, i * 16);
4830
4859
  return [mArray, new Float32Array([...new Array(limit * 3)].map(() => 1))];
4831
4860
  });
4832
4861
  React.useEffect(() => {
4833
- parentRef.current.instanceMatrix.needsUpdate = true;
4862
+ if (parentRef.current) parentRef.current.instanceMatrix.needsUpdate = true;
4834
4863
  });
4835
4864
  let iterations = 0;
4836
4865
  let count = 0;
4837
- const attributes = React.useRef([]);
4838
- React.useLayoutEffect(() => {
4839
- attributes.current = Object.entries(parentRef.current.geometry.attributes).filter(
4840
- ([_name, value]) => isInstancedBufferAttribute(value)
4841
- );
4842
- });
4843
4866
  useFrame(() => {
4844
4867
  if (frames === Infinity || iterations < frames) {
4868
+ if (!parentRef.current) return;
4845
4869
  parentRef.current.updateMatrix();
4846
4870
  parentRef.current.updateMatrixWorld();
4847
4871
  parentMatrix.copy(parentRef.current.matrixWorld).invert();
@@ -4862,13 +4886,22 @@ const Instances = /* @__PURE__ */ React.forwardRef(({ context, children, range,
4862
4886
  }
4863
4887
  iterations++;
4864
4888
  }
4889
+ if (boundsDirty.current && (frames === Infinity || iterations === frames)) {
4890
+ boundsDirty.current = false;
4891
+ if (parentRef.current.boundingBox) parentRef.current.computeBoundingBox();
4892
+ if (parentRef.current.boundingSphere) parentRef.current.computeBoundingSphere();
4893
+ }
4865
4894
  });
4866
4895
  const api = React.useMemo(
4867
4896
  () => ({
4868
4897
  getParent: () => parentRef,
4869
4898
  subscribe: (ref2) => {
4870
4899
  setInstances((instances2) => [...instances2, ref2]);
4871
- return () => setInstances((instances2) => instances2.filter((item) => item.current !== ref2.current));
4900
+ boundsDirty.current = true;
4901
+ return () => {
4902
+ setInstances((instances2) => instances2.filter((item) => item.current !== ref2.current));
4903
+ boundsDirty.current = true;
4904
+ };
4872
4905
  }
4873
4906
  }),
4874
4907
  []
@@ -4893,10 +4926,23 @@ const Merged = /* @__PURE__ */ React.forwardRef(function Merged2({ meshes, child
4893
4926
  if (!isArray) {
4894
4927
  for (const key of Object.keys(meshes)) if (!meshes[key].isMesh) delete meshes[key];
4895
4928
  }
4896
- const render = (args) => isArray ? children(...args) : children(
4897
- Object.keys(meshes).filter((key) => meshes[key].isMesh).reduce((acc, key, i) => ({ ...acc, [key]: args[i] }), {})
4898
- );
4899
- const components = (isArray ? meshes : Object.values(meshes)).map(({ geometry, material }) => /* @__PURE__ */ React.createElement(Instances, { key: geometry.uuid, geometry, material, ...props }));
4929
+ const render = (args) => {
4930
+ if (isArray) {
4931
+ return children(
4932
+ ...args
4933
+ );
4934
+ }
4935
+ const instanceMap = {};
4936
+ const keys = Object.keys(meshes).filter((key) => meshes[key].isMesh);
4937
+ keys.forEach((key, i) => {
4938
+ instanceMap[key] = args[i];
4939
+ });
4940
+ return children(instanceMap);
4941
+ };
4942
+ const components = (isArray ? meshes : Object.values(meshes)).map((mesh) => {
4943
+ const { geometry, material } = mesh;
4944
+ return /* @__PURE__ */ React.createElement(Instances, { key: geometry.uuid, geometry, material, ...props });
4945
+ });
4900
4946
  return /* @__PURE__ */ React.createElement("group", { ref }, renderRecursive(render, components));
4901
4947
  });
4902
4948
  function renderRecursive(render, components, results = []) {
@@ -5970,12 +6016,13 @@ function Sampler({ children, weight, transform, instances, mesh, count = 16, ...
5970
6016
  return /* @__PURE__ */ React.createElement("group", { ref: group, ...props }, children);
5971
6017
  }
5972
6018
 
6019
+ const pathStyle = (path) => path.userData?.style;
5973
6020
  const Svg = /* @__PURE__ */ forwardRef(
5974
6021
  function R3FSvg({ src, skipFill, skipStrokes, fillMaterial, strokeMaterial, fillMeshProps, strokeMeshProps, ...props }, ref) {
5975
6022
  const svg = useLoader(SVGLoader, !src.startsWith("<svg") ? src : `data:image/svg+xml;utf8,${src}`);
5976
6023
  const strokeGeometries = useMemo(
5977
6024
  () => skipStrokes ? [] : svg.paths.map(
5978
- (path) => path.userData?.style.stroke === void 0 || path.userData.style.stroke === "none" ? null : path.subPaths.map((subPath) => SVGLoader.pointsToStroke(subPath.getPoints(), path.userData.style))
6025
+ (path) => pathStyle(path)?.stroke === void 0 || pathStyle(path).stroke === "none" ? null : path.subPaths.map((subPath) => SVGLoader.pointsToStroke(subPath.getPoints(), pathStyle(path)))
5979
6026
  ),
5980
6027
  [svg, skipStrokes]
5981
6028
  );
@@ -5983,21 +6030,21 @@ const Svg = /* @__PURE__ */ forwardRef(
5983
6030
  return () => strokeGeometries.forEach((group) => group && group.map((g) => g.dispose()));
5984
6031
  }, [strokeGeometries]);
5985
6032
  let renderOrder = 0;
5986
- return /* @__PURE__ */ React.createElement("object3D", { ref, ...props }, /* @__PURE__ */ React.createElement("object3D", { scale: [1, -1, 1] }, svg.paths.map((path, p) => /* @__PURE__ */ React.createElement(Fragment, { key: p }, !skipFill && path.userData?.style.fill !== void 0 && path.userData.style.fill !== "none" && SVGLoader.createShapes(path).map((shape, s) => /* @__PURE__ */ React.createElement("mesh", { key: s, ...fillMeshProps, renderOrder: renderOrder++ }, /* @__PURE__ */ React.createElement("shapeGeometry", { args: [shape] }), /* @__PURE__ */ React.createElement(
6033
+ return /* @__PURE__ */ React.createElement("object3D", { ref, ...props }, /* @__PURE__ */ React.createElement("object3D", { scale: [1, -1, 1] }, svg.paths.map((path, p) => /* @__PURE__ */ React.createElement(Fragment, { key: p }, !skipFill && pathStyle(path)?.fill !== void 0 && pathStyle(path).fill !== "none" && SVGLoader.createShapes(path).map((shape, s) => /* @__PURE__ */ React.createElement("mesh", { key: s, ...fillMeshProps, renderOrder: renderOrder++ }, /* @__PURE__ */ React.createElement("shapeGeometry", { args: [shape] }), /* @__PURE__ */ React.createElement(
5987
6034
  "meshBasicMaterial",
5988
6035
  {
5989
- color: path.userData.style.fill,
5990
- opacity: path.userData.style.fillOpacity,
6036
+ color: pathStyle(path).fill,
6037
+ opacity: pathStyle(path).fillOpacity,
5991
6038
  transparent: true,
5992
6039
  side: DoubleSide,
5993
6040
  depthWrite: false,
5994
6041
  ...fillMaterial
5995
6042
  }
5996
- ))), !skipStrokes && path.userData?.style.stroke !== void 0 && path.userData.style.stroke !== "none" && path.subPaths.map((_subPath, s) => /* @__PURE__ */ React.createElement("mesh", { key: s, geometry: strokeGeometries[p][s], ...strokeMeshProps, renderOrder: renderOrder++ }, /* @__PURE__ */ React.createElement(
6043
+ ))), !skipStrokes && pathStyle(path)?.stroke !== void 0 && pathStyle(path).stroke !== "none" && path.subPaths.map((_subPath, s) => /* @__PURE__ */ React.createElement("mesh", { key: s, geometry: strokeGeometries[p][s], ...strokeMeshProps, renderOrder: renderOrder++ }, /* @__PURE__ */ React.createElement(
5997
6044
  "meshBasicMaterial",
5998
6045
  {
5999
- color: path.userData.style.stroke,
6000
- opacity: path.userData.style.strokeOpacity,
6046
+ color: pathStyle(path).stroke,
6047
+ opacity: pathStyle(path).strokeOpacity,
6001
6048
  transparent: true,
6002
6049
  side: DoubleSide,
6003
6050
  depthWrite: false,
@@ -6220,8 +6267,8 @@ function useVideoTexture(srcOrSrcObject, {
6220
6267
  });
6221
6268
  if (src && IS_BROWSER && src.endsWith(".m3u8")) {
6222
6269
  const hls = hlsRef.current = await getHls(hlsConfig);
6223
- if (hls) {
6224
- hls.on(Events.MEDIA_ATTACHED, () => void hls.loadSource(src));
6270
+ if (hls && _HLSModule) {
6271
+ hls.on(_HLSModule.Events.MEDIA_ATTACHED, () => void hls.loadSource(src));
6225
6272
  hls.attachMedia(video2);
6226
6273
  }
6227
6274
  }
@@ -6441,9 +6488,125 @@ function Fbx({
6441
6488
  return /* @__PURE__ */ React.createElement(Clone, { ...props, object });
6442
6489
  }
6443
6490
 
6491
+ const SERVICE_KEY = "__drei_ktx2_service__";
6492
+ const DEFAULT_TRANSCODER_PATH = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/basis/";
6493
+ class KTX2LoaderServiceImpl {
6494
+ loader = null;
6495
+ renderer = null;
6496
+ _isReady = false;
6497
+ transcoderPath = DEFAULT_TRANSCODER_PATH;
6498
+ pendingCallbacks = [];
6499
+ /**
6500
+ * Get or create the singleton KTX2Loader instance.
6501
+ * The loader is created lazily on first access.
6502
+ */
6503
+ getLoader() {
6504
+ if (!this.loader) {
6505
+ this.loader = new KTX2Loader();
6506
+ this.loader.setTranscoderPath(this.transcoderPath);
6507
+ }
6508
+ return this.loader;
6509
+ }
6510
+ /**
6511
+ * Register a renderer and call detectSupport.
6512
+ * Should be called from within React context (useLayoutEffect).
6513
+ * Flushes any queued callbacks.
6514
+ */
6515
+ registerRenderer(renderer) {
6516
+ if (this._isReady && this.renderer === renderer) {
6517
+ return;
6518
+ }
6519
+ this.renderer = renderer;
6520
+ const loader = this.getLoader();
6521
+ loader.detectSupport(renderer);
6522
+ this._isReady = true;
6523
+ this.flushPendingCallbacks();
6524
+ }
6525
+ /**
6526
+ * Check if the service is ready (has renderer registered).
6527
+ */
6528
+ isReady() {
6529
+ return this._isReady;
6530
+ }
6531
+ /**
6532
+ * Get the registered renderer, if any.
6533
+ */
6534
+ getRenderer() {
6535
+ return this.renderer;
6536
+ }
6537
+ /**
6538
+ * Register a callback to run when renderer becomes available.
6539
+ * If renderer is already available, runs immediately.
6540
+ */
6541
+ onReady(callback) {
6542
+ if (this._isReady) {
6543
+ callback();
6544
+ } else {
6545
+ this.pendingCallbacks.push(callback);
6546
+ }
6547
+ }
6548
+ /**
6549
+ * Process all pending callbacks.
6550
+ */
6551
+ flushPendingCallbacks() {
6552
+ const callbacks = this.pendingCallbacks;
6553
+ this.pendingCallbacks = [];
6554
+ for (const callback of callbacks) {
6555
+ try {
6556
+ callback();
6557
+ } catch (error) {
6558
+ console.error("KTX2LoaderService: Error in pending callback:", error);
6559
+ }
6560
+ }
6561
+ }
6562
+ /**
6563
+ * Set the transcoder path for basis/ktx2 decoding.
6564
+ */
6565
+ setTranscoderPath(path) {
6566
+ this.transcoderPath = path;
6567
+ if (this.loader) {
6568
+ this.loader.setTranscoderPath(path);
6569
+ }
6570
+ }
6571
+ /**
6572
+ * Get the current transcoder path.
6573
+ */
6574
+ getTranscoderPath() {
6575
+ return this.transcoderPath;
6576
+ }
6577
+ /**
6578
+ * Dispose of the loader and reset state.
6579
+ * Useful for testing or cleanup.
6580
+ */
6581
+ dispose() {
6582
+ if (this.loader) {
6583
+ this.loader.dispose();
6584
+ }
6585
+ const path = this.transcoderPath;
6586
+ this.loader = null;
6587
+ this.renderer = null;
6588
+ this._isReady = false;
6589
+ this.transcoderPath = path;
6590
+ this.pendingCallbacks = [];
6591
+ }
6592
+ }
6593
+ const KTX2LoaderService = globalThis[SERVICE_KEY] || (globalThis[SERVICE_KEY] = new KTX2LoaderServiceImpl());
6594
+
6444
6595
  let dracoLoader = null;
6445
6596
  let decoderPath = "https://www.gstatic.com/draco/versioned/decoders/1.5.5/";
6446
- function extensions(useDraco = true, useMeshopt = true, extendLoader) {
6597
+ let legacyApiWarned = false;
6598
+ function isOptionsObject(arg) {
6599
+ return typeof arg === "object" && arg !== null && !Array.isArray(arg);
6600
+ }
6601
+ function warnLegacyApi() {
6602
+ if (!legacyApiWarned) {
6603
+ legacyApiWarned = true;
6604
+ console.warn(
6605
+ "useGLTF: Boolean arguments are deprecated. Use options object instead:\n useGLTF(path, { draco: true, meshopt: true, ktx2: true })"
6606
+ );
6607
+ }
6608
+ }
6609
+ function extensions(useDraco = true, useMeshopt = true, useKTX2 = false, extendLoader, renderer) {
6447
6610
  return (loader) => {
6448
6611
  if (extendLoader) {
6449
6612
  extendLoader(loader);
@@ -6459,36 +6622,110 @@ function extensions(useDraco = true, useMeshopt = true, extendLoader) {
6459
6622
  const decoder = typeof MeshoptDecoder === "function" ? MeshoptDecoder() : MeshoptDecoder;
6460
6623
  loader.setMeshoptDecoder(decoder);
6461
6624
  }
6625
+ if (useKTX2) {
6626
+ const ktx2Loader = KTX2LoaderService.getLoader();
6627
+ if (typeof useKTX2 === "string") {
6628
+ ktx2Loader.setTranscoderPath(useKTX2);
6629
+ }
6630
+ if (renderer) {
6631
+ ktx2Loader.detectSupport(renderer);
6632
+ }
6633
+ loader.setKTX2Loader(ktx2Loader);
6634
+ }
6462
6635
  };
6463
6636
  }
6464
- const useGLTF = (path, useDraco, useMeshopt, extendLoader) => useLoader(GLTFLoader, path, extensions(useDraco, useMeshopt, extendLoader));
6465
- useGLTF.preload = (path, useDraco, useMeshopt, extendLoader) => useLoader.preload(GLTFLoader, path, extensions(useDraco, useMeshopt, extendLoader));
6637
+ function useGLTF(path, optionsOrDraco, useMeshoptArg, useKTX2Arg, extendLoaderArg) {
6638
+ let draco = true;
6639
+ let meshopt = true;
6640
+ let ktx2 = false;
6641
+ let extendLoader;
6642
+ if (isOptionsObject(optionsOrDraco)) {
6643
+ draco = optionsOrDraco.draco ?? true;
6644
+ meshopt = optionsOrDraco.meshopt ?? true;
6645
+ ktx2 = optionsOrDraco.ktx2 ?? false;
6646
+ extendLoader = optionsOrDraco.extendLoader;
6647
+ } else if (optionsOrDraco !== void 0) {
6648
+ warnLegacyApi();
6649
+ draco = optionsOrDraco;
6650
+ meshopt = useMeshoptArg ?? true;
6651
+ ktx2 = useKTX2Arg ?? false;
6652
+ extendLoader = extendLoaderArg;
6653
+ }
6654
+ const renderer = useThree((state) => state.renderer);
6655
+ useLayoutEffect(() => {
6656
+ if (ktx2) {
6657
+ KTX2LoaderService.registerRenderer(renderer);
6658
+ }
6659
+ }, [ktx2, renderer]);
6660
+ return useLoader(GLTFLoader, path, extensions(draco, meshopt, ktx2, extendLoader, ktx2 ? renderer : void 0));
6661
+ }
6662
+ useGLTF.preload = (path, optionsOrDraco, useMeshoptArg, useKTX2Arg, extendLoaderArg) => {
6663
+ let draco = true;
6664
+ let meshopt = true;
6665
+ let ktx2 = false;
6666
+ let extendLoader;
6667
+ if (isOptionsObject(optionsOrDraco)) {
6668
+ draco = optionsOrDraco.draco ?? true;
6669
+ meshopt = optionsOrDraco.meshopt ?? true;
6670
+ ktx2 = optionsOrDraco.ktx2 ?? false;
6671
+ extendLoader = optionsOrDraco.extendLoader;
6672
+ } else if (optionsOrDraco !== void 0) {
6673
+ warnLegacyApi();
6674
+ draco = optionsOrDraco;
6675
+ meshopt = useMeshoptArg ?? true;
6676
+ ktx2 = useKTX2Arg ?? false;
6677
+ extendLoader = extendLoaderArg;
6678
+ }
6679
+ if (ktx2) {
6680
+ KTX2LoaderService.onReady(() => {
6681
+ const renderer = KTX2LoaderService.getRenderer();
6682
+ useLoader.preload(GLTFLoader, path, extensions(draco, meshopt, ktx2, extendLoader, renderer));
6683
+ });
6684
+ } else {
6685
+ useLoader.preload(GLTFLoader, path, extensions(draco, meshopt, false, extendLoader));
6686
+ }
6687
+ };
6466
6688
  useGLTF.clear = (path) => useLoader.clear(GLTFLoader, path);
6467
6689
  useGLTF.setDecoderPath = (path) => {
6468
6690
  decoderPath = path;
6469
6691
  };
6692
+ useGLTF.setKTX2TranscoderPath = (path) => {
6693
+ KTX2LoaderService.setTranscoderPath(path);
6694
+ };
6470
6695
  const Gltf = /* @__PURE__ */ React.forwardRef(
6471
- ({ src, useDraco, useMeshOpt, extendLoader, ...props }, ref) => {
6472
- const { scene } = useGLTF(src, useDraco, useMeshOpt, extendLoader);
6696
+ ({ src, useDraco, useMeshOpt, extendLoader, options, ...props }, ref) => {
6697
+ const opts = options ?? {
6698
+ draco: useDraco,
6699
+ meshopt: useMeshOpt,
6700
+ extendLoader
6701
+ };
6702
+ const { scene } = useGLTF(src, opts);
6473
6703
  return /* @__PURE__ */ React.createElement(Clone, { ref, ...props, object: scene });
6474
6704
  }
6475
6705
  );
6476
6706
 
6477
- let transcoderPath = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/basis/";
6478
6707
  function useKTX2(input, basisPath = true, extendLoader) {
6479
6708
  const renderer = useThree((state) => state.renderer);
6709
+ useLayoutEffect(() => {
6710
+ KTX2LoaderService.registerRenderer(renderer);
6711
+ }, [renderer]);
6480
6712
  const textures = useLoader(KTX2Loader, IsObject(input) ? Object.values(input) : input, (loader) => {
6481
6713
  if (extendLoader) {
6482
6714
  extendLoader(loader);
6483
6715
  }
6484
6716
  if (basisPath) {
6485
- loader.setTranscoderPath(typeof basisPath === "string" ? basisPath : transcoderPath);
6717
+ const path = typeof basisPath === "string" ? basisPath : KTX2LoaderService.getTranscoderPath();
6718
+ loader.setTranscoderPath(path);
6486
6719
  }
6487
6720
  loader.detectSupport(renderer);
6488
6721
  });
6489
6722
  useEffect(() => {
6490
6723
  const array = Array.isArray(textures) ? textures : [textures];
6491
- array.forEach((texture) => renderer.initTexture(texture));
6724
+ array.forEach((texture) => {
6725
+ if ("initTexture" in renderer) {
6726
+ renderer.initTexture(texture);
6727
+ }
6728
+ });
6492
6729
  }, [renderer, textures]);
6493
6730
  if (IsObject(input)) {
6494
6731
  const keys = Object.keys(input);
@@ -6499,23 +6736,81 @@ function useKTX2(input, basisPath = true, extendLoader) {
6499
6736
  return textures;
6500
6737
  }
6501
6738
  }
6502
- useKTX2.preload = (url, basisPath = true, extendLoader) => useLoader.preload(KTX2Loader, url, (loader) => {
6503
- if (extendLoader) {
6504
- extendLoader(loader);
6505
- }
6506
- if (basisPath) {
6507
- loader.setTranscoderPath(typeof basisPath === "string" ? basisPath : transcoderPath);
6508
- }
6509
- });
6739
+ useKTX2.preload = (url, basisPath = true, extendLoader) => {
6740
+ KTX2LoaderService.onReady(() => {
6741
+ const renderer = KTX2LoaderService.getRenderer();
6742
+ useLoader.preload(KTX2Loader, url, (loader) => {
6743
+ if (extendLoader) {
6744
+ extendLoader(loader);
6745
+ }
6746
+ if (basisPath) {
6747
+ const path = typeof basisPath === "string" ? basisPath : KTX2LoaderService.getTranscoderPath();
6748
+ loader.setTranscoderPath(path);
6749
+ }
6750
+ if (renderer) {
6751
+ loader.detectSupport(renderer);
6752
+ }
6753
+ });
6754
+ });
6755
+ };
6510
6756
  useKTX2.clear = (input) => useLoader.clear(KTX2Loader, input);
6511
6757
  useKTX2.setTranscoderPath = (path) => {
6512
- transcoderPath = path;
6758
+ KTX2LoaderService.setTranscoderPath(path);
6513
6759
  };
6514
6760
  const Ktx2 = ({ children, input, basisPath, extendLoader }) => {
6515
6761
  const texture = useKTX2(input, basisPath, extendLoader);
6516
6762
  return /* @__PURE__ */ React.createElement(React.Fragment, null, children?.(texture));
6517
6763
  };
6518
6764
 
6765
+ const useVariants = (model, inVariant) => {
6766
+ const [activeVariant, setActiveVariant] = useState(null);
6767
+ const [materials, setMaterials] = useState([]);
6768
+ useEffect(() => {
6769
+ model.parser.getDependencies("material").then((materials2) => {
6770
+ setMaterials(materials2);
6771
+ });
6772
+ }, [model]);
6773
+ const variants = useMemo(() => {
6774
+ return model.userData.gltfExtensions?.KHR_materials_variants?.variants;
6775
+ }, [model]);
6776
+ const applyVariant = useCallback(
6777
+ (variantIndex) => {
6778
+ model.scene.traverse(async (object) => {
6779
+ if (!("isMesh" in object) || !object.userData.gltfExtensions) return;
6780
+ const meshObject = object;
6781
+ const meshVariantDef = meshObject.userData.gltfExtensions.KHR_materials_variants;
6782
+ if (!meshVariantDef) return;
6783
+ if (!meshObject.userData.originalMaterial) meshObject.userData.originalMaterial = meshObject.material;
6784
+ const mapping = meshVariantDef.mappings.find((mapping2) => mapping2.variants.includes(variantIndex));
6785
+ if (mapping) {
6786
+ meshObject.material = await model.parser.getDependency("material", mapping.material);
6787
+ model.parser.assignFinalMaterial(meshObject);
6788
+ } else meshObject.material = meshObject.userData.originalMaterial;
6789
+ if (Array.isArray(meshObject.material)) for (const mat of meshObject.material) mat.needsUpdate = true;
6790
+ else meshObject.material.needsUpdate = true;
6791
+ });
6792
+ },
6793
+ [model]
6794
+ );
6795
+ const setVariant = useCallback(
6796
+ (variantName) => {
6797
+ if (!variants) return;
6798
+ const newVariant = variantName && variants.some((v) => v.name === variantName) ? variantName : null;
6799
+ setActiveVariant(newVariant);
6800
+ },
6801
+ [variants]
6802
+ );
6803
+ useEffect(() => {
6804
+ if (!variants) return;
6805
+ const variantIndex = variants.findIndex((v) => v.name === activeVariant);
6806
+ applyVariant(variantIndex > -1 ? variantIndex : 0);
6807
+ }, [variants, activeVariant, applyVariant]);
6808
+ useEffect(() => {
6809
+ setVariant(inVariant ?? null);
6810
+ }, [inVariant, setVariant]);
6811
+ return { variants, activeVariant, setVariant, materials };
6812
+ };
6813
+
6519
6814
  const WebcamVideoTexture = /* @__PURE__ */ forwardRef(
6520
6815
  ({
6521
6816
  constraints = {
@@ -6703,6 +6998,7 @@ function useEffectfulState(fn, deps = [], cb) {
6703
6998
  }
6704
6999
 
6705
7000
  function Stats({ showPanel = 0, className, parent }) {
7001
+ React.useEffect(() => void console.warn("drei: <Stats /> is deprecated, use <StatsGl /> instead."), []);
6706
7002
  const stats = useEffectfulState(() => new StatsImpl(), []);
6707
7003
  React.useEffect(() => {
6708
7004
  if (stats) {
@@ -6731,6 +7027,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
6731
7027
  const stats2 = new Stats$1({
6732
7028
  ...props
6733
7029
  });
7030
+ stats2.init(renderer);
6734
7031
  return stats2;
6735
7032
  }, [renderer]);
6736
7033
  React.useImperativeHandle(fref, () => stats.domElement, [stats]);
@@ -6748,7 +7045,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
6748
7045
  return () => {
6749
7046
  if (classNames.length) stats.domElement.classList.remove(...classNames);
6750
7047
  node?.removeChild(stats.domElement);
6751
- stats.end();
7048
+ stats.dispose();
6752
7049
  };
6753
7050
  }
6754
7051
  }, [parent, stats, className, id, clearStatsGlStyle]);
@@ -6756,7 +7053,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
6756
7053
  () => {
6757
7054
  stats.begin();
6758
7055
  },
6759
- { before: "render" }
7056
+ { before: "update" }
6760
7057
  );
6761
7058
  useFrame(
6762
7059
  () => {
@@ -6806,11 +7103,11 @@ const RenderCubeTexture = /* @__PURE__ */ React.forwardRef(
6806
7103
  depthBuffer,
6807
7104
  generateMipmaps
6808
7105
  };
6809
- const fboA2 = new THREE.WebGLCubeRenderTarget(fboSize, settings);
7106
+ const fboA2 = new WebGLCubeRenderTarget(fboSize, settings);
6810
7107
  fboA2.texture.isRenderTargetTexture = !flip;
6811
7108
  fboA2.texture.flipY = true;
6812
7109
  fboA2.texture.type = THREE.HalfFloatType;
6813
- const fboB2 = new THREE.WebGLCubeRenderTarget(fboSize, settings);
7110
+ const fboB2 = new WebGLCubeRenderTarget(fboSize, settings);
6814
7111
  fboB2.texture.isRenderTargetTexture = !flip;
6815
7112
  fboB2.texture.flipY = true;
6816
7113
  fboB2.texture.type = THREE.HalfFloatType;
@@ -7139,8 +7436,9 @@ const TUNNEL_KEY = "__drei_view_tunnel__";
7139
7436
  const tracked = globalThis[TUNNEL_KEY] || (globalThis[TUNNEL_KEY] = tunnel());
7140
7437
  function computeContainerPosition(canvasSize, trackRect, forceEven) {
7141
7438
  const { right, top: trackTop, left: trackLeft, bottom: trackBottom, width, height } = trackRect;
7142
- const isOffscreen = trackRect.bottom < 0 || trackTop > canvasSize.height || right < 0 || trackRect.left > canvasSize.width;
7143
7439
  const canvasBottom = canvasSize.top + canvasSize.height;
7440
+ const canvasRight = canvasSize.left + canvasSize.width;
7441
+ const isOffscreen = trackBottom < canvasSize.top || trackTop > canvasBottom || right < canvasSize.left || trackLeft > canvasRight;
7144
7442
  const rawBottom = canvasBottom - trackBottom;
7145
7443
  const rawLeft = trackLeft - canvasSize.left;
7146
7444
  const rawTop = trackTop - canvasSize.top;
@@ -7700,12 +7998,12 @@ useEnvironment.preload = (preloadOptions) => {
7700
7998
  if (extensions) extensions(loader2);
7701
7999
  });
7702
8000
  };
7703
- const clearDefaultOptins = {
8001
+ const clearDefaultOptions = {
7704
8002
  files: defaultFiles,
7705
8003
  preset: void 0
7706
8004
  };
7707
8005
  useEnvironment.clear = (clearOptions) => {
7708
- const options = { ...clearDefaultOptins, ...clearOptions };
8006
+ const options = { ...clearDefaultOptions, ...clearOptions };
7709
8007
  let { files } = options;
7710
8008
  const { preset } = options;
7711
8009
  if (preset) {
@@ -8399,9 +8697,14 @@ function Select({
8399
8697
  const oldControlsEnabled = controls?.enabled;
8400
8698
  let isDown = false;
8401
8699
  function prepareRay(event, vec) {
8402
- const { offsetX, offsetY } = event;
8700
+ const canvas = gl.domElement;
8701
+ const rect = canvas.getBoundingClientRect();
8702
+ const x = event.clientX - rect.left;
8703
+ const y = event.clientY - rect.top;
8403
8704
  const { width, height } = size;
8404
- vec.set(offsetX / width * 2 - 1, -(offsetY / height) * 2 + 1);
8705
+ const normalizedX = x / width * 2 - 1;
8706
+ const normalizedY = -(y / height) * 2 + 1;
8707
+ vec.set(normalizedX, normalizedY, -1);
8405
8708
  }
8406
8709
  function onSelectStart(event) {
8407
8710
  if (controls) controls.enabled = false;
@@ -8480,4 +8783,4 @@ function useSelect() {
8480
8783
  return React.useContext(context);
8481
8784
  }
8482
8785
 
8483
- export { AdaptiveDpr, AdaptiveEvents, ArcballControls, BBAnchor, Backdrop, Billboard, Bounds, Box, CameraShake, Capsule, CatmullRomLine, Center, Circle, Clone, Cloud, CloudInstance, Clouds, ComputedAttribute, Cone, CubeCamera, CubeTexture, CubicBezierLine, CurveModifier, CycleRaycast, Cylinder, Decal, Detailed, DetectGPU, DeviceOrientationControls, Dodecahedron, DragControls, Edges, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, Example, Extrude, Fbo, Fbx, FirstPersonControls, Fisheye, Float, FlyControls, GizmoHelper, GizmoViewcube, GizmoViewport, Gltf, Helper, Html, Hud, Icosahedron, Instance, InstancedAttribute, Instances, IsObject, KeyboardControls, Ktx2, Lathe, Lightformer, Loader, MapControls, Mask, MatcapTexture, Merged, MotionPathControls, NormalTexture, Octahedron, OrbitControls, OrthographicCamera, PerformanceMonitor, PerspectiveCamera, PivotControls, Plane, Point, PointMaterial, PointMaterialImpl, PointerLockControls, Points, PointsBuffer, Polyhedron, PositionMesh, PositionPoint, PositionalAudio, Preload, PresentationControls, Progress, QuadraticBezierLine, RenderCubeTexture, RenderTexture, Resize, Ring, RoundedBox, RoundedBoxGeometry, Sampler, ScreenQuad, ScreenSizer, ScreenSpace, ScreenVideoTexture, Scroll, ScrollControls, Select, Shadow, Shape, Sky, Sphere, SpriteAnimator, Stage, Stats, StatsGl, Svg, Tetrahedron, Text3D, Texture, Torus, TorusKnot, TrackballControls, TrailTexture, TransformControls, Tube, VideoTexture, View, WebcamVideoTexture, calcPosFromAngles, checkIfFrameIsEmpty, createInstances, getFirstFrame, meshBounds, presetsObj, useAnimations, useAspect, useBounds, useContextBridge, useCubeCamera, useCubeTexture, useCursor, useCustomRaycast, useDepthBuffer, useDetectGPU, useEnvironment, useFBO, useFBX, useFont, useGLTF, useGizmoContext, useHelper, useIntersect, useKTX2, useKeyboardControls, useMask, useMatcapTexture, useMotion, useNormalTexture, usePerformanceMonitor, useProgress, useScroll, useSelect, useSpriteAnimator, useSpriteLoader, useSurfaceSampler, useTexture, useTrailTexture, useVideoTexture };
8786
+ export { AdaptiveDpr, AdaptiveEvents, ArcballControls, BBAnchor, Backdrop, Billboard, Bounds, Box, CameraShake, Capsule, CatmullRomLine, Center, Circle, Clone, Cloud, CloudInstance, Clouds, ComputedAttribute, Cone, CubeCamera, CubeTexture, CubicBezierLine, CurveModifier, CycleRaycast, Cylinder, Decal, Detailed, DetectGPU, DeviceOrientationControls, Dodecahedron, DragControls, Edges, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, Example, Extrude, Fbo, Fbx, FirstPersonControls, Fisheye, Float, FlyControls, GizmoHelper, GizmoViewcube, GizmoViewport, Gltf, Helper, Html, Hud, Icosahedron, Instance, InstancedAttribute, Instances, IsObject, KeyboardControls, Ktx2, Lathe, Lightformer, Loader, MapControls, Mask, MatcapTexture, Merged, MotionPathControls, NormalTexture, Octahedron, OrbitControls, OrthographicCamera, PerformanceMonitor, PerspectiveCamera, PivotControls, Plane, Point, PointMaterial, PointMaterialImpl, PointerLockControls, Points, PointsBuffer, Polyhedron, PositionMesh, PositionPoint, PositionalAudio, Preload, PresentationControls, Progress, QuadraticBezierLine, RenderCubeTexture, RenderTexture, Resize, Ring, RoundedBox, RoundedBoxGeometry, Sampler, ScreenQuad, ScreenSizer, ScreenSpace, ScreenVideoTexture, Scroll, ScrollControls, Select, Shadow, Shape, Sky, Sphere, SpriteAnimator, Stage, Stats, StatsGl, Svg, Tetrahedron, Text3D, Texture, Torus, TorusKnot, TrackballControls, TrailTexture, TransformControls, Tube, VideoTexture, View, WebcamVideoTexture, calcPosFromAngles, checkIfFrameIsEmpty, createInstances, getFirstFrame, meshBounds, presetsObj, useAnimations, useAspect, useBounds, useContextBridge, useCubeCamera, useCubeTexture, useCursor, useCustomRaycast, useDepthBuffer, useDetectGPU, useEnvironment, useFBO, useFBX, useFont, useGLTF, useGizmoContext, useHelper, useIntersect, useKTX2, useKeyboardControls, useMask, useMatcapTexture, useMotion, useNormalTexture, usePerformanceMonitor, useProgress, useScroll, useSelect, useSpriteAnimator, useSpriteLoader, useSurfaceSampler, useTexture, useTrailTexture, useVariants, useVideoTexture };