@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/core/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 } from 'react';
|
|
3
3
|
import { useThree, useFrame, extend, createPortal, useInstanceHandle, context as context$9, useLoader, applyProps, addEffect, addAfterEffect } from '@react-three/fiber';
|
|
4
4
|
import * as THREE from 'three';
|
|
5
|
-
import { REVISION, WebGLRenderTarget, Frustum, Matrix4, Vector3, Vector4, Vector2, Color, InstancedInterleavedBuffer, InterleavedBufferAttribute, WebGLCubeRenderTarget, HalfFloatType, CubeCamera as CubeCamera$1, MathUtils, TextureLoader, Texture as Texture$1, MeshLambertMaterial,
|
|
5
|
+
import { REVISION, WebGLRenderTarget, Frustum, Matrix4, Vector3, Vector4, Vector2, Color, InstancedInterleavedBuffer, InterleavedBufferAttribute, WebGLCubeRenderTarget, HalfFloatType, CubeCamera as CubeCamera$1, EventDispatcher, Euler, Quaternion, MathUtils, TextureLoader, Texture as Texture$1, MeshLambertMaterial, DynamicDrawUsage, CatmullRomCurve3, CubicBezierCurve3, QuadraticBezierCurve3, Shape as Shape$1, Object3D, CanvasTexture, PerspectiveCamera as PerspectiveCamera$1, OrthographicCamera as OrthographicCamera$1, AudioListener, AudioLoader, AnimationMixer, BufferAttribute, Box3, Sphere as Sphere$1, InstancedBufferAttribute, DoubleSide, DepthTexture, DepthFormat, UnsignedShortType, CubeTextureLoader, DefaultLoadingManager, Ray, Raycaster, Camera, CubeReflectionMapping, EquirectangularReflectionMapping, Scene, RepeatWrapping } from 'three';
|
|
6
6
|
import { ArcballControls as ArcballControls$1 } from 'three/examples/jsm/controls/ArcballControls.js';
|
|
7
|
-
import { 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';
|
|
@@ -180,6 +178,7 @@ function shaderMaterial(uniforms, vertexShader, fragmentShader, onInit) {
|
|
|
180
178
|
});
|
|
181
179
|
}
|
|
182
180
|
this.uniforms = THREE.UniformsUtils.clone(this.uniforms);
|
|
181
|
+
Object.assign(this, parameters);
|
|
183
182
|
}
|
|
184
183
|
};
|
|
185
184
|
}
|
|
@@ -196,7 +195,7 @@ const version = /* @__PURE__ */ getVersion();
|
|
|
196
195
|
function isLight(object) {
|
|
197
196
|
return object.isLight;
|
|
198
197
|
}
|
|
199
|
-
function isGeometry
|
|
198
|
+
function isGeometry(object) {
|
|
200
199
|
return !!object.geometry;
|
|
201
200
|
}
|
|
202
201
|
const accumulativeContext = /* @__PURE__ */ React.createContext(
|
|
@@ -441,7 +440,7 @@ vec3 texelOld = texture2D(previousShadowMap, vUv).rgb;
|
|
|
441
440
|
this.lights = [];
|
|
442
441
|
this.meshes = [];
|
|
443
442
|
this.scene.traverse((object) => {
|
|
444
|
-
if (isGeometry
|
|
443
|
+
if (isGeometry(object)) {
|
|
445
444
|
this.meshes.push({ object, material: object.material });
|
|
446
445
|
} else if (isLight(object)) {
|
|
447
446
|
this.lights.push({ object, intensity: object.intensity });
|
|
@@ -1062,6 +1061,81 @@ const ArcballControls = /* @__PURE__ */ forwardRef(
|
|
|
1062
1061
|
}
|
|
1063
1062
|
);
|
|
1064
1063
|
|
|
1064
|
+
let DeviceOrientationControls$1 = class DeviceOrientationControls extends EventDispatcher {
|
|
1065
|
+
object;
|
|
1066
|
+
changeEvent = { type: "change" };
|
|
1067
|
+
EPS = 1e-6;
|
|
1068
|
+
enabled = true;
|
|
1069
|
+
deviceOrientation = { alpha: 0, beta: 0, gamma: 0 };
|
|
1070
|
+
screenOrientation = 0;
|
|
1071
|
+
alphaOffset = 0;
|
|
1072
|
+
// radians
|
|
1073
|
+
constructor(object) {
|
|
1074
|
+
super();
|
|
1075
|
+
this.object = object;
|
|
1076
|
+
this.object.rotation.reorder("YXZ");
|
|
1077
|
+
this.connect();
|
|
1078
|
+
}
|
|
1079
|
+
onDeviceOrientationChangeEvent = (event) => {
|
|
1080
|
+
this.deviceOrientation = event;
|
|
1081
|
+
};
|
|
1082
|
+
onScreenOrientationChangeEvent = () => {
|
|
1083
|
+
this.screenOrientation = window.orientation || 0;
|
|
1084
|
+
};
|
|
1085
|
+
// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
|
|
1086
|
+
zee = new Vector3(0, 0, 1);
|
|
1087
|
+
euler = new Euler();
|
|
1088
|
+
q0 = new Quaternion();
|
|
1089
|
+
q1 = new Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
|
|
1090
|
+
// - PI/2 around the x-axis
|
|
1091
|
+
setObjectQuaternion = (quaternion, alpha, beta, gamma, orient) => {
|
|
1092
|
+
this.euler.set(beta, alpha, -gamma, "YXZ");
|
|
1093
|
+
quaternion.setFromEuler(this.euler);
|
|
1094
|
+
quaternion.multiply(this.q1);
|
|
1095
|
+
quaternion.multiply(this.q0.setFromAxisAngle(this.zee, -orient));
|
|
1096
|
+
};
|
|
1097
|
+
connect = () => {
|
|
1098
|
+
this.onScreenOrientationChangeEvent();
|
|
1099
|
+
if (window.DeviceOrientationEvent !== void 0 && // @ts-ignore
|
|
1100
|
+
typeof window.DeviceOrientationEvent.requestPermission === "function") {
|
|
1101
|
+
window.DeviceOrientationEvent.requestPermission().then((response) => {
|
|
1102
|
+
if (response == "granted") {
|
|
1103
|
+
window.addEventListener("orientationchange", this.onScreenOrientationChangeEvent);
|
|
1104
|
+
window.addEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
|
|
1105
|
+
}
|
|
1106
|
+
}).catch((error) => {
|
|
1107
|
+
console.error("THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:", error);
|
|
1108
|
+
});
|
|
1109
|
+
} else {
|
|
1110
|
+
window.addEventListener("orientationchange", this.onScreenOrientationChangeEvent);
|
|
1111
|
+
window.addEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
|
|
1112
|
+
}
|
|
1113
|
+
this.enabled = true;
|
|
1114
|
+
};
|
|
1115
|
+
disconnect = () => {
|
|
1116
|
+
window.removeEventListener("orientationchange", this.onScreenOrientationChangeEvent);
|
|
1117
|
+
window.removeEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
|
|
1118
|
+
this.enabled = false;
|
|
1119
|
+
};
|
|
1120
|
+
lastQuaternion = new Quaternion();
|
|
1121
|
+
update = () => {
|
|
1122
|
+
if (this.enabled === false) return;
|
|
1123
|
+
const device = this.deviceOrientation;
|
|
1124
|
+
if (device) {
|
|
1125
|
+
const alpha = device.alpha ? MathUtils.degToRad(device.alpha) + this.alphaOffset : 0;
|
|
1126
|
+
const beta = device.beta ? MathUtils.degToRad(device.beta) : 0;
|
|
1127
|
+
const gamma = device.gamma ? MathUtils.degToRad(device.gamma) : 0;
|
|
1128
|
+
const orient = this.screenOrientation ? MathUtils.degToRad(this.screenOrientation) : 0;
|
|
1129
|
+
this.setObjectQuaternion(this.object.quaternion, alpha, beta, gamma, orient);
|
|
1130
|
+
if (8 * (1 - this.lastQuaternion.dot(this.object.quaternion)) > this.EPS) {
|
|
1131
|
+
this.lastQuaternion.copy(this.object.quaternion);
|
|
1132
|
+
this.dispatchEvent(this.changeEvent);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
};
|
|
1136
|
+
dispose = () => this.disconnect();
|
|
1137
|
+
};
|
|
1138
|
+
|
|
1065
1139
|
const DeviceOrientationControls = /* @__PURE__ */ React.forwardRef(
|
|
1066
1140
|
(props, ref) => {
|
|
1067
1141
|
const { camera, onChange, makeDefault, ...rest } = props;
|
|
@@ -1097,11 +1171,11 @@ const DeviceOrientationControls = /* @__PURE__ */ React.forwardRef(
|
|
|
1097
1171
|
);
|
|
1098
1172
|
|
|
1099
1173
|
const initialModelPosition = /* @__PURE__ */ new THREE.Vector3();
|
|
1100
|
-
const mousePosition2D = /* @__PURE__ */ new THREE.Vector2();
|
|
1101
1174
|
const mousePosition3D = /* @__PURE__ */ new THREE.Vector3();
|
|
1102
1175
|
const dragOffset = /* @__PURE__ */ new THREE.Vector3();
|
|
1103
1176
|
const dragPlaneNormal = /* @__PURE__ */ new THREE.Vector3();
|
|
1104
1177
|
const dragPlane = /* @__PURE__ */ new THREE.Plane();
|
|
1178
|
+
const startPointerPos = /* @__PURE__ */ new THREE.Vector3();
|
|
1105
1179
|
const DragControls = React.forwardRef(
|
|
1106
1180
|
({
|
|
1107
1181
|
autoTransform = true,
|
|
@@ -1117,89 +1191,132 @@ const DragControls = React.forwardRef(
|
|
|
1117
1191
|
...props
|
|
1118
1192
|
}, fRef) => {
|
|
1119
1193
|
const defaultControls = useThree((state) => state.controls);
|
|
1120
|
-
const { camera,
|
|
1194
|
+
const { camera, invalidate } = useThree();
|
|
1121
1195
|
const ref = React.useRef(null);
|
|
1122
|
-
const
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
dragPlane.setFromNormalAndCoplanarPoint(dragPlaneNormal, mousePosition3D);
|
|
1156
|
-
raycaster.ray.intersectPlane(dragPlane, mousePosition3D);
|
|
1157
|
-
const previousLocalMatrix = ref.current.matrix.clone();
|
|
1158
|
-
const previousWorldMatrix = ref.current.matrixWorld.clone();
|
|
1159
|
-
const intendedNewPosition = new THREE.Vector3(
|
|
1160
|
-
mousePosition3D.x - dragOffset.x,
|
|
1161
|
-
mousePosition3D.y - dragOffset.y,
|
|
1162
|
-
mousePosition3D.z - dragOffset.z
|
|
1163
|
-
);
|
|
1164
|
-
if (dragLimits) {
|
|
1165
|
-
intendedNewPosition.x = dragLimits[0] ? Math.max(Math.min(intendedNewPosition.x, dragLimits[0][1]), dragLimits[0][0]) : intendedNewPosition.x;
|
|
1166
|
-
intendedNewPosition.y = dragLimits[1] ? Math.max(Math.min(intendedNewPosition.y, dragLimits[1][1]), dragLimits[1][0]) : intendedNewPosition.y;
|
|
1167
|
-
intendedNewPosition.z = dragLimits[2] ? Math.max(Math.min(intendedNewPosition.z, dragLimits[2][1]), dragLimits[2][0]) : intendedNewPosition.z;
|
|
1168
|
-
}
|
|
1169
|
-
if (autoTransform) {
|
|
1170
|
-
ref.current.matrix.setPosition(intendedNewPosition);
|
|
1171
|
-
const deltaLocalMatrix = ref.current.matrix.clone().multiply(previousLocalMatrix.invert());
|
|
1172
|
-
const deltaWorldMatrix = ref.current.matrix.clone().multiply(previousWorldMatrix.invert());
|
|
1173
|
-
onDrag && onDrag(ref.current.matrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
1174
|
-
} else {
|
|
1175
|
-
const tempMatrix = new THREE.Matrix4().copy(ref.current.matrix);
|
|
1176
|
-
tempMatrix.setPosition(intendedNewPosition);
|
|
1177
|
-
const deltaLocalMatrix = tempMatrix.clone().multiply(previousLocalMatrix.invert());
|
|
1178
|
-
const deltaWorldMatrix = tempMatrix.clone().multiply(previousWorldMatrix.invert());
|
|
1179
|
-
onDrag && onDrag(tempMatrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
1196
|
+
const dragState = React.useRef({
|
|
1197
|
+
active: false,
|
|
1198
|
+
intentional: false,
|
|
1199
|
+
// Has moved past threshold
|
|
1200
|
+
pointerId: -1
|
|
1201
|
+
});
|
|
1202
|
+
const threshold = dragConfig?.threshold ?? 0;
|
|
1203
|
+
const filterTaps = dragConfig?.filterTaps ?? true;
|
|
1204
|
+
const handlePointerDown = React.useCallback(
|
|
1205
|
+
(event) => {
|
|
1206
|
+
event.stopPropagation();
|
|
1207
|
+
event.target.setPointerCapture(event.pointerId);
|
|
1208
|
+
dragState.current.active = true;
|
|
1209
|
+
dragState.current.intentional = threshold === 0;
|
|
1210
|
+
dragState.current.pointerId = event.pointerId;
|
|
1211
|
+
if (defaultControls) defaultControls.enabled = false;
|
|
1212
|
+
ref.current.matrix.decompose(initialModelPosition, new THREE.Quaternion(), new THREE.Vector3());
|
|
1213
|
+
mousePosition3D.copy(event.point);
|
|
1214
|
+
startPointerPos.copy(event.point);
|
|
1215
|
+
dragOffset.copy(mousePosition3D).sub(initialModelPosition);
|
|
1216
|
+
if (!axisLock) {
|
|
1217
|
+
camera.getWorldDirection(dragPlaneNormal).negate();
|
|
1218
|
+
} else {
|
|
1219
|
+
switch (axisLock) {
|
|
1220
|
+
case "x":
|
|
1221
|
+
dragPlaneNormal.set(1, 0, 0);
|
|
1222
|
+
break;
|
|
1223
|
+
case "y":
|
|
1224
|
+
dragPlaneNormal.set(0, 1, 0);
|
|
1225
|
+
break;
|
|
1226
|
+
case "z":
|
|
1227
|
+
dragPlaneNormal.set(0, 0, 1);
|
|
1228
|
+
break;
|
|
1180
1229
|
}
|
|
1181
|
-
invalidate();
|
|
1182
|
-
},
|
|
1183
|
-
onDragEnd: () => {
|
|
1184
|
-
if (defaultControls) defaultControls.enabled = true;
|
|
1185
|
-
onDragEnd && onDragEnd();
|
|
1186
|
-
invalidate();
|
|
1187
1230
|
}
|
|
1231
|
+
dragPlane.setFromNormalAndCoplanarPoint(dragPlaneNormal, mousePosition3D);
|
|
1232
|
+
if (dragState.current.intentional) {
|
|
1233
|
+
onDragStart && onDragStart(initialModelPosition);
|
|
1234
|
+
}
|
|
1235
|
+
invalidate();
|
|
1188
1236
|
},
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1237
|
+
[defaultControls, camera, axisLock, threshold, onDragStart, invalidate]
|
|
1238
|
+
);
|
|
1239
|
+
const handlePointerMove = React.useCallback(
|
|
1240
|
+
(event) => {
|
|
1241
|
+
if (!dragState.current.active || event.pointerId !== dragState.current.pointerId) return;
|
|
1242
|
+
const intersection = event.ray.intersectPlane(dragPlane, mousePosition3D);
|
|
1243
|
+
if (!intersection) return;
|
|
1244
|
+
if (!dragState.current.intentional) {
|
|
1245
|
+
const distance = mousePosition3D.distanceTo(startPointerPos);
|
|
1246
|
+
if (distance < threshold) return;
|
|
1247
|
+
dragState.current.intentional = true;
|
|
1248
|
+
onDragStart && onDragStart(initialModelPosition);
|
|
1194
1249
|
}
|
|
1195
|
-
|
|
1250
|
+
const previousLocalMatrix = ref.current.matrix.clone();
|
|
1251
|
+
const previousWorldMatrix = ref.current.matrixWorld.clone();
|
|
1252
|
+
const intendedNewPosition = new THREE.Vector3(
|
|
1253
|
+
mousePosition3D.x - dragOffset.x,
|
|
1254
|
+
mousePosition3D.y - dragOffset.y,
|
|
1255
|
+
mousePosition3D.z - dragOffset.z
|
|
1256
|
+
);
|
|
1257
|
+
if (dragLimits) {
|
|
1258
|
+
intendedNewPosition.x = dragLimits[0] ? Math.max(Math.min(intendedNewPosition.x, dragLimits[0][1]), dragLimits[0][0]) : intendedNewPosition.x;
|
|
1259
|
+
intendedNewPosition.y = dragLimits[1] ? Math.max(Math.min(intendedNewPosition.y, dragLimits[1][1]), dragLimits[1][0]) : intendedNewPosition.y;
|
|
1260
|
+
intendedNewPosition.z = dragLimits[2] ? Math.max(Math.min(intendedNewPosition.z, dragLimits[2][1]), dragLimits[2][0]) : intendedNewPosition.z;
|
|
1261
|
+
}
|
|
1262
|
+
if (autoTransform) {
|
|
1263
|
+
ref.current.matrix.setPosition(intendedNewPosition);
|
|
1264
|
+
const deltaLocalMatrix = ref.current.matrix.clone().multiply(previousLocalMatrix.invert());
|
|
1265
|
+
const deltaWorldMatrix = ref.current.matrix.clone().multiply(previousWorldMatrix.invert());
|
|
1266
|
+
onDrag && onDrag(ref.current.matrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
1267
|
+
} else {
|
|
1268
|
+
const tempMatrix = new THREE.Matrix4().copy(ref.current.matrix);
|
|
1269
|
+
tempMatrix.setPosition(intendedNewPosition);
|
|
1270
|
+
const deltaLocalMatrix = tempMatrix.clone().multiply(previousLocalMatrix.invert());
|
|
1271
|
+
const deltaWorldMatrix = tempMatrix.clone().multiply(previousWorldMatrix.invert());
|
|
1272
|
+
onDrag && onDrag(tempMatrix, deltaLocalMatrix, ref.current.matrixWorld, deltaWorldMatrix);
|
|
1273
|
+
}
|
|
1274
|
+
invalidate();
|
|
1275
|
+
},
|
|
1276
|
+
[autoTransform, dragLimits, threshold, onDragStart, onDrag, invalidate]
|
|
1277
|
+
);
|
|
1278
|
+
const handlePointerUp = React.useCallback(
|
|
1279
|
+
(event) => {
|
|
1280
|
+
if (!dragState.current.active || event.pointerId !== dragState.current.pointerId) return;
|
|
1281
|
+
event.target.releasePointerCapture(event.pointerId);
|
|
1282
|
+
const wasIntentional = dragState.current.intentional;
|
|
1283
|
+
dragState.current.active = false;
|
|
1284
|
+
dragState.current.intentional = false;
|
|
1285
|
+
dragState.current.pointerId = -1;
|
|
1286
|
+
if (defaultControls) defaultControls.enabled = true;
|
|
1287
|
+
if (wasIntentional || !filterTaps) {
|
|
1288
|
+
onDragEnd && onDragEnd();
|
|
1289
|
+
}
|
|
1290
|
+
invalidate();
|
|
1291
|
+
},
|
|
1292
|
+
[defaultControls, filterTaps, onDragEnd, invalidate]
|
|
1196
1293
|
);
|
|
1294
|
+
const handlePointerEnter = React.useCallback(() => {
|
|
1295
|
+
onHover && onHover(true);
|
|
1296
|
+
}, [onHover]);
|
|
1297
|
+
const handlePointerLeave = React.useCallback(() => {
|
|
1298
|
+
onHover && onHover(false);
|
|
1299
|
+
}, [onHover]);
|
|
1197
1300
|
React.useImperativeHandle(fRef, () => ref.current, []);
|
|
1198
1301
|
React.useLayoutEffect(() => {
|
|
1199
1302
|
if (!matrix) return;
|
|
1200
1303
|
ref.current.matrix = matrix;
|
|
1201
1304
|
}, [matrix]);
|
|
1202
|
-
return /* @__PURE__ */ React.createElement(
|
|
1305
|
+
return /* @__PURE__ */ React.createElement(
|
|
1306
|
+
"group",
|
|
1307
|
+
{
|
|
1308
|
+
ref,
|
|
1309
|
+
onPointerDown: handlePointerDown,
|
|
1310
|
+
onPointerMove: handlePointerMove,
|
|
1311
|
+
onPointerUp: handlePointerUp,
|
|
1312
|
+
onPointerEnter: handlePointerEnter,
|
|
1313
|
+
onPointerLeave: handlePointerLeave,
|
|
1314
|
+
matrix,
|
|
1315
|
+
matrixAutoUpdate: false,
|
|
1316
|
+
...props
|
|
1317
|
+
},
|
|
1318
|
+
children
|
|
1319
|
+
);
|
|
1203
1320
|
}
|
|
1204
1321
|
);
|
|
1205
1322
|
|
|
@@ -1301,14 +1418,23 @@ function KeyboardControls({ map, children, onChange, domElement }) {
|
|
|
1301
1418
|
obj.pressed = false;
|
|
1302
1419
|
if (up) fn(false);
|
|
1303
1420
|
};
|
|
1421
|
+
const blurHandler = () => {
|
|
1422
|
+
const resetState = map.reduce((prev, cur) => ({ ...prev, [cur.name]: false }), {});
|
|
1423
|
+
set(resetState);
|
|
1424
|
+
Object.values(keyMap).forEach((obj) => {
|
|
1425
|
+
obj.pressed = false;
|
|
1426
|
+
});
|
|
1427
|
+
};
|
|
1304
1428
|
const source = domElement || window;
|
|
1305
1429
|
source.addEventListener("keydown", downHandler, { passive: true });
|
|
1306
1430
|
source.addEventListener("keyup", upHandler, { passive: true });
|
|
1431
|
+
window.addEventListener("blur", blurHandler);
|
|
1307
1432
|
return () => {
|
|
1308
1433
|
source.removeEventListener("keydown", downHandler);
|
|
1309
1434
|
source.removeEventListener("keyup", upHandler);
|
|
1435
|
+
window.removeEventListener("blur", blurHandler);
|
|
1310
1436
|
};
|
|
1311
|
-
}, [domElement, key]);
|
|
1437
|
+
}, [domElement, key, onChange]);
|
|
1312
1438
|
return /* @__PURE__ */ React.createElement(context$8.Provider, { value: api, children });
|
|
1313
1439
|
}
|
|
1314
1440
|
function useKeyboardControls(sel) {
|
|
@@ -1330,20 +1456,28 @@ const MapControls = /* @__PURE__ */ React.forwardRef((props = { enableDamping: t
|
|
|
1330
1456
|
const controls = React.useMemo(() => new MapControls$1(explCamera), [explCamera]);
|
|
1331
1457
|
React.useEffect(() => {
|
|
1332
1458
|
controls.connect(explDomElement);
|
|
1459
|
+
return () => void controls.dispose();
|
|
1460
|
+
}, [explDomElement, controls]);
|
|
1461
|
+
React.useEffect(() => {
|
|
1333
1462
|
const callback = (e) => {
|
|
1334
1463
|
invalidate();
|
|
1335
1464
|
if (onChange) onChange(e);
|
|
1336
1465
|
};
|
|
1466
|
+
const onStartCb = (e) => {
|
|
1467
|
+
if (onStart) onStart(e);
|
|
1468
|
+
};
|
|
1469
|
+
const onEndCb = (e) => {
|
|
1470
|
+
if (onEnd) onEnd(e);
|
|
1471
|
+
};
|
|
1337
1472
|
controls.addEventListener("change", callback);
|
|
1338
|
-
|
|
1339
|
-
|
|
1473
|
+
controls.addEventListener("start", onStartCb);
|
|
1474
|
+
controls.addEventListener("end", onEndCb);
|
|
1340
1475
|
return () => {
|
|
1341
|
-
controls.
|
|
1476
|
+
controls.removeEventListener("start", onStartCb);
|
|
1477
|
+
controls.removeEventListener("end", onEndCb);
|
|
1342
1478
|
controls.removeEventListener("change", callback);
|
|
1343
|
-
if (onStart) controls.removeEventListener("start", onStart);
|
|
1344
|
-
if (onEnd) controls.removeEventListener("end", onEnd);
|
|
1345
1479
|
};
|
|
1346
|
-
}, [onChange, onStart, onEnd, controls, invalidate
|
|
1480
|
+
}, [onChange, onStart, onEnd, controls, invalidate]);
|
|
1347
1481
|
React.useEffect(() => {
|
|
1348
1482
|
if (makeDefault) {
|
|
1349
1483
|
const old = get().controls;
|
|
@@ -1351,7 +1485,9 @@ const MapControls = /* @__PURE__ */ React.forwardRef((props = { enableDamping: t
|
|
|
1351
1485
|
return () => set({ controls: old });
|
|
1352
1486
|
}
|
|
1353
1487
|
}, [makeDefault, controls]);
|
|
1354
|
-
useFrame(() =>
|
|
1488
|
+
useFrame(() => {
|
|
1489
|
+
if (controls.enabled) controls.update();
|
|
1490
|
+
}, -1);
|
|
1355
1491
|
return /* @__PURE__ */ React.createElement("primitive", { ref, object: controls, enableDamping: true, ...rest });
|
|
1356
1492
|
});
|
|
1357
1493
|
|
|
@@ -1477,20 +1613,16 @@ const OrbitControls = /* @__PURE__ */ React.forwardRef(
|
|
|
1477
1613
|
onEnd,
|
|
1478
1614
|
...restProps
|
|
1479
1615
|
}, ref) => {
|
|
1480
|
-
const invalidate = useThree(
|
|
1481
|
-
const defaultCamera = useThree((state) => state.camera);
|
|
1482
|
-
const gl = useThree((state) => state.gl);
|
|
1483
|
-
const events = useThree((state) => state.events);
|
|
1484
|
-
const setEvents = useThree((state) => state.setEvents);
|
|
1485
|
-
const set = useThree((state) => state.set);
|
|
1486
|
-
const get = useThree((state) => state.get);
|
|
1487
|
-
const performance = useThree((state) => state.performance);
|
|
1616
|
+
const { invalidate, camera: defaultCamera, renderer, events, setEvents, set, get, performance } = useThree();
|
|
1488
1617
|
const explCamera = camera || defaultCamera;
|
|
1489
|
-
const explDomElement = domElement || events.connected ||
|
|
1618
|
+
const explDomElement = domElement || events.connected || renderer.domElement;
|
|
1490
1619
|
const controls = React.useMemo(() => new OrbitControls$1(explCamera), [explCamera]);
|
|
1491
|
-
useFrame(
|
|
1492
|
-
|
|
1493
|
-
|
|
1620
|
+
useFrame(
|
|
1621
|
+
() => {
|
|
1622
|
+
if (controls.enabled) controls.update();
|
|
1623
|
+
},
|
|
1624
|
+
{ before: "update" }
|
|
1625
|
+
);
|
|
1494
1626
|
React.useEffect(() => {
|
|
1495
1627
|
if (keyEvents) {
|
|
1496
1628
|
controls.connect(keyEvents === true ? explDomElement : keyEvents);
|
|
@@ -1604,9 +1736,8 @@ function PresentationControls({
|
|
|
1604
1736
|
azimuth = [-Infinity, Infinity],
|
|
1605
1737
|
damping = 0.25
|
|
1606
1738
|
}) {
|
|
1607
|
-
const events = useThree(
|
|
1608
|
-
const
|
|
1609
|
-
const explDomElement = domElement || events.connected || gl.domElement;
|
|
1739
|
+
const { events, renderer, invalidate } = useThree();
|
|
1740
|
+
const explDomElement = domElement || events.connected || renderer.domElement;
|
|
1610
1741
|
const { size } = useThree();
|
|
1611
1742
|
const rPolar = React.useMemo(
|
|
1612
1743
|
() => [rotation[0] + polar[0], rotation[0] + polar[1]],
|
|
@@ -1623,18 +1754,20 @@ function PresentationControls({
|
|
|
1623
1754
|
React.useEffect(() => {
|
|
1624
1755
|
if (global && cursor && enabled) {
|
|
1625
1756
|
explDomElement.style.cursor = "grab";
|
|
1626
|
-
|
|
1757
|
+
renderer.domElement.style.cursor = "";
|
|
1627
1758
|
return () => {
|
|
1628
1759
|
explDomElement.style.cursor = "default";
|
|
1629
|
-
|
|
1760
|
+
renderer.domElement.style.cursor = "default";
|
|
1630
1761
|
};
|
|
1631
1762
|
}
|
|
1632
1763
|
}, [global, cursor, explDomElement, enabled]);
|
|
1633
1764
|
const [animation] = React.useState({ scale: 1, rotation: rInitial, damping });
|
|
1634
1765
|
const ref = React.useRef(null);
|
|
1635
1766
|
useFrame((state, delta) => {
|
|
1636
|
-
|
|
1637
|
-
easing.
|
|
1767
|
+
let changed = false;
|
|
1768
|
+
changed ||= easing.damp3(ref.current.scale, animation.scale, animation.damping, delta);
|
|
1769
|
+
changed ||= easing.dampE(ref.current.rotation, animation.rotation, animation.damping, delta);
|
|
1770
|
+
if (changed) state.invalidate();
|
|
1638
1771
|
});
|
|
1639
1772
|
const bind = useGesture(
|
|
1640
1773
|
{
|
|
@@ -1642,6 +1775,7 @@ function PresentationControls({
|
|
|
1642
1775
|
if (cursor && !global && enabled) explDomElement.style.cursor = last ? "auto" : "grab";
|
|
1643
1776
|
},
|
|
1644
1777
|
onDrag: ({ down, delta: [x, y], memo: [oldY, oldX] = animation.rotation || rInitial }) => {
|
|
1778
|
+
invalidate();
|
|
1645
1779
|
if (!enabled) return [y, x];
|
|
1646
1780
|
if (cursor) explDomElement.style.cursor = down ? "grabbing" : "grab";
|
|
1647
1781
|
x = MathUtils.clamp(oldX + x / size.width * Math.PI * speed, ...rAzimuth);
|
|
@@ -1650,14 +1784,27 @@ function PresentationControls({
|
|
|
1650
1784
|
animation.rotation = snap && !down ? rInitial : [y, x, 0];
|
|
1651
1785
|
animation.damping = snap && !down && typeof snap !== "boolean" ? snap : damping;
|
|
1652
1786
|
return [y, x];
|
|
1787
|
+
},
|
|
1788
|
+
onDragEnd: () => {
|
|
1789
|
+
invalidate();
|
|
1653
1790
|
}
|
|
1654
1791
|
},
|
|
1655
|
-
{ target: global ? explDomElement : void 0 }
|
|
1792
|
+
{ target: global ? explDomElement : void 0, enabled }
|
|
1656
1793
|
);
|
|
1657
1794
|
return /* @__PURE__ */ React.createElement("group", { ref, ...bind?.() }, children);
|
|
1658
1795
|
}
|
|
1659
1796
|
|
|
1797
|
+
function roundToPixelRatio(value) {
|
|
1798
|
+
const ratio = window.devicePixelRatio || 1;
|
|
1799
|
+
return Math.round(value * ratio) / ratio;
|
|
1800
|
+
}
|
|
1801
|
+
function getMaxAnisotropy(renderer) {
|
|
1802
|
+
const r = renderer;
|
|
1803
|
+
return r?.getMaxAnisotropy?.() ?? r?.capabilities?.getMaxAnisotropy?.() ?? 1;
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1660
1806
|
const context$7 = /* @__PURE__ */ React.createContext(null);
|
|
1807
|
+
const rootCache = /* @__PURE__ */ new WeakMap();
|
|
1661
1808
|
function useScroll() {
|
|
1662
1809
|
return React.useContext(context$7);
|
|
1663
1810
|
}
|
|
@@ -1671,6 +1818,7 @@ function ScrollControls({
|
|
|
1671
1818
|
damping = 0.25,
|
|
1672
1819
|
maxSpeed = Infinity,
|
|
1673
1820
|
prepend = false,
|
|
1821
|
+
pixelPerfect = true,
|
|
1674
1822
|
style = {},
|
|
1675
1823
|
children
|
|
1676
1824
|
}) {
|
|
@@ -1680,6 +1828,7 @@ function ScrollControls({
|
|
|
1680
1828
|
const [fixed] = React.useState(() => document.createElement("div"));
|
|
1681
1829
|
const target = gl.domElement.parentNode;
|
|
1682
1830
|
const scroll = React.useRef(0);
|
|
1831
|
+
const disableScrollUpdate = React.useRef(false);
|
|
1683
1832
|
const state = React.useMemo(() => {
|
|
1684
1833
|
const state2 = {
|
|
1685
1834
|
el,
|
|
@@ -1692,6 +1841,7 @@ function ScrollControls({
|
|
|
1692
1841
|
delta: 0,
|
|
1693
1842
|
scroll,
|
|
1694
1843
|
pages,
|
|
1844
|
+
pixelPerfect,
|
|
1695
1845
|
// 0-1 for a range between from -> from + distance
|
|
1696
1846
|
range(from, distance2, margin = 0) {
|
|
1697
1847
|
const start = from - margin;
|
|
@@ -1710,7 +1860,7 @@ function ScrollControls({
|
|
|
1710
1860
|
}
|
|
1711
1861
|
};
|
|
1712
1862
|
return state2;
|
|
1713
|
-
}, [eps, damping, horizontal, pages]);
|
|
1863
|
+
}, [eps, damping, horizontal, pages, pixelPerfect]);
|
|
1714
1864
|
React.useEffect(() => {
|
|
1715
1865
|
el.style.position = "absolute";
|
|
1716
1866
|
el.style.width = "100%";
|
|
@@ -1760,16 +1910,20 @@ function ScrollControls({
|
|
|
1760
1910
|
const scrollLength = el[horizontal ? "scrollWidth" : "scrollHeight"];
|
|
1761
1911
|
const scrollThreshold = scrollLength - containerLength;
|
|
1762
1912
|
let current = 0;
|
|
1763
|
-
let disableScroll =
|
|
1913
|
+
let disableScroll = false;
|
|
1764
1914
|
let firstRun = true;
|
|
1765
1915
|
const onScroll = () => {
|
|
1766
1916
|
if (!enabled || firstRun) return;
|
|
1917
|
+
if (disableScrollUpdate.current) {
|
|
1918
|
+
disableScrollUpdate.current = false;
|
|
1919
|
+
return;
|
|
1920
|
+
}
|
|
1767
1921
|
invalidate();
|
|
1768
1922
|
current = el[horizontal ? "scrollLeft" : "scrollTop"];
|
|
1769
1923
|
scroll.current = current / scrollThreshold;
|
|
1770
1924
|
if (infinite) {
|
|
1771
1925
|
if (!disableScroll) {
|
|
1772
|
-
if (current >= scrollThreshold) {
|
|
1926
|
+
if (current >= scrollThreshold - 1) {
|
|
1773
1927
|
const damp = 1 - state.offset;
|
|
1774
1928
|
el[horizontal ? "scrollLeft" : "scrollTop"] = 1;
|
|
1775
1929
|
scroll.current = state.offset = -damp;
|
|
@@ -1786,11 +1940,34 @@ function ScrollControls({
|
|
|
1786
1940
|
};
|
|
1787
1941
|
el.addEventListener("scroll", onScroll, { passive: true });
|
|
1788
1942
|
requestAnimationFrame(() => firstRun = false);
|
|
1789
|
-
const
|
|
1790
|
-
|
|
1943
|
+
const onResize = () => {
|
|
1944
|
+
if (!el) return;
|
|
1945
|
+
const scrollLength2 = el[horizontal ? "scrollWidth" : "scrollHeight"];
|
|
1946
|
+
const containerLength2 = el[horizontal ? "clientWidth" : "clientHeight"];
|
|
1947
|
+
disableScrollUpdate.current = true;
|
|
1948
|
+
el[horizontal ? "scrollLeft" : "scrollTop"] = state.offset * (scrollLength2 - containerLength2);
|
|
1949
|
+
};
|
|
1950
|
+
const onWheel = (e) => {
|
|
1951
|
+
if (horizontal) {
|
|
1952
|
+
const previous = el.scrollLeft;
|
|
1953
|
+
el.scrollLeft += e.deltaY / 2;
|
|
1954
|
+
if (infinite && previous === el.scrollLeft) {
|
|
1955
|
+
onScroll();
|
|
1956
|
+
}
|
|
1957
|
+
} else if (infinite) {
|
|
1958
|
+
if (el.scrollTop <= 1 && e.deltaY < 0) {
|
|
1959
|
+
onScroll();
|
|
1960
|
+
} else if (el.scrollTop >= el.scrollHeight - el.clientHeight - 1 && e.deltaY > 0) {
|
|
1961
|
+
onScroll();
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
};
|
|
1965
|
+
if (horizontal || infinite) el.addEventListener("wheel", onWheel, { passive: true });
|
|
1966
|
+
if (horizontal) window.addEventListener("resize", onResize);
|
|
1791
1967
|
return () => {
|
|
1792
1968
|
el.removeEventListener("scroll", onScroll);
|
|
1793
|
-
if (horizontal) el.removeEventListener("wheel", onWheel);
|
|
1969
|
+
if (horizontal || infinite) el.removeEventListener("wheel", onWheel);
|
|
1970
|
+
if (horizontal) window.removeEventListener("resize", onResize);
|
|
1794
1971
|
};
|
|
1795
1972
|
}
|
|
1796
1973
|
}, [el, events, size, infinite, state, invalidate, horizontal, enabled]);
|
|
@@ -1823,10 +2000,23 @@ const ScrollHtml = React.forwardRef(
|
|
|
1823
2000
|
React.useImperativeHandle(ref, () => group.current, []);
|
|
1824
2001
|
const { width, height } = useThree((state2) => state2.size);
|
|
1825
2002
|
const fiberState = React.useContext(context$9);
|
|
1826
|
-
const root = React.useMemo(() =>
|
|
2003
|
+
const root = React.useMemo(() => {
|
|
2004
|
+
let root2 = rootCache.get(state.fixed);
|
|
2005
|
+
if (!root2) {
|
|
2006
|
+
root2 = ReactDOM.createRoot(state.fixed);
|
|
2007
|
+
rootCache.set(state.fixed, root2);
|
|
2008
|
+
}
|
|
2009
|
+
return root2;
|
|
2010
|
+
}, [state.fixed]);
|
|
1827
2011
|
useFrame(() => {
|
|
1828
2012
|
if (state.delta > state.eps) {
|
|
1829
|
-
|
|
2013
|
+
let x = state.horizontal ? -width * (state.pages - 1) * state.offset : 0;
|
|
2014
|
+
let y = state.horizontal ? 0 : height * (state.pages - 1) * -state.offset;
|
|
2015
|
+
if (state.pixelPerfect) {
|
|
2016
|
+
x = roundToPixelRatio(x);
|
|
2017
|
+
y = roundToPixelRatio(y);
|
|
2018
|
+
}
|
|
2019
|
+
group.current.style.transform = `translate3d(${x}px,${y}px,0)`;
|
|
1830
2020
|
}
|
|
1831
2021
|
});
|
|
1832
2022
|
root.render(
|
|
@@ -2194,10 +2384,10 @@ const CloudInstance = /* @__PURE__ */ React.forwardRef(
|
|
|
2194
2384
|
return /* @__PURE__ */ React.createElement("group", { ref, ...props });
|
|
2195
2385
|
}
|
|
2196
2386
|
);
|
|
2197
|
-
const Cloud = /* @__PURE__ */ React.forwardRef((props, fref) => {
|
|
2387
|
+
const Cloud = /* @__PURE__ */ React.forwardRef(({ materialFactory, ...props }, fref) => {
|
|
2198
2388
|
const parent = React.useContext(context$6);
|
|
2199
2389
|
if (parent) return /* @__PURE__ */ React.createElement(CloudInstance, { ref: fref, ...props });
|
|
2200
|
-
return /* @__PURE__ */ React.createElement(Clouds,
|
|
2390
|
+
return /* @__PURE__ */ React.createElement(Clouds, { materialFactory }, /* @__PURE__ */ React.createElement(CloudInstance, { ref: fref, ...props }));
|
|
2201
2391
|
});
|
|
2202
2392
|
|
|
2203
2393
|
const CatmullRomLine = /* @__PURE__ */ React.forwardRef(function CatmullRomLine2({
|
|
@@ -2719,7 +2909,7 @@ const Text3D = /* @__PURE__ */ React.forwardRef(
|
|
|
2719
2909
|
return {
|
|
2720
2910
|
font,
|
|
2721
2911
|
size,
|
|
2722
|
-
height,
|
|
2912
|
+
depth: height,
|
|
2723
2913
|
bevelThickness,
|
|
2724
2914
|
bevelSize,
|
|
2725
2915
|
bevelEnabled,
|
|
@@ -2755,377 +2945,6 @@ const Text3D = /* @__PURE__ */ React.forwardRef(
|
|
|
2755
2945
|
}
|
|
2756
2946
|
);
|
|
2757
2947
|
|
|
2758
|
-
const WireframeMaterialShaders = {
|
|
2759
|
-
uniforms: {
|
|
2760
|
-
strokeOpacity: 1,
|
|
2761
|
-
fillOpacity: 0.25,
|
|
2762
|
-
fillMix: 0,
|
|
2763
|
-
thickness: 0.05,
|
|
2764
|
-
colorBackfaces: false,
|
|
2765
|
-
dashInvert: true,
|
|
2766
|
-
dash: false,
|
|
2767
|
-
dashRepeats: 4,
|
|
2768
|
-
dashLength: 0.5,
|
|
2769
|
-
squeeze: false,
|
|
2770
|
-
squeezeMin: 0.2,
|
|
2771
|
-
squeezeMax: 1,
|
|
2772
|
-
stroke: /* @__PURE__ */ new THREE.Color("#ff0000"),
|
|
2773
|
-
backfaceStroke: /* @__PURE__ */ new THREE.Color("#0000ff"),
|
|
2774
|
-
fill: /* @__PURE__ */ new THREE.Color("#00ff00")
|
|
2775
|
-
},
|
|
2776
|
-
vertex: (
|
|
2777
|
-
/* glsl */
|
|
2778
|
-
`
|
|
2779
|
-
attribute vec3 barycentric;
|
|
2780
|
-
|
|
2781
|
-
varying vec3 v_edges_Barycentric;
|
|
2782
|
-
varying vec3 v_edges_Position;
|
|
2783
|
-
|
|
2784
|
-
void initWireframe() {
|
|
2785
|
-
v_edges_Barycentric = barycentric;
|
|
2786
|
-
v_edges_Position = position.xyz;
|
|
2787
|
-
}
|
|
2788
|
-
`
|
|
2789
|
-
),
|
|
2790
|
-
fragment: (
|
|
2791
|
-
/* glsl */
|
|
2792
|
-
`
|
|
2793
|
-
#ifndef PI
|
|
2794
|
-
#define PI 3.1415926535897932384626433832795
|
|
2795
|
-
#endif
|
|
2796
|
-
|
|
2797
|
-
varying vec3 v_edges_Barycentric;
|
|
2798
|
-
varying vec3 v_edges_Position;
|
|
2799
|
-
|
|
2800
|
-
uniform float strokeOpacity;
|
|
2801
|
-
uniform float fillOpacity;
|
|
2802
|
-
uniform float fillMix;
|
|
2803
|
-
uniform float thickness;
|
|
2804
|
-
uniform bool colorBackfaces;
|
|
2805
|
-
|
|
2806
|
-
// Dash
|
|
2807
|
-
uniform bool dashInvert;
|
|
2808
|
-
uniform bool dash;
|
|
2809
|
-
uniform bool dashOnly;
|
|
2810
|
-
uniform float dashRepeats;
|
|
2811
|
-
uniform float dashLength;
|
|
2812
|
-
|
|
2813
|
-
// Squeeze
|
|
2814
|
-
uniform bool squeeze;
|
|
2815
|
-
uniform float squeezeMin;
|
|
2816
|
-
uniform float squeezeMax;
|
|
2817
|
-
|
|
2818
|
-
// Colors
|
|
2819
|
-
uniform vec3 stroke;
|
|
2820
|
-
uniform vec3 backfaceStroke;
|
|
2821
|
-
uniform vec3 fill;
|
|
2822
|
-
|
|
2823
|
-
// This is like
|
|
2824
|
-
float wireframe_aastep(float threshold, float dist) {
|
|
2825
|
-
float afwidth = fwidth(dist) * 0.5;
|
|
2826
|
-
return smoothstep(threshold - afwidth, threshold + afwidth, dist);
|
|
2827
|
-
}
|
|
2828
|
-
|
|
2829
|
-
float wireframe_map(float value, float min1, float max1, float min2, float max2) {
|
|
2830
|
-
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
|
2831
|
-
}
|
|
2832
|
-
|
|
2833
|
-
float getWireframe() {
|
|
2834
|
-
vec3 barycentric = v_edges_Barycentric;
|
|
2835
|
-
|
|
2836
|
-
// Distance from center of each triangle to its edges.
|
|
2837
|
-
float d = min(min(barycentric.x, barycentric.y), barycentric.z);
|
|
2838
|
-
|
|
2839
|
-
// for dashed rendering, we can use this to get the 0 .. 1 value of the line length
|
|
2840
|
-
float positionAlong = max(barycentric.x, barycentric.y);
|
|
2841
|
-
if (barycentric.y < barycentric.x && barycentric.y < barycentric.z) {
|
|
2842
|
-
positionAlong = 1.0 - positionAlong;
|
|
2843
|
-
}
|
|
2844
|
-
|
|
2845
|
-
// the thickness of the stroke
|
|
2846
|
-
float computedThickness = wireframe_map(thickness, 0.0, 1.0, 0.0, 0.34);
|
|
2847
|
-
|
|
2848
|
-
// if we want to shrink the thickness toward the center of the line segment
|
|
2849
|
-
if (squeeze) {
|
|
2850
|
-
computedThickness *= mix(squeezeMin, squeezeMax, (1.0 - sin(positionAlong * PI)));
|
|
2851
|
-
}
|
|
2852
|
-
|
|
2853
|
-
// Create dash pattern
|
|
2854
|
-
if (dash) {
|
|
2855
|
-
// here we offset the stroke position depending on whether it
|
|
2856
|
-
// should overlap or not
|
|
2857
|
-
float offset = 1.0 / dashRepeats * dashLength / 2.0;
|
|
2858
|
-
if (!dashInvert) {
|
|
2859
|
-
offset += 1.0 / dashRepeats / 2.0;
|
|
2860
|
-
}
|
|
2861
|
-
|
|
2862
|
-
// if we should animate the dash or not
|
|
2863
|
-
// if (dashAnimate) {
|
|
2864
|
-
// offset += time * 0.22;
|
|
2865
|
-
// }
|
|
2866
|
-
|
|
2867
|
-
// create the repeating dash pattern
|
|
2868
|
-
float pattern = fract((positionAlong + offset) * dashRepeats);
|
|
2869
|
-
computedThickness *= 1.0 - wireframe_aastep(dashLength, pattern);
|
|
2870
|
-
}
|
|
2871
|
-
|
|
2872
|
-
// compute the anti-aliased stroke edge
|
|
2873
|
-
float edge = 1.0 - wireframe_aastep(computedThickness, d);
|
|
2874
|
-
|
|
2875
|
-
return edge;
|
|
2876
|
-
}
|
|
2877
|
-
`
|
|
2878
|
-
)
|
|
2879
|
-
};
|
|
2880
|
-
const WireframeMaterial = /* @__PURE__ */ shaderMaterial(
|
|
2881
|
-
WireframeMaterialShaders.uniforms,
|
|
2882
|
-
WireframeMaterialShaders.vertex + /* glsl */
|
|
2883
|
-
`
|
|
2884
|
-
void main() {
|
|
2885
|
-
initWireframe();
|
|
2886
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
2887
|
-
}
|
|
2888
|
-
`,
|
|
2889
|
-
WireframeMaterialShaders.fragment + /* glsl */
|
|
2890
|
-
`
|
|
2891
|
-
void main () {
|
|
2892
|
-
// Compute color
|
|
2893
|
-
|
|
2894
|
-
float edge = getWireframe();
|
|
2895
|
-
vec4 colorStroke = vec4(stroke, edge);
|
|
2896
|
-
|
|
2897
|
-
#ifdef FLIP_SIDED
|
|
2898
|
-
colorStroke.rgb = backfaceStroke;
|
|
2899
|
-
#endif
|
|
2900
|
-
|
|
2901
|
-
vec4 colorFill = vec4(fill, fillOpacity);
|
|
2902
|
-
vec4 outColor = mix(colorFill, colorStroke, edge * strokeOpacity);
|
|
2903
|
-
|
|
2904
|
-
gl_FragColor = outColor;
|
|
2905
|
-
}
|
|
2906
|
-
`
|
|
2907
|
-
);
|
|
2908
|
-
function setWireframeOverride(material, uniforms) {
|
|
2909
|
-
material.onBeforeCompile = (shader) => {
|
|
2910
|
-
shader.uniforms = {
|
|
2911
|
-
...shader.uniforms,
|
|
2912
|
-
...uniforms
|
|
2913
|
-
};
|
|
2914
|
-
shader.vertexShader = shader.vertexShader.replace(
|
|
2915
|
-
"void main() {",
|
|
2916
|
-
`
|
|
2917
|
-
${WireframeMaterialShaders.vertex}
|
|
2918
|
-
void main() {
|
|
2919
|
-
initWireframe();
|
|
2920
|
-
`
|
|
2921
|
-
);
|
|
2922
|
-
shader.fragmentShader = shader.fragmentShader.replace(
|
|
2923
|
-
"void main() {",
|
|
2924
|
-
`
|
|
2925
|
-
${WireframeMaterialShaders.fragment}
|
|
2926
|
-
void main() {
|
|
2927
|
-
`
|
|
2928
|
-
);
|
|
2929
|
-
shader.fragmentShader = shader.fragmentShader.replace(
|
|
2930
|
-
"#include <color_fragment>",
|
|
2931
|
-
/* glsl */
|
|
2932
|
-
`
|
|
2933
|
-
#include <color_fragment>
|
|
2934
|
-
float edge = getWireframe();
|
|
2935
|
-
vec4 colorStroke = vec4(stroke, edge);
|
|
2936
|
-
#ifdef FLIP_SIDED
|
|
2937
|
-
colorStroke.rgb = backfaceStroke;
|
|
2938
|
-
#endif
|
|
2939
|
-
vec4 colorFill = vec4(mix(diffuseColor.rgb, fill, fillMix), mix(diffuseColor.a, fillOpacity, fillMix));
|
|
2940
|
-
vec4 outColor = mix(colorFill, colorStroke, edge * strokeOpacity);
|
|
2941
|
-
|
|
2942
|
-
diffuseColor.rgb = outColor.rgb;
|
|
2943
|
-
diffuseColor.a *= outColor.a;
|
|
2944
|
-
`
|
|
2945
|
-
);
|
|
2946
|
-
};
|
|
2947
|
-
material.side = THREE.DoubleSide;
|
|
2948
|
-
material.transparent = true;
|
|
2949
|
-
}
|
|
2950
|
-
function useWireframeUniforms(uniforms, props) {
|
|
2951
|
-
React.useEffect(
|
|
2952
|
-
() => void (uniforms.fillOpacity.value = props.fillOpacity ?? uniforms.fillOpacity.value),
|
|
2953
|
-
[props.fillOpacity]
|
|
2954
|
-
);
|
|
2955
|
-
React.useEffect(() => void (uniforms.fillMix.value = props.fillMix ?? uniforms.fillMix.value), [props.fillMix]);
|
|
2956
|
-
React.useEffect(
|
|
2957
|
-
() => void (uniforms.strokeOpacity.value = props.strokeOpacity ?? uniforms.strokeOpacity.value),
|
|
2958
|
-
[props.strokeOpacity]
|
|
2959
|
-
);
|
|
2960
|
-
React.useEffect(
|
|
2961
|
-
() => void (uniforms.thickness.value = props.thickness ?? uniforms.thickness.value),
|
|
2962
|
-
[props.thickness]
|
|
2963
|
-
);
|
|
2964
|
-
React.useEffect(() => void (uniforms.colorBackfaces.value = !!props.colorBackfaces), [props.colorBackfaces]);
|
|
2965
|
-
React.useEffect(() => void (uniforms.dash.value = !!props.dash), [props.dash]);
|
|
2966
|
-
React.useEffect(() => void (uniforms.dashInvert.value = !!props.dashInvert), [props.dashInvert]);
|
|
2967
|
-
React.useEffect(
|
|
2968
|
-
() => void (uniforms.dashRepeats.value = props.dashRepeats ?? uniforms.dashRepeats.value),
|
|
2969
|
-
[props.dashRepeats]
|
|
2970
|
-
);
|
|
2971
|
-
React.useEffect(
|
|
2972
|
-
() => void (uniforms.dashLength.value = props.dashLength ?? uniforms.dashLength.value),
|
|
2973
|
-
[props.dashLength]
|
|
2974
|
-
);
|
|
2975
|
-
React.useEffect(() => void (uniforms.squeeze.value = !!props.squeeze), [props.squeeze]);
|
|
2976
|
-
React.useEffect(
|
|
2977
|
-
() => void (uniforms.squeezeMin.value = props.squeezeMin ?? uniforms.squeezeMin.value),
|
|
2978
|
-
[props.squeezeMin]
|
|
2979
|
-
);
|
|
2980
|
-
React.useEffect(
|
|
2981
|
-
() => void (uniforms.squeezeMax.value = props.squeezeMax ?? uniforms.squeezeMax.value),
|
|
2982
|
-
[props.squeezeMax]
|
|
2983
|
-
);
|
|
2984
|
-
React.useEffect(
|
|
2985
|
-
() => void (uniforms.stroke.value = props.stroke ? new THREE.Color(props.stroke) : uniforms.stroke.value),
|
|
2986
|
-
[props.stroke]
|
|
2987
|
-
);
|
|
2988
|
-
React.useEffect(
|
|
2989
|
-
() => void (uniforms.fill.value = props.fill ? new THREE.Color(props.fill) : uniforms.fill.value),
|
|
2990
|
-
[props.fill]
|
|
2991
|
-
);
|
|
2992
|
-
React.useEffect(
|
|
2993
|
-
() => void (uniforms.backfaceStroke.value = props.backfaceStroke ? new THREE.Color(props.backfaceStroke) : uniforms.backfaceStroke.value),
|
|
2994
|
-
[props.backfaceStroke]
|
|
2995
|
-
);
|
|
2996
|
-
}
|
|
2997
|
-
|
|
2998
|
-
function isWithGeometry(object) {
|
|
2999
|
-
return !!object?.geometry;
|
|
3000
|
-
}
|
|
3001
|
-
function isGeometry(object) {
|
|
3002
|
-
return !!object?.isBufferGeometry;
|
|
3003
|
-
}
|
|
3004
|
-
function isRefObject$1(object) {
|
|
3005
|
-
return !!object?.current;
|
|
3006
|
-
}
|
|
3007
|
-
function isRef$1(object) {
|
|
3008
|
-
return object?.current !== void 0;
|
|
3009
|
-
}
|
|
3010
|
-
function isWireframeGeometry(geometry) {
|
|
3011
|
-
return geometry.type === "WireframeGeometry";
|
|
3012
|
-
}
|
|
3013
|
-
function getUniforms() {
|
|
3014
|
-
const u = {};
|
|
3015
|
-
for (const key in WireframeMaterialShaders.uniforms) {
|
|
3016
|
-
u[key] = { value: WireframeMaterialShaders.uniforms[key] };
|
|
3017
|
-
}
|
|
3018
|
-
return u;
|
|
3019
|
-
}
|
|
3020
|
-
function getBarycentricCoordinates(geometry, removeEdge) {
|
|
3021
|
-
const position = geometry.getAttribute("position");
|
|
3022
|
-
const count = position.count;
|
|
3023
|
-
const barycentric = [];
|
|
3024
|
-
for (let i = 0; i < count; i++) {
|
|
3025
|
-
const even = i % 2 === 0;
|
|
3026
|
-
const Q = removeEdge ? 1 : 0;
|
|
3027
|
-
if (even) {
|
|
3028
|
-
barycentric.push(0, 0, 1, 0, 1, 0, 1, 0, Q);
|
|
3029
|
-
} else {
|
|
3030
|
-
barycentric.push(0, 1, 0, 0, 0, 1, 1, 0, Q);
|
|
3031
|
-
}
|
|
3032
|
-
}
|
|
3033
|
-
return new THREE.BufferAttribute(Float32Array.from(barycentric), 3);
|
|
3034
|
-
}
|
|
3035
|
-
function getInputGeometry(inputGeometry) {
|
|
3036
|
-
const geo = isRefObject$1(inputGeometry) ? inputGeometry.current : inputGeometry;
|
|
3037
|
-
if (!isGeometry(geo)) {
|
|
3038
|
-
if (isWireframeGeometry(geo)) {
|
|
3039
|
-
throw new Error("Wireframe: WireframeGeometry is not supported.");
|
|
3040
|
-
}
|
|
3041
|
-
const parent = geo.parent;
|
|
3042
|
-
if (isWithGeometry(parent)) {
|
|
3043
|
-
if (isWireframeGeometry(parent.geometry)) {
|
|
3044
|
-
throw new Error("Wireframe: WireframeGeometry is not supported.");
|
|
3045
|
-
}
|
|
3046
|
-
return parent.geometry;
|
|
3047
|
-
}
|
|
3048
|
-
} else {
|
|
3049
|
-
return geo;
|
|
3050
|
-
}
|
|
3051
|
-
}
|
|
3052
|
-
function setBarycentricCoordinates(geometry, simplify) {
|
|
3053
|
-
if (geometry.index) {
|
|
3054
|
-
console.warn("Wireframe: Requires non-indexed geometry, converting to non-indexed geometry.");
|
|
3055
|
-
const nonIndexedGeo = geometry.toNonIndexed();
|
|
3056
|
-
geometry.copy(nonIndexedGeo);
|
|
3057
|
-
geometry.setIndex(null);
|
|
3058
|
-
}
|
|
3059
|
-
const newBarycentric = getBarycentricCoordinates(geometry, simplify);
|
|
3060
|
-
geometry.setAttribute("barycentric", newBarycentric);
|
|
3061
|
-
}
|
|
3062
|
-
function WireframeWithCustomGeo({
|
|
3063
|
-
geometry: customGeometry,
|
|
3064
|
-
simplify = false,
|
|
3065
|
-
...props
|
|
3066
|
-
}) {
|
|
3067
|
-
extend({ MeshWireframeMaterial: WireframeMaterial });
|
|
3068
|
-
const [geometry, setGeometry] = React.useState(null);
|
|
3069
|
-
React.useLayoutEffect(() => {
|
|
3070
|
-
const geom = getInputGeometry(customGeometry);
|
|
3071
|
-
if (!geom) {
|
|
3072
|
-
throw new Error("Wireframe: geometry prop must be a BufferGeometry or a ref to a BufferGeometry.");
|
|
3073
|
-
}
|
|
3074
|
-
setBarycentricCoordinates(geom, simplify);
|
|
3075
|
-
if (isRef$1(customGeometry)) {
|
|
3076
|
-
setGeometry(geom);
|
|
3077
|
-
}
|
|
3078
|
-
}, [simplify, customGeometry]);
|
|
3079
|
-
const drawnGeo = isRef$1(customGeometry) ? geometry : customGeometry;
|
|
3080
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, drawnGeo && /* @__PURE__ */ React.createElement("mesh", { geometry: drawnGeo }, /* @__PURE__ */ React.createElement(
|
|
3081
|
-
"meshWireframeMaterial",
|
|
3082
|
-
{
|
|
3083
|
-
attach: "material",
|
|
3084
|
-
transparent: true,
|
|
3085
|
-
side: THREE.DoubleSide,
|
|
3086
|
-
polygonOffset: true,
|
|
3087
|
-
polygonOffsetFactor: -4,
|
|
3088
|
-
...props
|
|
3089
|
-
}
|
|
3090
|
-
)));
|
|
3091
|
-
}
|
|
3092
|
-
function WireframeWithoutCustomGeo({
|
|
3093
|
-
simplify = false,
|
|
3094
|
-
...props
|
|
3095
|
-
}) {
|
|
3096
|
-
const objectRef = React.useRef(null);
|
|
3097
|
-
const uniforms = React.useMemo(() => getUniforms(), [WireframeMaterialShaders.uniforms]);
|
|
3098
|
-
useWireframeUniforms(uniforms, props);
|
|
3099
|
-
React.useLayoutEffect(() => {
|
|
3100
|
-
const geom = getInputGeometry(objectRef);
|
|
3101
|
-
if (!geom) {
|
|
3102
|
-
throw new Error("Wireframe: Must be a child of a Mesh, Line or Points object or specify a geometry prop.");
|
|
3103
|
-
}
|
|
3104
|
-
const og = geom.clone();
|
|
3105
|
-
setBarycentricCoordinates(geom, simplify);
|
|
3106
|
-
return () => {
|
|
3107
|
-
geom.copy(og);
|
|
3108
|
-
og.dispose();
|
|
3109
|
-
};
|
|
3110
|
-
}, [simplify]);
|
|
3111
|
-
React.useLayoutEffect(() => {
|
|
3112
|
-
const parentMesh = objectRef.current.parent;
|
|
3113
|
-
const og = parentMesh.material.clone();
|
|
3114
|
-
setWireframeOverride(parentMesh.material, uniforms);
|
|
3115
|
-
return () => {
|
|
3116
|
-
parentMesh.material.dispose();
|
|
3117
|
-
parentMesh.material = og;
|
|
3118
|
-
};
|
|
3119
|
-
}, []);
|
|
3120
|
-
return /* @__PURE__ */ React.createElement("object3D", { ref: objectRef });
|
|
3121
|
-
}
|
|
3122
|
-
function Wireframe({ geometry: customGeometry, ...props }) {
|
|
3123
|
-
if (customGeometry) {
|
|
3124
|
-
return /* @__PURE__ */ React.createElement(WireframeWithCustomGeo, { geometry: customGeometry, ...props });
|
|
3125
|
-
}
|
|
3126
|
-
return /* @__PURE__ */ React.createElement(WireframeWithoutCustomGeo, { ...props });
|
|
3127
|
-
}
|
|
3128
|
-
|
|
3129
2948
|
const Context = /* @__PURE__ */ React.createContext({});
|
|
3130
2949
|
const useGizmoContext = () => {
|
|
3131
2950
|
return React.useContext(Context);
|
|
@@ -3273,7 +3092,7 @@ const FaceMaterial = ({
|
|
|
3273
3092
|
"meshBasicMaterial",
|
|
3274
3093
|
{
|
|
3275
3094
|
map: texture,
|
|
3276
|
-
"map-anisotropy":
|
|
3095
|
+
"map-anisotropy": getMaxAnisotropy(renderer),
|
|
3277
3096
|
attach: `material-${index}`,
|
|
3278
3097
|
color: hover ? hoverColor : "white",
|
|
3279
3098
|
transparent: true,
|
|
@@ -3384,7 +3203,7 @@ function AxisHead({
|
|
|
3384
3203
|
"spriteMaterial",
|
|
3385
3204
|
{
|
|
3386
3205
|
map: texture,
|
|
3387
|
-
"map-anisotropy":
|
|
3206
|
+
"map-anisotropy": getMaxAnisotropy(renderer),
|
|
3388
3207
|
alphaTest: 0.3,
|
|
3389
3208
|
opacity: label ? 1 : 0.75,
|
|
3390
3209
|
toneMapped: false
|
|
@@ -3421,6 +3240,11 @@ const GizmoViewport = ({
|
|
|
3421
3240
|
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 }))));
|
|
3422
3241
|
};
|
|
3423
3242
|
|
|
3243
|
+
const roundEven = (n) => {
|
|
3244
|
+
const rounded = Math.ceil(n);
|
|
3245
|
+
return rounded % 2 === 0 ? rounded : rounded + 1;
|
|
3246
|
+
};
|
|
3247
|
+
|
|
3424
3248
|
const v1 = /* @__PURE__ */ new Vector3();
|
|
3425
3249
|
const v2 = /* @__PURE__ */ new Vector3();
|
|
3426
3250
|
const v3 = /* @__PURE__ */ new Vector3();
|
|
@@ -3519,9 +3343,12 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3519
3343
|
as = "div",
|
|
3520
3344
|
wrapperClass,
|
|
3521
3345
|
pointerEvents = "auto",
|
|
3346
|
+
pixelPerfect = true,
|
|
3522
3347
|
...props
|
|
3523
3348
|
}, ref) => {
|
|
3524
3349
|
const { gl, camera, scene, size, raycaster, events, viewport } = useThree();
|
|
3350
|
+
const forceEven = useThree((state) => state.internal.forceEven);
|
|
3351
|
+
const { frustum } = useThree();
|
|
3525
3352
|
const [el] = React.useState(() => document.createElement(as));
|
|
3526
3353
|
const root = React.useRef(null);
|
|
3527
3354
|
const group = React.useRef(null);
|
|
@@ -3546,38 +3373,50 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3546
3373
|
el2.style.position = null;
|
|
3547
3374
|
el2.style.pointerEvents = null;
|
|
3548
3375
|
}
|
|
3549
|
-
}, [occlude]);
|
|
3376
|
+
}, [occlude, zIndexRange, gl.domElement]);
|
|
3550
3377
|
React.useLayoutEffect(() => {
|
|
3551
3378
|
if (group.current) {
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3379
|
+
if (!root.current) {
|
|
3380
|
+
root.current = ReactDOM.createRoot(el);
|
|
3381
|
+
scene.updateMatrixWorld();
|
|
3382
|
+
if (transform) {
|
|
3383
|
+
el.style.cssText = `position:absolute;top:0;left:0;pointer-events:none;overflow:hidden;`;
|
|
3384
|
+
} else {
|
|
3385
|
+
el.style.cssText = `position:absolute;top:0;left:0;transform:translate3d(0,-9999px,0);transform-origin:0 0;`;
|
|
3386
|
+
}
|
|
3559
3387
|
}
|
|
3560
3388
|
if (target) {
|
|
3561
3389
|
if (prepend) target.prepend(el);
|
|
3562
3390
|
else target.appendChild(el);
|
|
3563
3391
|
}
|
|
3564
3392
|
return () => {
|
|
3565
|
-
if (target
|
|
3566
|
-
|
|
3393
|
+
if (target && target.contains(el)) {
|
|
3394
|
+
target.removeChild(el);
|
|
3395
|
+
}
|
|
3567
3396
|
};
|
|
3568
3397
|
}
|
|
3569
|
-
}, [target, transform]);
|
|
3398
|
+
}, [target, transform, el, prepend, scene]);
|
|
3570
3399
|
React.useLayoutEffect(() => {
|
|
3571
3400
|
if (wrapperClass) el.className = wrapperClass;
|
|
3572
|
-
}, [wrapperClass]);
|
|
3401
|
+
}, [wrapperClass, el]);
|
|
3402
|
+
React.useLayoutEffect(() => {
|
|
3403
|
+
return () => {
|
|
3404
|
+
if (root.current) {
|
|
3405
|
+
root.current.unmount();
|
|
3406
|
+
root.current = null;
|
|
3407
|
+
}
|
|
3408
|
+
};
|
|
3409
|
+
}, []);
|
|
3573
3410
|
const styles = React.useMemo(() => {
|
|
3411
|
+
const width = forceEven ? roundEven(size.width) : size.width;
|
|
3412
|
+
const height = forceEven ? roundEven(size.height) : size.height;
|
|
3574
3413
|
if (transform) {
|
|
3575
3414
|
return {
|
|
3576
3415
|
position: "absolute",
|
|
3577
3416
|
top: 0,
|
|
3578
3417
|
left: 0,
|
|
3579
|
-
width
|
|
3580
|
-
height
|
|
3418
|
+
width,
|
|
3419
|
+
height,
|
|
3581
3420
|
transformStyle: "preserve-3d",
|
|
3582
3421
|
pointerEvents: "none"
|
|
3583
3422
|
};
|
|
@@ -3586,15 +3425,15 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3586
3425
|
position: "absolute",
|
|
3587
3426
|
transform: center ? "translate3d(-50%,-50%,0)" : "none",
|
|
3588
3427
|
...fullscreen && {
|
|
3589
|
-
top: -size.height / 2,
|
|
3590
|
-
left: -size.width / 2,
|
|
3591
|
-
width
|
|
3592
|
-
height
|
|
3428
|
+
top: forceEven ? roundEven(-size.height / 2) : -size.height / 2,
|
|
3429
|
+
left: forceEven ? roundEven(-size.width / 2) : -size.width / 2,
|
|
3430
|
+
width,
|
|
3431
|
+
height
|
|
3593
3432
|
},
|
|
3594
3433
|
...style
|
|
3595
3434
|
};
|
|
3596
3435
|
}
|
|
3597
|
-
}, [style, center, fullscreen, size, transform]);
|
|
3436
|
+
}, [style, center, fullscreen, size, transform, forceEven]);
|
|
3598
3437
|
const transformInnerStyles = React.useMemo(
|
|
3599
3438
|
() => ({ position: "absolute", pointerEvents }),
|
|
3600
3439
|
[pointerEvents]
|
|
@@ -3608,7 +3447,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3608
3447
|
} else {
|
|
3609
3448
|
root.current?.render(/* @__PURE__ */ React.createElement("div", { ref, style: styles, className, children }));
|
|
3610
3449
|
}
|
|
3611
|
-
});
|
|
3450
|
+
}, [transform, styles, transformInnerStyles, ref, className, style, children]);
|
|
3612
3451
|
const visible = React.useRef(true);
|
|
3613
3452
|
useFrame((gl2) => {
|
|
3614
3453
|
if (group.current) {
|
|
@@ -3640,7 +3479,12 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3640
3479
|
const zRange = occlude ? isRayCastOcclusion ? [zIndexRange[0], halfRange] : [halfRange - 1, 0] : zIndexRange;
|
|
3641
3480
|
el.style.zIndex = `${objectZIndex(group.current, camera, zRange)}`;
|
|
3642
3481
|
if (transform) {
|
|
3643
|
-
|
|
3482
|
+
let widthHalf = forceEven ? roundEven(size.width / 2) : size.width / 2;
|
|
3483
|
+
let heightHalf = forceEven ? roundEven(size.height / 2) : size.height / 2;
|
|
3484
|
+
if (pixelPerfect) {
|
|
3485
|
+
widthHalf = roundToPixelRatio(widthHalf);
|
|
3486
|
+
heightHalf = roundToPixelRatio(heightHalf);
|
|
3487
|
+
}
|
|
3644
3488
|
const fov = camera.projectionMatrix.elements[5] * heightHalf;
|
|
3645
3489
|
const { isOrthographicCamera, top, left, bottom, right } = camera;
|
|
3646
3490
|
const cameraMatrix = getCameraCSSMatrix(camera.matrixWorldInverse);
|
|
@@ -3651,8 +3495,10 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3651
3495
|
matrix.elements[3] = matrix.elements[7] = matrix.elements[11] = 0;
|
|
3652
3496
|
matrix.elements[15] = 1;
|
|
3653
3497
|
}
|
|
3654
|
-
|
|
3655
|
-
|
|
3498
|
+
const elWidth = forceEven ? roundEven(size.width) : size.width;
|
|
3499
|
+
const elHeight = forceEven ? roundEven(size.height) : size.height;
|
|
3500
|
+
el.style.width = elWidth + "px";
|
|
3501
|
+
el.style.height = elHeight + "px";
|
|
3656
3502
|
el.style.perspective = isOrthographicCamera ? "" : `${fov}px`;
|
|
3657
3503
|
if (transformOuterRef.current && transformInnerRef.current) {
|
|
3658
3504
|
transformOuterRef.current.style.transform = `${cameraTransform}${cameraMatrix}translate(${widthHalf}px,${heightHalf}px)`;
|
|
@@ -3660,7 +3506,13 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3660
3506
|
}
|
|
3661
3507
|
} else {
|
|
3662
3508
|
const scale = distanceFactor === void 0 ? 1 : objectScale(group.current, camera) * distanceFactor;
|
|
3663
|
-
|
|
3509
|
+
let x = forceEven ? roundEven(vec[0]) : vec[0];
|
|
3510
|
+
let y = forceEven ? roundEven(vec[1]) : vec[1];
|
|
3511
|
+
if (pixelPerfect) {
|
|
3512
|
+
x = roundToPixelRatio(x);
|
|
3513
|
+
y = roundToPixelRatio(y);
|
|
3514
|
+
}
|
|
3515
|
+
el.style.transform = `translate3d(${x}px,${y}px,0) scale(${scale})`;
|
|
3664
3516
|
}
|
|
3665
3517
|
oldPosition.current = vec;
|
|
3666
3518
|
oldZoom.current = camera.zoom;
|
|
@@ -3671,8 +3523,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3671
3523
|
if (transformOuterRef.current) {
|
|
3672
3524
|
const el2 = transformOuterRef.current.children[0];
|
|
3673
3525
|
if (el2?.clientWidth && el2?.clientHeight) {
|
|
3674
|
-
|
|
3675
|
-
if (isOrthographicCamera || geometry) {
|
|
3526
|
+
if (geometry) {
|
|
3676
3527
|
if (props.scale) {
|
|
3677
3528
|
if (!Array.isArray(props.scale)) {
|
|
3678
3529
|
occlusionMeshRef.current.scale.setScalar(1 / props.scale);
|
|
@@ -3704,68 +3555,16 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
3704
3555
|
}
|
|
3705
3556
|
}
|
|
3706
3557
|
});
|
|
3707
|
-
|
|
3708
|
-
() => ({
|
|
3709
|
-
vertexShader: !transform ? (
|
|
3710
|
-
/* glsl */
|
|
3711
|
-
`
|
|
3712
|
-
/*
|
|
3713
|
-
This shader is from the THREE's SpriteMaterial.
|
|
3714
|
-
We need to turn the backing plane into a Sprite
|
|
3715
|
-
(make it always face the camera) if "transfrom"
|
|
3716
|
-
is false.
|
|
3717
|
-
*/
|
|
3718
|
-
#include <common>
|
|
3719
|
-
|
|
3720
|
-
void main() {
|
|
3721
|
-
vec2 center = vec2(0., 1.);
|
|
3722
|
-
float rotation = 0.0;
|
|
3723
|
-
|
|
3724
|
-
// This is somewhat arbitrary, but it seems to work well
|
|
3725
|
-
// Need to figure out how to derive this dynamically if it even matters
|
|
3726
|
-
float size = 0.03;
|
|
3727
|
-
|
|
3728
|
-
vec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );
|
|
3729
|
-
vec2 scale;
|
|
3730
|
-
scale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );
|
|
3731
|
-
scale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );
|
|
3732
|
-
|
|
3733
|
-
bool isPerspective = isPerspectiveMatrix( projectionMatrix );
|
|
3734
|
-
if ( isPerspective ) scale *= - mvPosition.z;
|
|
3735
|
-
|
|
3736
|
-
vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale * size;
|
|
3737
|
-
vec2 rotatedPosition;
|
|
3738
|
-
rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;
|
|
3739
|
-
rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;
|
|
3740
|
-
mvPosition.xy += rotatedPosition;
|
|
3741
|
-
|
|
3742
|
-
gl_Position = projectionMatrix * mvPosition;
|
|
3743
|
-
}
|
|
3744
|
-
`
|
|
3745
|
-
) : void 0,
|
|
3746
|
-
fragmentShader: (
|
|
3747
|
-
/* glsl */
|
|
3748
|
-
`
|
|
3749
|
-
void main() {
|
|
3750
|
-
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
|
3751
|
-
}
|
|
3752
|
-
`
|
|
3753
|
-
)
|
|
3754
|
-
}),
|
|
3755
|
-
[transform]
|
|
3756
|
-
);
|
|
3757
|
-
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(
|
|
3758
|
-
"shaderMaterial",
|
|
3759
|
-
{
|
|
3760
|
-
side: DoubleSide,
|
|
3761
|
-
vertexShader: shaders.vertexShader,
|
|
3762
|
-
fragmentShader: shaders.fragmentShader
|
|
3763
|
-
}
|
|
3764
|
-
)));
|
|
3558
|
+
return /* @__PURE__ */ React.createElement("group", { ...props, ref: group }, occlude && !isRayCastOcclusion && /* @__PURE__ */ React.createElement("mesh", { castShadow, receiveShadow, ref: occlusionMeshRef }, geometry || /* @__PURE__ */ React.createElement("planeGeometry", null), material));
|
|
3765
3559
|
}
|
|
3766
3560
|
);
|
|
3767
3561
|
|
|
3768
3562
|
const context$4 = /* @__PURE__ */ React.createContext(null);
|
|
3563
|
+
const resolveObject = (object, fallback) => {
|
|
3564
|
+
if (!object) return fallback;
|
|
3565
|
+
if ("current" in object) return object.current;
|
|
3566
|
+
return object;
|
|
3567
|
+
};
|
|
3769
3568
|
|
|
3770
3569
|
const vec1$1 = /* @__PURE__ */ new THREE.Vector3();
|
|
3771
3570
|
const vec2$1 = /* @__PURE__ */ new THREE.Vector3();
|
|
@@ -3800,6 +3599,8 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
3800
3599
|
onDragStart,
|
|
3801
3600
|
onDrag,
|
|
3802
3601
|
onDragEnd,
|
|
3602
|
+
onHover,
|
|
3603
|
+
dragState,
|
|
3803
3604
|
userData,
|
|
3804
3605
|
LineComponent: Line
|
|
3805
3606
|
} = React.useContext(context$4);
|
|
@@ -3831,7 +3632,13 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
3831
3632
|
const onPointerMove = React.useCallback(
|
|
3832
3633
|
(e) => {
|
|
3833
3634
|
e.stopPropagation();
|
|
3834
|
-
if (!isHovered)
|
|
3635
|
+
if (!isHovered) {
|
|
3636
|
+
const drag = dragState.current;
|
|
3637
|
+
if (drag === null || drag.component === "Arrow" && drag.axis === axis) {
|
|
3638
|
+
setIsHovered(true);
|
|
3639
|
+
onHover({ component: "Arrow", axis, hovering: true });
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3835
3642
|
if (clickInfo.current) {
|
|
3836
3643
|
const { clickPoint, dir } = clickInfo.current;
|
|
3837
3644
|
const [min, max] = translationLimits?.[axis] || [void 0, void 0];
|
|
@@ -3850,7 +3657,7 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
3850
3657
|
onDrag(offsetMatrix$1);
|
|
3851
3658
|
}
|
|
3852
3659
|
},
|
|
3853
|
-
[annotations, onDrag, isHovered, translation, translationLimits, axis]
|
|
3660
|
+
[annotations, onDrag, onHover, dragState, isHovered, translation, translationLimits, axis]
|
|
3854
3661
|
);
|
|
3855
3662
|
const onPointerUp = React.useCallback(
|
|
3856
3663
|
(e) => {
|
|
@@ -3865,10 +3672,16 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
3865
3672
|
},
|
|
3866
3673
|
[annotations, camControls, onDragEnd]
|
|
3867
3674
|
);
|
|
3868
|
-
const onPointerOut = React.useCallback(
|
|
3869
|
-
e
|
|
3870
|
-
|
|
3871
|
-
|
|
3675
|
+
const onPointerOut = React.useCallback(
|
|
3676
|
+
(e) => {
|
|
3677
|
+
e.stopPropagation();
|
|
3678
|
+
if (isHovered) {
|
|
3679
|
+
setIsHovered(false);
|
|
3680
|
+
onHover({ component: "Arrow", axis, hovering: false });
|
|
3681
|
+
}
|
|
3682
|
+
},
|
|
3683
|
+
[onHover, axis, isHovered]
|
|
3684
|
+
);
|
|
3872
3685
|
const { cylinderLength, coneWidth, coneLength, matrixL } = React.useMemo(() => {
|
|
3873
3686
|
const coneWidth2 = fixed ? lineWidth / scale * 1.6 : scale / 20;
|
|
3874
3687
|
const coneLength2 = fixed ? 0.2 : scale / 5;
|
|
@@ -3972,6 +3785,8 @@ const rotMatrix = /* @__PURE__ */ new THREE.Matrix4();
|
|
|
3972
3785
|
const posNew = /* @__PURE__ */ new THREE.Vector3();
|
|
3973
3786
|
const ray$1 = /* @__PURE__ */ new THREE.Ray();
|
|
3974
3787
|
const intersection$1 = /* @__PURE__ */ new THREE.Vector3();
|
|
3788
|
+
const viewPlane = /* @__PURE__ */ new THREE.Plane();
|
|
3789
|
+
const viewIntersection = /* @__PURE__ */ new THREE.Vector3();
|
|
3975
3790
|
const AxisRotator = ({
|
|
3976
3791
|
dir1,
|
|
3977
3792
|
dir2,
|
|
@@ -3992,6 +3807,8 @@ const AxisRotator = ({
|
|
|
3992
3807
|
onDragStart,
|
|
3993
3808
|
onDrag,
|
|
3994
3809
|
onDragEnd,
|
|
3810
|
+
onHover,
|
|
3811
|
+
dragState,
|
|
3995
3812
|
userData,
|
|
3996
3813
|
LineComponent: Line
|
|
3997
3814
|
} = React.useContext(context$4);
|
|
@@ -4025,14 +3842,29 @@ const AxisRotator = ({
|
|
|
4025
3842
|
const onPointerMove = React.useCallback(
|
|
4026
3843
|
(e) => {
|
|
4027
3844
|
e.stopPropagation();
|
|
4028
|
-
if (!isHovered)
|
|
3845
|
+
if (!isHovered) {
|
|
3846
|
+
const drag = dragState.current;
|
|
3847
|
+
if (drag === null || drag.component === "Rotator" && drag.axis === axis) {
|
|
3848
|
+
setIsHovered(true);
|
|
3849
|
+
onHover({ component: "Rotator", axis, hovering: true });
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
4029
3852
|
if (clickInfo.current) {
|
|
4030
3853
|
const { clickPoint, origin, e1, e2, normal, plane } = clickInfo.current;
|
|
4031
3854
|
const [min, max] = rotationLimits?.[axis] || [void 0, void 0];
|
|
4032
3855
|
ray$1.copy(e.ray);
|
|
4033
|
-
ray$1.
|
|
4034
|
-
|
|
4035
|
-
|
|
3856
|
+
const dotProduct = Math.abs(ray$1.direction.dot(normal));
|
|
3857
|
+
if (dotProduct < 0.1) {
|
|
3858
|
+
viewPlane.setFromNormalAndCoplanarPoint(ray$1.direction.clone().negate(), origin);
|
|
3859
|
+
ray$1.intersectPlane(viewPlane, viewIntersection);
|
|
3860
|
+
const toIntersection = viewIntersection.clone().sub(origin);
|
|
3861
|
+
const projectedDist = toIntersection.dot(normal);
|
|
3862
|
+
intersection$1.copy(viewIntersection).sub(normal.clone().multiplyScalar(projectedDist));
|
|
3863
|
+
} else {
|
|
3864
|
+
ray$1.intersectPlane(plane, intersection$1);
|
|
3865
|
+
ray$1.direction.negate();
|
|
3866
|
+
ray$1.intersectPlane(plane, intersection$1);
|
|
3867
|
+
}
|
|
4036
3868
|
let deltaAngle = calculateAngle(clickPoint, intersection$1, origin, e1, e2);
|
|
4037
3869
|
let degrees = toDegrees(deltaAngle);
|
|
4038
3870
|
if (e.shiftKey) {
|
|
@@ -4058,7 +3890,7 @@ const AxisRotator = ({
|
|
|
4058
3890
|
onDrag(rotMatrix);
|
|
4059
3891
|
}
|
|
4060
3892
|
},
|
|
4061
|
-
[annotations, onDrag, isHovered, rotationLimits, axis]
|
|
3893
|
+
[annotations, onDrag, onHover, dragState, isHovered, rotationLimits, axis]
|
|
4062
3894
|
);
|
|
4063
3895
|
const onPointerUp = React.useCallback(
|
|
4064
3896
|
(e) => {
|
|
@@ -4074,10 +3906,16 @@ const AxisRotator = ({
|
|
|
4074
3906
|
},
|
|
4075
3907
|
[annotations, camControls, onDragEnd]
|
|
4076
3908
|
);
|
|
4077
|
-
const onPointerOut = React.useCallback(
|
|
4078
|
-
e
|
|
4079
|
-
|
|
4080
|
-
|
|
3909
|
+
const onPointerOut = React.useCallback(
|
|
3910
|
+
(e) => {
|
|
3911
|
+
e.stopPropagation();
|
|
3912
|
+
if (isHovered) {
|
|
3913
|
+
setIsHovered(false);
|
|
3914
|
+
onHover({ component: "Rotator", axis, hovering: false });
|
|
3915
|
+
}
|
|
3916
|
+
},
|
|
3917
|
+
[onHover, axis, isHovered]
|
|
3918
|
+
);
|
|
4081
3919
|
const matrixL = React.useMemo(() => {
|
|
4082
3920
|
const dir1N = dir1.clone().normalize();
|
|
4083
3921
|
const dir2N = dir2.clone().normalize();
|
|
@@ -4178,6 +4016,8 @@ const PlaneSlider = ({
|
|
|
4178
4016
|
onDragStart,
|
|
4179
4017
|
onDrag,
|
|
4180
4018
|
onDragEnd,
|
|
4019
|
+
onHover,
|
|
4020
|
+
dragState,
|
|
4181
4021
|
userData,
|
|
4182
4022
|
LineComponent: Line
|
|
4183
4023
|
} = React.useContext(context$4);
|
|
@@ -4213,7 +4053,13 @@ const PlaneSlider = ({
|
|
|
4213
4053
|
const onPointerMove = React.useCallback(
|
|
4214
4054
|
(e) => {
|
|
4215
4055
|
e.stopPropagation();
|
|
4216
|
-
if (!isHovered)
|
|
4056
|
+
if (!isHovered) {
|
|
4057
|
+
const drag = dragState.current;
|
|
4058
|
+
if (drag === null || drag.component === "Slider" && drag.axis === axis) {
|
|
4059
|
+
setIsHovered(true);
|
|
4060
|
+
onHover({ component: "Slider", axis, hovering: true });
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4217
4063
|
if (clickInfo.current) {
|
|
4218
4064
|
const { clickPoint, e1, e2, plane } = clickInfo.current;
|
|
4219
4065
|
const [minX, maxX] = translationLimits?.[(axis + 1) % 3] || [void 0, void 0];
|
|
@@ -4249,7 +4095,7 @@ const PlaneSlider = ({
|
|
|
4249
4095
|
onDrag(offsetMatrix);
|
|
4250
4096
|
}
|
|
4251
4097
|
},
|
|
4252
|
-
[annotations, onDrag, isHovered, translation, translationLimits, axis]
|
|
4098
|
+
[annotations, onDrag, onHover, dragState, isHovered, translation, translationLimits, axis]
|
|
4253
4099
|
);
|
|
4254
4100
|
const onPointerUp = React.useCallback(
|
|
4255
4101
|
(e) => {
|
|
@@ -4264,10 +4110,16 @@ const PlaneSlider = ({
|
|
|
4264
4110
|
},
|
|
4265
4111
|
[annotations, camControls, onDragEnd]
|
|
4266
4112
|
);
|
|
4267
|
-
const onPointerOut = React.useCallback(
|
|
4268
|
-
e
|
|
4269
|
-
|
|
4270
|
-
|
|
4113
|
+
const onPointerOut = React.useCallback(
|
|
4114
|
+
(e) => {
|
|
4115
|
+
e.stopPropagation();
|
|
4116
|
+
if (isHovered) {
|
|
4117
|
+
setIsHovered(false);
|
|
4118
|
+
onHover({ component: "Slider", axis, hovering: false });
|
|
4119
|
+
}
|
|
4120
|
+
},
|
|
4121
|
+
[onHover, axis, isHovered]
|
|
4122
|
+
);
|
|
4271
4123
|
const matrixL = React.useMemo(() => {
|
|
4272
4124
|
const dir1N = dir1.clone().normalize();
|
|
4273
4125
|
const dir2N = dir2.clone().normalize();
|
|
@@ -4405,6 +4257,8 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
4405
4257
|
onDragStart,
|
|
4406
4258
|
onDrag,
|
|
4407
4259
|
onDragEnd,
|
|
4260
|
+
onHover,
|
|
4261
|
+
dragState,
|
|
4408
4262
|
userData
|
|
4409
4263
|
} = React.useContext(context$4);
|
|
4410
4264
|
const size = useThree((state) => state.size);
|
|
@@ -4441,7 +4295,13 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
4441
4295
|
const onPointerMove = React.useCallback(
|
|
4442
4296
|
(e) => {
|
|
4443
4297
|
e.stopPropagation();
|
|
4444
|
-
if (!isHovered)
|
|
4298
|
+
if (!isHovered) {
|
|
4299
|
+
const drag = dragState.current;
|
|
4300
|
+
if (drag === null || drag.component === "Sphere" && drag.axis === axis) {
|
|
4301
|
+
setIsHovered(true);
|
|
4302
|
+
onHover({ component: "Sphere", axis, hovering: true });
|
|
4303
|
+
}
|
|
4304
|
+
}
|
|
4445
4305
|
if (clickInfo.current) {
|
|
4446
4306
|
const { clickPoint, dir, mPLG, mPLGInv, offsetMultiplier } = clickInfo.current;
|
|
4447
4307
|
const [min, max] = scaleLimits?.[axis] || [1e-5, void 0];
|
|
@@ -4467,7 +4327,7 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
4467
4327
|
onDrag(scaleMatrix);
|
|
4468
4328
|
}
|
|
4469
4329
|
},
|
|
4470
|
-
[annotations, position, onDrag, isHovered, scaleLimits, axis]
|
|
4330
|
+
[annotations, position, onDrag, onHover, dragState, isHovered, scaleLimits, axis]
|
|
4471
4331
|
);
|
|
4472
4332
|
const onPointerUp = React.useCallback(
|
|
4473
4333
|
(e) => {
|
|
@@ -4484,10 +4344,16 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
4484
4344
|
},
|
|
4485
4345
|
[annotations, camControls, onDragEnd, position]
|
|
4486
4346
|
);
|
|
4487
|
-
const onPointerOut = React.useCallback(
|
|
4488
|
-
e
|
|
4489
|
-
|
|
4490
|
-
|
|
4347
|
+
const onPointerOut = React.useCallback(
|
|
4348
|
+
(e) => {
|
|
4349
|
+
e.stopPropagation();
|
|
4350
|
+
if (isHovered) {
|
|
4351
|
+
setIsHovered(false);
|
|
4352
|
+
onHover({ component: "Sphere", axis, hovering: false });
|
|
4353
|
+
}
|
|
4354
|
+
},
|
|
4355
|
+
[onHover, axis, isHovered]
|
|
4356
|
+
);
|
|
4491
4357
|
const { radius, matrixL } = React.useMemo(() => {
|
|
4492
4358
|
const radius2 = fixed ? lineWidth / scale * 1.8 : scale / 22.5;
|
|
4493
4359
|
const quaternion = new THREE.Quaternion().setFromUnitVectors(upV, direction.clone().normalize());
|
|
@@ -4542,6 +4408,7 @@ const mW = /* @__PURE__ */ new THREE.Matrix4();
|
|
|
4542
4408
|
const mL = /* @__PURE__ */ new THREE.Matrix4();
|
|
4543
4409
|
const mL0Inv = /* @__PURE__ */ new THREE.Matrix4();
|
|
4544
4410
|
const mdL = /* @__PURE__ */ new THREE.Matrix4();
|
|
4411
|
+
const mdW = /* @__PURE__ */ new THREE.Matrix4();
|
|
4545
4412
|
const mG = /* @__PURE__ */ new THREE.Matrix4();
|
|
4546
4413
|
const bb = /* @__PURE__ */ new THREE.Box3();
|
|
4547
4414
|
const bbObj = /* @__PURE__ */ new THREE.Box3();
|
|
@@ -4557,9 +4424,11 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4557
4424
|
({
|
|
4558
4425
|
enabled = true,
|
|
4559
4426
|
matrix,
|
|
4427
|
+
object,
|
|
4560
4428
|
onDragStart,
|
|
4561
4429
|
onDrag,
|
|
4562
4430
|
onDragEnd,
|
|
4431
|
+
onHover,
|
|
4563
4432
|
autoTransform = true,
|
|
4564
4433
|
anchor,
|
|
4565
4434
|
disableAxes = false,
|
|
@@ -4595,14 +4464,35 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4595
4464
|
const gizmoRef = React.useRef(null);
|
|
4596
4465
|
const childrenRef = React.useRef(null);
|
|
4597
4466
|
const translation = React.useRef([0, 0, 0]);
|
|
4467
|
+
const dragState = React.useRef(null);
|
|
4598
4468
|
const cameraScale = React.useRef(new THREE.Vector3(1, 1, 1));
|
|
4599
4469
|
const gizmoScale = React.useRef(new THREE.Vector3(1, 1, 1));
|
|
4470
|
+
React.useEffect(() => {
|
|
4471
|
+
if (object) {
|
|
4472
|
+
const target = resolveObject(object);
|
|
4473
|
+
if (target) {
|
|
4474
|
+
const pivot = ref.current;
|
|
4475
|
+
const didAutoUpdate = target.matrixAutoUpdate;
|
|
4476
|
+
target.updateWorldMatrix(true, true);
|
|
4477
|
+
target.matrixAutoUpdate = false;
|
|
4478
|
+
pivot.matrix.copy(target.matrix);
|
|
4479
|
+
return () => {
|
|
4480
|
+
if (didAutoUpdate) {
|
|
4481
|
+
target.matrixAutoUpdate = true;
|
|
4482
|
+
target.matrix.decompose(target.position, target.quaternion, target.scale);
|
|
4483
|
+
}
|
|
4484
|
+
};
|
|
4485
|
+
}
|
|
4486
|
+
}
|
|
4487
|
+
}, [object]);
|
|
4600
4488
|
React.useLayoutEffect(() => {
|
|
4601
4489
|
if (!anchor) return;
|
|
4602
|
-
childrenRef.current
|
|
4603
|
-
|
|
4490
|
+
const anchorTarget = resolveObject(object, childrenRef.current);
|
|
4491
|
+
if (!anchorTarget) return;
|
|
4492
|
+
anchorTarget.updateWorldMatrix(true, true);
|
|
4493
|
+
mPInv.copy(anchorTarget.matrixWorld).invert();
|
|
4604
4494
|
bb.makeEmpty();
|
|
4605
|
-
|
|
4495
|
+
anchorTarget.traverse((obj) => {
|
|
4606
4496
|
if (!obj.geometry) return;
|
|
4607
4497
|
if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
|
|
4608
4498
|
mL.copy(obj.matrixWorld).premultiply(mPInv);
|
|
@@ -4617,15 +4507,24 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4617
4507
|
gizmoRef.current.position.copy(vPosition);
|
|
4618
4508
|
invalidate();
|
|
4619
4509
|
});
|
|
4510
|
+
const mergedUserData = React.useMemo(
|
|
4511
|
+
() => ({
|
|
4512
|
+
...userData,
|
|
4513
|
+
...depthTest === false && { interactivePriority: 1 }
|
|
4514
|
+
}),
|
|
4515
|
+
[userData, depthTest]
|
|
4516
|
+
);
|
|
4620
4517
|
const config = React.useMemo(
|
|
4621
4518
|
() => ({
|
|
4622
4519
|
onDragStart: (props2) => {
|
|
4520
|
+
dragState.current = props2;
|
|
4623
4521
|
mL0.copy(ref.current.matrix);
|
|
4624
4522
|
mW0.copy(ref.current.matrixWorld);
|
|
4625
4523
|
onDragStart && onDragStart(props2);
|
|
4626
4524
|
invalidate();
|
|
4627
4525
|
},
|
|
4628
|
-
onDrag: (
|
|
4526
|
+
onDrag: (mdW_) => {
|
|
4527
|
+
mdW.copy(mdW_);
|
|
4629
4528
|
mP.copy(parentRef.current.matrixWorld);
|
|
4630
4529
|
mPInv.copy(mP).invert();
|
|
4631
4530
|
mW.copy(mW0).premultiply(mdW);
|
|
@@ -4635,13 +4534,20 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4635
4534
|
if (autoTransform) {
|
|
4636
4535
|
ref.current.matrix.copy(mL);
|
|
4637
4536
|
}
|
|
4638
|
-
|
|
4537
|
+
const target = resolveObject(object);
|
|
4538
|
+
if (target) target.matrix.copy(mL);
|
|
4539
|
+
onDrag && onDrag({ local: mL, deltaLocal: mdL, world: mW, deltaWorld: mdW });
|
|
4639
4540
|
invalidate();
|
|
4640
4541
|
},
|
|
4641
4542
|
onDragEnd: () => {
|
|
4642
|
-
|
|
4543
|
+
dragState.current = null;
|
|
4544
|
+
if (onDragEnd) onDragEnd({ local: mL, deltaLocal: mdL, world: mW, deltaWorld: mdW });
|
|
4643
4545
|
invalidate();
|
|
4644
4546
|
},
|
|
4547
|
+
onHover: (props2) => {
|
|
4548
|
+
if (onHover) onHover(props2);
|
|
4549
|
+
},
|
|
4550
|
+
dragState,
|
|
4645
4551
|
translation,
|
|
4646
4552
|
translationLimits,
|
|
4647
4553
|
rotationLimits,
|
|
@@ -4653,7 +4559,7 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4653
4559
|
fixed,
|
|
4654
4560
|
depthTest,
|
|
4655
4561
|
renderOrder,
|
|
4656
|
-
userData,
|
|
4562
|
+
userData: mergedUserData,
|
|
4657
4563
|
annotations,
|
|
4658
4564
|
annotationsClass,
|
|
4659
4565
|
LineComponent: LineComp
|
|
@@ -4662,6 +4568,7 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4662
4568
|
onDragStart,
|
|
4663
4569
|
onDrag,
|
|
4664
4570
|
onDragEnd,
|
|
4571
|
+
onHover,
|
|
4665
4572
|
translation,
|
|
4666
4573
|
translationLimits,
|
|
4667
4574
|
rotationLimits,
|
|
@@ -4673,11 +4580,12 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4673
4580
|
...axisColors,
|
|
4674
4581
|
hoveredColor,
|
|
4675
4582
|
opacity,
|
|
4676
|
-
|
|
4583
|
+
mergedUserData,
|
|
4677
4584
|
autoTransform,
|
|
4678
4585
|
annotations,
|
|
4679
4586
|
annotationsClass,
|
|
4680
|
-
LineComp
|
|
4587
|
+
LineComp,
|
|
4588
|
+
object
|
|
4681
4589
|
]
|
|
4682
4590
|
);
|
|
4683
4591
|
const vec = new THREE.Vector3();
|
|
@@ -4744,7 +4652,9 @@ const TransformControls = /* @__PURE__ */ React.forwardRef(
|
|
|
4744
4652
|
const group = React.useRef(null);
|
|
4745
4653
|
React.useLayoutEffect(() => {
|
|
4746
4654
|
if (object) {
|
|
4747
|
-
controls.attach(
|
|
4655
|
+
controls.attach(
|
|
4656
|
+
object instanceof THREE.Object3D ? object : object.current
|
|
4657
|
+
);
|
|
4748
4658
|
} else if (group.current instanceof THREE.Object3D) {
|
|
4749
4659
|
controls.attach(group.current);
|
|
4750
4660
|
}
|
|
@@ -4840,7 +4750,7 @@ const PointMaterial = /* @__PURE__ */ React.forwardRef((props, ref) => {
|
|
|
4840
4750
|
return /* @__PURE__ */ React.createElement("primitive", { ...props, object: material, ref, attach: "material" });
|
|
4841
4751
|
});
|
|
4842
4752
|
|
|
4843
|
-
const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, loop =
|
|
4753
|
+
const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, loop = false, autoplay, ...props }, ref) => {
|
|
4844
4754
|
const sound = React.useRef(null);
|
|
4845
4755
|
React.useImperativeHandle(ref, () => sound.current, []);
|
|
4846
4756
|
const camera = useThree(({ camera: camera2 }) => camera2);
|
|
@@ -4852,7 +4762,9 @@ const PositionalAudio = /* @__PURE__ */ React.forwardRef(({ url, distance = 1, l
|
|
|
4852
4762
|
_sound.setBuffer(Array.isArray(buffer) ? buffer[0] : buffer);
|
|
4853
4763
|
_sound.setRefDistance(distance);
|
|
4854
4764
|
_sound.setLoop(loop);
|
|
4855
|
-
if (autoplay && !_sound.isPlaying)
|
|
4765
|
+
if (autoplay && !_sound.isPlaying) {
|
|
4766
|
+
_sound.play();
|
|
4767
|
+
}
|
|
4856
4768
|
}
|
|
4857
4769
|
}, [buffer, camera, distance, loop]);
|
|
4858
4770
|
React.useEffect(() => {
|
|
@@ -4921,7 +4833,6 @@ const tempMatrix = /* @__PURE__ */ new THREE.Matrix4();
|
|
|
4921
4833
|
const translation = /* @__PURE__ */ new THREE.Vector3();
|
|
4922
4834
|
const rotation = /* @__PURE__ */ new THREE.Quaternion();
|
|
4923
4835
|
const scale = /* @__PURE__ */ new THREE.Vector3();
|
|
4924
|
-
const isInstancedBufferAttribute = (attr) => attr.isInstancedBufferAttribute;
|
|
4925
4836
|
const Instance = /* @__PURE__ */ React.forwardRef(({ context, children, ...props }, ref) => {
|
|
4926
4837
|
React.useMemo(() => extend({ PositionMesh }), []);
|
|
4927
4838
|
const group = React.useRef(null);
|
|
@@ -4941,24 +4852,20 @@ const Instances = /* @__PURE__ */ React.forwardRef(({ context, children, range,
|
|
|
4941
4852
|
const parentRef = React.useRef(null);
|
|
4942
4853
|
React.useImperativeHandle(ref, () => parentRef.current, []);
|
|
4943
4854
|
const [instances, setInstances] = React.useState([]);
|
|
4855
|
+
const boundsDirty = React.useRef(true);
|
|
4944
4856
|
const [[matrices, colors]] = React.useState(() => {
|
|
4945
4857
|
const mArray = new Float32Array(limit * 16);
|
|
4946
4858
|
for (let i = 0; i < limit; i++) tempMatrix.identity().toArray(mArray, i * 16);
|
|
4947
4859
|
return [mArray, new Float32Array([...new Array(limit * 3)].map(() => 1))];
|
|
4948
4860
|
});
|
|
4949
4861
|
React.useEffect(() => {
|
|
4950
|
-
parentRef.current.instanceMatrix.needsUpdate = true;
|
|
4862
|
+
if (parentRef.current) parentRef.current.instanceMatrix.needsUpdate = true;
|
|
4951
4863
|
});
|
|
4952
4864
|
let iterations = 0;
|
|
4953
4865
|
let count = 0;
|
|
4954
|
-
const attributes = React.useRef([]);
|
|
4955
|
-
React.useLayoutEffect(() => {
|
|
4956
|
-
attributes.current = Object.entries(parentRef.current.geometry.attributes).filter(
|
|
4957
|
-
([_name, value]) => isInstancedBufferAttribute(value)
|
|
4958
|
-
);
|
|
4959
|
-
});
|
|
4960
4866
|
useFrame(() => {
|
|
4961
4867
|
if (frames === Infinity || iterations < frames) {
|
|
4868
|
+
if (!parentRef.current) return;
|
|
4962
4869
|
parentRef.current.updateMatrix();
|
|
4963
4870
|
parentRef.current.updateMatrixWorld();
|
|
4964
4871
|
parentMatrix.copy(parentRef.current.matrixWorld).invert();
|
|
@@ -4979,13 +4886,22 @@ const Instances = /* @__PURE__ */ React.forwardRef(({ context, children, range,
|
|
|
4979
4886
|
}
|
|
4980
4887
|
iterations++;
|
|
4981
4888
|
}
|
|
4889
|
+
if (boundsDirty.current && (frames === Infinity || iterations === frames)) {
|
|
4890
|
+
boundsDirty.current = false;
|
|
4891
|
+
if (parentRef.current.boundingBox) parentRef.current.computeBoundingBox();
|
|
4892
|
+
if (parentRef.current.boundingSphere) parentRef.current.computeBoundingSphere();
|
|
4893
|
+
}
|
|
4982
4894
|
});
|
|
4983
4895
|
const api = React.useMemo(
|
|
4984
4896
|
() => ({
|
|
4985
4897
|
getParent: () => parentRef,
|
|
4986
4898
|
subscribe: (ref2) => {
|
|
4987
4899
|
setInstances((instances2) => [...instances2, ref2]);
|
|
4988
|
-
|
|
4900
|
+
boundsDirty.current = true;
|
|
4901
|
+
return () => {
|
|
4902
|
+
setInstances((instances2) => instances2.filter((item) => item.current !== ref2.current));
|
|
4903
|
+
boundsDirty.current = true;
|
|
4904
|
+
};
|
|
4989
4905
|
}
|
|
4990
4906
|
}),
|
|
4991
4907
|
[]
|
|
@@ -5010,10 +4926,23 @@ const Merged = /* @__PURE__ */ React.forwardRef(function Merged2({ meshes, child
|
|
|
5010
4926
|
if (!isArray) {
|
|
5011
4927
|
for (const key of Object.keys(meshes)) if (!meshes[key].isMesh) delete meshes[key];
|
|
5012
4928
|
}
|
|
5013
|
-
const render = (args) =>
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
4929
|
+
const render = (args) => {
|
|
4930
|
+
if (isArray) {
|
|
4931
|
+
return children(
|
|
4932
|
+
...args
|
|
4933
|
+
);
|
|
4934
|
+
}
|
|
4935
|
+
const instanceMap = {};
|
|
4936
|
+
const keys = Object.keys(meshes).filter((key) => meshes[key].isMesh);
|
|
4937
|
+
keys.forEach((key, i) => {
|
|
4938
|
+
instanceMap[key] = args[i];
|
|
4939
|
+
});
|
|
4940
|
+
return children(instanceMap);
|
|
4941
|
+
};
|
|
4942
|
+
const components = (isArray ? meshes : Object.values(meshes)).map((mesh) => {
|
|
4943
|
+
const { geometry, material } = mesh;
|
|
4944
|
+
return /* @__PURE__ */ React.createElement(Instances, { key: geometry.uuid, geometry, material, ...props });
|
|
4945
|
+
});
|
|
5017
4946
|
return /* @__PURE__ */ React.createElement("group", { ref }, renderRecursive(render, components));
|
|
5018
4947
|
});
|
|
5019
4948
|
function renderRecursive(render, components, results = []) {
|
|
@@ -5039,7 +4968,7 @@ function createInstances() {
|
|
|
5039
4968
|
];
|
|
5040
4969
|
}
|
|
5041
4970
|
const InstancedAttribute = React.forwardRef(
|
|
5042
|
-
({ name, defaultValue, normalized, usage = THREE.DynamicDrawUsage }, fref) => {
|
|
4971
|
+
({ name, defaultValue, normalized, usage = THREE.DynamicDrawUsage, type = "float" }, fref) => {
|
|
5043
4972
|
const ref = React.useRef(null);
|
|
5044
4973
|
React.useImperativeHandle(fref, () => ref.current, []);
|
|
5045
4974
|
React.useLayoutEffect(() => {
|
|
@@ -5047,7 +4976,26 @@ const InstancedAttribute = React.forwardRef(
|
|
|
5047
4976
|
parent.geometry.attributes[name] = ref.current;
|
|
5048
4977
|
const value = Array.isArray(defaultValue) ? defaultValue : [defaultValue];
|
|
5049
4978
|
const array = Array.from({ length: parent.userData.limit }, () => value).flat();
|
|
5050
|
-
|
|
4979
|
+
switch (type) {
|
|
4980
|
+
case "float":
|
|
4981
|
+
ref.current.array = new Float32Array(array);
|
|
4982
|
+
break;
|
|
4983
|
+
case "int":
|
|
4984
|
+
ref.current.array = new Int32Array(array);
|
|
4985
|
+
break;
|
|
4986
|
+
case "uint":
|
|
4987
|
+
ref.current.array = new Uint32Array(array);
|
|
4988
|
+
break;
|
|
4989
|
+
case "short":
|
|
4990
|
+
ref.current.array = new Int16Array(array);
|
|
4991
|
+
break;
|
|
4992
|
+
case "ushort":
|
|
4993
|
+
ref.current.array = new Uint16Array(array);
|
|
4994
|
+
break;
|
|
4995
|
+
case "byte":
|
|
4996
|
+
ref.current.array = new Uint8Array(array);
|
|
4997
|
+
break;
|
|
4998
|
+
}
|
|
5051
4999
|
ref.current.itemSize = value.length;
|
|
5052
5000
|
ref.current.count = array.length / ref.current.itemSize;
|
|
5053
5001
|
return () => {
|
|
@@ -6068,12 +6016,13 @@ function Sampler({ children, weight, transform, instances, mesh, count = 16, ...
|
|
|
6068
6016
|
return /* @__PURE__ */ React.createElement("group", { ref: group, ...props }, children);
|
|
6069
6017
|
}
|
|
6070
6018
|
|
|
6019
|
+
const pathStyle = (path) => path.userData?.style;
|
|
6071
6020
|
const Svg = /* @__PURE__ */ forwardRef(
|
|
6072
6021
|
function R3FSvg({ src, skipFill, skipStrokes, fillMaterial, strokeMaterial, fillMeshProps, strokeMeshProps, ...props }, ref) {
|
|
6073
6022
|
const svg = useLoader(SVGLoader, !src.startsWith("<svg") ? src : `data:image/svg+xml;utf8,${src}`);
|
|
6074
6023
|
const strokeGeometries = useMemo(
|
|
6075
6024
|
() => skipStrokes ? [] : svg.paths.map(
|
|
6076
|
-
(path) => path
|
|
6025
|
+
(path) => pathStyle(path)?.stroke === void 0 || pathStyle(path).stroke === "none" ? null : path.subPaths.map((subPath) => SVGLoader.pointsToStroke(subPath.getPoints(), pathStyle(path)))
|
|
6077
6026
|
),
|
|
6078
6027
|
[svg, skipStrokes]
|
|
6079
6028
|
);
|
|
@@ -6081,21 +6030,21 @@ const Svg = /* @__PURE__ */ forwardRef(
|
|
|
6081
6030
|
return () => strokeGeometries.forEach((group) => group && group.map((g) => g.dispose()));
|
|
6082
6031
|
}, [strokeGeometries]);
|
|
6083
6032
|
let renderOrder = 0;
|
|
6084
|
-
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
|
|
6033
|
+
return /* @__PURE__ */ React.createElement("object3D", { ref, ...props }, /* @__PURE__ */ React.createElement("object3D", { scale: [1, -1, 1] }, svg.paths.map((path, p) => /* @__PURE__ */ React.createElement(Fragment, { key: p }, !skipFill && pathStyle(path)?.fill !== void 0 && pathStyle(path).fill !== "none" && SVGLoader.createShapes(path).map((shape, s) => /* @__PURE__ */ React.createElement("mesh", { key: s, ...fillMeshProps, renderOrder: renderOrder++ }, /* @__PURE__ */ React.createElement("shapeGeometry", { args: [shape] }), /* @__PURE__ */ React.createElement(
|
|
6085
6034
|
"meshBasicMaterial",
|
|
6086
6035
|
{
|
|
6087
|
-
color: path.
|
|
6088
|
-
opacity: path.
|
|
6036
|
+
color: pathStyle(path).fill,
|
|
6037
|
+
opacity: pathStyle(path).fillOpacity,
|
|
6089
6038
|
transparent: true,
|
|
6090
6039
|
side: DoubleSide,
|
|
6091
6040
|
depthWrite: false,
|
|
6092
6041
|
...fillMaterial
|
|
6093
6042
|
}
|
|
6094
|
-
))), !skipStrokes && path
|
|
6043
|
+
))), !skipStrokes && pathStyle(path)?.stroke !== void 0 && pathStyle(path).stroke !== "none" && path.subPaths.map((_subPath, s) => /* @__PURE__ */ React.createElement("mesh", { key: s, geometry: strokeGeometries[p][s], ...strokeMeshProps, renderOrder: renderOrder++ }, /* @__PURE__ */ React.createElement(
|
|
6095
6044
|
"meshBasicMaterial",
|
|
6096
6045
|
{
|
|
6097
|
-
color: path.
|
|
6098
|
-
opacity: path.
|
|
6046
|
+
color: pathStyle(path).stroke,
|
|
6047
|
+
opacity: pathStyle(path).strokeOpacity,
|
|
6099
6048
|
transparent: true,
|
|
6100
6049
|
side: DoubleSide,
|
|
6101
6050
|
depthWrite: false,
|
|
@@ -6318,8 +6267,8 @@ function useVideoTexture(srcOrSrcObject, {
|
|
|
6318
6267
|
});
|
|
6319
6268
|
if (src && IS_BROWSER && src.endsWith(".m3u8")) {
|
|
6320
6269
|
const hls = hlsRef.current = await getHls(hlsConfig);
|
|
6321
|
-
if (hls) {
|
|
6322
|
-
hls.on(Events.MEDIA_ATTACHED, () => void hls.loadSource(src));
|
|
6270
|
+
if (hls && _HLSModule) {
|
|
6271
|
+
hls.on(_HLSModule.Events.MEDIA_ATTACHED, () => void hls.loadSource(src));
|
|
6323
6272
|
hls.attachMedia(video2);
|
|
6324
6273
|
}
|
|
6325
6274
|
}
|
|
@@ -6539,9 +6488,125 @@ function Fbx({
|
|
|
6539
6488
|
return /* @__PURE__ */ React.createElement(Clone, { ...props, object });
|
|
6540
6489
|
}
|
|
6541
6490
|
|
|
6491
|
+
const SERVICE_KEY = "__drei_ktx2_service__";
|
|
6492
|
+
const DEFAULT_TRANSCODER_PATH = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/basis/";
|
|
6493
|
+
class KTX2LoaderServiceImpl {
|
|
6494
|
+
loader = null;
|
|
6495
|
+
renderer = null;
|
|
6496
|
+
_isReady = false;
|
|
6497
|
+
transcoderPath = DEFAULT_TRANSCODER_PATH;
|
|
6498
|
+
pendingCallbacks = [];
|
|
6499
|
+
/**
|
|
6500
|
+
* Get or create the singleton KTX2Loader instance.
|
|
6501
|
+
* The loader is created lazily on first access.
|
|
6502
|
+
*/
|
|
6503
|
+
getLoader() {
|
|
6504
|
+
if (!this.loader) {
|
|
6505
|
+
this.loader = new KTX2Loader();
|
|
6506
|
+
this.loader.setTranscoderPath(this.transcoderPath);
|
|
6507
|
+
}
|
|
6508
|
+
return this.loader;
|
|
6509
|
+
}
|
|
6510
|
+
/**
|
|
6511
|
+
* Register a renderer and call detectSupport.
|
|
6512
|
+
* Should be called from within React context (useLayoutEffect).
|
|
6513
|
+
* Flushes any queued callbacks.
|
|
6514
|
+
*/
|
|
6515
|
+
registerRenderer(renderer) {
|
|
6516
|
+
if (this._isReady && this.renderer === renderer) {
|
|
6517
|
+
return;
|
|
6518
|
+
}
|
|
6519
|
+
this.renderer = renderer;
|
|
6520
|
+
const loader = this.getLoader();
|
|
6521
|
+
loader.detectSupport(renderer);
|
|
6522
|
+
this._isReady = true;
|
|
6523
|
+
this.flushPendingCallbacks();
|
|
6524
|
+
}
|
|
6525
|
+
/**
|
|
6526
|
+
* Check if the service is ready (has renderer registered).
|
|
6527
|
+
*/
|
|
6528
|
+
isReady() {
|
|
6529
|
+
return this._isReady;
|
|
6530
|
+
}
|
|
6531
|
+
/**
|
|
6532
|
+
* Get the registered renderer, if any.
|
|
6533
|
+
*/
|
|
6534
|
+
getRenderer() {
|
|
6535
|
+
return this.renderer;
|
|
6536
|
+
}
|
|
6537
|
+
/**
|
|
6538
|
+
* Register a callback to run when renderer becomes available.
|
|
6539
|
+
* If renderer is already available, runs immediately.
|
|
6540
|
+
*/
|
|
6541
|
+
onReady(callback) {
|
|
6542
|
+
if (this._isReady) {
|
|
6543
|
+
callback();
|
|
6544
|
+
} else {
|
|
6545
|
+
this.pendingCallbacks.push(callback);
|
|
6546
|
+
}
|
|
6547
|
+
}
|
|
6548
|
+
/**
|
|
6549
|
+
* Process all pending callbacks.
|
|
6550
|
+
*/
|
|
6551
|
+
flushPendingCallbacks() {
|
|
6552
|
+
const callbacks = this.pendingCallbacks;
|
|
6553
|
+
this.pendingCallbacks = [];
|
|
6554
|
+
for (const callback of callbacks) {
|
|
6555
|
+
try {
|
|
6556
|
+
callback();
|
|
6557
|
+
} catch (error) {
|
|
6558
|
+
console.error("KTX2LoaderService: Error in pending callback:", error);
|
|
6559
|
+
}
|
|
6560
|
+
}
|
|
6561
|
+
}
|
|
6562
|
+
/**
|
|
6563
|
+
* Set the transcoder path for basis/ktx2 decoding.
|
|
6564
|
+
*/
|
|
6565
|
+
setTranscoderPath(path) {
|
|
6566
|
+
this.transcoderPath = path;
|
|
6567
|
+
if (this.loader) {
|
|
6568
|
+
this.loader.setTranscoderPath(path);
|
|
6569
|
+
}
|
|
6570
|
+
}
|
|
6571
|
+
/**
|
|
6572
|
+
* Get the current transcoder path.
|
|
6573
|
+
*/
|
|
6574
|
+
getTranscoderPath() {
|
|
6575
|
+
return this.transcoderPath;
|
|
6576
|
+
}
|
|
6577
|
+
/**
|
|
6578
|
+
* Dispose of the loader and reset state.
|
|
6579
|
+
* Useful for testing or cleanup.
|
|
6580
|
+
*/
|
|
6581
|
+
dispose() {
|
|
6582
|
+
if (this.loader) {
|
|
6583
|
+
this.loader.dispose();
|
|
6584
|
+
}
|
|
6585
|
+
const path = this.transcoderPath;
|
|
6586
|
+
this.loader = null;
|
|
6587
|
+
this.renderer = null;
|
|
6588
|
+
this._isReady = false;
|
|
6589
|
+
this.transcoderPath = path;
|
|
6590
|
+
this.pendingCallbacks = [];
|
|
6591
|
+
}
|
|
6592
|
+
}
|
|
6593
|
+
const KTX2LoaderService = globalThis[SERVICE_KEY] || (globalThis[SERVICE_KEY] = new KTX2LoaderServiceImpl());
|
|
6594
|
+
|
|
6542
6595
|
let dracoLoader = null;
|
|
6543
6596
|
let decoderPath = "https://www.gstatic.com/draco/versioned/decoders/1.5.5/";
|
|
6544
|
-
|
|
6597
|
+
let legacyApiWarned = false;
|
|
6598
|
+
function isOptionsObject(arg) {
|
|
6599
|
+
return typeof arg === "object" && arg !== null && !Array.isArray(arg);
|
|
6600
|
+
}
|
|
6601
|
+
function warnLegacyApi() {
|
|
6602
|
+
if (!legacyApiWarned) {
|
|
6603
|
+
legacyApiWarned = true;
|
|
6604
|
+
console.warn(
|
|
6605
|
+
"useGLTF: Boolean arguments are deprecated. Use options object instead:\n useGLTF(path, { draco: true, meshopt: true, ktx2: true })"
|
|
6606
|
+
);
|
|
6607
|
+
}
|
|
6608
|
+
}
|
|
6609
|
+
function extensions(useDraco = true, useMeshopt = true, useKTX2 = false, extendLoader, renderer) {
|
|
6545
6610
|
return (loader) => {
|
|
6546
6611
|
if (extendLoader) {
|
|
6547
6612
|
extendLoader(loader);
|
|
@@ -6557,31 +6622,110 @@ function extensions(useDraco = true, useMeshopt = true, extendLoader) {
|
|
|
6557
6622
|
const decoder = typeof MeshoptDecoder === "function" ? MeshoptDecoder() : MeshoptDecoder;
|
|
6558
6623
|
loader.setMeshoptDecoder(decoder);
|
|
6559
6624
|
}
|
|
6625
|
+
if (useKTX2) {
|
|
6626
|
+
const ktx2Loader = KTX2LoaderService.getLoader();
|
|
6627
|
+
if (typeof useKTX2 === "string") {
|
|
6628
|
+
ktx2Loader.setTranscoderPath(useKTX2);
|
|
6629
|
+
}
|
|
6630
|
+
if (renderer) {
|
|
6631
|
+
ktx2Loader.detectSupport(renderer);
|
|
6632
|
+
}
|
|
6633
|
+
loader.setKTX2Loader(ktx2Loader);
|
|
6634
|
+
}
|
|
6560
6635
|
};
|
|
6561
6636
|
}
|
|
6562
|
-
|
|
6563
|
-
|
|
6637
|
+
function useGLTF(path, optionsOrDraco, useMeshoptArg, useKTX2Arg, extendLoaderArg) {
|
|
6638
|
+
let draco = true;
|
|
6639
|
+
let meshopt = true;
|
|
6640
|
+
let ktx2 = false;
|
|
6641
|
+
let extendLoader;
|
|
6642
|
+
if (isOptionsObject(optionsOrDraco)) {
|
|
6643
|
+
draco = optionsOrDraco.draco ?? true;
|
|
6644
|
+
meshopt = optionsOrDraco.meshopt ?? true;
|
|
6645
|
+
ktx2 = optionsOrDraco.ktx2 ?? false;
|
|
6646
|
+
extendLoader = optionsOrDraco.extendLoader;
|
|
6647
|
+
} else if (optionsOrDraco !== void 0) {
|
|
6648
|
+
warnLegacyApi();
|
|
6649
|
+
draco = optionsOrDraco;
|
|
6650
|
+
meshopt = useMeshoptArg ?? true;
|
|
6651
|
+
ktx2 = useKTX2Arg ?? false;
|
|
6652
|
+
extendLoader = extendLoaderArg;
|
|
6653
|
+
}
|
|
6654
|
+
const renderer = useThree((state) => state.renderer);
|
|
6655
|
+
useLayoutEffect(() => {
|
|
6656
|
+
if (ktx2) {
|
|
6657
|
+
KTX2LoaderService.registerRenderer(renderer);
|
|
6658
|
+
}
|
|
6659
|
+
}, [ktx2, renderer]);
|
|
6660
|
+
return useLoader(GLTFLoader, path, extensions(draco, meshopt, ktx2, extendLoader, ktx2 ? renderer : void 0));
|
|
6661
|
+
}
|
|
6662
|
+
useGLTF.preload = (path, optionsOrDraco, useMeshoptArg, useKTX2Arg, extendLoaderArg) => {
|
|
6663
|
+
let draco = true;
|
|
6664
|
+
let meshopt = true;
|
|
6665
|
+
let ktx2 = false;
|
|
6666
|
+
let extendLoader;
|
|
6667
|
+
if (isOptionsObject(optionsOrDraco)) {
|
|
6668
|
+
draco = optionsOrDraco.draco ?? true;
|
|
6669
|
+
meshopt = optionsOrDraco.meshopt ?? true;
|
|
6670
|
+
ktx2 = optionsOrDraco.ktx2 ?? false;
|
|
6671
|
+
extendLoader = optionsOrDraco.extendLoader;
|
|
6672
|
+
} else if (optionsOrDraco !== void 0) {
|
|
6673
|
+
warnLegacyApi();
|
|
6674
|
+
draco = optionsOrDraco;
|
|
6675
|
+
meshopt = useMeshoptArg ?? true;
|
|
6676
|
+
ktx2 = useKTX2Arg ?? false;
|
|
6677
|
+
extendLoader = extendLoaderArg;
|
|
6678
|
+
}
|
|
6679
|
+
if (ktx2) {
|
|
6680
|
+
KTX2LoaderService.onReady(() => {
|
|
6681
|
+
const renderer = KTX2LoaderService.getRenderer();
|
|
6682
|
+
useLoader.preload(GLTFLoader, path, extensions(draco, meshopt, ktx2, extendLoader, renderer));
|
|
6683
|
+
});
|
|
6684
|
+
} else {
|
|
6685
|
+
useLoader.preload(GLTFLoader, path, extensions(draco, meshopt, false, extendLoader));
|
|
6686
|
+
}
|
|
6687
|
+
};
|
|
6564
6688
|
useGLTF.clear = (path) => useLoader.clear(GLTFLoader, path);
|
|
6565
6689
|
useGLTF.setDecoderPath = (path) => {
|
|
6566
6690
|
decoderPath = path;
|
|
6567
6691
|
};
|
|
6692
|
+
useGLTF.setKTX2TranscoderPath = (path) => {
|
|
6693
|
+
KTX2LoaderService.setTranscoderPath(path);
|
|
6694
|
+
};
|
|
6568
6695
|
const Gltf = /* @__PURE__ */ React.forwardRef(
|
|
6569
|
-
({ src, useDraco, useMeshOpt, extendLoader, ...props }, ref) => {
|
|
6570
|
-
const
|
|
6696
|
+
({ src, useDraco, useMeshOpt, extendLoader, options, ...props }, ref) => {
|
|
6697
|
+
const opts = options ?? {
|
|
6698
|
+
draco: useDraco,
|
|
6699
|
+
meshopt: useMeshOpt,
|
|
6700
|
+
extendLoader
|
|
6701
|
+
};
|
|
6702
|
+
const { scene } = useGLTF(src, opts);
|
|
6571
6703
|
return /* @__PURE__ */ React.createElement(Clone, { ref, ...props, object: scene });
|
|
6572
6704
|
}
|
|
6573
6705
|
);
|
|
6574
6706
|
|
|
6575
|
-
|
|
6576
|
-
function useKTX2(input, basisPath = `${cdn}/basis/`) {
|
|
6707
|
+
function useKTX2(input, basisPath = true, extendLoader) {
|
|
6577
6708
|
const renderer = useThree((state) => state.renderer);
|
|
6709
|
+
useLayoutEffect(() => {
|
|
6710
|
+
KTX2LoaderService.registerRenderer(renderer);
|
|
6711
|
+
}, [renderer]);
|
|
6578
6712
|
const textures = useLoader(KTX2Loader, IsObject(input) ? Object.values(input) : input, (loader) => {
|
|
6713
|
+
if (extendLoader) {
|
|
6714
|
+
extendLoader(loader);
|
|
6715
|
+
}
|
|
6716
|
+
if (basisPath) {
|
|
6717
|
+
const path = typeof basisPath === "string" ? basisPath : KTX2LoaderService.getTranscoderPath();
|
|
6718
|
+
loader.setTranscoderPath(path);
|
|
6719
|
+
}
|
|
6579
6720
|
loader.detectSupport(renderer);
|
|
6580
|
-
loader.setTranscoderPath(basisPath);
|
|
6581
6721
|
});
|
|
6582
6722
|
useEffect(() => {
|
|
6583
6723
|
const array = Array.isArray(textures) ? textures : [textures];
|
|
6584
|
-
array.forEach((texture) =>
|
|
6724
|
+
array.forEach((texture) => {
|
|
6725
|
+
if ("initTexture" in renderer) {
|
|
6726
|
+
renderer.initTexture(texture);
|
|
6727
|
+
}
|
|
6728
|
+
});
|
|
6585
6729
|
}, [renderer, textures]);
|
|
6586
6730
|
if (IsObject(input)) {
|
|
6587
6731
|
const keys = Object.keys(input);
|
|
@@ -6592,19 +6736,81 @@ function useKTX2(input, basisPath = `${cdn}/basis/`) {
|
|
|
6592
6736
|
return textures;
|
|
6593
6737
|
}
|
|
6594
6738
|
}
|
|
6595
|
-
useKTX2.preload = (url, basisPath =
|
|
6596
|
-
|
|
6597
|
-
|
|
6739
|
+
useKTX2.preload = (url, basisPath = true, extendLoader) => {
|
|
6740
|
+
KTX2LoaderService.onReady(() => {
|
|
6741
|
+
const renderer = KTX2LoaderService.getRenderer();
|
|
6742
|
+
useLoader.preload(KTX2Loader, url, (loader) => {
|
|
6743
|
+
if (extendLoader) {
|
|
6744
|
+
extendLoader(loader);
|
|
6745
|
+
}
|
|
6746
|
+
if (basisPath) {
|
|
6747
|
+
const path = typeof basisPath === "string" ? basisPath : KTX2LoaderService.getTranscoderPath();
|
|
6748
|
+
loader.setTranscoderPath(path);
|
|
6749
|
+
}
|
|
6750
|
+
if (renderer) {
|
|
6751
|
+
loader.detectSupport(renderer);
|
|
6752
|
+
}
|
|
6753
|
+
});
|
|
6754
|
+
});
|
|
6755
|
+
};
|
|
6598
6756
|
useKTX2.clear = (input) => useLoader.clear(KTX2Loader, input);
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
const texture = useKTX2(input, basisPath);
|
|
6757
|
+
useKTX2.setTranscoderPath = (path) => {
|
|
6758
|
+
KTX2LoaderService.setTranscoderPath(path);
|
|
6759
|
+
};
|
|
6760
|
+
const Ktx2 = ({ children, input, basisPath, extendLoader }) => {
|
|
6761
|
+
const texture = useKTX2(input, basisPath, extendLoader);
|
|
6605
6762
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, children?.(texture));
|
|
6606
6763
|
};
|
|
6607
6764
|
|
|
6765
|
+
const useVariants = (model, inVariant) => {
|
|
6766
|
+
const [activeVariant, setActiveVariant] = useState(null);
|
|
6767
|
+
const [materials, setMaterials] = useState([]);
|
|
6768
|
+
useEffect(() => {
|
|
6769
|
+
model.parser.getDependencies("material").then((materials2) => {
|
|
6770
|
+
setMaterials(materials2);
|
|
6771
|
+
});
|
|
6772
|
+
}, [model]);
|
|
6773
|
+
const variants = useMemo(() => {
|
|
6774
|
+
return model.userData.gltfExtensions?.KHR_materials_variants?.variants;
|
|
6775
|
+
}, [model]);
|
|
6776
|
+
const applyVariant = useCallback(
|
|
6777
|
+
(variantIndex) => {
|
|
6778
|
+
model.scene.traverse(async (object) => {
|
|
6779
|
+
if (!("isMesh" in object) || !object.userData.gltfExtensions) return;
|
|
6780
|
+
const meshObject = object;
|
|
6781
|
+
const meshVariantDef = meshObject.userData.gltfExtensions.KHR_materials_variants;
|
|
6782
|
+
if (!meshVariantDef) return;
|
|
6783
|
+
if (!meshObject.userData.originalMaterial) meshObject.userData.originalMaterial = meshObject.material;
|
|
6784
|
+
const mapping = meshVariantDef.mappings.find((mapping2) => mapping2.variants.includes(variantIndex));
|
|
6785
|
+
if (mapping) {
|
|
6786
|
+
meshObject.material = await model.parser.getDependency("material", mapping.material);
|
|
6787
|
+
model.parser.assignFinalMaterial(meshObject);
|
|
6788
|
+
} else meshObject.material = meshObject.userData.originalMaterial;
|
|
6789
|
+
if (Array.isArray(meshObject.material)) for (const mat of meshObject.material) mat.needsUpdate = true;
|
|
6790
|
+
else meshObject.material.needsUpdate = true;
|
|
6791
|
+
});
|
|
6792
|
+
},
|
|
6793
|
+
[model]
|
|
6794
|
+
);
|
|
6795
|
+
const setVariant = useCallback(
|
|
6796
|
+
(variantName) => {
|
|
6797
|
+
if (!variants) return;
|
|
6798
|
+
const newVariant = variantName && variants.some((v) => v.name === variantName) ? variantName : null;
|
|
6799
|
+
setActiveVariant(newVariant);
|
|
6800
|
+
},
|
|
6801
|
+
[variants]
|
|
6802
|
+
);
|
|
6803
|
+
useEffect(() => {
|
|
6804
|
+
if (!variants) return;
|
|
6805
|
+
const variantIndex = variants.findIndex((v) => v.name === activeVariant);
|
|
6806
|
+
applyVariant(variantIndex > -1 ? variantIndex : 0);
|
|
6807
|
+
}, [variants, activeVariant, applyVariant]);
|
|
6808
|
+
useEffect(() => {
|
|
6809
|
+
setVariant(inVariant ?? null);
|
|
6810
|
+
}, [inVariant, setVariant]);
|
|
6811
|
+
return { variants, activeVariant, setVariant, materials };
|
|
6812
|
+
};
|
|
6813
|
+
|
|
6608
6814
|
const WebcamVideoTexture = /* @__PURE__ */ forwardRef(
|
|
6609
6815
|
({
|
|
6610
6816
|
constraints = {
|
|
@@ -6792,6 +6998,7 @@ function useEffectfulState(fn, deps = [], cb) {
|
|
|
6792
6998
|
}
|
|
6793
6999
|
|
|
6794
7000
|
function Stats({ showPanel = 0, className, parent }) {
|
|
7001
|
+
React.useEffect(() => void console.warn("drei: <Stats /> is deprecated, use <StatsGl /> instead."), []);
|
|
6795
7002
|
const stats = useEffectfulState(() => new StatsImpl(), []);
|
|
6796
7003
|
React.useEffect(() => {
|
|
6797
7004
|
if (stats) {
|
|
@@ -6820,6 +7027,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
|
|
|
6820
7027
|
const stats2 = new Stats$1({
|
|
6821
7028
|
...props
|
|
6822
7029
|
});
|
|
7030
|
+
stats2.init(renderer);
|
|
6823
7031
|
return stats2;
|
|
6824
7032
|
}, [renderer]);
|
|
6825
7033
|
React.useImperativeHandle(fref, () => stats.domElement, [stats]);
|
|
@@ -6837,7 +7045,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
|
|
|
6837
7045
|
return () => {
|
|
6838
7046
|
if (classNames.length) stats.domElement.classList.remove(...classNames);
|
|
6839
7047
|
node?.removeChild(stats.domElement);
|
|
6840
|
-
stats.
|
|
7048
|
+
stats.dispose();
|
|
6841
7049
|
};
|
|
6842
7050
|
}
|
|
6843
7051
|
}, [parent, stats, className, id, clearStatsGlStyle]);
|
|
@@ -6845,7 +7053,7 @@ const StatsGl = /* @__PURE__ */ React.forwardRef(
|
|
|
6845
7053
|
() => {
|
|
6846
7054
|
stats.begin();
|
|
6847
7055
|
},
|
|
6848
|
-
{ before: "
|
|
7056
|
+
{ before: "update" }
|
|
6849
7057
|
);
|
|
6850
7058
|
useFrame(
|
|
6851
7059
|
() => {
|
|
@@ -6895,11 +7103,11 @@ const RenderCubeTexture = /* @__PURE__ */ React.forwardRef(
|
|
|
6895
7103
|
depthBuffer,
|
|
6896
7104
|
generateMipmaps
|
|
6897
7105
|
};
|
|
6898
|
-
const fboA2 = new
|
|
7106
|
+
const fboA2 = new WebGLCubeRenderTarget(fboSize, settings);
|
|
6899
7107
|
fboA2.texture.isRenderTargetTexture = !flip;
|
|
6900
7108
|
fboA2.texture.flipY = true;
|
|
6901
7109
|
fboA2.texture.type = THREE.HalfFloatType;
|
|
6902
|
-
const fboB2 = new
|
|
7110
|
+
const fboB2 = new WebGLCubeRenderTarget(fboSize, settings);
|
|
6903
7111
|
fboB2.texture.isRenderTargetTexture = !flip;
|
|
6904
7112
|
fboB2.texture.flipY = true;
|
|
6905
7113
|
fboB2.texture.type = THREE.HalfFloatType;
|
|
@@ -7077,18 +7285,21 @@ function Fisheye({
|
|
|
7077
7285
|
const normal = new THREE.Vector3();
|
|
7078
7286
|
const sph = new THREE.Sphere(new THREE.Vector3(), radius);
|
|
7079
7287
|
const normalMatrix = new THREE.Matrix3();
|
|
7080
|
-
const compute = React.useCallback(
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7288
|
+
const compute = React.useCallback(
|
|
7289
|
+
(event, state, prev) => {
|
|
7290
|
+
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
7291
|
+
state.raycaster.setFromCamera(state.pointer, orthoC);
|
|
7292
|
+
if (!state.raycaster.ray.intersectSphere(sph, normal)) return;
|
|
7293
|
+
else normal.normalize();
|
|
7294
|
+
normalMatrix.getNormalMatrix(cubeApi.current.camera.matrixWorld);
|
|
7295
|
+
cubeApi.current.camera.getWorldPosition(state.raycaster.ray.origin);
|
|
7296
|
+
state.raycaster.ray.direction.set(0, 0, 1).reflect(normal);
|
|
7297
|
+
state.raycaster.ray.direction.x *= -1;
|
|
7298
|
+
state.raycaster.ray.direction.applyNormalMatrix(normalMatrix).multiplyScalar(-1);
|
|
7299
|
+
return void 0;
|
|
7300
|
+
},
|
|
7301
|
+
[width, height]
|
|
7302
|
+
);
|
|
7092
7303
|
useFrame(
|
|
7093
7304
|
({ gl }) => {
|
|
7094
7305
|
if (renderPriority) gl.render(sphere.current, orthoC);
|
|
@@ -7223,14 +7434,23 @@ const isWebGPURenderer = (def) => !!def.isWebGPURenderer;
|
|
|
7223
7434
|
const col = /* @__PURE__ */ new THREE.Color();
|
|
7224
7435
|
const TUNNEL_KEY = "__drei_view_tunnel__";
|
|
7225
7436
|
const tracked = globalThis[TUNNEL_KEY] || (globalThis[TUNNEL_KEY] = tunnel());
|
|
7226
|
-
function computeContainerPosition(canvasSize, trackRect) {
|
|
7437
|
+
function computeContainerPosition(canvasSize, trackRect, forceEven) {
|
|
7227
7438
|
const { right, top: trackTop, left: trackLeft, bottom: trackBottom, width, height } = trackRect;
|
|
7228
|
-
const isOffscreen = trackRect.bottom < 0 || trackTop > canvasSize.height || right < 0 || trackRect.left > canvasSize.width;
|
|
7229
7439
|
const canvasBottom = canvasSize.top + canvasSize.height;
|
|
7230
|
-
const
|
|
7231
|
-
const
|
|
7232
|
-
const
|
|
7233
|
-
|
|
7440
|
+
const canvasRight = canvasSize.left + canvasSize.width;
|
|
7441
|
+
const isOffscreen = trackBottom < canvasSize.top || trackTop > canvasBottom || right < canvasSize.left || trackLeft > canvasRight;
|
|
7442
|
+
const rawBottom = canvasBottom - trackBottom;
|
|
7443
|
+
const rawLeft = trackLeft - canvasSize.left;
|
|
7444
|
+
const rawTop = trackTop - canvasSize.top;
|
|
7445
|
+
const position = forceEven ? {
|
|
7446
|
+
width: roundEven(width),
|
|
7447
|
+
height: roundEven(height),
|
|
7448
|
+
left: roundEven(rawLeft),
|
|
7449
|
+
top: roundEven(rawTop),
|
|
7450
|
+
bottom: roundEven(rawBottom),
|
|
7451
|
+
right: roundEven(right)
|
|
7452
|
+
} : { width, height, left: rawLeft, top: rawTop, bottom: rawBottom, right };
|
|
7453
|
+
return { position, isOffscreen };
|
|
7234
7454
|
}
|
|
7235
7455
|
function prepareSkissor(renderer, camera, {
|
|
7236
7456
|
left,
|
|
@@ -7270,6 +7490,7 @@ function clear(renderer) {
|
|
|
7270
7490
|
}
|
|
7271
7491
|
function Container({ visible = true, canvasSize, scene, index, children, frames, rect, track }) {
|
|
7272
7492
|
const { scene: portalScene, camera: portalCamera, renderer, get, setEvents } = useThree();
|
|
7493
|
+
const forceEven = useThree((state) => state.internal.forceEven);
|
|
7273
7494
|
const [isOffscreen, setOffscreen] = React.useState(false);
|
|
7274
7495
|
const mountedRef = React.useRef(true);
|
|
7275
7496
|
React.useEffect(() => {
|
|
@@ -7287,7 +7508,7 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
7287
7508
|
frameCount++;
|
|
7288
7509
|
}
|
|
7289
7510
|
if (rect.current) {
|
|
7290
|
-
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, rect.current);
|
|
7511
|
+
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, rect.current, forceEven);
|
|
7291
7512
|
if (isOffscreen !== _isOffscreen) setOffscreen(_isOffscreen);
|
|
7292
7513
|
if (visible && !_isOffscreen && rect.current) {
|
|
7293
7514
|
const targetScene = children ? portalScene : scene;
|
|
@@ -7309,14 +7530,14 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
7309
7530
|
React.useLayoutEffect(() => {
|
|
7310
7531
|
const curRect = rect.current;
|
|
7311
7532
|
if (curRect && (!visible || !isOffscreen)) {
|
|
7312
|
-
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect);
|
|
7533
|
+
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect, forceEven);
|
|
7313
7534
|
if (!_isOffscreen) {
|
|
7314
7535
|
const autoClear = prepareSkissor(renderer, portalCamera, position);
|
|
7315
7536
|
clear(renderer);
|
|
7316
7537
|
finishSkissor(renderer, autoClear);
|
|
7317
7538
|
}
|
|
7318
7539
|
}
|
|
7319
|
-
}, [visible, isOffscreen, renderer, portalCamera, canvasSize]);
|
|
7540
|
+
}, [visible, isOffscreen, renderer, portalCamera, canvasSize, forceEven]);
|
|
7320
7541
|
React.useEffect(() => {
|
|
7321
7542
|
if (!track) return;
|
|
7322
7543
|
const curRect = rect.current;
|
|
@@ -7324,7 +7545,7 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
7324
7545
|
setEvents({ connected: track.current });
|
|
7325
7546
|
return () => {
|
|
7326
7547
|
if (curRect) {
|
|
7327
|
-
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect);
|
|
7548
|
+
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect, forceEven);
|
|
7328
7549
|
if (!_isOffscreen) {
|
|
7329
7550
|
const autoClear = prepareSkissor(renderer, portalCamera, position);
|
|
7330
7551
|
clear(renderer);
|
|
@@ -7333,13 +7554,14 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
7333
7554
|
}
|
|
7334
7555
|
setEvents({ connected: old });
|
|
7335
7556
|
};
|
|
7336
|
-
}, [track, renderer, portalCamera, canvasSize, get, setEvents]);
|
|
7557
|
+
}, [track, renderer, portalCamera, canvasSize, get, setEvents, forceEven]);
|
|
7337
7558
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, children, /* @__PURE__ */ React.createElement("group", { onPointerOver: () => null }));
|
|
7338
7559
|
}
|
|
7339
7560
|
const CanvasView = /* @__PURE__ */ React.forwardRef(
|
|
7340
7561
|
({ track, visible = true, index = 1, id, style, className, frames = Infinity, children, ...props }, fref) => {
|
|
7341
7562
|
const rect = React.useRef(null);
|
|
7342
7563
|
const { size, scene } = useThree();
|
|
7564
|
+
const forceEven = useThree((state) => state.internal.forceEven);
|
|
7343
7565
|
const [virtualScene] = React.useState(() => new THREE.Scene());
|
|
7344
7566
|
const [ready, toggle] = React.useReducer(() => true, false);
|
|
7345
7567
|
const compute = React.useCallback(
|
|
@@ -7376,12 +7598,12 @@ const CanvasView = /* @__PURE__ */ React.forwardRef(
|
|
|
7376
7598
|
{
|
|
7377
7599
|
events: { compute, priority: index },
|
|
7378
7600
|
size: {
|
|
7379
|
-
width: rect.current?.width,
|
|
7380
|
-
height: rect.current?.height,
|
|
7601
|
+
width: forceEven && rect.current?.width ? roundEven(rect.current.width) : rect.current?.width,
|
|
7602
|
+
height: forceEven && rect.current?.height ? roundEven(rect.current.height) : rect.current?.height,
|
|
7381
7603
|
// @ts-ignore
|
|
7382
|
-
top: rect.current?.top,
|
|
7604
|
+
top: forceEven && rect.current?.top ? roundEven(rect.current.top) : rect.current?.top,
|
|
7383
7605
|
// @ts-ignore
|
|
7384
|
-
left: rect.current?.left
|
|
7606
|
+
left: forceEven && rect.current?.left ? roundEven(rect.current.left) : rect.current?.left
|
|
7385
7607
|
}
|
|
7386
7608
|
}
|
|
7387
7609
|
));
|
|
@@ -7776,12 +7998,12 @@ useEnvironment.preload = (preloadOptions) => {
|
|
|
7776
7998
|
if (extensions) extensions(loader2);
|
|
7777
7999
|
});
|
|
7778
8000
|
};
|
|
7779
|
-
const
|
|
8001
|
+
const clearDefaultOptions = {
|
|
7780
8002
|
files: defaultFiles,
|
|
7781
8003
|
preset: void 0
|
|
7782
8004
|
};
|
|
7783
8005
|
useEnvironment.clear = (clearOptions) => {
|
|
7784
|
-
const options = { ...
|
|
8006
|
+
const options = { ...clearDefaultOptions, ...clearOptions };
|
|
7785
8007
|
let { files } = options;
|
|
7786
8008
|
const { preset } = options;
|
|
7787
8009
|
if (preset) {
|
|
@@ -8475,9 +8697,14 @@ function Select({
|
|
|
8475
8697
|
const oldControlsEnabled = controls?.enabled;
|
|
8476
8698
|
let isDown = false;
|
|
8477
8699
|
function prepareRay(event, vec) {
|
|
8478
|
-
const
|
|
8700
|
+
const canvas = gl.domElement;
|
|
8701
|
+
const rect = canvas.getBoundingClientRect();
|
|
8702
|
+
const x = event.clientX - rect.left;
|
|
8703
|
+
const y = event.clientY - rect.top;
|
|
8479
8704
|
const { width, height } = size;
|
|
8480
|
-
|
|
8705
|
+
const normalizedX = x / width * 2 - 1;
|
|
8706
|
+
const normalizedY = -(y / height) * 2 + 1;
|
|
8707
|
+
vec.set(normalizedX, normalizedY, -1);
|
|
8481
8708
|
}
|
|
8482
8709
|
function onSelectStart(event) {
|
|
8483
8710
|
if (controls) controls.enabled = false;
|
|
@@ -8556,4 +8783,4 @@ function useSelect() {
|
|
|
8556
8783
|
return React.useContext(context);
|
|
8557
8784
|
}
|
|
8558
8785
|
|
|
8559
|
-
export { AdaptiveDpr, AdaptiveEvents, ArcballControls, BBAnchor, Backdrop, Billboard, Bounds, Box, CameraShake, Capsule, CatmullRomLine, Center, Circle, Clone, Cloud, CloudInstance, Clouds, ComputedAttribute, Cone, CubeCamera, CubeTexture, CubicBezierLine, CurveModifier, CycleRaycast, Cylinder, Decal, Detailed, DetectGPU, DeviceOrientationControls, Dodecahedron, DragControls, Edges, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, Example, Extrude, Fbo, Fbx, FirstPersonControls, Fisheye, Float, FlyControls, GizmoHelper, GizmoViewcube, GizmoViewport, Gltf, Helper, Html, Hud, Icosahedron, Instance, InstancedAttribute, Instances, IsObject, KeyboardControls, Ktx2, Lathe, Lightformer, Loader, MapControls, Mask, MatcapTexture, Merged, MotionPathControls, NormalTexture, Octahedron, OrbitControls, OrthographicCamera, PerformanceMonitor, PerspectiveCamera, PivotControls, Plane, Point, PointMaterial, PointMaterialImpl, PointerLockControls, Points, PointsBuffer, Polyhedron, PositionMesh, PositionPoint, PositionalAudio, Preload, PresentationControls, Progress, QuadraticBezierLine, RenderCubeTexture, RenderTexture, Resize, Ring, RoundedBox, RoundedBoxGeometry, Sampler, ScreenQuad, ScreenSizer, ScreenSpace, ScreenVideoTexture, Scroll, ScrollControls, Select, Shadow, Shape, Sky, Sphere, SpriteAnimator, Stage, Stats, StatsGl, Svg, Tetrahedron, Text3D, Texture, Torus, TorusKnot, TrackballControls, TrailTexture, TransformControls, Tube, VideoTexture, View, WebcamVideoTexture,
|
|
8786
|
+
export { AdaptiveDpr, AdaptiveEvents, ArcballControls, BBAnchor, Backdrop, Billboard, Bounds, Box, CameraShake, Capsule, CatmullRomLine, Center, Circle, Clone, Cloud, CloudInstance, Clouds, ComputedAttribute, Cone, CubeCamera, CubeTexture, CubicBezierLine, CurveModifier, CycleRaycast, Cylinder, Decal, Detailed, DetectGPU, DeviceOrientationControls, Dodecahedron, DragControls, Edges, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, Example, Extrude, Fbo, Fbx, FirstPersonControls, Fisheye, Float, FlyControls, GizmoHelper, GizmoViewcube, GizmoViewport, Gltf, Helper, Html, Hud, Icosahedron, Instance, InstancedAttribute, Instances, IsObject, KeyboardControls, Ktx2, Lathe, Lightformer, Loader, MapControls, Mask, MatcapTexture, Merged, MotionPathControls, NormalTexture, Octahedron, OrbitControls, OrthographicCamera, PerformanceMonitor, PerspectiveCamera, PivotControls, Plane, Point, PointMaterial, PointMaterialImpl, PointerLockControls, Points, PointsBuffer, Polyhedron, PositionMesh, PositionPoint, PositionalAudio, Preload, PresentationControls, Progress, QuadraticBezierLine, RenderCubeTexture, RenderTexture, Resize, Ring, RoundedBox, RoundedBoxGeometry, Sampler, ScreenQuad, ScreenSizer, ScreenSpace, ScreenVideoTexture, Scroll, ScrollControls, Select, Shadow, Shape, Sky, Sphere, SpriteAnimator, Stage, Stats, StatsGl, Svg, Tetrahedron, Text3D, Texture, Torus, TorusKnot, TrackballControls, TrailTexture, TransformControls, Tube, VideoTexture, View, WebcamVideoTexture, calcPosFromAngles, checkIfFrameIsEmpty, createInstances, getFirstFrame, meshBounds, presetsObj, useAnimations, useAspect, useBounds, useContextBridge, useCubeCamera, useCubeTexture, useCursor, useCustomRaycast, useDepthBuffer, useDetectGPU, useEnvironment, useFBO, useFBX, useFont, useGLTF, useGizmoContext, useHelper, useIntersect, useKTX2, useKeyboardControls, useMask, useMatcapTexture, useMotion, useNormalTexture, usePerformanceMonitor, useProgress, useScroll, useSelect, useSpriteAnimator, useSpriteLoader, useSurfaceSampler, useTexture, useTrailTexture, useVariants, useVideoTexture };
|