@react-three/drei 11.0.0-alpha.4 → 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/README.md +17 -1
- package/core/index.d.mts +249 -108
- package/core/index.d.ts +249 -108
- package/core/index.mjs +919 -692
- package/experimental/index.d.mts +24 -4
- package/experimental/index.d.ts +24 -4
- package/experimental/index.mjs +1 -0
- package/external/index.d.mts +42 -6
- package/external/index.d.ts +42 -6
- package/external/index.mjs +4 -4
- package/index.d.mts +266 -110
- package/index.d.ts +266 -110
- package/index.mjs +920 -693
- package/legacy/index.d.mts +344 -142
- package/legacy/index.d.ts +344 -142
- package/legacy/index.mjs +1536 -803
- package/native/index.d.mts +385 -489
- package/native/index.d.ts +385 -489
- package/native/index.mjs +2047 -2434
- package/package.json +8 -9
- package/webgpu/index.d.mts +416 -332
- package/webgpu/index.d.ts +416 -332
- package/webgpu/index.mjs +2273 -1880
package/index.mjs
CHANGED
|
@@ -2,10 +2,8 @@ import * as React from 'react';
|
|
|
2
2
|
import { forwardRef, useImperativeHandle, useMemo, useEffect, useCallback, useRef, useLayoutEffect, useState, Fragment, createContext, useContext, Suspense } from 'react';
|
|
3
3
|
import { useThree, useFrame, extend, createPortal, applyProps, useInstanceHandle, context as context$9, useLoader, 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, Object3D, WebGLCubeRenderTarget, HalfFloatType, CubeCamera as CubeCamera$1, MathUtils, TextureLoader, Texture as Texture$1, MeshLambertMaterial,
|
|
5
|
+
import { REVISION, WebGLRenderTarget, Frustum, Matrix4, Vector3, Vector4, Vector2, Color, InstancedInterleavedBuffer, InterleavedBufferAttribute, Object3D, WebGLCubeRenderTarget, HalfFloatType, CubeCamera as CubeCamera$1, EventDispatcher, Euler, Quaternion, MathUtils, TextureLoader, Texture as Texture$1, MeshLambertMaterial, DynamicDrawUsage, CatmullRomCurve3, CubicBezierCurve3, QuadraticBezierCurve3, Shape as Shape$1, 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, Mesh, Spherical } from 'three';
|
|
6
6
|
import { ArcballControls as ArcballControls$1 } from 'three/examples/jsm/controls/ArcballControls.js';
|
|
7
|
-
import { DeviceOrientationControls as DeviceOrientationControls$1 } from 'three-stdlib';
|
|
8
|
-
import { useGesture } from '@use-gesture/react';
|
|
9
7
|
import { FirstPersonControls as FirstPersonControls$1 } from 'three/examples/jsm/controls/FirstPersonControls.js';
|
|
10
8
|
import { FlyControls as FlyControls$1 } from 'three/examples/jsm/controls/FlyControls.js';
|
|
11
9
|
import { create as create$1 } from 'zustand';
|
|
@@ -14,6 +12,7 @@ import { MapControls as MapControls$1 } from 'three/examples/jsm/controls/MapCon
|
|
|
14
12
|
import { misc, easing } from 'maath';
|
|
15
13
|
import { OrbitControls as OrbitControls$1 } from 'three/addons/controls/OrbitControls.js';
|
|
16
14
|
import { PointerLockControls as PointerLockControls$1 } from 'three/examples/jsm/controls/PointerLockControls.js';
|
|
15
|
+
import { useGesture } from '@use-gesture/react';
|
|
17
16
|
import * as ReactDOM from 'react-dom/client';
|
|
18
17
|
import { TrackballControls as TrackballControls$1 } from 'three/examples/jsm/controls/TrackballControls.js';
|
|
19
18
|
import { SimplexNoise } from 'three/examples/jsm/math/SimplexNoise.js';
|
|
@@ -32,7 +31,6 @@ import { TransformControls as TransformControls$1 } from 'three/examples/jsm/con
|
|
|
32
31
|
import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils.js';
|
|
33
32
|
import { MeshSurfaceSampler } from 'three/examples/jsm/math/MeshSurfaceSampler.js';
|
|
34
33
|
import { SVGLoader } from 'three/examples/jsm/loaders/SVGLoader.js';
|
|
35
|
-
import { Events } from 'hls.js';
|
|
36
34
|
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
|
|
37
35
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
38
36
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
@@ -184,6 +182,7 @@ function shaderMaterial(uniforms, vertexShader, fragmentShader, onInit) {
|
|
|
184
182
|
});
|
|
185
183
|
}
|
|
186
184
|
this.uniforms = THREE.UniformsUtils.clone(this.uniforms);
|
|
185
|
+
Object.assign(this, parameters);
|
|
187
186
|
}
|
|
188
187
|
};
|
|
189
188
|
}
|
|
@@ -200,7 +199,7 @@ const version = /* @__PURE__ */ getVersion();
|
|
|
200
199
|
function isLight(object) {
|
|
201
200
|
return object.isLight;
|
|
202
201
|
}
|
|
203
|
-
function isGeometry
|
|
202
|
+
function isGeometry(object) {
|
|
204
203
|
return !!object.geometry;
|
|
205
204
|
}
|
|
206
205
|
const accumulativeContext = /* @__PURE__ */ React.createContext(
|
|
@@ -445,7 +444,7 @@ vec3 texelOld = texture2D(previousShadowMap, vUv).rgb;
|
|
|
445
444
|
this.lights = [];
|
|
446
445
|
this.meshes = [];
|
|
447
446
|
this.scene.traverse((object) => {
|
|
448
|
-
if (isGeometry
|
|
447
|
+
if (isGeometry(object)) {
|
|
449
448
|
this.meshes.push({ object, material: object.material });
|
|
450
449
|
} else if (isLight(object)) {
|
|
451
450
|
this.lights.push({ object, intensity: object.intensity });
|
|
@@ -1334,6 +1333,81 @@ const ArcballControls = /* @__PURE__ */ forwardRef(
|
|
|
1334
1333
|
}
|
|
1335
1334
|
);
|
|
1336
1335
|
|
|
1336
|
+
let DeviceOrientationControls$1 = class DeviceOrientationControls extends EventDispatcher {
|
|
1337
|
+
object;
|
|
1338
|
+
changeEvent = { type: "change" };
|
|
1339
|
+
EPS = 1e-6;
|
|
1340
|
+
enabled = true;
|
|
1341
|
+
deviceOrientation = { alpha: 0, beta: 0, gamma: 0 };
|
|
1342
|
+
screenOrientation = 0;
|
|
1343
|
+
alphaOffset = 0;
|
|
1344
|
+
// radians
|
|
1345
|
+
constructor(object) {
|
|
1346
|
+
super();
|
|
1347
|
+
this.object = object;
|
|
1348
|
+
this.object.rotation.reorder("YXZ");
|
|
1349
|
+
this.connect();
|
|
1350
|
+
}
|
|
1351
|
+
onDeviceOrientationChangeEvent = (event) => {
|
|
1352
|
+
this.deviceOrientation = event;
|
|
1353
|
+
};
|
|
1354
|
+
onScreenOrientationChangeEvent = () => {
|
|
1355
|
+
this.screenOrientation = window.orientation || 0;
|
|
1356
|
+
};
|
|
1357
|
+
// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
|
|
1358
|
+
zee = new Vector3(0, 0, 1);
|
|
1359
|
+
euler = new Euler();
|
|
1360
|
+
q0 = new Quaternion();
|
|
1361
|
+
q1 = new Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
|
|
1362
|
+
// - PI/2 around the x-axis
|
|
1363
|
+
setObjectQuaternion = (quaternion, alpha, beta, gamma, orient) => {
|
|
1364
|
+
this.euler.set(beta, alpha, -gamma, "YXZ");
|
|
1365
|
+
quaternion.setFromEuler(this.euler);
|
|
1366
|
+
quaternion.multiply(this.q1);
|
|
1367
|
+
quaternion.multiply(this.q0.setFromAxisAngle(this.zee, -orient));
|
|
1368
|
+
};
|
|
1369
|
+
connect = () => {
|
|
1370
|
+
this.onScreenOrientationChangeEvent();
|
|
1371
|
+
if (window.DeviceOrientationEvent !== void 0 && // @ts-ignore
|
|
1372
|
+
typeof window.DeviceOrientationEvent.requestPermission === "function") {
|
|
1373
|
+
window.DeviceOrientationEvent.requestPermission().then((response) => {
|
|
1374
|
+
if (response == "granted") {
|
|
1375
|
+
window.addEventListener("orientationchange", this.onScreenOrientationChangeEvent);
|
|
1376
|
+
window.addEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
|
|
1377
|
+
}
|
|
1378
|
+
}).catch((error) => {
|
|
1379
|
+
console.error("THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:", error);
|
|
1380
|
+
});
|
|
1381
|
+
} else {
|
|
1382
|
+
window.addEventListener("orientationchange", this.onScreenOrientationChangeEvent);
|
|
1383
|
+
window.addEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
|
|
1384
|
+
}
|
|
1385
|
+
this.enabled = true;
|
|
1386
|
+
};
|
|
1387
|
+
disconnect = () => {
|
|
1388
|
+
window.removeEventListener("orientationchange", this.onScreenOrientationChangeEvent);
|
|
1389
|
+
window.removeEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
|
|
1390
|
+
this.enabled = false;
|
|
1391
|
+
};
|
|
1392
|
+
lastQuaternion = new Quaternion();
|
|
1393
|
+
update = () => {
|
|
1394
|
+
if (this.enabled === false) return;
|
|
1395
|
+
const device = this.deviceOrientation;
|
|
1396
|
+
if (device) {
|
|
1397
|
+
const alpha = device.alpha ? MathUtils.degToRad(device.alpha) + this.alphaOffset : 0;
|
|
1398
|
+
const beta = device.beta ? MathUtils.degToRad(device.beta) : 0;
|
|
1399
|
+
const gamma = device.gamma ? MathUtils.degToRad(device.gamma) : 0;
|
|
1400
|
+
const orient = this.screenOrientation ? MathUtils.degToRad(this.screenOrientation) : 0;
|
|
1401
|
+
this.setObjectQuaternion(this.object.quaternion, alpha, beta, gamma, orient);
|
|
1402
|
+
if (8 * (1 - this.lastQuaternion.dot(this.object.quaternion)) > this.EPS) {
|
|
1403
|
+
this.lastQuaternion.copy(this.object.quaternion);
|
|
1404
|
+
this.dispatchEvent(this.changeEvent);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
dispose = () => this.disconnect();
|
|
1409
|
+
};
|
|
1410
|
+
|
|
1337
1411
|
const DeviceOrientationControls = /* @__PURE__ */ React.forwardRef(
|
|
1338
1412
|
(props, ref) => {
|
|
1339
1413
|
const { camera, onChange, makeDefault, ...rest } = props;
|
|
@@ -1369,11 +1443,11 @@ const DeviceOrientationControls = /* @__PURE__ */ React.forwardRef(
|
|
|
1369
1443
|
);
|
|
1370
1444
|
|
|
1371
1445
|
const initialModelPosition = /* @__PURE__ */ new THREE.Vector3();
|
|
1372
|
-
const mousePosition2D = /* @__PURE__ */ new THREE.Vector2();
|
|
1373
1446
|
const mousePosition3D = /* @__PURE__ */ new THREE.Vector3();
|
|
1374
1447
|
const dragOffset = /* @__PURE__ */ new THREE.Vector3();
|
|
1375
1448
|
const dragPlaneNormal = /* @__PURE__ */ new THREE.Vector3();
|
|
1376
1449
|
const dragPlane = /* @__PURE__ */ new THREE.Plane();
|
|
1450
|
+
const startPointerPos = /* @__PURE__ */ new THREE.Vector3();
|
|
1377
1451
|
const DragControls = React.forwardRef(
|
|
1378
1452
|
({
|
|
1379
1453
|
autoTransform = true,
|
|
@@ -1389,89 +1463,132 @@ const DragControls = React.forwardRef(
|
|
|
1389
1463
|
...props
|
|
1390
1464
|
}, fRef) => {
|
|
1391
1465
|
const defaultControls = useThree((state) => state.controls);
|
|
1392
|
-
const { camera,
|
|
1466
|
+
const { camera, invalidate } = useThree();
|
|
1393
1467
|
const ref = React.useRef(null);
|
|
1394
|
-
const
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
dragPlane.setFromNormalAndCoplanarPoint(dragPlaneNormal, mousePosition3D);
|
|
1428
|
-
raycaster.ray.intersectPlane(dragPlane, mousePosition3D);
|
|
1429
|
-
const previousLocalMatrix = ref.current.matrix.clone();
|
|
1430
|
-
const previousWorldMatrix = ref.current.matrixWorld.clone();
|
|
1431
|
-
const intendedNewPosition = new THREE.Vector3(
|
|
1432
|
-
mousePosition3D.x - dragOffset.x,
|
|
1433
|
-
mousePosition3D.y - dragOffset.y,
|
|
1434
|
-
mousePosition3D.z - dragOffset.z
|
|
1435
|
-
);
|
|
1436
|
-
if (dragLimits) {
|
|
1437
|
-
intendedNewPosition.x = dragLimits[0] ? Math.max(Math.min(intendedNewPosition.x, dragLimits[0][1]), dragLimits[0][0]) : intendedNewPosition.x;
|
|
1438
|
-
intendedNewPosition.y = dragLimits[1] ? Math.max(Math.min(intendedNewPosition.y, dragLimits[1][1]), dragLimits[1][0]) : intendedNewPosition.y;
|
|
1439
|
-
intendedNewPosition.z = dragLimits[2] ? Math.max(Math.min(intendedNewPosition.z, dragLimits[2][1]), dragLimits[2][0]) : intendedNewPosition.z;
|
|
1440
|
-
}
|
|
1441
|
-
if (autoTransform) {
|
|
1442
|
-
ref.current.matrix.setPosition(intendedNewPosition);
|
|
1443
|
-
const deltaLocalMatrix = ref.current.matrix.clone().multiply(previousLocalMatrix.invert());
|
|
1444
|
-
const deltaWorldMatrix = ref.current.matrix.clone().multiply(previousWorldMatrix.invert());
|
|
1445
|
-
onDrag && onDrag(ref.current.matrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
1446
|
-
} else {
|
|
1447
|
-
const tempMatrix = new THREE.Matrix4().copy(ref.current.matrix);
|
|
1448
|
-
tempMatrix.setPosition(intendedNewPosition);
|
|
1449
|
-
const deltaLocalMatrix = tempMatrix.clone().multiply(previousLocalMatrix.invert());
|
|
1450
|
-
const deltaWorldMatrix = tempMatrix.clone().multiply(previousWorldMatrix.invert());
|
|
1451
|
-
onDrag && onDrag(tempMatrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
1468
|
+
const dragState = React.useRef({
|
|
1469
|
+
active: false,
|
|
1470
|
+
intentional: false,
|
|
1471
|
+
// Has moved past threshold
|
|
1472
|
+
pointerId: -1
|
|
1473
|
+
});
|
|
1474
|
+
const threshold = dragConfig?.threshold ?? 0;
|
|
1475
|
+
const filterTaps = dragConfig?.filterTaps ?? true;
|
|
1476
|
+
const handlePointerDown = React.useCallback(
|
|
1477
|
+
(event) => {
|
|
1478
|
+
event.stopPropagation();
|
|
1479
|
+
event.target.setPointerCapture(event.pointerId);
|
|
1480
|
+
dragState.current.active = true;
|
|
1481
|
+
dragState.current.intentional = threshold === 0;
|
|
1482
|
+
dragState.current.pointerId = event.pointerId;
|
|
1483
|
+
if (defaultControls) defaultControls.enabled = false;
|
|
1484
|
+
ref.current.matrix.decompose(initialModelPosition, new THREE.Quaternion(), new THREE.Vector3());
|
|
1485
|
+
mousePosition3D.copy(event.point);
|
|
1486
|
+
startPointerPos.copy(event.point);
|
|
1487
|
+
dragOffset.copy(mousePosition3D).sub(initialModelPosition);
|
|
1488
|
+
if (!axisLock) {
|
|
1489
|
+
camera.getWorldDirection(dragPlaneNormal).negate();
|
|
1490
|
+
} else {
|
|
1491
|
+
switch (axisLock) {
|
|
1492
|
+
case "x":
|
|
1493
|
+
dragPlaneNormal.set(1, 0, 0);
|
|
1494
|
+
break;
|
|
1495
|
+
case "y":
|
|
1496
|
+
dragPlaneNormal.set(0, 1, 0);
|
|
1497
|
+
break;
|
|
1498
|
+
case "z":
|
|
1499
|
+
dragPlaneNormal.set(0, 0, 1);
|
|
1500
|
+
break;
|
|
1452
1501
|
}
|
|
1453
|
-
invalidate();
|
|
1454
|
-
},
|
|
1455
|
-
onDragEnd: () => {
|
|
1456
|
-
if (defaultControls) defaultControls.enabled = true;
|
|
1457
|
-
onDragEnd && onDragEnd();
|
|
1458
|
-
invalidate();
|
|
1459
1502
|
}
|
|
1503
|
+
dragPlane.setFromNormalAndCoplanarPoint(dragPlaneNormal, mousePosition3D);
|
|
1504
|
+
if (dragState.current.intentional) {
|
|
1505
|
+
onDragStart && onDragStart(initialModelPosition);
|
|
1506
|
+
}
|
|
1507
|
+
invalidate();
|
|
1460
1508
|
},
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1509
|
+
[defaultControls, camera, axisLock, threshold, onDragStart, invalidate]
|
|
1510
|
+
);
|
|
1511
|
+
const handlePointerMove = React.useCallback(
|
|
1512
|
+
(event) => {
|
|
1513
|
+
if (!dragState.current.active || event.pointerId !== dragState.current.pointerId) return;
|
|
1514
|
+
const intersection = event.ray.intersectPlane(dragPlane, mousePosition3D);
|
|
1515
|
+
if (!intersection) return;
|
|
1516
|
+
if (!dragState.current.intentional) {
|
|
1517
|
+
const distance = mousePosition3D.distanceTo(startPointerPos);
|
|
1518
|
+
if (distance < threshold) return;
|
|
1519
|
+
dragState.current.intentional = true;
|
|
1520
|
+
onDragStart && onDragStart(initialModelPosition);
|
|
1466
1521
|
}
|
|
1467
|
-
|
|
1522
|
+
const previousLocalMatrix = ref.current.matrix.clone();
|
|
1523
|
+
const previousWorldMatrix = ref.current.matrixWorld.clone();
|
|
1524
|
+
const intendedNewPosition = new THREE.Vector3(
|
|
1525
|
+
mousePosition3D.x - dragOffset.x,
|
|
1526
|
+
mousePosition3D.y - dragOffset.y,
|
|
1527
|
+
mousePosition3D.z - dragOffset.z
|
|
1528
|
+
);
|
|
1529
|
+
if (dragLimits) {
|
|
1530
|
+
intendedNewPosition.x = dragLimits[0] ? Math.max(Math.min(intendedNewPosition.x, dragLimits[0][1]), dragLimits[0][0]) : intendedNewPosition.x;
|
|
1531
|
+
intendedNewPosition.y = dragLimits[1] ? Math.max(Math.min(intendedNewPosition.y, dragLimits[1][1]), dragLimits[1][0]) : intendedNewPosition.y;
|
|
1532
|
+
intendedNewPosition.z = dragLimits[2] ? Math.max(Math.min(intendedNewPosition.z, dragLimits[2][1]), dragLimits[2][0]) : intendedNewPosition.z;
|
|
1533
|
+
}
|
|
1534
|
+
if (autoTransform) {
|
|
1535
|
+
ref.current.matrix.setPosition(intendedNewPosition);
|
|
1536
|
+
const deltaLocalMatrix = ref.current.matrix.clone().multiply(previousLocalMatrix.invert());
|
|
1537
|
+
const deltaWorldMatrix = ref.current.matrix.clone().multiply(previousWorldMatrix.invert());
|
|
1538
|
+
onDrag && onDrag(ref.current.matrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
1539
|
+
} else {
|
|
1540
|
+
const tempMatrix = new THREE.Matrix4().copy(ref.current.matrix);
|
|
1541
|
+
tempMatrix.setPosition(intendedNewPosition);
|
|
1542
|
+
const deltaLocalMatrix = tempMatrix.clone().multiply(previousLocalMatrix.invert());
|
|
1543
|
+
const deltaWorldMatrix = tempMatrix.clone().multiply(previousWorldMatrix.invert());
|
|
1544
|
+
onDrag && onDrag(tempMatrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
1545
|
+
}
|
|
1546
|
+
invalidate();
|
|
1547
|
+
},
|
|
1548
|
+
[autoTransform, dragLimits, threshold, onDragStart, onDrag, invalidate]
|
|
1549
|
+
);
|
|
1550
|
+
const handlePointerUp = React.useCallback(
|
|
1551
|
+
(event) => {
|
|
1552
|
+
if (!dragState.current.active || event.pointerId !== dragState.current.pointerId) return;
|
|
1553
|
+
event.target.releasePointerCapture(event.pointerId);
|
|
1554
|
+
const wasIntentional = dragState.current.intentional;
|
|
1555
|
+
dragState.current.active = false;
|
|
1556
|
+
dragState.current.intentional = false;
|
|
1557
|
+
dragState.current.pointerId = -1;
|
|
1558
|
+
if (defaultControls) defaultControls.enabled = true;
|
|
1559
|
+
if (wasIntentional || !filterTaps) {
|
|
1560
|
+
onDragEnd && onDragEnd();
|
|
1561
|
+
}
|
|
1562
|
+
invalidate();
|
|
1563
|
+
},
|
|
1564
|
+
[defaultControls, filterTaps, onDragEnd, invalidate]
|
|
1468
1565
|
);
|
|
1566
|
+
const handlePointerEnter = React.useCallback(() => {
|
|
1567
|
+
onHover && onHover(true);
|
|
1568
|
+
}, [onHover]);
|
|
1569
|
+
const handlePointerLeave = React.useCallback(() => {
|
|
1570
|
+
onHover && onHover(false);
|
|
1571
|
+
}, [onHover]);
|
|
1469
1572
|
React.useImperativeHandle(fRef, () => ref.current, []);
|
|
1470
1573
|
React.useLayoutEffect(() => {
|
|
1471
1574
|
if (!matrix) return;
|
|
1472
1575
|
ref.current.matrix = matrix;
|
|
1473
1576
|
}, [matrix]);
|
|
1474
|
-
return /* @__PURE__ */ React.createElement(
|
|
1577
|
+
return /* @__PURE__ */ React.createElement(
|
|
1578
|
+
"group",
|
|
1579
|
+
{
|
|
1580
|
+
ref,
|
|
1581
|
+
onPointerDown: handlePointerDown,
|
|
1582
|
+
onPointerMove: handlePointerMove,
|
|
1583
|
+
onPointerUp: handlePointerUp,
|
|
1584
|
+
onPointerEnter: handlePointerEnter,
|
|
1585
|
+
onPointerLeave: handlePointerLeave,
|
|
1586
|
+
matrix,
|
|
1587
|
+
matrixAutoUpdate: false,
|
|
1588
|
+
...props
|
|
1589
|
+
},
|
|
1590
|
+
children
|
|
1591
|
+
);
|
|
1475
1592
|
}
|
|
1476
1593
|
);
|
|
1477
1594
|
|
|
@@ -1573,14 +1690,23 @@ function KeyboardControls({ map, children, onChange, domElement }) {
|
|
|
1573
1690
|
obj.pressed = false;
|
|
1574
1691
|
if (up) fn(false);
|
|
1575
1692
|
};
|
|
1693
|
+
const blurHandler = () => {
|
|
1694
|
+
const resetState = map.reduce((prev, cur) => ({ ...prev, [cur.name]: false }), {});
|
|
1695
|
+
set(resetState);
|
|
1696
|
+
Object.values(keyMap).forEach((obj) => {
|
|
1697
|
+
obj.pressed = false;
|
|
1698
|
+
});
|
|
1699
|
+
};
|
|
1576
1700
|
const source = domElement || window;
|
|
1577
1701
|
source.addEventListener("keydown", downHandler, { passive: true });
|
|
1578
1702
|
source.addEventListener("keyup", upHandler, { passive: true });
|
|
1703
|
+
window.addEventListener("blur", blurHandler);
|
|
1579
1704
|
return () => {
|
|
1580
1705
|
source.removeEventListener("keydown", downHandler);
|
|
1581
1706
|
source.removeEventListener("keyup", upHandler);
|
|
1707
|
+
window.removeEventListener("blur", blurHandler);
|
|
1582
1708
|
};
|
|
1583
|
-
}, [domElement, key]);
|
|
1709
|
+
}, [domElement, key, onChange]);
|
|
1584
1710
|
return /* @__PURE__ */ React.createElement(context$8.Provider, { value: api, children });
|
|
1585
1711
|
}
|
|
1586
1712
|
function useKeyboardControls(sel) {
|
|
@@ -1602,20 +1728,28 @@ const MapControls = /* @__PURE__ */ React.forwardRef((props = { enableDamping: t
|
|
|
1602
1728
|
const controls = React.useMemo(() => new MapControls$1(explCamera), [explCamera]);
|
|
1603
1729
|
React.useEffect(() => {
|
|
1604
1730
|
controls.connect(explDomElement);
|
|
1731
|
+
return () => void controls.dispose();
|
|
1732
|
+
}, [explDomElement, controls]);
|
|
1733
|
+
React.useEffect(() => {
|
|
1605
1734
|
const callback = (e) => {
|
|
1606
1735
|
invalidate();
|
|
1607
1736
|
if (onChange) onChange(e);
|
|
1608
1737
|
};
|
|
1738
|
+
const onStartCb = (e) => {
|
|
1739
|
+
if (onStart) onStart(e);
|
|
1740
|
+
};
|
|
1741
|
+
const onEndCb = (e) => {
|
|
1742
|
+
if (onEnd) onEnd(e);
|
|
1743
|
+
};
|
|
1609
1744
|
controls.addEventListener("change", callback);
|
|
1610
|
-
|
|
1611
|
-
|
|
1745
|
+
controls.addEventListener("start", onStartCb);
|
|
1746
|
+
controls.addEventListener("end", onEndCb);
|
|
1612
1747
|
return () => {
|
|
1613
|
-
controls.
|
|
1748
|
+
controls.removeEventListener("start", onStartCb);
|
|
1749
|
+
controls.removeEventListener("end", onEndCb);
|
|
1614
1750
|
controls.removeEventListener("change", callback);
|
|
1615
|
-
if (onStart) controls.removeEventListener("start", onStart);
|
|
1616
|
-
if (onEnd) controls.removeEventListener("end", onEnd);
|
|
1617
1751
|
};
|
|
1618
|
-
}, [onChange, onStart, onEnd, controls, invalidate
|
|
1752
|
+
}, [onChange, onStart, onEnd, controls, invalidate]);
|
|
1619
1753
|
React.useEffect(() => {
|
|
1620
1754
|
if (makeDefault) {
|
|
1621
1755
|
const old = get().controls;
|
|
@@ -1623,7 +1757,9 @@ const MapControls = /* @__PURE__ */ React.forwardRef((props = { enableDamping: t
|
|
|
1623
1757
|
return () => set({ controls: old });
|
|
1624
1758
|
}
|
|
1625
1759
|
}, [makeDefault, controls]);
|
|
1626
|
-
useFrame(() =>
|
|
1760
|
+
useFrame(() => {
|
|
1761
|
+
if (controls.enabled) controls.update();
|
|
1762
|
+
}, -1);
|
|
1627
1763
|
return /* @__PURE__ */ React.createElement("primitive", { ref, object: controls, enableDamping: true, ...rest });
|
|
1628
1764
|
});
|
|
1629
1765
|
|
|
@@ -1749,20 +1885,16 @@ const OrbitControls = /* @__PURE__ */ React.forwardRef(
|
|
|
1749
1885
|
onEnd,
|
|
1750
1886
|
...restProps
|
|
1751
1887
|
}, ref) => {
|
|
1752
|
-
const invalidate = useThree(
|
|
1753
|
-
const defaultCamera = useThree((state) => state.camera);
|
|
1754
|
-
const gl = useThree((state) => state.gl);
|
|
1755
|
-
const events = useThree((state) => state.events);
|
|
1756
|
-
const setEvents = useThree((state) => state.setEvents);
|
|
1757
|
-
const set = useThree((state) => state.set);
|
|
1758
|
-
const get = useThree((state) => state.get);
|
|
1759
|
-
const performance = useThree((state) => state.performance);
|
|
1888
|
+
const { invalidate, camera: defaultCamera, renderer, events, setEvents, set, get, performance } = useThree();
|
|
1760
1889
|
const explCamera = camera || defaultCamera;
|
|
1761
|
-
const explDomElement = domElement || events.connected ||
|
|
1890
|
+
const explDomElement = domElement || events.connected || renderer.domElement;
|
|
1762
1891
|
const controls = React.useMemo(() => new OrbitControls$1(explCamera), [explCamera]);
|
|
1763
|
-
useFrame(
|
|
1764
|
-
|
|
1765
|
-
|
|
1892
|
+
useFrame(
|
|
1893
|
+
() => {
|
|
1894
|
+
if (controls.enabled) controls.update();
|
|
1895
|
+
},
|
|
1896
|
+
{ before: "update" }
|
|
1897
|
+
);
|
|
1766
1898
|
React.useEffect(() => {
|
|
1767
1899
|
if (keyEvents) {
|
|
1768
1900
|
controls.connect(keyEvents === true ? explDomElement : keyEvents);
|
|
@@ -1876,9 +2008,8 @@ function PresentationControls({
|
|
|
1876
2008
|
azimuth = [-Infinity, Infinity],
|
|
1877
2009
|
damping = 0.25
|
|
1878
2010
|
}) {
|
|
1879
|
-
const events = useThree(
|
|
1880
|
-
const
|
|
1881
|
-
const explDomElement = domElement || events.connected || gl.domElement;
|
|
2011
|
+
const { events, renderer, invalidate } = useThree();
|
|
2012
|
+
const explDomElement = domElement || events.connected || renderer.domElement;
|
|
1882
2013
|
const { size } = useThree();
|
|
1883
2014
|
const rPolar = React.useMemo(
|
|
1884
2015
|
() => [rotation[0] + polar[0], rotation[0] + polar[1]],
|
|
@@ -1895,18 +2026,20 @@ function PresentationControls({
|
|
|
1895
2026
|
React.useEffect(() => {
|
|
1896
2027
|
if (global && cursor && enabled) {
|
|
1897
2028
|
explDomElement.style.cursor = "grab";
|
|
1898
|
-
|
|
2029
|
+
renderer.domElement.style.cursor = "";
|
|
1899
2030
|
return () => {
|
|
1900
2031
|
explDomElement.style.cursor = "default";
|
|
1901
|
-
|
|
2032
|
+
renderer.domElement.style.cursor = "default";
|
|
1902
2033
|
};
|
|
1903
2034
|
}
|
|
1904
2035
|
}, [global, cursor, explDomElement, enabled]);
|
|
1905
2036
|
const [animation] = React.useState({ scale: 1, rotation: rInitial, damping });
|
|
1906
2037
|
const ref = React.useRef(null);
|
|
1907
2038
|
useFrame((state, delta) => {
|
|
1908
|
-
|
|
1909
|
-
easing.
|
|
2039
|
+
let changed = false;
|
|
2040
|
+
changed ||= easing.damp3(ref.current.scale, animation.scale, animation.damping, delta);
|
|
2041
|
+
changed ||= easing.dampE(ref.current.rotation, animation.rotation, animation.damping, delta);
|
|
2042
|
+
if (changed) state.invalidate();
|
|
1910
2043
|
});
|
|
1911
2044
|
const bind = useGesture(
|
|
1912
2045
|
{
|
|
@@ -1914,6 +2047,7 @@ function PresentationControls({
|
|
|
1914
2047
|
if (cursor && !global && enabled) explDomElement.style.cursor = last ? "auto" : "grab";
|
|
1915
2048
|
},
|
|
1916
2049
|
onDrag: ({ down, delta: [x, y], memo: [oldY, oldX] = animation.rotation || rInitial }) => {
|
|
2050
|
+
invalidate();
|
|
1917
2051
|
if (!enabled) return [y, x];
|
|
1918
2052
|
if (cursor) explDomElement.style.cursor = down ? "grabbing" : "grab";
|
|
1919
2053
|
x = MathUtils.clamp(oldX + x / size.width * Math.PI * speed, ...rAzimuth);
|
|
@@ -1922,14 +2056,27 @@ function PresentationControls({
|
|
|
1922
2056
|
animation.rotation = snap && !down ? rInitial : [y, x, 0];
|
|
1923
2057
|
animation.damping = snap && !down && typeof snap !== "boolean" ? snap : damping;
|
|
1924
2058
|
return [y, x];
|
|
2059
|
+
},
|
|
2060
|
+
onDragEnd: () => {
|
|
2061
|
+
invalidate();
|
|
1925
2062
|
}
|
|
1926
2063
|
},
|
|
1927
|
-
{ target: global ? explDomElement : void 0 }
|
|
2064
|
+
{ target: global ? explDomElement : void 0, enabled }
|
|
1928
2065
|
);
|
|
1929
2066
|
return /* @__PURE__ */ React.createElement("group", { ref, ...bind?.() }, children);
|
|
1930
2067
|
}
|
|
1931
2068
|
|
|
2069
|
+
function roundToPixelRatio(value) {
|
|
2070
|
+
const ratio = window.devicePixelRatio || 1;
|
|
2071
|
+
return Math.round(value * ratio) / ratio;
|
|
2072
|
+
}
|
|
2073
|
+
function getMaxAnisotropy(renderer) {
|
|
2074
|
+
const r = renderer;
|
|
2075
|
+
return r?.getMaxAnisotropy?.() ?? r?.capabilities?.getMaxAnisotropy?.() ?? 1;
|
|
2076
|
+
}
|
|
2077
|
+
|
|
1932
2078
|
const context$7 = /* @__PURE__ */ React.createContext(null);
|
|
2079
|
+
const rootCache = /* @__PURE__ */ new WeakMap();
|
|
1933
2080
|
function useScroll() {
|
|
1934
2081
|
return React.useContext(context$7);
|
|
1935
2082
|
}
|
|
@@ -1943,6 +2090,7 @@ function ScrollControls({
|
|
|
1943
2090
|
damping = 0.25,
|
|
1944
2091
|
maxSpeed = Infinity,
|
|
1945
2092
|
prepend = false,
|
|
2093
|
+
pixelPerfect = true,
|
|
1946
2094
|
style = {},
|
|
1947
2095
|
children
|
|
1948
2096
|
}) {
|
|
@@ -1952,6 +2100,7 @@ function ScrollControls({
|
|
|
1952
2100
|
const [fixed] = React.useState(() => document.createElement("div"));
|
|
1953
2101
|
const target = gl.domElement.parentNode;
|
|
1954
2102
|
const scroll = React.useRef(0);
|
|
2103
|
+
const disableScrollUpdate = React.useRef(false);
|
|
1955
2104
|
const state = React.useMemo(() => {
|
|
1956
2105
|
const state2 = {
|
|
1957
2106
|
el,
|
|
@@ -1964,6 +2113,7 @@ function ScrollControls({
|
|
|
1964
2113
|
delta: 0,
|
|
1965
2114
|
scroll,
|
|
1966
2115
|
pages,
|
|
2116
|
+
pixelPerfect,
|
|
1967
2117
|
// 0-1 for a range between from -> from + distance
|
|
1968
2118
|
range(from, distance2, margin = 0) {
|
|
1969
2119
|
const start = from - margin;
|
|
@@ -1982,7 +2132,7 @@ function ScrollControls({
|
|
|
1982
2132
|
}
|
|
1983
2133
|
};
|
|
1984
2134
|
return state2;
|
|
1985
|
-
}, [eps, damping, horizontal, pages]);
|
|
2135
|
+
}, [eps, damping, horizontal, pages, pixelPerfect]);
|
|
1986
2136
|
React.useEffect(() => {
|
|
1987
2137
|
el.style.position = "absolute";
|
|
1988
2138
|
el.style.width = "100%";
|
|
@@ -2032,16 +2182,20 @@ function ScrollControls({
|
|
|
2032
2182
|
const scrollLength = el[horizontal ? "scrollWidth" : "scrollHeight"];
|
|
2033
2183
|
const scrollThreshold = scrollLength - containerLength;
|
|
2034
2184
|
let current = 0;
|
|
2035
|
-
let disableScroll =
|
|
2185
|
+
let disableScroll = false;
|
|
2036
2186
|
let firstRun = true;
|
|
2037
2187
|
const onScroll = () => {
|
|
2038
2188
|
if (!enabled || firstRun) return;
|
|
2189
|
+
if (disableScrollUpdate.current) {
|
|
2190
|
+
disableScrollUpdate.current = false;
|
|
2191
|
+
return;
|
|
2192
|
+
}
|
|
2039
2193
|
invalidate();
|
|
2040
2194
|
current = el[horizontal ? "scrollLeft" : "scrollTop"];
|
|
2041
2195
|
scroll.current = current / scrollThreshold;
|
|
2042
2196
|
if (infinite) {
|
|
2043
2197
|
if (!disableScroll) {
|
|
2044
|
-
if (current >= scrollThreshold) {
|
|
2198
|
+
if (current >= scrollThreshold - 1) {
|
|
2045
2199
|
const damp = 1 - state.offset;
|
|
2046
2200
|
el[horizontal ? "scrollLeft" : "scrollTop"] = 1;
|
|
2047
2201
|
scroll.current = state.offset = -damp;
|
|
@@ -2058,11 +2212,34 @@ function ScrollControls({
|
|
|
2058
2212
|
};
|
|
2059
2213
|
el.addEventListener("scroll", onScroll, { passive: true });
|
|
2060
2214
|
requestAnimationFrame(() => firstRun = false);
|
|
2061
|
-
const
|
|
2062
|
-
|
|
2215
|
+
const onResize = () => {
|
|
2216
|
+
if (!el) return;
|
|
2217
|
+
const scrollLength2 = el[horizontal ? "scrollWidth" : "scrollHeight"];
|
|
2218
|
+
const containerLength2 = el[horizontal ? "clientWidth" : "clientHeight"];
|
|
2219
|
+
disableScrollUpdate.current = true;
|
|
2220
|
+
el[horizontal ? "scrollLeft" : "scrollTop"] = state.offset * (scrollLength2 - containerLength2);
|
|
2221
|
+
};
|
|
2222
|
+
const onWheel = (e) => {
|
|
2223
|
+
if (horizontal) {
|
|
2224
|
+
const previous = el.scrollLeft;
|
|
2225
|
+
el.scrollLeft += e.deltaY / 2;
|
|
2226
|
+
if (infinite && previous === el.scrollLeft) {
|
|
2227
|
+
onScroll();
|
|
2228
|
+
}
|
|
2229
|
+
} else if (infinite) {
|
|
2230
|
+
if (el.scrollTop <= 1 && e.deltaY < 0) {
|
|
2231
|
+
onScroll();
|
|
2232
|
+
} else if (el.scrollTop >= el.scrollHeight - el.clientHeight - 1 && e.deltaY > 0) {
|
|
2233
|
+
onScroll();
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
};
|
|
2237
|
+
if (horizontal || infinite) el.addEventListener("wheel", onWheel, { passive: true });
|
|
2238
|
+
if (horizontal) window.addEventListener("resize", onResize);
|
|
2063
2239
|
return () => {
|
|
2064
2240
|
el.removeEventListener("scroll", onScroll);
|
|
2065
|
-
if (horizontal) el.removeEventListener("wheel", onWheel);
|
|
2241
|
+
if (horizontal || infinite) el.removeEventListener("wheel", onWheel);
|
|
2242
|
+
if (horizontal) window.removeEventListener("resize", onResize);
|
|
2066
2243
|
};
|
|
2067
2244
|
}
|
|
2068
2245
|
}, [el, events, size, infinite, state, invalidate, horizontal, enabled]);
|
|
@@ -2095,10 +2272,23 @@ const ScrollHtml = React.forwardRef(
|
|
|
2095
2272
|
React.useImperativeHandle(ref, () => group.current, []);
|
|
2096
2273
|
const { width, height } = useThree((state2) => state2.size);
|
|
2097
2274
|
const fiberState = React.useContext(context$9);
|
|
2098
|
-
const root = React.useMemo(() =>
|
|
2275
|
+
const root = React.useMemo(() => {
|
|
2276
|
+
let root2 = rootCache.get(state.fixed);
|
|
2277
|
+
if (!root2) {
|
|
2278
|
+
root2 = ReactDOM.createRoot(state.fixed);
|
|
2279
|
+
rootCache.set(state.fixed, root2);
|
|
2280
|
+
}
|
|
2281
|
+
return root2;
|
|
2282
|
+
}, [state.fixed]);
|
|
2099
2283
|
useFrame(() => {
|
|
2100
2284
|
if (state.delta > state.eps) {
|
|
2101
|
-
|
|
2285
|
+
let x = state.horizontal ? -width * (state.pages - 1) * state.offset : 0;
|
|
2286
|
+
let y = state.horizontal ? 0 : height * (state.pages - 1) * -state.offset;
|
|
2287
|
+
if (state.pixelPerfect) {
|
|
2288
|
+
x = roundToPixelRatio(x);
|
|
2289
|
+
y = roundToPixelRatio(y);
|
|
2290
|
+
}
|
|
2291
|
+
group.current.style.transform = `translate3d(${x}px,${y}px,0)`;
|
|
2102
2292
|
}
|
|
2103
2293
|
});
|
|
2104
2294
|
root.render(
|
|
@@ -2466,10 +2656,10 @@ const CloudInstance = /* @__PURE__ */ React.forwardRef(
|
|
|
2466
2656
|
return /* @__PURE__ */ React.createElement("group", { ref, ...props });
|
|
2467
2657
|
}
|
|
2468
2658
|
);
|
|
2469
|
-
const Cloud = /* @__PURE__ */ React.forwardRef((props, fref) => {
|
|
2659
|
+
const Cloud = /* @__PURE__ */ React.forwardRef(({ materialFactory, ...props }, fref) => {
|
|
2470
2660
|
const parent = React.useContext(context$6);
|
|
2471
2661
|
if (parent) return /* @__PURE__ */ React.createElement(CloudInstance, { ref: fref, ...props });
|
|
2472
|
-
return /* @__PURE__ */ React.createElement(Clouds,
|
|
2662
|
+
return /* @__PURE__ */ React.createElement(Clouds, { materialFactory }, /* @__PURE__ */ React.createElement(CloudInstance, { ref: fref, ...props }));
|
|
2473
2663
|
});
|
|
2474
2664
|
|
|
2475
2665
|
const CatmullRomLine = /* @__PURE__ */ React.forwardRef(function CatmullRomLine2({
|
|
@@ -2991,7 +3181,7 @@ const Text3D = /* @__PURE__ */ React.forwardRef(
|
|
|
2991
3181
|
return {
|
|
2992
3182
|
font,
|
|
2993
3183
|
size,
|
|
2994
|
-
height,
|
|
3184
|
+
depth: height,
|
|
2995
3185
|
bevelThickness,
|
|
2996
3186
|
bevelSize,
|
|
2997
3187
|
bevelEnabled,
|
|
@@ -3027,377 +3217,6 @@ const Text3D = /* @__PURE__ */ React.forwardRef(
|
|
|
3027
3217
|
}
|
|
3028
3218
|
);
|
|
3029
3219
|
|
|
3030
|
-
const WireframeMaterialShaders = {
|
|
3031
|
-
uniforms: {
|
|
3032
|
-
strokeOpacity: 1,
|
|
3033
|
-
fillOpacity: 0.25,
|
|
3034
|
-
fillMix: 0,
|
|
3035
|
-
thickness: 0.05,
|
|
3036
|
-
colorBackfaces: false,
|
|
3037
|
-
dashInvert: true,
|
|
3038
|
-
dash: false,
|
|
3039
|
-
dashRepeats: 4,
|
|
3040
|
-
dashLength: 0.5,
|
|
3041
|
-
squeeze: false,
|
|
3042
|
-
squeezeMin: 0.2,
|
|
3043
|
-
squeezeMax: 1,
|
|
3044
|
-
stroke: /* @__PURE__ */ new THREE.Color("#ff0000"),
|
|
3045
|
-
backfaceStroke: /* @__PURE__ */ new THREE.Color("#0000ff"),
|
|
3046
|
-
fill: /* @__PURE__ */ new THREE.Color("#00ff00")
|
|
3047
|
-
},
|
|
3048
|
-
vertex: (
|
|
3049
|
-
/* glsl */
|
|
3050
|
-
`
|
|
3051
|
-
attribute vec3 barycentric;
|
|
3052
|
-
|
|
3053
|
-
varying vec3 v_edges_Barycentric;
|
|
3054
|
-
varying vec3 v_edges_Position;
|
|
3055
|
-
|
|
3056
|
-
void initWireframe() {
|
|
3057
|
-
v_edges_Barycentric = barycentric;
|
|
3058
|
-
v_edges_Position = position.xyz;
|
|
3059
|
-
}
|
|
3060
|
-
`
|
|
3061
|
-
),
|
|
3062
|
-
fragment: (
|
|
3063
|
-
/* glsl */
|
|
3064
|
-
`
|
|
3065
|
-
#ifndef PI
|
|
3066
|
-
#define PI 3.1415926535897932384626433832795
|
|
3067
|
-
#endif
|
|
3068
|
-
|
|
3069
|
-
varying vec3 v_edges_Barycentric;
|
|
3070
|
-
varying vec3 v_edges_Position;
|
|
3071
|
-
|
|
3072
|
-
uniform float strokeOpacity;
|
|
3073
|
-
uniform float fillOpacity;
|
|
3074
|
-
uniform float fillMix;
|
|
3075
|
-
uniform float thickness;
|
|
3076
|
-
uniform bool colorBackfaces;
|
|
3077
|
-
|
|
3078
|
-
// Dash
|
|
3079
|
-
uniform bool dashInvert;
|
|
3080
|
-
uniform bool dash;
|
|
3081
|
-
uniform bool dashOnly;
|
|
3082
|
-
uniform float dashRepeats;
|
|
3083
|
-
uniform float dashLength;
|
|
3084
|
-
|
|
3085
|
-
// Squeeze
|
|
3086
|
-
uniform bool squeeze;
|
|
3087
|
-
uniform float squeezeMin;
|
|
3088
|
-
uniform float squeezeMax;
|
|
3089
|
-
|
|
3090
|
-
// Colors
|
|
3091
|
-
uniform vec3 stroke;
|
|
3092
|
-
uniform vec3 backfaceStroke;
|
|
3093
|
-
uniform vec3 fill;
|
|
3094
|
-
|
|
3095
|
-
// This is like
|
|
3096
|
-
float wireframe_aastep(float threshold, float dist) {
|
|
3097
|
-
float afwidth = fwidth(dist) * 0.5;
|
|
3098
|
-
return smoothstep(threshold - afwidth, threshold + afwidth, dist);
|
|
3099
|
-
}
|
|
3100
|
-
|
|
3101
|
-
float wireframe_map(float value, float min1, float max1, float min2, float max2) {
|
|
3102
|
-
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
|
3103
|
-
}
|
|
3104
|
-
|
|
3105
|
-
float getWireframe() {
|
|
3106
|
-
vec3 barycentric = v_edges_Barycentric;
|
|
3107
|
-
|
|
3108
|
-
// Distance from center of each triangle to its edges.
|
|
3109
|
-
float d = min(min(barycentric.x, barycentric.y), barycentric.z);
|
|
3110
|
-
|
|
3111
|
-
// for dashed rendering, we can use this to get the 0 .. 1 value of the line length
|
|
3112
|
-
float positionAlong = max(barycentric.x, barycentric.y);
|
|
3113
|
-
if (barycentric.y < barycentric.x && barycentric.y < barycentric.z) {
|
|
3114
|
-
positionAlong = 1.0 - positionAlong;
|
|
3115
|
-
}
|
|
3116
|
-
|
|
3117
|
-
// the thickness of the stroke
|
|
3118
|
-
float computedThickness = wireframe_map(thickness, 0.0, 1.0, 0.0, 0.34);
|
|
3119
|
-
|
|
3120
|
-
// if we want to shrink the thickness toward the center of the line segment
|
|
3121
|
-
if (squeeze) {
|
|
3122
|
-
computedThickness *= mix(squeezeMin, squeezeMax, (1.0 - sin(positionAlong * PI)));
|
|
3123
|
-
}
|
|
3124
|
-
|
|
3125
|
-
// Create dash pattern
|
|
3126
|
-
if (dash) {
|
|
3127
|
-
// here we offset the stroke position depending on whether it
|
|
3128
|
-
// should overlap or not
|
|
3129
|
-
float offset = 1.0 / dashRepeats * dashLength / 2.0;
|
|
3130
|
-
if (!dashInvert) {
|
|
3131
|
-
offset += 1.0 / dashRepeats / 2.0;
|
|
3132
|
-
}
|
|
3133
|
-
|
|
3134
|
-
// if we should animate the dash or not
|
|
3135
|
-
// if (dashAnimate) {
|
|
3136
|
-
// offset += time * 0.22;
|
|
3137
|
-
// }
|
|
3138
|
-
|
|
3139
|
-
// create the repeating dash pattern
|
|
3140
|
-
float pattern = fract((positionAlong + offset) * dashRepeats);
|
|
3141
|
-
computedThickness *= 1.0 - wireframe_aastep(dashLength, pattern);
|
|
3142
|
-
}
|
|
3143
|
-
|
|
3144
|
-
// compute the anti-aliased stroke edge
|
|
3145
|
-
float edge = 1.0 - wireframe_aastep(computedThickness, d);
|
|
3146
|
-
|
|
3147
|
-
return edge;
|
|
3148
|
-
}
|
|
3149
|
-
`
|
|
3150
|
-
)
|
|
3151
|
-
};
|
|
3152
|
-
const WireframeMaterial = /* @__PURE__ */ shaderMaterial(
|
|
3153
|
-
WireframeMaterialShaders.uniforms,
|
|
3154
|
-
WireframeMaterialShaders.vertex + /* glsl */
|
|
3155
|
-
`
|
|
3156
|
-
void main() {
|
|
3157
|
-
initWireframe();
|
|
3158
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
3159
|
-
}
|
|
3160
|
-
`,
|
|
3161
|
-
WireframeMaterialShaders.fragment + /* glsl */
|
|
3162
|
-
`
|
|
3163
|
-
void main () {
|
|
3164
|
-
// Compute color
|
|
3165
|
-
|
|
3166
|
-
float edge = getWireframe();
|
|
3167
|
-
vec4 colorStroke = vec4(stroke, edge);
|
|
3168
|
-
|
|
3169
|
-
#ifdef FLIP_SIDED
|
|
3170
|
-
colorStroke.rgb = backfaceStroke;
|
|
3171
|
-
#endif
|
|
3172
|
-
|
|
3173
|
-
vec4 colorFill = vec4(fill, fillOpacity);
|
|
3174
|
-
vec4 outColor = mix(colorFill, colorStroke, edge * strokeOpacity);
|
|
3175
|
-
|
|
3176
|
-
gl_FragColor = outColor;
|
|
3177
|
-
}
|
|
3178
|
-
`
|
|
3179
|
-
);
|
|
3180
|
-
function setWireframeOverride(material, uniforms) {
|
|
3181
|
-
material.onBeforeCompile = (shader) => {
|
|
3182
|
-
shader.uniforms = {
|
|
3183
|
-
...shader.uniforms,
|
|
3184
|
-
...uniforms
|
|
3185
|
-
};
|
|
3186
|
-
shader.vertexShader = shader.vertexShader.replace(
|
|
3187
|
-
"void main() {",
|
|
3188
|
-
`
|
|
3189
|
-
${WireframeMaterialShaders.vertex}
|
|
3190
|
-
void main() {
|
|
3191
|
-
initWireframe();
|
|
3192
|
-
`
|
|
3193
|
-
);
|
|
3194
|
-
shader.fragmentShader = shader.fragmentShader.replace(
|
|
3195
|
-
"void main() {",
|
|
3196
|
-
`
|
|
3197
|
-
${WireframeMaterialShaders.fragment}
|
|
3198
|
-
void main() {
|
|
3199
|
-
`
|
|
3200
|
-
);
|
|
3201
|
-
shader.fragmentShader = shader.fragmentShader.replace(
|
|
3202
|
-
"#include <color_fragment>",
|
|
3203
|
-
/* glsl */
|
|
3204
|
-
`
|
|
3205
|
-
#include <color_fragment>
|
|
3206
|
-
float edge = getWireframe();
|
|
3207
|
-
vec4 colorStroke = vec4(stroke, edge);
|
|
3208
|
-
#ifdef FLIP_SIDED
|
|
3209
|
-
colorStroke.rgb = backfaceStroke;
|
|
3210
|
-
#endif
|
|
3211
|
-
vec4 colorFill = vec4(mix(diffuseColor.rgb, fill, fillMix), mix(diffuseColor.a, fillOpacity, fillMix));
|
|
3212
|
-
vec4 outColor = mix(colorFill, colorStroke, edge * strokeOpacity);
|
|
3213
|
-
|
|
3214
|
-
diffuseColor.rgb = outColor.rgb;
|
|
3215
|
-
diffuseColor.a *= outColor.a;
|
|
3216
|
-
`
|
|
3217
|
-
);
|
|
3218
|
-
};
|
|
3219
|
-
material.side = THREE.DoubleSide;
|
|
3220
|
-
material.transparent = true;
|
|
3221
|
-
}
|
|
3222
|
-
function useWireframeUniforms(uniforms, props) {
|
|
3223
|
-
React.useEffect(
|
|
3224
|
-
() => void (uniforms.fillOpacity.value = props.fillOpacity ?? uniforms.fillOpacity.value),
|
|
3225
|
-
[props.fillOpacity]
|
|
3226
|
-
);
|
|
3227
|
-
React.useEffect(() => void (uniforms.fillMix.value = props.fillMix ?? uniforms.fillMix.value), [props.fillMix]);
|
|
3228
|
-
React.useEffect(
|
|
3229
|
-
() => void (uniforms.strokeOpacity.value = props.strokeOpacity ?? uniforms.strokeOpacity.value),
|
|
3230
|
-
[props.strokeOpacity]
|
|
3231
|
-
);
|
|
3232
|
-
React.useEffect(
|
|
3233
|
-
() => void (uniforms.thickness.value = props.thickness ?? uniforms.thickness.value),
|
|
3234
|
-
[props.thickness]
|
|
3235
|
-
);
|
|
3236
|
-
React.useEffect(() => void (uniforms.colorBackfaces.value = !!props.colorBackfaces), [props.colorBackfaces]);
|
|
3237
|
-
React.useEffect(() => void (uniforms.dash.value = !!props.dash), [props.dash]);
|
|
3238
|
-
React.useEffect(() => void (uniforms.dashInvert.value = !!props.dashInvert), [props.dashInvert]);
|
|
3239
|
-
React.useEffect(
|
|
3240
|
-
() => void (uniforms.dashRepeats.value = props.dashRepeats ?? uniforms.dashRepeats.value),
|
|
3241
|
-
[props.dashRepeats]
|
|
3242
|
-
);
|
|
3243
|
-
React.useEffect(
|
|
3244
|
-
() => void (uniforms.dashLength.value = props.dashLength ?? uniforms.dashLength.value),
|
|
3245
|
-
[props.dashLength]
|
|
3246
|
-
);
|
|
3247
|
-
React.useEffect(() => void (uniforms.squeeze.value = !!props.squeeze), [props.squeeze]);
|
|
3248
|
-
React.useEffect(
|
|
3249
|
-
() => void (uniforms.squeezeMin.value = props.squeezeMin ?? uniforms.squeezeMin.value),
|
|
3250
|
-
[props.squeezeMin]
|
|
3251
|
-
);
|
|
3252
|
-
React.useEffect(
|
|
3253
|
-
() => void (uniforms.squeezeMax.value = props.squeezeMax ?? uniforms.squeezeMax.value),
|
|
3254
|
-
[props.squeezeMax]
|
|
3255
|
-
);
|
|
3256
|
-
React.useEffect(
|
|
3257
|
-
() => void (uniforms.stroke.value = props.stroke ? new THREE.Color(props.stroke) : uniforms.stroke.value),
|
|
3258
|
-
[props.stroke]
|
|
3259
|
-
);
|
|
3260
|
-
React.useEffect(
|
|
3261
|
-
() => void (uniforms.fill.value = props.fill ? new THREE.Color(props.fill) : uniforms.fill.value),
|
|
3262
|
-
[props.fill]
|
|
3263
|
-
);
|
|
3264
|
-
React.useEffect(
|
|
3265
|
-
() => void (uniforms.backfaceStroke.value = props.backfaceStroke ? new THREE.Color(props.backfaceStroke) : uniforms.backfaceStroke.value),
|
|
3266
|
-
[props.backfaceStroke]
|
|
3267
|
-
);
|
|
3268
|
-
}
|
|
3269
|
-
|
|
3270
|
-
function isWithGeometry(object) {
|
|
3271
|
-
return !!object?.geometry;
|
|
3272
|
-
}
|
|
3273
|
-
function isGeometry(object) {
|
|
3274
|
-
return !!object?.isBufferGeometry;
|
|
3275
|
-
}
|
|
3276
|
-
function isRefObject$1(object) {
|
|
3277
|
-
return !!object?.current;
|
|
3278
|
-
}
|
|
3279
|
-
function isRef$1(object) {
|
|
3280
|
-
return object?.current !== void 0;
|
|
3281
|
-
}
|
|
3282
|
-
function isWireframeGeometry(geometry) {
|
|
3283
|
-
return geometry.type === "WireframeGeometry";
|
|
3284
|
-
}
|
|
3285
|
-
function getUniforms() {
|
|
3286
|
-
const u = {};
|
|
3287
|
-
for (const key in WireframeMaterialShaders.uniforms) {
|
|
3288
|
-
u[key] = { value: WireframeMaterialShaders.uniforms[key] };
|
|
3289
|
-
}
|
|
3290
|
-
return u;
|
|
3291
|
-
}
|
|
3292
|
-
function getBarycentricCoordinates(geometry, removeEdge) {
|
|
3293
|
-
const position = geometry.getAttribute("position");
|
|
3294
|
-
const count = position.count;
|
|
3295
|
-
const barycentric = [];
|
|
3296
|
-
for (let i = 0; i < count; i++) {
|
|
3297
|
-
const even = i % 2 === 0;
|
|
3298
|
-
const Q = removeEdge ? 1 : 0;
|
|
3299
|
-
if (even) {
|
|
3300
|
-
barycentric.push(0, 0, 1, 0, 1, 0, 1, 0, Q);
|
|
3301
|
-
} else {
|
|
3302
|
-
barycentric.push(0, 1, 0, 0, 0, 1, 1, 0, Q);
|
|
3303
|
-
}
|
|
3304
|
-
}
|
|
3305
|
-
return new THREE.BufferAttribute(Float32Array.from(barycentric), 3);
|
|
3306
|
-
}
|
|
3307
|
-
function getInputGeometry(inputGeometry) {
|
|
3308
|
-
const geo = isRefObject$1(inputGeometry) ? inputGeometry.current : inputGeometry;
|
|
3309
|
-
if (!isGeometry(geo)) {
|
|
3310
|
-
if (isWireframeGeometry(geo)) {
|
|
3311
|
-
throw new Error("Wireframe: WireframeGeometry is not supported.");
|
|
3312
|
-
}
|
|
3313
|
-
const parent = geo.parent;
|
|
3314
|
-
if (isWithGeometry(parent)) {
|
|
3315
|
-
if (isWireframeGeometry(parent.geometry)) {
|
|
3316
|
-
throw new Error("Wireframe: WireframeGeometry is not supported.");
|
|
3317
|
-
}
|
|
3318
|
-
return parent.geometry;
|
|
3319
|
-
}
|
|
3320
|
-
} else {
|
|
3321
|
-
return geo;
|
|
3322
|
-
}
|
|
3323
|
-
}
|
|
3324
|
-
function setBarycentricCoordinates(geometry, simplify) {
|
|
3325
|
-
if (geometry.index) {
|
|
3326
|
-
console.warn("Wireframe: Requires non-indexed geometry, converting to non-indexed geometry.");
|
|
3327
|
-
const nonIndexedGeo = geometry.toNonIndexed();
|
|
3328
|
-
geometry.copy(nonIndexedGeo);
|
|
3329
|
-
geometry.setIndex(null);
|
|
3330
|
-
}
|
|
3331
|
-
const newBarycentric = getBarycentricCoordinates(geometry, simplify);
|
|
3332
|
-
geometry.setAttribute("barycentric", newBarycentric);
|
|
3333
|
-
}
|
|
3334
|
-
function WireframeWithCustomGeo({
|
|
3335
|
-
geometry: customGeometry,
|
|
3336
|
-
simplify = false,
|
|
3337
|
-
...props
|
|
3338
|
-
}) {
|
|
3339
|
-
extend({ MeshWireframeMaterial: WireframeMaterial });
|
|
3340
|
-
const [geometry, setGeometry] = React.useState(null);
|
|
3341
|
-
React.useLayoutEffect(() => {
|
|
3342
|
-
const geom = getInputGeometry(customGeometry);
|
|
3343
|
-
if (!geom) {
|
|
3344
|
-
throw new Error("Wireframe: geometry prop must be a BufferGeometry or a ref to a BufferGeometry.");
|
|
3345
|
-
}
|
|
3346
|
-
setBarycentricCoordinates(geom, simplify);
|
|
3347
|
-
if (isRef$1(customGeometry)) {
|
|
3348
|
-
setGeometry(geom);
|
|
3349
|
-
}
|
|
3350
|
-
}, [simplify, customGeometry]);
|
|
3351
|
-
const drawnGeo = isRef$1(customGeometry) ? geometry : customGeometry;
|
|
3352
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, drawnGeo && /* @__PURE__ */ React.createElement("mesh", { geometry: drawnGeo }, /* @__PURE__ */ React.createElement(
|
|
3353
|
-
"meshWireframeMaterial",
|
|
3354
|
-
{
|
|
3355
|
-
attach: "material",
|
|
3356
|
-
transparent: true,
|
|
3357
|
-
side: THREE.DoubleSide,
|
|
3358
|
-
polygonOffset: true,
|
|
3359
|
-
polygonOffsetFactor: -4,
|
|
3360
|
-
...props
|
|
3361
|
-
}
|
|
3362
|
-
)));
|
|
3363
|
-
}
|
|
3364
|
-
function WireframeWithoutCustomGeo({
|
|
3365
|
-
simplify = false,
|
|
3366
|
-
...props
|
|
3367
|
-
}) {
|
|
3368
|
-
const objectRef = React.useRef(null);
|
|
3369
|
-
const uniforms = React.useMemo(() => getUniforms(), [WireframeMaterialShaders.uniforms]);
|
|
3370
|
-
useWireframeUniforms(uniforms, props);
|
|
3371
|
-
React.useLayoutEffect(() => {
|
|
3372
|
-
const geom = getInputGeometry(objectRef);
|
|
3373
|
-
if (!geom) {
|
|
3374
|
-
throw new Error("Wireframe: Must be a child of a Mesh, Line or Points object or specify a geometry prop.");
|
|
3375
|
-
}
|
|
3376
|
-
const og = geom.clone();
|
|
3377
|
-
setBarycentricCoordinates(geom, simplify);
|
|
3378
|
-
return () => {
|
|
3379
|
-
geom.copy(og);
|
|
3380
|
-
og.dispose();
|
|
3381
|
-
};
|
|
3382
|
-
}, [simplify]);
|
|
3383
|
-
React.useLayoutEffect(() => {
|
|
3384
|
-
const parentMesh = objectRef.current.parent;
|
|
3385
|
-
const og = parentMesh.material.clone();
|
|
3386
|
-
setWireframeOverride(parentMesh.material, uniforms);
|
|
3387
|
-
return () => {
|
|
3388
|
-
parentMesh.material.dispose();
|
|
3389
|
-
parentMesh.material = og;
|
|
3390
|
-
};
|
|
3391
|
-
}, []);
|
|
3392
|
-
return /* @__PURE__ */ React.createElement("object3D", { ref: objectRef });
|
|
3393
|
-
}
|
|
3394
|
-
function Wireframe({ geometry: customGeometry, ...props }) {
|
|
3395
|
-
if (customGeometry) {
|
|
3396
|
-
return /* @__PURE__ */ React.createElement(WireframeWithCustomGeo, { geometry: customGeometry, ...props });
|
|
3397
|
-
}
|
|
3398
|
-
return /* @__PURE__ */ React.createElement(WireframeWithoutCustomGeo, { ...props });
|
|
3399
|
-
}
|
|
3400
|
-
|
|
3401
3220
|
const Context = /* @__PURE__ */ React.createContext({});
|
|
3402
3221
|
const useGizmoContext = () => {
|
|
3403
3222
|
return React.useContext(Context);
|
|
@@ -3545,7 +3364,7 @@ const FaceMaterial = ({
|
|
|
3545
3364
|
"meshBasicMaterial",
|
|
3546
3365
|
{
|
|
3547
3366
|
map: texture,
|
|
3548
|
-
"map-anisotropy":
|
|
3367
|
+
"map-anisotropy": getMaxAnisotropy(renderer),
|
|
3549
3368
|
attach: `material-${index}`,
|
|
3550
3369
|
color: hover ? hoverColor : "white",
|
|
3551
3370
|
transparent: true,
|
|
@@ -3656,7 +3475,7 @@ function AxisHead({
|
|
|
3656
3475
|
"spriteMaterial",
|
|
3657
3476
|
{
|
|
3658
3477
|
map: texture,
|
|
3659
|
-
"map-anisotropy":
|
|
3478
|
+
"map-anisotropy": getMaxAnisotropy(renderer),
|
|
3660
3479
|
alphaTest: 0.3,
|
|
3661
3480
|
opacity: label ? 1 : 0.75,
|
|
3662
3481
|
toneMapped: false
|
|
@@ -3693,6 +3512,11 @@ const GizmoViewport = ({
|
|
|
3693
3512
|
return /* @__PURE__ */ React.createElement("group", { scale: 40, ...props }, /* @__PURE__ */ React.createElement(Axis, { color: colorX, rotation: [0, 0, 0], scale: axisScale }), /* @__PURE__ */ React.createElement(Axis, { color: colorY, rotation: [0, 0, Math.PI / 2], scale: axisScale }), /* @__PURE__ */ React.createElement(Axis, { color: colorZ, rotation: [0, -Math.PI / 2, 0], scale: axisScale }), !hideAxisHeads && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(AxisHead, { arcStyle: colorX, position: [1, 0, 0], label: labels[0], ...axisHeadProps }), /* @__PURE__ */ React.createElement(AxisHead, { arcStyle: colorY, position: [0, 1, 0], label: labels[1], ...axisHeadProps }), /* @__PURE__ */ React.createElement(AxisHead, { arcStyle: colorZ, position: [0, 0, 1], label: labels[2], ...axisHeadProps }), !hideNegativeAxes && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(AxisHead, { arcStyle: colorX, position: [-1, 0, 0], ...axisHeadProps }), /* @__PURE__ */ React.createElement(AxisHead, { arcStyle: colorY, position: [0, -1, 0], ...axisHeadProps }), /* @__PURE__ */ React.createElement(AxisHead, { arcStyle: colorZ, position: [0, 0, -1], ...axisHeadProps }))));
|
|
3694
3513
|
};
|
|
3695
3514
|
|
|
3515
|
+
const roundEven = (n) => {
|
|
3516
|
+
const rounded = Math.ceil(n);
|
|
3517
|
+
return rounded % 2 === 0 ? rounded : rounded + 1;
|
|
3518
|
+
};
|
|
3519
|
+
|
|
3696
3520
|
const v1 = /* @__PURE__ */ new Vector3();
|
|
3697
3521
|
const v2 = /* @__PURE__ */ new Vector3();
|
|
3698
3522
|
const v3 = /* @__PURE__ */ new Vector3();
|
|
@@ -3791,9 +3615,12 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3791
3615
|
as = "div",
|
|
3792
3616
|
wrapperClass,
|
|
3793
3617
|
pointerEvents = "auto",
|
|
3618
|
+
pixelPerfect = true,
|
|
3794
3619
|
...props
|
|
3795
3620
|
}, ref) => {
|
|
3796
3621
|
const { gl, camera, scene, size, raycaster, events, viewport } = useThree();
|
|
3622
|
+
const forceEven = useThree((state) => state.internal.forceEven);
|
|
3623
|
+
const { frustum } = useThree();
|
|
3797
3624
|
const [el] = React.useState(() => document.createElement(as));
|
|
3798
3625
|
const root = React.useRef(null);
|
|
3799
3626
|
const group = React.useRef(null);
|
|
@@ -3818,38 +3645,50 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3818
3645
|
el2.style.position = null;
|
|
3819
3646
|
el2.style.pointerEvents = null;
|
|
3820
3647
|
}
|
|
3821
|
-
}, [occlude]);
|
|
3648
|
+
}, [occlude, zIndexRange, gl.domElement]);
|
|
3822
3649
|
React.useLayoutEffect(() => {
|
|
3823
3650
|
if (group.current) {
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3651
|
+
if (!root.current) {
|
|
3652
|
+
root.current = ReactDOM.createRoot(el);
|
|
3653
|
+
scene.updateMatrixWorld();
|
|
3654
|
+
if (transform) {
|
|
3655
|
+
el.style.cssText = `position:absolute;top:0;left:0;pointer-events:none;overflow:hidden;`;
|
|
3656
|
+
} else {
|
|
3657
|
+
el.style.cssText = `position:absolute;top:0;left:0;transform:translate3d(0,-9999px,0);transform-origin:0 0;`;
|
|
3658
|
+
}
|
|
3831
3659
|
}
|
|
3832
3660
|
if (target) {
|
|
3833
3661
|
if (prepend) target.prepend(el);
|
|
3834
3662
|
else target.appendChild(el);
|
|
3835
3663
|
}
|
|
3836
3664
|
return () => {
|
|
3837
|
-
if (target
|
|
3838
|
-
|
|
3665
|
+
if (target && target.contains(el)) {
|
|
3666
|
+
target.removeChild(el);
|
|
3667
|
+
}
|
|
3839
3668
|
};
|
|
3840
3669
|
}
|
|
3841
|
-
}, [target, transform]);
|
|
3670
|
+
}, [target, transform, el, prepend, scene]);
|
|
3842
3671
|
React.useLayoutEffect(() => {
|
|
3843
3672
|
if (wrapperClass) el.className = wrapperClass;
|
|
3844
|
-
}, [wrapperClass]);
|
|
3673
|
+
}, [wrapperClass, el]);
|
|
3674
|
+
React.useLayoutEffect(() => {
|
|
3675
|
+
return () => {
|
|
3676
|
+
if (root.current) {
|
|
3677
|
+
root.current.unmount();
|
|
3678
|
+
root.current = null;
|
|
3679
|
+
}
|
|
3680
|
+
};
|
|
3681
|
+
}, []);
|
|
3845
3682
|
const styles = React.useMemo(() => {
|
|
3683
|
+
const width = forceEven ? roundEven(size.width) : size.width;
|
|
3684
|
+
const height = forceEven ? roundEven(size.height) : size.height;
|
|
3846
3685
|
if (transform) {
|
|
3847
3686
|
return {
|
|
3848
3687
|
position: "absolute",
|
|
3849
3688
|
top: 0,
|
|
3850
3689
|
left: 0,
|
|
3851
|
-
width
|
|
3852
|
-
height
|
|
3690
|
+
width,
|
|
3691
|
+
height,
|
|
3853
3692
|
transformStyle: "preserve-3d",
|
|
3854
3693
|
pointerEvents: "none"
|
|
3855
3694
|
};
|
|
@@ -3858,15 +3697,15 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3858
3697
|
position: "absolute",
|
|
3859
3698
|
transform: center ? "translate3d(-50%,-50%,0)" : "none",
|
|
3860
3699
|
...fullscreen && {
|
|
3861
|
-
top: -size.height / 2,
|
|
3862
|
-
left: -size.width / 2,
|
|
3863
|
-
width
|
|
3864
|
-
height
|
|
3700
|
+
top: forceEven ? roundEven(-size.height / 2) : -size.height / 2,
|
|
3701
|
+
left: forceEven ? roundEven(-size.width / 2) : -size.width / 2,
|
|
3702
|
+
width,
|
|
3703
|
+
height
|
|
3865
3704
|
},
|
|
3866
3705
|
...style
|
|
3867
3706
|
};
|
|
3868
3707
|
}
|
|
3869
|
-
}, [style, center, fullscreen, size, transform]);
|
|
3708
|
+
}, [style, center, fullscreen, size, transform, forceEven]);
|
|
3870
3709
|
const transformInnerStyles = React.useMemo(
|
|
3871
3710
|
() => ({ position: "absolute", pointerEvents }),
|
|
3872
3711
|
[pointerEvents]
|
|
@@ -3880,7 +3719,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3880
3719
|
} else {
|
|
3881
3720
|
root.current?.render(/* @__PURE__ */ React.createElement("div", { ref, style: styles, className, children }));
|
|
3882
3721
|
}
|
|
3883
|
-
});
|
|
3722
|
+
}, [transform, styles, transformInnerStyles, ref, className, style, children]);
|
|
3884
3723
|
const visible = React.useRef(true);
|
|
3885
3724
|
useFrame((gl2) => {
|
|
3886
3725
|
if (group.current) {
|
|
@@ -3912,7 +3751,12 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3912
3751
|
const zRange = occlude ? isRayCastOcclusion ? [zIndexRange[0], halfRange] : [halfRange - 1, 0] : zIndexRange;
|
|
3913
3752
|
el.style.zIndex = `${objectZIndex(group.current, camera, zRange)}`;
|
|
3914
3753
|
if (transform) {
|
|
3915
|
-
|
|
3754
|
+
let widthHalf = forceEven ? roundEven(size.width / 2) : size.width / 2;
|
|
3755
|
+
let heightHalf = forceEven ? roundEven(size.height / 2) : size.height / 2;
|
|
3756
|
+
if (pixelPerfect) {
|
|
3757
|
+
widthHalf = roundToPixelRatio(widthHalf);
|
|
3758
|
+
heightHalf = roundToPixelRatio(heightHalf);
|
|
3759
|
+
}
|
|
3916
3760
|
const fov = camera.projectionMatrix.elements[5] * heightHalf;
|
|
3917
3761
|
const { isOrthographicCamera, top, left, bottom, right } = camera;
|
|
3918
3762
|
const cameraMatrix = getCameraCSSMatrix(camera.matrixWorldInverse);
|
|
@@ -3923,8 +3767,10 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3923
3767
|
matrix.elements[3] = matrix.elements[7] = matrix.elements[11] = 0;
|
|
3924
3768
|
matrix.elements[15] = 1;
|
|
3925
3769
|
}
|
|
3926
|
-
|
|
3927
|
-
|
|
3770
|
+
const elWidth = forceEven ? roundEven(size.width) : size.width;
|
|
3771
|
+
const elHeight = forceEven ? roundEven(size.height) : size.height;
|
|
3772
|
+
el.style.width = elWidth + "px";
|
|
3773
|
+
el.style.height = elHeight + "px";
|
|
3928
3774
|
el.style.perspective = isOrthographicCamera ? "" : `${fov}px`;
|
|
3929
3775
|
if (transformOuterRef.current && transformInnerRef.current) {
|
|
3930
3776
|
transformOuterRef.current.style.transform = `${cameraTransform}${cameraMatrix}translate(${widthHalf}px,${heightHalf}px)`;
|
|
@@ -3932,7 +3778,13 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3932
3778
|
}
|
|
3933
3779
|
} else {
|
|
3934
3780
|
const scale = distanceFactor === void 0 ? 1 : objectScale(group.current, camera) * distanceFactor;
|
|
3935
|
-
|
|
3781
|
+
let x = forceEven ? roundEven(vec[0]) : vec[0];
|
|
3782
|
+
let y = forceEven ? roundEven(vec[1]) : vec[1];
|
|
3783
|
+
if (pixelPerfect) {
|
|
3784
|
+
x = roundToPixelRatio(x);
|
|
3785
|
+
y = roundToPixelRatio(y);
|
|
3786
|
+
}
|
|
3787
|
+
el.style.transform = `translate3d(${x}px,${y}px,0) scale(${scale})`;
|
|
3936
3788
|
}
|
|
3937
3789
|
oldPosition.current = vec;
|
|
3938
3790
|
oldZoom.current = camera.zoom;
|
|
@@ -3943,8 +3795,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3943
3795
|
if (transformOuterRef.current) {
|
|
3944
3796
|
const el2 = transformOuterRef.current.children[0];
|
|
3945
3797
|
if (el2?.clientWidth && el2?.clientHeight) {
|
|
3946
|
-
|
|
3947
|
-
if (isOrthographicCamera || geometry) {
|
|
3798
|
+
if (geometry) {
|
|
3948
3799
|
if (props.scale) {
|
|
3949
3800
|
if (!Array.isArray(props.scale)) {
|
|
3950
3801
|
occlusionMeshRef.current.scale.setScalar(1 / props.scale);
|
|
@@ -3976,68 +3827,16 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3976
3827
|
}
|
|
3977
3828
|
}
|
|
3978
3829
|
});
|
|
3979
|
-
|
|
3980
|
-
() => ({
|
|
3981
|
-
vertexShader: !transform ? (
|
|
3982
|
-
/* glsl */
|
|
3983
|
-
`
|
|
3984
|
-
/*
|
|
3985
|
-
This shader is from the THREE's SpriteMaterial.
|
|
3986
|
-
We need to turn the backing plane into a Sprite
|
|
3987
|
-
(make it always face the camera) if "transfrom"
|
|
3988
|
-
is false.
|
|
3989
|
-
*/
|
|
3990
|
-
#include <common>
|
|
3991
|
-
|
|
3992
|
-
void main() {
|
|
3993
|
-
vec2 center = vec2(0., 1.);
|
|
3994
|
-
float rotation = 0.0;
|
|
3995
|
-
|
|
3996
|
-
// This is somewhat arbitrary, but it seems to work well
|
|
3997
|
-
// Need to figure out how to derive this dynamically if it even matters
|
|
3998
|
-
float size = 0.03;
|
|
3999
|
-
|
|
4000
|
-
vec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );
|
|
4001
|
-
vec2 scale;
|
|
4002
|
-
scale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );
|
|
4003
|
-
scale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );
|
|
4004
|
-
|
|
4005
|
-
bool isPerspective = isPerspectiveMatrix( projectionMatrix );
|
|
4006
|
-
if ( isPerspective ) scale *= - mvPosition.z;
|
|
4007
|
-
|
|
4008
|
-
vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale * size;
|
|
4009
|
-
vec2 rotatedPosition;
|
|
4010
|
-
rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;
|
|
4011
|
-
rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;
|
|
4012
|
-
mvPosition.xy += rotatedPosition;
|
|
4013
|
-
|
|
4014
|
-
gl_Position = projectionMatrix * mvPosition;
|
|
4015
|
-
}
|
|
4016
|
-
`
|
|
4017
|
-
) : void 0,
|
|
4018
|
-
fragmentShader: (
|
|
4019
|
-
/* glsl */
|
|
4020
|
-
`
|
|
4021
|
-
void main() {
|
|
4022
|
-
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
|
4023
|
-
}
|
|
4024
|
-
`
|
|
4025
|
-
)
|
|
4026
|
-
}),
|
|
4027
|
-
[transform]
|
|
4028
|
-
);
|
|
4029
|
-
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(
|
|
4030
|
-
"shaderMaterial",
|
|
4031
|
-
{
|
|
4032
|
-
side: DoubleSide,
|
|
4033
|
-
vertexShader: shaders.vertexShader,
|
|
4034
|
-
fragmentShader: shaders.fragmentShader
|
|
4035
|
-
}
|
|
4036
|
-
)));
|
|
3830
|
+
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));
|
|
4037
3831
|
}
|
|
4038
3832
|
);
|
|
4039
3833
|
|
|
4040
3834
|
const context$4 = /* @__PURE__ */ React.createContext(null);
|
|
3835
|
+
const resolveObject = (object, fallback) => {
|
|
3836
|
+
if (!object) return fallback;
|
|
3837
|
+
if ("current" in object) return object.current;
|
|
3838
|
+
return object;
|
|
3839
|
+
};
|
|
4041
3840
|
|
|
4042
3841
|
const vec1$1 = /* @__PURE__ */ new THREE.Vector3();
|
|
4043
3842
|
const vec2$1 = /* @__PURE__ */ new THREE.Vector3();
|
|
@@ -4072,6 +3871,8 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
4072
3871
|
onDragStart,
|
|
4073
3872
|
onDrag,
|
|
4074
3873
|
onDragEnd,
|
|
3874
|
+
onHover,
|
|
3875
|
+
dragState,
|
|
4075
3876
|
userData,
|
|
4076
3877
|
LineComponent: Line
|
|
4077
3878
|
} = React.useContext(context$4);
|
|
@@ -4103,7 +3904,13 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
4103
3904
|
const onPointerMove = React.useCallback(
|
|
4104
3905
|
(e) => {
|
|
4105
3906
|
e.stopPropagation();
|
|
4106
|
-
if (!isHovered)
|
|
3907
|
+
if (!isHovered) {
|
|
3908
|
+
const drag = dragState.current;
|
|
3909
|
+
if (drag === null || drag.component === "Arrow" && drag.axis === axis) {
|
|
3910
|
+
setIsHovered(true);
|
|
3911
|
+
onHover({ component: "Arrow", axis, hovering: true });
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
4107
3914
|
if (clickInfo.current) {
|
|
4108
3915
|
const { clickPoint, dir } = clickInfo.current;
|
|
4109
3916
|
const [min, max] = translationLimits?.[axis] || [void 0, void 0];
|
|
@@ -4122,7 +3929,7 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
4122
3929
|
onDrag(offsetMatrix$1);
|
|
4123
3930
|
}
|
|
4124
3931
|
},
|
|
4125
|
-
[annotations, onDrag, isHovered, translation, translationLimits, axis]
|
|
3932
|
+
[annotations, onDrag, onHover, dragState, isHovered, translation, translationLimits, axis]
|
|
4126
3933
|
);
|
|
4127
3934
|
const onPointerUp = React.useCallback(
|
|
4128
3935
|
(e) => {
|
|
@@ -4137,10 +3944,16 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
4137
3944
|
},
|
|
4138
3945
|
[annotations, camControls, onDragEnd]
|
|
4139
3946
|
);
|
|
4140
|
-
const onPointerOut = React.useCallback(
|
|
4141
|
-
e
|
|
4142
|
-
|
|
4143
|
-
|
|
3947
|
+
const onPointerOut = React.useCallback(
|
|
3948
|
+
(e) => {
|
|
3949
|
+
e.stopPropagation();
|
|
3950
|
+
if (isHovered) {
|
|
3951
|
+
setIsHovered(false);
|
|
3952
|
+
onHover({ component: "Arrow", axis, hovering: false });
|
|
3953
|
+
}
|
|
3954
|
+
},
|
|
3955
|
+
[onHover, axis, isHovered]
|
|
3956
|
+
);
|
|
4144
3957
|
const { cylinderLength, coneWidth, coneLength, matrixL } = React.useMemo(() => {
|
|
4145
3958
|
const coneWidth2 = fixed ? lineWidth / scale * 1.6 : scale / 20;
|
|
4146
3959
|
const coneLength2 = fixed ? 0.2 : scale / 5;
|
|
@@ -4244,6 +4057,8 @@ const rotMatrix = /* @__PURE__ */ new THREE.Matrix4();
|
|
|
4244
4057
|
const posNew = /* @__PURE__ */ new THREE.Vector3();
|
|
4245
4058
|
const ray$1 = /* @__PURE__ */ new THREE.Ray();
|
|
4246
4059
|
const intersection$1 = /* @__PURE__ */ new THREE.Vector3();
|
|
4060
|
+
const viewPlane = /* @__PURE__ */ new THREE.Plane();
|
|
4061
|
+
const viewIntersection = /* @__PURE__ */ new THREE.Vector3();
|
|
4247
4062
|
const AxisRotator = ({
|
|
4248
4063
|
dir1,
|
|
4249
4064
|
dir2,
|
|
@@ -4264,6 +4079,8 @@ const AxisRotator = ({
|
|
|
4264
4079
|
onDragStart,
|
|
4265
4080
|
onDrag,
|
|
4266
4081
|
onDragEnd,
|
|
4082
|
+
onHover,
|
|
4083
|
+
dragState,
|
|
4267
4084
|
userData,
|
|
4268
4085
|
LineComponent: Line
|
|
4269
4086
|
} = React.useContext(context$4);
|
|
@@ -4297,14 +4114,29 @@ const AxisRotator = ({
|
|
|
4297
4114
|
const onPointerMove = React.useCallback(
|
|
4298
4115
|
(e) => {
|
|
4299
4116
|
e.stopPropagation();
|
|
4300
|
-
if (!isHovered)
|
|
4117
|
+
if (!isHovered) {
|
|
4118
|
+
const drag = dragState.current;
|
|
4119
|
+
if (drag === null || drag.component === "Rotator" && drag.axis === axis) {
|
|
4120
|
+
setIsHovered(true);
|
|
4121
|
+
onHover({ component: "Rotator", axis, hovering: true });
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
4301
4124
|
if (clickInfo.current) {
|
|
4302
4125
|
const { clickPoint, origin, e1, e2, normal, plane } = clickInfo.current;
|
|
4303
4126
|
const [min, max] = rotationLimits?.[axis] || [void 0, void 0];
|
|
4304
4127
|
ray$1.copy(e.ray);
|
|
4305
|
-
ray$1.
|
|
4306
|
-
|
|
4307
|
-
|
|
4128
|
+
const dotProduct = Math.abs(ray$1.direction.dot(normal));
|
|
4129
|
+
if (dotProduct < 0.1) {
|
|
4130
|
+
viewPlane.setFromNormalAndCoplanarPoint(ray$1.direction.clone().negate(), origin);
|
|
4131
|
+
ray$1.intersectPlane(viewPlane, viewIntersection);
|
|
4132
|
+
const toIntersection = viewIntersection.clone().sub(origin);
|
|
4133
|
+
const projectedDist = toIntersection.dot(normal);
|
|
4134
|
+
intersection$1.copy(viewIntersection).sub(normal.clone().multiplyScalar(projectedDist));
|
|
4135
|
+
} else {
|
|
4136
|
+
ray$1.intersectPlane(plane, intersection$1);
|
|
4137
|
+
ray$1.direction.negate();
|
|
4138
|
+
ray$1.intersectPlane(plane, intersection$1);
|
|
4139
|
+
}
|
|
4308
4140
|
let deltaAngle = calculateAngle(clickPoint, intersection$1, origin, e1, e2);
|
|
4309
4141
|
let degrees = toDegrees(deltaAngle);
|
|
4310
4142
|
if (e.shiftKey) {
|
|
@@ -4330,7 +4162,7 @@ const AxisRotator = ({
|
|
|
4330
4162
|
onDrag(rotMatrix);
|
|
4331
4163
|
}
|
|
4332
4164
|
},
|
|
4333
|
-
[annotations, onDrag, isHovered, rotationLimits, axis]
|
|
4165
|
+
[annotations, onDrag, onHover, dragState, isHovered, rotationLimits, axis]
|
|
4334
4166
|
);
|
|
4335
4167
|
const onPointerUp = React.useCallback(
|
|
4336
4168
|
(e) => {
|
|
@@ -4346,10 +4178,16 @@ const AxisRotator = ({
|
|
|
4346
4178
|
},
|
|
4347
4179
|
[annotations, camControls, onDragEnd]
|
|
4348
4180
|
);
|
|
4349
|
-
const onPointerOut = React.useCallback(
|
|
4350
|
-
e
|
|
4351
|
-
|
|
4352
|
-
|
|
4181
|
+
const onPointerOut = React.useCallback(
|
|
4182
|
+
(e) => {
|
|
4183
|
+
e.stopPropagation();
|
|
4184
|
+
if (isHovered) {
|
|
4185
|
+
setIsHovered(false);
|
|
4186
|
+
onHover({ component: "Rotator", axis, hovering: false });
|
|
4187
|
+
}
|
|
4188
|
+
},
|
|
4189
|
+
[onHover, axis, isHovered]
|
|
4190
|
+
);
|
|
4353
4191
|
const matrixL = React.useMemo(() => {
|
|
4354
4192
|
const dir1N = dir1.clone().normalize();
|
|
4355
4193
|
const dir2N = dir2.clone().normalize();
|
|
@@ -4450,6 +4288,8 @@ const PlaneSlider = ({
|
|
|
4450
4288
|
onDragStart,
|
|
4451
4289
|
onDrag,
|
|
4452
4290
|
onDragEnd,
|
|
4291
|
+
onHover,
|
|
4292
|
+
dragState,
|
|
4453
4293
|
userData,
|
|
4454
4294
|
LineComponent: Line
|
|
4455
4295
|
} = React.useContext(context$4);
|
|
@@ -4485,7 +4325,13 @@ const PlaneSlider = ({
|
|
|
4485
4325
|
const onPointerMove = React.useCallback(
|
|
4486
4326
|
(e) => {
|
|
4487
4327
|
e.stopPropagation();
|
|
4488
|
-
if (!isHovered)
|
|
4328
|
+
if (!isHovered) {
|
|
4329
|
+
const drag = dragState.current;
|
|
4330
|
+
if (drag === null || drag.component === "Slider" && drag.axis === axis) {
|
|
4331
|
+
setIsHovered(true);
|
|
4332
|
+
onHover({ component: "Slider", axis, hovering: true });
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4489
4335
|
if (clickInfo.current) {
|
|
4490
4336
|
const { clickPoint, e1, e2, plane } = clickInfo.current;
|
|
4491
4337
|
const [minX, maxX] = translationLimits?.[(axis + 1) % 3] || [void 0, void 0];
|
|
@@ -4521,7 +4367,7 @@ const PlaneSlider = ({
|
|
|
4521
4367
|
onDrag(offsetMatrix);
|
|
4522
4368
|
}
|
|
4523
4369
|
},
|
|
4524
|
-
[annotations, onDrag, isHovered, translation, translationLimits, axis]
|
|
4370
|
+
[annotations, onDrag, onHover, dragState, isHovered, translation, translationLimits, axis]
|
|
4525
4371
|
);
|
|
4526
4372
|
const onPointerUp = React.useCallback(
|
|
4527
4373
|
(e) => {
|
|
@@ -4536,10 +4382,16 @@ const PlaneSlider = ({
|
|
|
4536
4382
|
},
|
|
4537
4383
|
[annotations, camControls, onDragEnd]
|
|
4538
4384
|
);
|
|
4539
|
-
const onPointerOut = React.useCallback(
|
|
4540
|
-
e
|
|
4541
|
-
|
|
4542
|
-
|
|
4385
|
+
const onPointerOut = React.useCallback(
|
|
4386
|
+
(e) => {
|
|
4387
|
+
e.stopPropagation();
|
|
4388
|
+
if (isHovered) {
|
|
4389
|
+
setIsHovered(false);
|
|
4390
|
+
onHover({ component: "Slider", axis, hovering: false });
|
|
4391
|
+
}
|
|
4392
|
+
},
|
|
4393
|
+
[onHover, axis, isHovered]
|
|
4394
|
+
);
|
|
4543
4395
|
const matrixL = React.useMemo(() => {
|
|
4544
4396
|
const dir1N = dir1.clone().normalize();
|
|
4545
4397
|
const dir2N = dir2.clone().normalize();
|
|
@@ -4677,6 +4529,8 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
4677
4529
|
onDragStart,
|
|
4678
4530
|
onDrag,
|
|
4679
4531
|
onDragEnd,
|
|
4532
|
+
onHover,
|
|
4533
|
+
dragState,
|
|
4680
4534
|
userData
|
|
4681
4535
|
} = React.useContext(context$4);
|
|
4682
4536
|
const size = useThree((state) => state.size);
|
|
@@ -4713,7 +4567,13 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
4713
4567
|
const onPointerMove = React.useCallback(
|
|
4714
4568
|
(e) => {
|
|
4715
4569
|
e.stopPropagation();
|
|
4716
|
-
if (!isHovered)
|
|
4570
|
+
if (!isHovered) {
|
|
4571
|
+
const drag = dragState.current;
|
|
4572
|
+
if (drag === null || drag.component === "Sphere" && drag.axis === axis) {
|
|
4573
|
+
setIsHovered(true);
|
|
4574
|
+
onHover({ component: "Sphere", axis, hovering: true });
|
|
4575
|
+
}
|
|
4576
|
+
}
|
|
4717
4577
|
if (clickInfo.current) {
|
|
4718
4578
|
const { clickPoint, dir, mPLG, mPLGInv, offsetMultiplier } = clickInfo.current;
|
|
4719
4579
|
const [min, max] = scaleLimits?.[axis] || [1e-5, void 0];
|
|
@@ -4739,7 +4599,7 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
4739
4599
|
onDrag(scaleMatrix);
|
|
4740
4600
|
}
|
|
4741
4601
|
},
|
|
4742
|
-
[annotations, position, onDrag, isHovered, scaleLimits, axis]
|
|
4602
|
+
[annotations, position, onDrag, onHover, dragState, isHovered, scaleLimits, axis]
|
|
4743
4603
|
);
|
|
4744
4604
|
const onPointerUp = React.useCallback(
|
|
4745
4605
|
(e) => {
|
|
@@ -4756,10 +4616,16 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
4756
4616
|
},
|
|
4757
4617
|
[annotations, camControls, onDragEnd, position]
|
|
4758
4618
|
);
|
|
4759
|
-
const onPointerOut = React.useCallback(
|
|
4760
|
-
e
|
|
4761
|
-
|
|
4762
|
-
|
|
4619
|
+
const onPointerOut = React.useCallback(
|
|
4620
|
+
(e) => {
|
|
4621
|
+
e.stopPropagation();
|
|
4622
|
+
if (isHovered) {
|
|
4623
|
+
setIsHovered(false);
|
|
4624
|
+
onHover({ component: "Sphere", axis, hovering: false });
|
|
4625
|
+
}
|
|
4626
|
+
},
|
|
4627
|
+
[onHover, axis, isHovered]
|
|
4628
|
+
);
|
|
4763
4629
|
const { radius, matrixL } = React.useMemo(() => {
|
|
4764
4630
|
const radius2 = fixed ? lineWidth / scale * 1.8 : scale / 22.5;
|
|
4765
4631
|
const quaternion = new THREE.Quaternion().setFromUnitVectors(upV, direction.clone().normalize());
|
|
@@ -4814,6 +4680,7 @@ const mW = /* @__PURE__ */ new THREE.Matrix4();
|
|
|
4814
4680
|
const mL = /* @__PURE__ */ new THREE.Matrix4();
|
|
4815
4681
|
const mL0Inv = /* @__PURE__ */ new THREE.Matrix4();
|
|
4816
4682
|
const mdL = /* @__PURE__ */ new THREE.Matrix4();
|
|
4683
|
+
const mdW = /* @__PURE__ */ new THREE.Matrix4();
|
|
4817
4684
|
const mG = /* @__PURE__ */ new THREE.Matrix4();
|
|
4818
4685
|
const bb = /* @__PURE__ */ new THREE.Box3();
|
|
4819
4686
|
const bbObj = /* @__PURE__ */ new THREE.Box3();
|
|
@@ -4829,9 +4696,11 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4829
4696
|
({
|
|
4830
4697
|
enabled = true,
|
|
4831
4698
|
matrix,
|
|
4699
|
+
object,
|
|
4832
4700
|
onDragStart,
|
|
4833
4701
|
onDrag,
|
|
4834
4702
|
onDragEnd,
|
|
4703
|
+
onHover,
|
|
4835
4704
|
autoTransform = true,
|
|
4836
4705
|
anchor,
|
|
4837
4706
|
disableAxes = false,
|
|
@@ -4867,14 +4736,35 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4867
4736
|
const gizmoRef = React.useRef(null);
|
|
4868
4737
|
const childrenRef = React.useRef(null);
|
|
4869
4738
|
const translation = React.useRef([0, 0, 0]);
|
|
4739
|
+
const dragState = React.useRef(null);
|
|
4870
4740
|
const cameraScale = React.useRef(new THREE.Vector3(1, 1, 1));
|
|
4871
4741
|
const gizmoScale = React.useRef(new THREE.Vector3(1, 1, 1));
|
|
4742
|
+
React.useEffect(() => {
|
|
4743
|
+
if (object) {
|
|
4744
|
+
const target = resolveObject(object);
|
|
4745
|
+
if (target) {
|
|
4746
|
+
const pivot = ref.current;
|
|
4747
|
+
const didAutoUpdate = target.matrixAutoUpdate;
|
|
4748
|
+
target.updateWorldMatrix(true, true);
|
|
4749
|
+
target.matrixAutoUpdate = false;
|
|
4750
|
+
pivot.matrix.copy(target.matrix);
|
|
4751
|
+
return () => {
|
|
4752
|
+
if (didAutoUpdate) {
|
|
4753
|
+
target.matrixAutoUpdate = true;
|
|
4754
|
+
target.matrix.decompose(target.position, target.quaternion, target.scale);
|
|
4755
|
+
}
|
|
4756
|
+
};
|
|
4757
|
+
}
|
|
4758
|
+
}
|
|
4759
|
+
}, [object]);
|
|
4872
4760
|
React.useLayoutEffect(() => {
|
|
4873
4761
|
if (!anchor) return;
|
|
4874
|
-
childrenRef.current
|
|
4875
|
-
|
|
4762
|
+
const anchorTarget = resolveObject(object, childrenRef.current);
|
|
4763
|
+
if (!anchorTarget) return;
|
|
4764
|
+
anchorTarget.updateWorldMatrix(true, true);
|
|
4765
|
+
mPInv.copy(anchorTarget.matrixWorld).invert();
|
|
4876
4766
|
bb.makeEmpty();
|
|
4877
|
-
|
|
4767
|
+
anchorTarget.traverse((obj) => {
|
|
4878
4768
|
if (!obj.geometry) return;
|
|
4879
4769
|
if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
|
|
4880
4770
|
mL.copy(obj.matrixWorld).premultiply(mPInv);
|
|
@@ -4889,15 +4779,24 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4889
4779
|
gizmoRef.current.position.copy(vPosition);
|
|
4890
4780
|
invalidate();
|
|
4891
4781
|
});
|
|
4782
|
+
const mergedUserData = React.useMemo(
|
|
4783
|
+
() => ({
|
|
4784
|
+
...userData,
|
|
4785
|
+
...depthTest === false && { interactivePriority: 1 }
|
|
4786
|
+
}),
|
|
4787
|
+
[userData, depthTest]
|
|
4788
|
+
);
|
|
4892
4789
|
const config = React.useMemo(
|
|
4893
4790
|
() => ({
|
|
4894
4791
|
onDragStart: (props2) => {
|
|
4792
|
+
dragState.current = props2;
|
|
4895
4793
|
mL0.copy(ref.current.matrix);
|
|
4896
4794
|
mW0.copy(ref.current.matrixWorld);
|
|
4897
4795
|
onDragStart && onDragStart(props2);
|
|
4898
4796
|
invalidate();
|
|
4899
4797
|
},
|
|
4900
|
-
onDrag: (
|
|
4798
|
+
onDrag: (mdW_) => {
|
|
4799
|
+
mdW.copy(mdW_);
|
|
4901
4800
|
mP.copy(parentRef.current.matrixWorld);
|
|
4902
4801
|
mPInv.copy(mP).invert();
|
|
4903
4802
|
mW.copy(mW0).premultiply(mdW);
|
|
@@ -4907,13 +4806,20 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4907
4806
|
if (autoTransform) {
|
|
4908
4807
|
ref.current.matrix.copy(mL);
|
|
4909
4808
|
}
|
|
4910
|
-
|
|
4809
|
+
const target = resolveObject(object);
|
|
4810
|
+
if (target) target.matrix.copy(mL);
|
|
4811
|
+
onDrag && onDrag({ local: mL, deltaLocal: mdL, world: mW, deltaWorld: mdW });
|
|
4911
4812
|
invalidate();
|
|
4912
4813
|
},
|
|
4913
4814
|
onDragEnd: () => {
|
|
4914
|
-
|
|
4815
|
+
dragState.current = null;
|
|
4816
|
+
if (onDragEnd) onDragEnd({ local: mL, deltaLocal: mdL, world: mW, deltaWorld: mdW });
|
|
4915
4817
|
invalidate();
|
|
4916
4818
|
},
|
|
4819
|
+
onHover: (props2) => {
|
|
4820
|
+
if (onHover) onHover(props2);
|
|
4821
|
+
},
|
|
4822
|
+
dragState,
|
|
4917
4823
|
translation,
|
|
4918
4824
|
translationLimits,
|
|
4919
4825
|
rotationLimits,
|
|
@@ -4925,7 +4831,7 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4925
4831
|
fixed,
|
|
4926
4832
|
depthTest,
|
|
4927
4833
|
renderOrder,
|
|
4928
|
-
userData,
|
|
4834
|
+
userData: mergedUserData,
|
|
4929
4835
|
annotations,
|
|
4930
4836
|
annotationsClass,
|
|
4931
4837
|
LineComponent: LineComp
|
|
@@ -4934,6 +4840,7 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4934
4840
|
onDragStart,
|
|
4935
4841
|
onDrag,
|
|
4936
4842
|
onDragEnd,
|
|
4843
|
+
onHover,
|
|
4937
4844
|
translation,
|
|
4938
4845
|
translationLimits,
|
|
4939
4846
|
rotationLimits,
|
|
@@ -4945,11 +4852,12 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4945
4852
|
...axisColors,
|
|
4946
4853
|
hoveredColor,
|
|
4947
4854
|
opacity,
|
|
4948
|
-
|
|
4855
|
+
mergedUserData,
|
|
4949
4856
|
autoTransform,
|
|
4950
4857
|
annotations,
|
|
4951
4858
|
annotationsClass,
|
|
4952
|
-
LineComp
|
|
4859
|
+
LineComp,
|
|
4860
|
+
object
|
|
4953
4861
|
]
|
|
4954
4862
|
);
|
|
4955
4863
|
const vec = new THREE.Vector3();
|
|
@@ -5016,7 +4924,9 @@ const TransformControls = /* @__PURE__ */ React.forwardRef(
|
|
|
5016
4924
|
const group = React.useRef(null);
|
|
5017
4925
|
React.useLayoutEffect(() => {
|
|
5018
4926
|
if (object) {
|
|
5019
|
-
controls.attach(
|
|
4927
|
+
controls.attach(
|
|
4928
|
+
object instanceof THREE.Object3D ? object : object.current
|
|
4929
|
+
);
|
|
5020
4930
|
} else if (group.current instanceof THREE.Object3D) {
|
|
5021
4931
|
controls.attach(group.current);
|
|
5022
4932
|
}
|
|
@@ -5112,7 +5022,7 @@ const PointMaterial = /* @__PURE__ */ React.forwardRef((props, ref) => {
|
|
|
5112
5022
|
return /* @__PURE__ */ React.createElement("primitive", { ...props, object: material, ref, attach: "material" });
|
|
5113
5023
|
});
|
|
5114
5024
|
|
|
5115
|
-
const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, loop =
|
|
5025
|
+
const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, loop = false, autoplay, ...props }, ref) => {
|
|
5116
5026
|
const sound = React.useRef(null);
|
|
5117
5027
|
React.useImperativeHandle(ref, () => sound.current, []);
|
|
5118
5028
|
const camera = useThree(({ camera: camera2 }) => camera2);
|
|
@@ -5124,7 +5034,9 @@ const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, l
|
|
|
5124
5034
|
_sound.setBuffer(Array.isArray(buffer) ? buffer[0] : buffer);
|
|
5125
5035
|
_sound.setRefDistance(distance);
|
|
5126
5036
|
_sound.setLoop(loop);
|
|
5127
|
-
if (autoplay && !_sound.isPlaying)
|
|
5037
|
+
if (autoplay && !_sound.isPlaying) {
|
|
5038
|
+
_sound.play();
|
|
5039
|
+
}
|
|
5128
5040
|
}
|
|
5129
5041
|
}, [buffer, camera, distance, loop]);
|
|
5130
5042
|
React.useEffect(() => {
|
|
@@ -5193,7 +5105,6 @@ const tempMatrix = /* @__PURE__ */ new THREE.Matrix4();
|
|
|
5193
5105
|
const translation = /* @__PURE__ */ new THREE.Vector3();
|
|
5194
5106
|
const rotation = /* @__PURE__ */ new THREE.Quaternion();
|
|
5195
5107
|
const scale = /* @__PURE__ */ new THREE.Vector3();
|
|
5196
|
-
const isInstancedBufferAttribute = (attr) => attr.isInstancedBufferAttribute;
|
|
5197
5108
|
const Instance = /* @__PURE__ */ React.forwardRef(({ context, children, ...props }, ref) => {
|
|
5198
5109
|
React.useMemo(() => extend({ PositionMesh }), []);
|
|
5199
5110
|
const group = React.useRef(null);
|
|
@@ -5213,24 +5124,20 @@ const Instances = /* @__PURE__ */ React.forwardRef(({ context, children, range,
|
|
|
5213
5124
|
const parentRef = React.useRef(null);
|
|
5214
5125
|
React.useImperativeHandle(ref, () => parentRef.current, []);
|
|
5215
5126
|
const [instances, setInstances] = React.useState([]);
|
|
5127
|
+
const boundsDirty = React.useRef(true);
|
|
5216
5128
|
const [[matrices, colors]] = React.useState(() => {
|
|
5217
5129
|
const mArray = new Float32Array(limit * 16);
|
|
5218
5130
|
for (let i = 0; i < limit; i++) tempMatrix.identity().toArray(mArray, i * 16);
|
|
5219
5131
|
return [mArray, new Float32Array([...new Array(limit * 3)].map(() => 1))];
|
|
5220
5132
|
});
|
|
5221
5133
|
React.useEffect(() => {
|
|
5222
|
-
parentRef.current.instanceMatrix.needsUpdate = true;
|
|
5134
|
+
if (parentRef.current) parentRef.current.instanceMatrix.needsUpdate = true;
|
|
5223
5135
|
});
|
|
5224
5136
|
let iterations = 0;
|
|
5225
5137
|
let count = 0;
|
|
5226
|
-
const attributes = React.useRef([]);
|
|
5227
|
-
React.useLayoutEffect(() => {
|
|
5228
|
-
attributes.current = Object.entries(parentRef.current.geometry.attributes).filter(
|
|
5229
|
-
([_name, value]) => isInstancedBufferAttribute(value)
|
|
5230
|
-
);
|
|
5231
|
-
});
|
|
5232
5138
|
useFrame(() => {
|
|
5233
5139
|
if (frames === Infinity || iterations < frames) {
|
|
5140
|
+
if (!parentRef.current) return;
|
|
5234
5141
|
parentRef.current.updateMatrix();
|
|
5235
5142
|
parentRef.current.updateMatrixWorld();
|
|
5236
5143
|
parentMatrix.copy(parentRef.current.matrixWorld).invert();
|
|
@@ -5251,13 +5158,22 @@ const Instances = /* @__PURE__ */ React.forwardRef(({ context, children, range,
|
|
|
5251
5158
|
}
|
|
5252
5159
|
iterations++;
|
|
5253
5160
|
}
|
|
5161
|
+
if (boundsDirty.current && (frames === Infinity || iterations === frames)) {
|
|
5162
|
+
boundsDirty.current = false;
|
|
5163
|
+
if (parentRef.current.boundingBox) parentRef.current.computeBoundingBox();
|
|
5164
|
+
if (parentRef.current.boundingSphere) parentRef.current.computeBoundingSphere();
|
|
5165
|
+
}
|
|
5254
5166
|
});
|
|
5255
5167
|
const api = React.useMemo(
|
|
5256
5168
|
() => ({
|
|
5257
5169
|
getParent: () => parentRef,
|
|
5258
5170
|
subscribe: (ref2) => {
|
|
5259
5171
|
setInstances((instances2) => [...instances2, ref2]);
|
|
5260
|
-
|
|
5172
|
+
boundsDirty.current = true;
|
|
5173
|
+
return () => {
|
|
5174
|
+
setInstances((instances2) => instances2.filter((item) => item.current !== ref2.current));
|
|
5175
|
+
boundsDirty.current = true;
|
|
5176
|
+
};
|
|
5261
5177
|
}
|
|
5262
5178
|
}),
|
|
5263
5179
|
[]
|
|
@@ -5282,10 +5198,23 @@ const Merged = /* @__PURE__ */ React.forwardRef(function Merged2({ meshes, child
|
|
|
5282
5198
|
if (!isArray) {
|
|
5283
5199
|
for (const key of Object.keys(meshes)) if (!meshes[key].isMesh) delete meshes[key];
|
|
5284
5200
|
}
|
|
5285
|
-
const render = (args) =>
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5201
|
+
const render = (args) => {
|
|
5202
|
+
if (isArray) {
|
|
5203
|
+
return children(
|
|
5204
|
+
...args
|
|
5205
|
+
);
|
|
5206
|
+
}
|
|
5207
|
+
const instanceMap = {};
|
|
5208
|
+
const keys = Object.keys(meshes).filter((key) => meshes[key].isMesh);
|
|
5209
|
+
keys.forEach((key, i) => {
|
|
5210
|
+
instanceMap[key] = args[i];
|
|
5211
|
+
});
|
|
5212
|
+
return children(instanceMap);
|
|
5213
|
+
};
|
|
5214
|
+
const components = (isArray ? meshes : Object.values(meshes)).map((mesh) => {
|
|
5215
|
+
const { geometry, material } = mesh;
|
|
5216
|
+
return /* @__PURE__ */ React.createElement(Instances, { key: geometry.uuid, geometry, material, ...props });
|
|
5217
|
+
});
|
|
5289
5218
|
return /* @__PURE__ */ React.createElement("group", { ref }, renderRecursive(render, components));
|
|
5290
5219
|
});
|
|
5291
5220
|
function renderRecursive(render, components, results = []) {
|
|
@@ -5311,7 +5240,7 @@ function createInstances() {
|
|
|
5311
5240
|
];
|
|
5312
5241
|
}
|
|
5313
5242
|
const InstancedAttribute = React.forwardRef(
|
|
5314
|
-
({ name, defaultValue, normalized, usage = THREE.DynamicDrawUsage }, fref) => {
|
|
5243
|
+
({ name, defaultValue, normalized, usage = THREE.DynamicDrawUsage, type = "float" }, fref) => {
|
|
5315
5244
|
const ref = React.useRef(null);
|
|
5316
5245
|
React.useImperativeHandle(fref, () => ref.current, []);
|
|
5317
5246
|
React.useLayoutEffect(() => {
|
|
@@ -5319,7 +5248,26 @@ const InstancedAttribute = React.forwardRef(
|
|
|
5319
5248
|
parent.geometry.attributes[name] = ref.current;
|
|
5320
5249
|
const value = Array.isArray(defaultValue) ? defaultValue : [defaultValue];
|
|
5321
5250
|
const array = Array.from({ length: parent.userData.limit }, () => value).flat();
|
|
5322
|
-
|
|
5251
|
+
switch (type) {
|
|
5252
|
+
case "float":
|
|
5253
|
+
ref.current.array = new Float32Array(array);
|
|
5254
|
+
break;
|
|
5255
|
+
case "int":
|
|
5256
|
+
ref.current.array = new Int32Array(array);
|
|
5257
|
+
break;
|
|
5258
|
+
case "uint":
|
|
5259
|
+
ref.current.array = new Uint32Array(array);
|
|
5260
|
+
break;
|
|
5261
|
+
case "short":
|
|
5262
|
+
ref.current.array = new Int16Array(array);
|
|
5263
|
+
break;
|
|
5264
|
+
case "ushort":
|
|
5265
|
+
ref.current.array = new Uint16Array(array);
|
|
5266
|
+
break;
|
|
5267
|
+
case "byte":
|
|
5268
|
+
ref.current.array = new Uint8Array(array);
|
|
5269
|
+
break;
|
|
5270
|
+
}
|
|
5323
5271
|
ref.current.itemSize = value.length;
|
|
5324
5272
|
ref.current.count = array.length / ref.current.itemSize;
|
|
5325
5273
|
return () => {
|
|
@@ -6340,12 +6288,13 @@ function Sampler({ children, weight, transform, instances, mesh, count = 16, ...
|
|
|
6340
6288
|
return /* @__PURE__ */ React.createElement("group", { ref: group, ...props }, children);
|
|
6341
6289
|
}
|
|
6342
6290
|
|
|
6291
|
+
const pathStyle = (path) => path.userData?.style;
|
|
6343
6292
|
const Svg = /* @__PURE__ */ forwardRef(
|
|
6344
6293
|
function R3FSvg({ src, skipFill, skipStrokes, fillMaterial, strokeMaterial, fillMeshProps, strokeMeshProps, ...props }, ref) {
|
|
6345
6294
|
const svg = useLoader(SVGLoader, !src.startsWith("<svg") ? src : `data:image/svg+xml;utf8,${src}`);
|
|
6346
6295
|
const strokeGeometries = useMemo(
|
|
6347
6296
|
() => skipStrokes ? [] : svg.paths.map(
|
|
6348
|
-
(path) => path
|
|
6297
|
+
(path) => pathStyle(path)?.stroke === void 0 || pathStyle(path).stroke === "none" ? null : path.subPaths.map((subPath) => SVGLoader.pointsToStroke(subPath.getPoints(), pathStyle(path)))
|
|
6349
6298
|
),
|
|
6350
6299
|
[svg, skipStrokes]
|
|
6351
6300
|
);
|
|
@@ -6353,21 +6302,21 @@ const Svg = /* @__PURE__ */ forwardRef(
|
|
|
6353
6302
|
return () => strokeGeometries.forEach((group) => group && group.map((g) => g.dispose()));
|
|
6354
6303
|
}, [strokeGeometries]);
|
|
6355
6304
|
let renderOrder = 0;
|
|
6356
|
-
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
|
|
6305
|
+
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(
|
|
6357
6306
|
"meshBasicMaterial",
|
|
6358
6307
|
{
|
|
6359
|
-
color: path.
|
|
6360
|
-
opacity: path.
|
|
6308
|
+
color: pathStyle(path).fill,
|
|
6309
|
+
opacity: pathStyle(path).fillOpacity,
|
|
6361
6310
|
transparent: true,
|
|
6362
6311
|
side: DoubleSide,
|
|
6363
6312
|
depthWrite: false,
|
|
6364
6313
|
...fillMaterial
|
|
6365
6314
|
}
|
|
6366
|
-
))), !skipStrokes && path
|
|
6315
|
+
))), !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(
|
|
6367
6316
|
"meshBasicMaterial",
|
|
6368
6317
|
{
|
|
6369
|
-
color: path.
|
|
6370
|
-
opacity: path.
|
|
6318
|
+
color: pathStyle(path).stroke,
|
|
6319
|
+
opacity: pathStyle(path).strokeOpacity,
|
|
6371
6320
|
transparent: true,
|
|
6372
6321
|
side: DoubleSide,
|
|
6373
6322
|
depthWrite: false,
|
|
@@ -6590,8 +6539,8 @@ function useVideoTexture(srcOrSrcObject, {
|
|
|
6590
6539
|
});
|
|
6591
6540
|
if (src && IS_BROWSER && src.endsWith(".m3u8")) {
|
|
6592
6541
|
const hls = hlsRef.current = await getHls(hlsConfig);
|
|
6593
|
-
if (hls) {
|
|
6594
|
-
hls.on(Events.MEDIA_ATTACHED, () => void hls.loadSource(src));
|
|
6542
|
+
if (hls && _HLSModule) {
|
|
6543
|
+
hls.on(_HLSModule.Events.MEDIA_ATTACHED, () => void hls.loadSource(src));
|
|
6595
6544
|
hls.attachMedia(video2);
|
|
6596
6545
|
}
|
|
6597
6546
|
}
|
|
@@ -6811,9 +6760,125 @@ function Fbx({
|
|
|
6811
6760
|
return /* @__PURE__ */ React.createElement(Clone, { ...props, object });
|
|
6812
6761
|
}
|
|
6813
6762
|
|
|
6763
|
+
const SERVICE_KEY = "__drei_ktx2_service__";
|
|
6764
|
+
const DEFAULT_TRANSCODER_PATH = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/basis/";
|
|
6765
|
+
class KTX2LoaderServiceImpl {
|
|
6766
|
+
loader = null;
|
|
6767
|
+
renderer = null;
|
|
6768
|
+
_isReady = false;
|
|
6769
|
+
transcoderPath = DEFAULT_TRANSCODER_PATH;
|
|
6770
|
+
pendingCallbacks = [];
|
|
6771
|
+
/**
|
|
6772
|
+
* Get or create the singleton KTX2Loader instance.
|
|
6773
|
+
* The loader is created lazily on first access.
|
|
6774
|
+
*/
|
|
6775
|
+
getLoader() {
|
|
6776
|
+
if (!this.loader) {
|
|
6777
|
+
this.loader = new KTX2Loader();
|
|
6778
|
+
this.loader.setTranscoderPath(this.transcoderPath);
|
|
6779
|
+
}
|
|
6780
|
+
return this.loader;
|
|
6781
|
+
}
|
|
6782
|
+
/**
|
|
6783
|
+
* Register a renderer and call detectSupport.
|
|
6784
|
+
* Should be called from within React context (useLayoutEffect).
|
|
6785
|
+
* Flushes any queued callbacks.
|
|
6786
|
+
*/
|
|
6787
|
+
registerRenderer(renderer) {
|
|
6788
|
+
if (this._isReady && this.renderer === renderer) {
|
|
6789
|
+
return;
|
|
6790
|
+
}
|
|
6791
|
+
this.renderer = renderer;
|
|
6792
|
+
const loader = this.getLoader();
|
|
6793
|
+
loader.detectSupport(renderer);
|
|
6794
|
+
this._isReady = true;
|
|
6795
|
+
this.flushPendingCallbacks();
|
|
6796
|
+
}
|
|
6797
|
+
/**
|
|
6798
|
+
* Check if the service is ready (has renderer registered).
|
|
6799
|
+
*/
|
|
6800
|
+
isReady() {
|
|
6801
|
+
return this._isReady;
|
|
6802
|
+
}
|
|
6803
|
+
/**
|
|
6804
|
+
* Get the registered renderer, if any.
|
|
6805
|
+
*/
|
|
6806
|
+
getRenderer() {
|
|
6807
|
+
return this.renderer;
|
|
6808
|
+
}
|
|
6809
|
+
/**
|
|
6810
|
+
* Register a callback to run when renderer becomes available.
|
|
6811
|
+
* If renderer is already available, runs immediately.
|
|
6812
|
+
*/
|
|
6813
|
+
onReady(callback) {
|
|
6814
|
+
if (this._isReady) {
|
|
6815
|
+
callback();
|
|
6816
|
+
} else {
|
|
6817
|
+
this.pendingCallbacks.push(callback);
|
|
6818
|
+
}
|
|
6819
|
+
}
|
|
6820
|
+
/**
|
|
6821
|
+
* Process all pending callbacks.
|
|
6822
|
+
*/
|
|
6823
|
+
flushPendingCallbacks() {
|
|
6824
|
+
const callbacks = this.pendingCallbacks;
|
|
6825
|
+
this.pendingCallbacks = [];
|
|
6826
|
+
for (const callback of callbacks) {
|
|
6827
|
+
try {
|
|
6828
|
+
callback();
|
|
6829
|
+
} catch (error) {
|
|
6830
|
+
console.error("KTX2LoaderService: Error in pending callback:", error);
|
|
6831
|
+
}
|
|
6832
|
+
}
|
|
6833
|
+
}
|
|
6834
|
+
/**
|
|
6835
|
+
* Set the transcoder path for basis/ktx2 decoding.
|
|
6836
|
+
*/
|
|
6837
|
+
setTranscoderPath(path) {
|
|
6838
|
+
this.transcoderPath = path;
|
|
6839
|
+
if (this.loader) {
|
|
6840
|
+
this.loader.setTranscoderPath(path);
|
|
6841
|
+
}
|
|
6842
|
+
}
|
|
6843
|
+
/**
|
|
6844
|
+
* Get the current transcoder path.
|
|
6845
|
+
*/
|
|
6846
|
+
getTranscoderPath() {
|
|
6847
|
+
return this.transcoderPath;
|
|
6848
|
+
}
|
|
6849
|
+
/**
|
|
6850
|
+
* Dispose of the loader and reset state.
|
|
6851
|
+
* Useful for testing or cleanup.
|
|
6852
|
+
*/
|
|
6853
|
+
dispose() {
|
|
6854
|
+
if (this.loader) {
|
|
6855
|
+
this.loader.dispose();
|
|
6856
|
+
}
|
|
6857
|
+
const path = this.transcoderPath;
|
|
6858
|
+
this.loader = null;
|
|
6859
|
+
this.renderer = null;
|
|
6860
|
+
this._isReady = false;
|
|
6861
|
+
this.transcoderPath = path;
|
|
6862
|
+
this.pendingCallbacks = [];
|
|
6863
|
+
}
|
|
6864
|
+
}
|
|
6865
|
+
const KTX2LoaderService = globalThis[SERVICE_KEY] || (globalThis[SERVICE_KEY] = new KTX2LoaderServiceImpl());
|
|
6866
|
+
|
|
6814
6867
|
let dracoLoader = null;
|
|
6815
6868
|
let decoderPath = "https://www.gstatic.com/draco/versioned/decoders/1.5.5/";
|
|
6816
|
-
|
|
6869
|
+
let legacyApiWarned = false;
|
|
6870
|
+
function isOptionsObject(arg) {
|
|
6871
|
+
return typeof arg === "object" && arg !== null && !Array.isArray(arg);
|
|
6872
|
+
}
|
|
6873
|
+
function warnLegacyApi() {
|
|
6874
|
+
if (!legacyApiWarned) {
|
|
6875
|
+
legacyApiWarned = true;
|
|
6876
|
+
console.warn(
|
|
6877
|
+
"useGLTF: Boolean arguments are deprecated. Use options object instead:\n useGLTF(path, { draco: true, meshopt: true, ktx2: true })"
|
|
6878
|
+
);
|
|
6879
|
+
}
|
|
6880
|
+
}
|
|
6881
|
+
function extensions(useDraco = true, useMeshopt = true, useKTX2 = false, extendLoader, renderer) {
|
|
6817
6882
|
return (loader) => {
|
|
6818
6883
|
if (extendLoader) {
|
|
6819
6884
|
extendLoader(loader);
|
|
@@ -6829,31 +6894,110 @@ function extensions(useDraco = true, useMeshopt = true, extendLoader) {
|
|
|
6829
6894
|
const decoder = typeof MeshoptDecoder === "function" ? MeshoptDecoder() : MeshoptDecoder;
|
|
6830
6895
|
loader.setMeshoptDecoder(decoder);
|
|
6831
6896
|
}
|
|
6897
|
+
if (useKTX2) {
|
|
6898
|
+
const ktx2Loader = KTX2LoaderService.getLoader();
|
|
6899
|
+
if (typeof useKTX2 === "string") {
|
|
6900
|
+
ktx2Loader.setTranscoderPath(useKTX2);
|
|
6901
|
+
}
|
|
6902
|
+
if (renderer) {
|
|
6903
|
+
ktx2Loader.detectSupport(renderer);
|
|
6904
|
+
}
|
|
6905
|
+
loader.setKTX2Loader(ktx2Loader);
|
|
6906
|
+
}
|
|
6832
6907
|
};
|
|
6833
6908
|
}
|
|
6834
|
-
|
|
6835
|
-
|
|
6909
|
+
function useGLTF(path, optionsOrDraco, useMeshoptArg, useKTX2Arg, extendLoaderArg) {
|
|
6910
|
+
let draco = true;
|
|
6911
|
+
let meshopt = true;
|
|
6912
|
+
let ktx2 = false;
|
|
6913
|
+
let extendLoader;
|
|
6914
|
+
if (isOptionsObject(optionsOrDraco)) {
|
|
6915
|
+
draco = optionsOrDraco.draco ?? true;
|
|
6916
|
+
meshopt = optionsOrDraco.meshopt ?? true;
|
|
6917
|
+
ktx2 = optionsOrDraco.ktx2 ?? false;
|
|
6918
|
+
extendLoader = optionsOrDraco.extendLoader;
|
|
6919
|
+
} else if (optionsOrDraco !== void 0) {
|
|
6920
|
+
warnLegacyApi();
|
|
6921
|
+
draco = optionsOrDraco;
|
|
6922
|
+
meshopt = useMeshoptArg ?? true;
|
|
6923
|
+
ktx2 = useKTX2Arg ?? false;
|
|
6924
|
+
extendLoader = extendLoaderArg;
|
|
6925
|
+
}
|
|
6926
|
+
const renderer = useThree((state) => state.renderer);
|
|
6927
|
+
useLayoutEffect(() => {
|
|
6928
|
+
if (ktx2) {
|
|
6929
|
+
KTX2LoaderService.registerRenderer(renderer);
|
|
6930
|
+
}
|
|
6931
|
+
}, [ktx2, renderer]);
|
|
6932
|
+
return useLoader(GLTFLoader, path, extensions(draco, meshopt, ktx2, extendLoader, ktx2 ? renderer : void 0));
|
|
6933
|
+
}
|
|
6934
|
+
useGLTF.preload = (path, optionsOrDraco, useMeshoptArg, useKTX2Arg, extendLoaderArg) => {
|
|
6935
|
+
let draco = true;
|
|
6936
|
+
let meshopt = true;
|
|
6937
|
+
let ktx2 = false;
|
|
6938
|
+
let extendLoader;
|
|
6939
|
+
if (isOptionsObject(optionsOrDraco)) {
|
|
6940
|
+
draco = optionsOrDraco.draco ?? true;
|
|
6941
|
+
meshopt = optionsOrDraco.meshopt ?? true;
|
|
6942
|
+
ktx2 = optionsOrDraco.ktx2 ?? false;
|
|
6943
|
+
extendLoader = optionsOrDraco.extendLoader;
|
|
6944
|
+
} else if (optionsOrDraco !== void 0) {
|
|
6945
|
+
warnLegacyApi();
|
|
6946
|
+
draco = optionsOrDraco;
|
|
6947
|
+
meshopt = useMeshoptArg ?? true;
|
|
6948
|
+
ktx2 = useKTX2Arg ?? false;
|
|
6949
|
+
extendLoader = extendLoaderArg;
|
|
6950
|
+
}
|
|
6951
|
+
if (ktx2) {
|
|
6952
|
+
KTX2LoaderService.onReady(() => {
|
|
6953
|
+
const renderer = KTX2LoaderService.getRenderer();
|
|
6954
|
+
useLoader.preload(GLTFLoader, path, extensions(draco, meshopt, ktx2, extendLoader, renderer));
|
|
6955
|
+
});
|
|
6956
|
+
} else {
|
|
6957
|
+
useLoader.preload(GLTFLoader, path, extensions(draco, meshopt, false, extendLoader));
|
|
6958
|
+
}
|
|
6959
|
+
};
|
|
6836
6960
|
useGLTF.clear = (path) => useLoader.clear(GLTFLoader, path);
|
|
6837
6961
|
useGLTF.setDecoderPath = (path) => {
|
|
6838
6962
|
decoderPath = path;
|
|
6839
6963
|
};
|
|
6964
|
+
useGLTF.setKTX2TranscoderPath = (path) => {
|
|
6965
|
+
KTX2LoaderService.setTranscoderPath(path);
|
|
6966
|
+
};
|
|
6840
6967
|
const Gltf = /* @__PURE__ */ React.forwardRef(
|
|
6841
|
-
({ src, useDraco, useMeshOpt, extendLoader, ...props }, ref) => {
|
|
6842
|
-
const
|
|
6968
|
+
({ src, useDraco, useMeshOpt, extendLoader, options, ...props }, ref) => {
|
|
6969
|
+
const opts = options ?? {
|
|
6970
|
+
draco: useDraco,
|
|
6971
|
+
meshopt: useMeshOpt,
|
|
6972
|
+
extendLoader
|
|
6973
|
+
};
|
|
6974
|
+
const { scene } = useGLTF(src, opts);
|
|
6843
6975
|
return /* @__PURE__ */ React.createElement(Clone, { ref, ...props, object: scene });
|
|
6844
6976
|
}
|
|
6845
6977
|
);
|
|
6846
6978
|
|
|
6847
|
-
|
|
6848
|
-
function useKTX2(input, basisPath = `${cdn}/basis/`) {
|
|
6979
|
+
function useKTX2(input, basisPath = true, extendLoader) {
|
|
6849
6980
|
const renderer = useThree((state) => state.renderer);
|
|
6981
|
+
useLayoutEffect(() => {
|
|
6982
|
+
KTX2LoaderService.registerRenderer(renderer);
|
|
6983
|
+
}, [renderer]);
|
|
6850
6984
|
const textures = useLoader(KTX2Loader, IsObject(input) ? Object.values(input) : input, (loader) => {
|
|
6985
|
+
if (extendLoader) {
|
|
6986
|
+
extendLoader(loader);
|
|
6987
|
+
}
|
|
6988
|
+
if (basisPath) {
|
|
6989
|
+
const path = typeof basisPath === "string" ? basisPath : KTX2LoaderService.getTranscoderPath();
|
|
6990
|
+
loader.setTranscoderPath(path);
|
|
6991
|
+
}
|
|
6851
6992
|
loader.detectSupport(renderer);
|
|
6852
|
-
loader.setTranscoderPath(basisPath);
|
|
6853
6993
|
});
|
|
6854
6994
|
useEffect(() => {
|
|
6855
6995
|
const array = Array.isArray(textures) ? textures : [textures];
|
|
6856
|
-
array.forEach((texture) =>
|
|
6996
|
+
array.forEach((texture) => {
|
|
6997
|
+
if ("initTexture" in renderer) {
|
|
6998
|
+
renderer.initTexture(texture);
|
|
6999
|
+
}
|
|
7000
|
+
});
|
|
6857
7001
|
}, [renderer, textures]);
|
|
6858
7002
|
if (IsObject(input)) {
|
|
6859
7003
|
const keys = Object.keys(input);
|
|
@@ -6864,19 +7008,81 @@ function useKTX2(input, basisPath = `${cdn}/basis/`) {
|
|
|
6864
7008
|
return textures;
|
|
6865
7009
|
}
|
|
6866
7010
|
}
|
|
6867
|
-
useKTX2.preload = (url, basisPath =
|
|
6868
|
-
|
|
6869
|
-
|
|
7011
|
+
useKTX2.preload = (url, basisPath = true, extendLoader) => {
|
|
7012
|
+
KTX2LoaderService.onReady(() => {
|
|
7013
|
+
const renderer = KTX2LoaderService.getRenderer();
|
|
7014
|
+
useLoader.preload(KTX2Loader, url, (loader) => {
|
|
7015
|
+
if (extendLoader) {
|
|
7016
|
+
extendLoader(loader);
|
|
7017
|
+
}
|
|
7018
|
+
if (basisPath) {
|
|
7019
|
+
const path = typeof basisPath === "string" ? basisPath : KTX2LoaderService.getTranscoderPath();
|
|
7020
|
+
loader.setTranscoderPath(path);
|
|
7021
|
+
}
|
|
7022
|
+
if (renderer) {
|
|
7023
|
+
loader.detectSupport(renderer);
|
|
7024
|
+
}
|
|
7025
|
+
});
|
|
7026
|
+
});
|
|
7027
|
+
};
|
|
6870
7028
|
useKTX2.clear = (input) => useLoader.clear(KTX2Loader, input);
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
const texture = useKTX2(input, basisPath);
|
|
7029
|
+
useKTX2.setTranscoderPath = (path) => {
|
|
7030
|
+
KTX2LoaderService.setTranscoderPath(path);
|
|
7031
|
+
};
|
|
7032
|
+
const Ktx2 = ({ children, input, basisPath, extendLoader }) => {
|
|
7033
|
+
const texture = useKTX2(input, basisPath, extendLoader);
|
|
6877
7034
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, children?.(texture));
|
|
6878
7035
|
};
|
|
6879
7036
|
|
|
7037
|
+
const useVariants = (model, inVariant) => {
|
|
7038
|
+
const [activeVariant, setActiveVariant] = useState(null);
|
|
7039
|
+
const [materials, setMaterials] = useState([]);
|
|
7040
|
+
useEffect(() => {
|
|
7041
|
+
model.parser.getDependencies("material").then((materials2) => {
|
|
7042
|
+
setMaterials(materials2);
|
|
7043
|
+
});
|
|
7044
|
+
}, [model]);
|
|
7045
|
+
const variants = useMemo(() => {
|
|
7046
|
+
return model.userData.gltfExtensions?.KHR_materials_variants?.variants;
|
|
7047
|
+
}, [model]);
|
|
7048
|
+
const applyVariant = useCallback(
|
|
7049
|
+
(variantIndex) => {
|
|
7050
|
+
model.scene.traverse(async (object) => {
|
|
7051
|
+
if (!("isMesh" in object) || !object.userData.gltfExtensions) return;
|
|
7052
|
+
const meshObject = object;
|
|
7053
|
+
const meshVariantDef = meshObject.userData.gltfExtensions.KHR_materials_variants;
|
|
7054
|
+
if (!meshVariantDef) return;
|
|
7055
|
+
if (!meshObject.userData.originalMaterial) meshObject.userData.originalMaterial = meshObject.material;
|
|
7056
|
+
const mapping = meshVariantDef.mappings.find((mapping2) => mapping2.variants.includes(variantIndex));
|
|
7057
|
+
if (mapping) {
|
|
7058
|
+
meshObject.material = await model.parser.getDependency("material", mapping.material);
|
|
7059
|
+
model.parser.assignFinalMaterial(meshObject);
|
|
7060
|
+
} else meshObject.material = meshObject.userData.originalMaterial;
|
|
7061
|
+
if (Array.isArray(meshObject.material)) for (const mat of meshObject.material) mat.needsUpdate = true;
|
|
7062
|
+
else meshObject.material.needsUpdate = true;
|
|
7063
|
+
});
|
|
7064
|
+
},
|
|
7065
|
+
[model]
|
|
7066
|
+
);
|
|
7067
|
+
const setVariant = useCallback(
|
|
7068
|
+
(variantName) => {
|
|
7069
|
+
if (!variants) return;
|
|
7070
|
+
const newVariant = variantName && variants.some((v) => v.name === variantName) ? variantName : null;
|
|
7071
|
+
setActiveVariant(newVariant);
|
|
7072
|
+
},
|
|
7073
|
+
[variants]
|
|
7074
|
+
);
|
|
7075
|
+
useEffect(() => {
|
|
7076
|
+
if (!variants) return;
|
|
7077
|
+
const variantIndex = variants.findIndex((v) => v.name === activeVariant);
|
|
7078
|
+
applyVariant(variantIndex > -1 ? variantIndex : 0);
|
|
7079
|
+
}, [variants, activeVariant, applyVariant]);
|
|
7080
|
+
useEffect(() => {
|
|
7081
|
+
setVariant(inVariant ?? null);
|
|
7082
|
+
}, [inVariant, setVariant]);
|
|
7083
|
+
return { variants, activeVariant, setVariant, materials };
|
|
7084
|
+
};
|
|
7085
|
+
|
|
6880
7086
|
const WebcamVideoTexture = /* @__PURE__ */ forwardRef(
|
|
6881
7087
|
({
|
|
6882
7088
|
constraints = {
|
|
@@ -7064,6 +7270,7 @@ function useEffectfulState(fn, deps = [], cb) {
|
|
|
7064
7270
|
}
|
|
7065
7271
|
|
|
7066
7272
|
function Stats({ showPanel = 0, className, parent }) {
|
|
7273
|
+
React.useEffect(() => void console.warn("drei: <Stats /> is deprecated, use <StatsGl /> instead."), []);
|
|
7067
7274
|
const stats = useEffectfulState(() => new StatsImpl(), []);
|
|
7068
7275
|
React.useEffect(() => {
|
|
7069
7276
|
if (stats) {
|
|
@@ -7092,6 +7299,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
|
|
|
7092
7299
|
const stats2 = new Stats$1({
|
|
7093
7300
|
...props
|
|
7094
7301
|
});
|
|
7302
|
+
stats2.init(renderer);
|
|
7095
7303
|
return stats2;
|
|
7096
7304
|
}, [renderer]);
|
|
7097
7305
|
React.useImperativeHandle(fref, () => stats.domElement, [stats]);
|
|
@@ -7109,7 +7317,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
|
|
|
7109
7317
|
return () => {
|
|
7110
7318
|
if (classNames.length) stats.domElement.classList.remove(...classNames);
|
|
7111
7319
|
node?.removeChild(stats.domElement);
|
|
7112
|
-
stats.
|
|
7320
|
+
stats.dispose();
|
|
7113
7321
|
};
|
|
7114
7322
|
}
|
|
7115
7323
|
}, [parent, stats, className, id, clearStatsGlStyle]);
|
|
@@ -7117,7 +7325,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
|
|
|
7117
7325
|
() => {
|
|
7118
7326
|
stats.begin();
|
|
7119
7327
|
},
|
|
7120
|
-
{ before: "
|
|
7328
|
+
{ before: "update" }
|
|
7121
7329
|
);
|
|
7122
7330
|
useFrame(
|
|
7123
7331
|
() => {
|
|
@@ -7167,11 +7375,11 @@ const RenderCubeTexture = /* @__PURE__ */ React.forwardRef(
|
|
|
7167
7375
|
depthBuffer,
|
|
7168
7376
|
generateMipmaps
|
|
7169
7377
|
};
|
|
7170
|
-
const fboA2 = new
|
|
7378
|
+
const fboA2 = new WebGLCubeRenderTarget(fboSize, settings);
|
|
7171
7379
|
fboA2.texture.isRenderTargetTexture = !flip;
|
|
7172
7380
|
fboA2.texture.flipY = true;
|
|
7173
7381
|
fboA2.texture.type = THREE.HalfFloatType;
|
|
7174
|
-
const fboB2 = new
|
|
7382
|
+
const fboB2 = new WebGLCubeRenderTarget(fboSize, settings);
|
|
7175
7383
|
fboB2.texture.isRenderTargetTexture = !flip;
|
|
7176
7384
|
fboB2.texture.flipY = true;
|
|
7177
7385
|
fboB2.texture.type = THREE.HalfFloatType;
|
|
@@ -7349,18 +7557,21 @@ function Fisheye({
|
|
|
7349
7557
|
const normal = new THREE.Vector3();
|
|
7350
7558
|
const sph = new THREE.Sphere(new THREE.Vector3(), radius);
|
|
7351
7559
|
const normalMatrix = new THREE.Matrix3();
|
|
7352
|
-
const compute = React.useCallback(
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7560
|
+
const compute = React.useCallback(
|
|
7561
|
+
(event, state, prev) => {
|
|
7562
|
+
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
7563
|
+
state.raycaster.setFromCamera(state.pointer, orthoC);
|
|
7564
|
+
if (!state.raycaster.ray.intersectSphere(sph, normal)) return;
|
|
7565
|
+
else normal.normalize();
|
|
7566
|
+
normalMatrix.getNormalMatrix(cubeApi.current.camera.matrixWorld);
|
|
7567
|
+
cubeApi.current.camera.getWorldPosition(state.raycaster.ray.origin);
|
|
7568
|
+
state.raycaster.ray.direction.set(0, 0, 1).reflect(normal);
|
|
7569
|
+
state.raycaster.ray.direction.x *= -1;
|
|
7570
|
+
state.raycaster.ray.direction.applyNormalMatrix(normalMatrix).multiplyScalar(-1);
|
|
7571
|
+
return void 0;
|
|
7572
|
+
},
|
|
7573
|
+
[width, height]
|
|
7574
|
+
);
|
|
7364
7575
|
useFrame(
|
|
7365
7576
|
({ gl }) => {
|
|
7366
7577
|
if (renderPriority) gl.render(sphere.current, orthoC);
|
|
@@ -7495,14 +7706,23 @@ const isWebGPURenderer = (def) => !!def.isWebGPURenderer;
|
|
|
7495
7706
|
const col = /* @__PURE__ */ new THREE.Color();
|
|
7496
7707
|
const TUNNEL_KEY = "__drei_view_tunnel__";
|
|
7497
7708
|
const tracked = globalThis[TUNNEL_KEY] || (globalThis[TUNNEL_KEY] = tunnel());
|
|
7498
|
-
function computeContainerPosition(canvasSize, trackRect) {
|
|
7709
|
+
function computeContainerPosition(canvasSize, trackRect, forceEven) {
|
|
7499
7710
|
const { right, top: trackTop, left: trackLeft, bottom: trackBottom, width, height } = trackRect;
|
|
7500
|
-
const isOffscreen = trackRect.bottom < 0 || trackTop > canvasSize.height || right < 0 || trackRect.left > canvasSize.width;
|
|
7501
7711
|
const canvasBottom = canvasSize.top + canvasSize.height;
|
|
7502
|
-
const
|
|
7503
|
-
const
|
|
7504
|
-
const
|
|
7505
|
-
|
|
7712
|
+
const canvasRight = canvasSize.left + canvasSize.width;
|
|
7713
|
+
const isOffscreen = trackBottom < canvasSize.top || trackTop > canvasBottom || right < canvasSize.left || trackLeft > canvasRight;
|
|
7714
|
+
const rawBottom = canvasBottom - trackBottom;
|
|
7715
|
+
const rawLeft = trackLeft - canvasSize.left;
|
|
7716
|
+
const rawTop = trackTop - canvasSize.top;
|
|
7717
|
+
const position = forceEven ? {
|
|
7718
|
+
width: roundEven(width),
|
|
7719
|
+
height: roundEven(height),
|
|
7720
|
+
left: roundEven(rawLeft),
|
|
7721
|
+
top: roundEven(rawTop),
|
|
7722
|
+
bottom: roundEven(rawBottom),
|
|
7723
|
+
right: roundEven(right)
|
|
7724
|
+
} : { width, height, left: rawLeft, top: rawTop, bottom: rawBottom, right };
|
|
7725
|
+
return { position, isOffscreen };
|
|
7506
7726
|
}
|
|
7507
7727
|
function prepareSkissor(renderer, camera, {
|
|
7508
7728
|
left,
|
|
@@ -7542,6 +7762,7 @@ function clear(renderer) {
|
|
|
7542
7762
|
}
|
|
7543
7763
|
function Container({ visible = true, canvasSize, scene, index, children, frames, rect, track }) {
|
|
7544
7764
|
const { scene: portalScene, camera: portalCamera, renderer, get, setEvents } = useThree();
|
|
7765
|
+
const forceEven = useThree((state) => state.internal.forceEven);
|
|
7545
7766
|
const [isOffscreen, setOffscreen] = React.useState(false);
|
|
7546
7767
|
const mountedRef = React.useRef(true);
|
|
7547
7768
|
React.useEffect(() => {
|
|
@@ -7559,7 +7780,7 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
7559
7780
|
frameCount++;
|
|
7560
7781
|
}
|
|
7561
7782
|
if (rect.current) {
|
|
7562
|
-
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, rect.current);
|
|
7783
|
+
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, rect.current, forceEven);
|
|
7563
7784
|
if (isOffscreen !== _isOffscreen) setOffscreen(_isOffscreen);
|
|
7564
7785
|
if (visible && !_isOffscreen && rect.current) {
|
|
7565
7786
|
const targetScene = children ? portalScene : scene;
|
|
@@ -7581,14 +7802,14 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
7581
7802
|
React.useLayoutEffect(() => {
|
|
7582
7803
|
const curRect = rect.current;
|
|
7583
7804
|
if (curRect && (!visible || !isOffscreen)) {
|
|
7584
|
-
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect);
|
|
7805
|
+
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect, forceEven);
|
|
7585
7806
|
if (!_isOffscreen) {
|
|
7586
7807
|
const autoClear = prepareSkissor(renderer, portalCamera, position);
|
|
7587
7808
|
clear(renderer);
|
|
7588
7809
|
finishSkissor(renderer, autoClear);
|
|
7589
7810
|
}
|
|
7590
7811
|
}
|
|
7591
|
-
}, [visible, isOffscreen, renderer, portalCamera, canvasSize]);
|
|
7812
|
+
}, [visible, isOffscreen, renderer, portalCamera, canvasSize, forceEven]);
|
|
7592
7813
|
React.useEffect(() => {
|
|
7593
7814
|
if (!track) return;
|
|
7594
7815
|
const curRect = rect.current;
|
|
@@ -7596,7 +7817,7 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
7596
7817
|
setEvents({ connected: track.current });
|
|
7597
7818
|
return () => {
|
|
7598
7819
|
if (curRect) {
|
|
7599
|
-
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect);
|
|
7820
|
+
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect, forceEven);
|
|
7600
7821
|
if (!_isOffscreen) {
|
|
7601
7822
|
const autoClear = prepareSkissor(renderer, portalCamera, position);
|
|
7602
7823
|
clear(renderer);
|
|
@@ -7605,13 +7826,14 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
7605
7826
|
}
|
|
7606
7827
|
setEvents({ connected: old });
|
|
7607
7828
|
};
|
|
7608
|
-
}, [track, renderer, portalCamera, canvasSize, get, setEvents]);
|
|
7829
|
+
}, [track, renderer, portalCamera, canvasSize, get, setEvents, forceEven]);
|
|
7609
7830
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, children, /* @__PURE__ */ React.createElement("group", { onPointerOver: () => null }));
|
|
7610
7831
|
}
|
|
7611
7832
|
const CanvasView = /* @__PURE__ */ React.forwardRef(
|
|
7612
7833
|
({ track, visible = true, index = 1, id, style, className, frames = Infinity, children, ...props }, fref) => {
|
|
7613
7834
|
const rect = React.useRef(null);
|
|
7614
7835
|
const { size, scene } = useThree();
|
|
7836
|
+
const forceEven = useThree((state) => state.internal.forceEven);
|
|
7615
7837
|
const [virtualScene] = React.useState(() => new THREE.Scene());
|
|
7616
7838
|
const [ready, toggle] = React.useReducer(() => true, false);
|
|
7617
7839
|
const compute = React.useCallback(
|
|
@@ -7648,12 +7870,12 @@ const CanvasView = /* @__PURE__ */ React.forwardRef(
|
|
|
7648
7870
|
{
|
|
7649
7871
|
events: { compute, priority: index },
|
|
7650
7872
|
size: {
|
|
7651
|
-
width: rect.current?.width,
|
|
7652
|
-
height: rect.current?.height,
|
|
7873
|
+
width: forceEven && rect.current?.width ? roundEven(rect.current.width) : rect.current?.width,
|
|
7874
|
+
height: forceEven && rect.current?.height ? roundEven(rect.current.height) : rect.current?.height,
|
|
7653
7875
|
// @ts-ignore
|
|
7654
|
-
top: rect.current?.top,
|
|
7876
|
+
top: forceEven && rect.current?.top ? roundEven(rect.current.top) : rect.current?.top,
|
|
7655
7877
|
// @ts-ignore
|
|
7656
|
-
left: rect.current?.left
|
|
7878
|
+
left: forceEven && rect.current?.left ? roundEven(rect.current.left) : rect.current?.left
|
|
7657
7879
|
}
|
|
7658
7880
|
}
|
|
7659
7881
|
));
|
|
@@ -8048,12 +8270,12 @@ useEnvironment.preload = (preloadOptions) => {
|
|
|
8048
8270
|
if (extensions) extensions(loader2);
|
|
8049
8271
|
});
|
|
8050
8272
|
};
|
|
8051
|
-
const
|
|
8273
|
+
const clearDefaultOptions = {
|
|
8052
8274
|
files: defaultFiles,
|
|
8053
8275
|
preset: void 0
|
|
8054
8276
|
};
|
|
8055
8277
|
useEnvironment.clear = (clearOptions) => {
|
|
8056
|
-
const options = { ...
|
|
8278
|
+
const options = { ...clearDefaultOptions, ...clearOptions };
|
|
8057
8279
|
let { files } = options;
|
|
8058
8280
|
const { preset } = options;
|
|
8059
8281
|
if (preset) {
|
|
@@ -8747,9 +8969,14 @@ function Select({
|
|
|
8747
8969
|
const oldControlsEnabled = controls?.enabled;
|
|
8748
8970
|
let isDown = false;
|
|
8749
8971
|
function prepareRay(event, vec) {
|
|
8750
|
-
const
|
|
8972
|
+
const canvas = gl.domElement;
|
|
8973
|
+
const rect = canvas.getBoundingClientRect();
|
|
8974
|
+
const x = event.clientX - rect.left;
|
|
8975
|
+
const y = event.clientY - rect.top;
|
|
8751
8976
|
const { width, height } = size;
|
|
8752
|
-
|
|
8977
|
+
const normalizedX = x / width * 2 - 1;
|
|
8978
|
+
const normalizedY = -(y / height) * 2 + 1;
|
|
8979
|
+
vec.set(normalizedX, normalizedY, -1);
|
|
8753
8980
|
}
|
|
8754
8981
|
function onSelectStart(event) {
|
|
8755
8982
|
if (controls) controls.enabled = false;
|
|
@@ -12994,7 +13221,7 @@ const FacemeshDatas = {
|
|
|
12994
13221
|
|
|
12995
13222
|
const FaceLandmarkerContext = /* @__PURE__ */ createContext({});
|
|
12996
13223
|
const FaceLandmarkerDefaults = {
|
|
12997
|
-
basePath:
|
|
13224
|
+
basePath: `https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@${"0.10.17"}/wasm`,
|
|
12998
13225
|
options: {
|
|
12999
13226
|
baseOptions: {
|
|
13000
13227
|
modelAssetPath: "https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task",
|
|
@@ -13742,4 +13969,4 @@ const MarchingPlane = /* @__PURE__ */ React.forwardRef(
|
|
|
13742
13969
|
}
|
|
13743
13970
|
);
|
|
13744
13971
|
|
|
13745
|
-
export { AdaptiveDpr, AdaptiveEvents, ArcballControls, BBAnchor, Backdrop, Billboard, Bounds, Box, Bvh, CameraControls, 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, FaceControls, FaceLandmarker, FaceLandmarkerDefaults, Facemesh, FacemeshDatas, FacemeshEye, FacemeshEyeDefaults, Fbo, Fbx, FirstPersonControls, Fisheye, Float, FlyControls, GizmoHelper, GizmoViewcube, GizmoViewport, Gltf, Helper, Html, Hud, Icosahedron, Instance, InstancedAttribute, Instances, IsObject, KeyboardControls, Ktx2, Lathe, Lightformer, Loader, MapControls, MarchingCube, MarchingCubes, MarchingPlane, Mask, MatcapTexture, Merged, MotionPathControls, NormalTexture, Octahedron, OrbitControls, OrthographicCamera, Outlines, 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, Splat, SpriteAnimator, Stage, Stats, StatsGl, Svg, Tetrahedron, Text3D, Texture, Torus, TorusKnot, TrackballControls, Trail, TrailTexture, TransformControls, Tube, VideoTexture, View, WebcamVideoTexture,
|
|
13972
|
+
export { AdaptiveDpr, AdaptiveEvents, ArcballControls, BBAnchor, Backdrop, Billboard, Bounds, Box, Bvh, CameraControls, 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, FaceControls, FaceLandmarker, FaceLandmarkerDefaults, Facemesh, FacemeshDatas, FacemeshEye, FacemeshEyeDefaults, Fbo, Fbx, FirstPersonControls, Fisheye, Float, FlyControls, GizmoHelper, GizmoViewcube, GizmoViewport, Gltf, Helper, Html, Hud, Icosahedron, Instance, InstancedAttribute, Instances, IsObject, KeyboardControls, Ktx2, Lathe, Lightformer, Loader, MapControls, MarchingCube, MarchingCubes, MarchingPlane, Mask, MatcapTexture, Merged, MotionPathControls, NormalTexture, Octahedron, OrbitControls, OrthographicCamera, Outlines, 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, Splat, SpriteAnimator, Stage, Stats, StatsGl, Svg, Tetrahedron, Text3D, Texture, Torus, TorusKnot, TrackballControls, Trail, TrailTexture, TransformControls, Tube, VideoTexture, View, WebcamVideoTexture, calcPosFromAngles, checkIfFrameIsEmpty, createInstances, getFirstFrame, meshBounds, presetsObj, useAnimations, useAspect, useBVH, useBounds, useContextBridge, useCubeCamera, useCubeTexture, useCursor, useCustomRaycast, useDepthBuffer, useDetectGPU, useEnvironment, useFBO, useFBX, useFaceControls, useFaceLandmarker, useFont, useGLTF, useGizmoContext, useHelper, useIntersect, useKTX2, useKeyboardControls, useMask, useMatcapTexture, useMotion, useNormalTexture, usePerformanceMonitor, useProgress, useScroll, useSelect, useSpriteAnimator, useSpriteLoader, useSurfaceSampler, useTexture, useTrail, useTrailTexture, useVariants, useVideoTexture };
|