@react-three/drei 11.0.0-alpha.4 → 11.0.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/index.d.mts +64 -66
- package/core/index.d.ts +64 -66
- package/core/index.mjs +396 -472
- package/experimental/index.d.mts +4 -4
- package/experimental/index.d.ts +4 -4
- package/experimental/index.mjs +1 -0
- package/external/index.d.mts +4 -4
- package/external/index.d.ts +4 -4
- package/external/index.mjs +1 -0
- package/index.d.mts +65 -67
- package/index.d.ts +65 -67
- package/index.mjs +396 -472
- package/legacy/index.d.mts +141 -94
- package/legacy/index.d.ts +141 -94
- package/legacy/index.mjs +1264 -958
- package/native/index.d.mts +177 -370
- package/native/index.d.ts +177 -370
- package/native/index.mjs +1238 -2434
- package/package.json +2 -3
- package/webgpu/index.d.mts +180 -216
- package/webgpu/index.d.ts +180 -216
- package/webgpu/index.mjs +1228 -1787
package/legacy/index.mjs
CHANGED
|
@@ -2,9 +2,8 @@ import * as React from 'react';
|
|
|
2
2
|
import { forwardRef, useImperativeHandle, useMemo, useEffect, useCallback, useRef, useLayoutEffect, useState, Fragment, createContext, useContext } from 'react';
|
|
3
3
|
import { useThree, useFrame, extend, createPortal, applyProps, useInstanceHandle, context as context$a, useLoader, addEffect, addAfterEffect } from '@react-three/fiber';
|
|
4
4
|
import * as THREE from 'three';
|
|
5
|
-
import { REVISION, WebGLRenderTarget, HalfFloatType, LinearFilter, Vector2, Scene, Camera, BufferGeometry, BufferAttribute, Mesh, MeshStandardMaterial, Plane as Plane$1, Vector3, Matrix4, Vector4, PerspectiveCamera as PerspectiveCamera$1, DepthTexture, DepthFormat, UnsignedShortType, Frustum, MeshPhysicalMaterial, RGBAFormat, UnsignedByteType, Color, InstancedInterleavedBuffer, InterleavedBufferAttribute, Object3D, WebGLCubeRenderTarget, CubeCamera as CubeCamera$1, MathUtils, TextureLoader, Texture as Texture$1, MeshLambertMaterial,
|
|
5
|
+
import { REVISION, WebGLRenderTarget, HalfFloatType, LinearFilter, Vector2, Scene, Camera, BufferGeometry, BufferAttribute, Mesh, MeshStandardMaterial, Plane as Plane$1, Vector3, Matrix4, Vector4, PerspectiveCamera as PerspectiveCamera$1, DepthTexture, DepthFormat, UnsignedShortType, Frustum, MeshPhysicalMaterial, RGBAFormat, UnsignedByteType, Color, InstancedInterleavedBuffer, InterleavedBufferAttribute, Object3D, WebGLCubeRenderTarget, CubeCamera as CubeCamera$1, EventDispatcher, Euler, Quaternion, MathUtils, TextureLoader, Texture as Texture$1, MeshLambertMaterial, DynamicDrawUsage, CatmullRomCurve3, CubicBezierCurve3, QuadraticBezierCurve3, Shape as Shape$1, CanvasTexture, DoubleSide, OrthographicCamera as OrthographicCamera$1, AudioListener, AudioLoader, AnimationMixer, Box3, Sphere as Sphere$1, InstancedBufferAttribute, CubeTextureLoader, DefaultLoadingManager, Ray, Raycaster, CubeReflectionMapping, EquirectangularReflectionMapping, RepeatWrapping, ShaderMaterial, CylinderGeometry, AdditiveBlending, Spherical } from 'three';
|
|
6
6
|
import { ArcballControls as ArcballControls$1 } from 'three/examples/jsm/controls/ArcballControls.js';
|
|
7
|
-
import { DeviceOrientationControls as DeviceOrientationControls$1 } from 'three-stdlib';
|
|
8
7
|
import { useGesture } from '@use-gesture/react';
|
|
9
8
|
import { FirstPersonControls as FirstPersonControls$1 } from 'three/examples/jsm/controls/FirstPersonControls.js';
|
|
10
9
|
import { FlyControls as FlyControls$1 } from 'three/examples/jsm/controls/FlyControls.js';
|
|
@@ -188,6 +187,7 @@ function shaderMaterial(uniforms, vertexShader, fragmentShader, onInit) {
|
|
|
188
187
|
});
|
|
189
188
|
}
|
|
190
189
|
this.uniforms = THREE.UniformsUtils.clone(this.uniforms);
|
|
190
|
+
Object.assign(this, parameters);
|
|
191
191
|
onInit?.(this);
|
|
192
192
|
}
|
|
193
193
|
};
|
|
@@ -1517,6 +1517,7 @@ let MeshReflectorMaterial$1 = class MeshReflectorMaterial extends MeshStandardMa
|
|
|
1517
1517
|
uniform float depthScale;
|
|
1518
1518
|
uniform float depthToBlurRatioBias;
|
|
1519
1519
|
varying vec4 my_vUv;
|
|
1520
|
+
#include <tonemapping_pars_fragment>
|
|
1520
1521
|
${shader.fragmentShader}`;
|
|
1521
1522
|
shader.fragmentShader = shader.fragmentShader.replace(
|
|
1522
1523
|
"#include <emissivemap_fragment>",
|
|
@@ -1577,6 +1578,9 @@ let MeshReflectorMaterial$1 = class MeshReflectorMaterial extends MeshStandardMa
|
|
|
1577
1578
|
merge = mix(merge, blur, blurFactor);
|
|
1578
1579
|
#endif
|
|
1579
1580
|
|
|
1581
|
+
// Apply tone mapping to HDR reflection values before contrast adjustment
|
|
1582
|
+
merge.rgb = toneMapping(merge.rgb);
|
|
1583
|
+
|
|
1580
1584
|
vec4 newMerge = vec4(0.0, 0.0, 0.0, 1.0);
|
|
1581
1585
|
newMerge.r = (merge.r - 0.5) * mixContrast + 0.5;
|
|
1582
1586
|
newMerge.g = (merge.g - 0.5) * mixContrast + 0.5;
|
|
@@ -1835,6 +1839,7 @@ const MeshReflectorMaterial = /* @__PURE__ */ React.forwardRef(
|
|
|
1835
1839
|
useFrame(() => {
|
|
1836
1840
|
const parent = materialRef.current.parent || materialRef.current?.__r3f.parent?.object;
|
|
1837
1841
|
if (!parent) return;
|
|
1842
|
+
if (gl.xr.isPresenting) return;
|
|
1838
1843
|
parent.visible = false;
|
|
1839
1844
|
const currentXrEnabled = gl.xr.enabled;
|
|
1840
1845
|
const currentShadowAutoUpdate = gl.shadowMap.autoUpdate;
|
|
@@ -2248,6 +2253,8 @@ const MeshPortalMaterial = /* @__PURE__ */ React.forwardRef(
|
|
|
2248
2253
|
children,
|
|
2249
2254
|
events = void 0,
|
|
2250
2255
|
blur = 0,
|
|
2256
|
+
blend = 0,
|
|
2257
|
+
samples = 8,
|
|
2251
2258
|
eventPriority = 0,
|
|
2252
2259
|
renderPriority = 0,
|
|
2253
2260
|
worldUnits = false,
|
|
@@ -2260,7 +2267,7 @@ const MeshPortalMaterial = /* @__PURE__ */ React.forwardRef(
|
|
|
2260
2267
|
const maskRenderTarget = useFBO(resolution, resolution);
|
|
2261
2268
|
const [priority, setPriority] = React.useState(0);
|
|
2262
2269
|
useFrame(() => {
|
|
2263
|
-
const p = ref.current.blend > 0 ? Math.max(1, renderPriority) : 0;
|
|
2270
|
+
const p = (ref.current.blend ?? 0) > 0 ? Math.max(1, renderPriority) : 0;
|
|
2264
2271
|
if (priority !== p) setPriority(p);
|
|
2265
2272
|
});
|
|
2266
2273
|
React.useEffect(() => {
|
|
@@ -2334,7 +2341,8 @@ const MeshPortalMaterial = /* @__PURE__ */ React.forwardRef(
|
|
|
2334
2341
|
frames: visible ? Infinity : 0,
|
|
2335
2342
|
eventPriority,
|
|
2336
2343
|
renderPriority,
|
|
2337
|
-
compute
|
|
2344
|
+
compute,
|
|
2345
|
+
samples
|
|
2338
2346
|
},
|
|
2339
2347
|
children,
|
|
2340
2348
|
/* @__PURE__ */ React.createElement(
|
|
@@ -2414,7 +2422,7 @@ function ManagePortalScene({
|
|
|
2414
2422
|
scene.matrixWorld.copy(parent.matrixWorld);
|
|
2415
2423
|
} else scene.matrixWorld.identity();
|
|
2416
2424
|
if (priority) {
|
|
2417
|
-
if (material.current?.blend > 0 && material.current?.blend < 1) {
|
|
2425
|
+
if (material.current?.blend && material.current?.blend > 0 && material.current?.blend < 1) {
|
|
2418
2426
|
blend.value = material.current.blend;
|
|
2419
2427
|
state.gl.setRenderTarget(buffer1);
|
|
2420
2428
|
state.gl.render(scene, state.camera);
|
|
@@ -3207,12 +3215,12 @@ const Segments = /* @__PURE__ */ React.forwardRef((props, forwardedRef) => {
|
|
|
3207
3215
|
for (let i = 0; i < limit; i++) {
|
|
3208
3216
|
const segment = segments[i]?.current;
|
|
3209
3217
|
if (segment) {
|
|
3210
|
-
positions[i * 6 + 0] = segment.start
|
|
3211
|
-
positions[i * 6 + 1] = segment.start
|
|
3212
|
-
positions[i * 6 + 2] = segment.start
|
|
3213
|
-
positions[i * 6 + 3] = segment.end
|
|
3214
|
-
positions[i * 6 + 4] = segment.end
|
|
3215
|
-
positions[i * 6 + 5] = segment.end
|
|
3218
|
+
positions[i * 6 + 0] = segment.start?.x || 0;
|
|
3219
|
+
positions[i * 6 + 1] = segment.start?.y || 0;
|
|
3220
|
+
positions[i * 6 + 2] = segment.start?.z || 0;
|
|
3221
|
+
positions[i * 6 + 3] = segment.end?.x || 0;
|
|
3222
|
+
positions[i * 6 + 4] = segment.end?.y || 0;
|
|
3223
|
+
positions[i * 6 + 5] = segment.end?.z || 0;
|
|
3216
3224
|
colors[i * 6 + 0] = segment.color.r;
|
|
3217
3225
|
colors[i * 6 + 1] = segment.color.g;
|
|
3218
3226
|
colors[i * 6 + 2] = segment.color.b;
|
|
@@ -3247,7 +3255,10 @@ class SegmentObject {
|
|
|
3247
3255
|
this.end = new THREE.Vector3(0, 0, 0);
|
|
3248
3256
|
}
|
|
3249
3257
|
}
|
|
3250
|
-
const normPos = (pos) =>
|
|
3258
|
+
const normPos = (pos) => {
|
|
3259
|
+
if (!pos) return new THREE.Vector3(0, 0, 0);
|
|
3260
|
+
return pos instanceof THREE.Vector3 ? pos : new THREE.Vector3(...typeof pos === "number" ? [pos, pos, pos] : pos);
|
|
3261
|
+
};
|
|
3251
3262
|
const Segment = /* @__PURE__ */ React.forwardRef(({ color, start, end }, forwardedRef) => {
|
|
3252
3263
|
const api = React.useContext(context$9);
|
|
3253
3264
|
if (!api) throw "Segment must used inside Segments component.";
|
|
@@ -3569,6 +3580,81 @@ const ArcballControls = /* @__PURE__ */ forwardRef(
|
|
|
3569
3580
|
}
|
|
3570
3581
|
);
|
|
3571
3582
|
|
|
3583
|
+
let DeviceOrientationControls$1 = class DeviceOrientationControls extends EventDispatcher {
|
|
3584
|
+
object;
|
|
3585
|
+
changeEvent = { type: "change" };
|
|
3586
|
+
EPS = 1e-6;
|
|
3587
|
+
enabled = true;
|
|
3588
|
+
deviceOrientation = { alpha: 0, beta: 0, gamma: 0 };
|
|
3589
|
+
screenOrientation = 0;
|
|
3590
|
+
alphaOffset = 0;
|
|
3591
|
+
// radians
|
|
3592
|
+
constructor(object) {
|
|
3593
|
+
super();
|
|
3594
|
+
this.object = object;
|
|
3595
|
+
this.object.rotation.reorder("YXZ");
|
|
3596
|
+
this.connect();
|
|
3597
|
+
}
|
|
3598
|
+
onDeviceOrientationChangeEvent = (event) => {
|
|
3599
|
+
this.deviceOrientation = event;
|
|
3600
|
+
};
|
|
3601
|
+
onScreenOrientationChangeEvent = () => {
|
|
3602
|
+
this.screenOrientation = window.orientation || 0;
|
|
3603
|
+
};
|
|
3604
|
+
// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
|
|
3605
|
+
zee = new Vector3(0, 0, 1);
|
|
3606
|
+
euler = new Euler();
|
|
3607
|
+
q0 = new Quaternion();
|
|
3608
|
+
q1 = new Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
|
|
3609
|
+
// - PI/2 around the x-axis
|
|
3610
|
+
setObjectQuaternion = (quaternion, alpha, beta, gamma, orient) => {
|
|
3611
|
+
this.euler.set(beta, alpha, -gamma, "YXZ");
|
|
3612
|
+
quaternion.setFromEuler(this.euler);
|
|
3613
|
+
quaternion.multiply(this.q1);
|
|
3614
|
+
quaternion.multiply(this.q0.setFromAxisAngle(this.zee, -orient));
|
|
3615
|
+
};
|
|
3616
|
+
connect = () => {
|
|
3617
|
+
this.onScreenOrientationChangeEvent();
|
|
3618
|
+
if (window.DeviceOrientationEvent !== void 0 && // @ts-ignore
|
|
3619
|
+
typeof window.DeviceOrientationEvent.requestPermission === "function") {
|
|
3620
|
+
window.DeviceOrientationEvent.requestPermission().then((response) => {
|
|
3621
|
+
if (response == "granted") {
|
|
3622
|
+
window.addEventListener("orientationchange", this.onScreenOrientationChangeEvent);
|
|
3623
|
+
window.addEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
|
|
3624
|
+
}
|
|
3625
|
+
}).catch((error) => {
|
|
3626
|
+
console.error("THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:", error);
|
|
3627
|
+
});
|
|
3628
|
+
} else {
|
|
3629
|
+
window.addEventListener("orientationchange", this.onScreenOrientationChangeEvent);
|
|
3630
|
+
window.addEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
|
|
3631
|
+
}
|
|
3632
|
+
this.enabled = true;
|
|
3633
|
+
};
|
|
3634
|
+
disconnect = () => {
|
|
3635
|
+
window.removeEventListener("orientationchange", this.onScreenOrientationChangeEvent);
|
|
3636
|
+
window.removeEventListener("deviceorientation", this.onDeviceOrientationChangeEvent);
|
|
3637
|
+
this.enabled = false;
|
|
3638
|
+
};
|
|
3639
|
+
lastQuaternion = new Quaternion();
|
|
3640
|
+
update = () => {
|
|
3641
|
+
if (this.enabled === false) return;
|
|
3642
|
+
const device = this.deviceOrientation;
|
|
3643
|
+
if (device) {
|
|
3644
|
+
const alpha = device.alpha ? MathUtils.degToRad(device.alpha) + this.alphaOffset : 0;
|
|
3645
|
+
const beta = device.beta ? MathUtils.degToRad(device.beta) : 0;
|
|
3646
|
+
const gamma = device.gamma ? MathUtils.degToRad(device.gamma) : 0;
|
|
3647
|
+
const orient = this.screenOrientation ? MathUtils.degToRad(this.screenOrientation) : 0;
|
|
3648
|
+
this.setObjectQuaternion(this.object.quaternion, alpha, beta, gamma, orient);
|
|
3649
|
+
if (8 * (1 - this.lastQuaternion.dot(this.object.quaternion)) > this.EPS) {
|
|
3650
|
+
this.lastQuaternion.copy(this.object.quaternion);
|
|
3651
|
+
this.dispatchEvent(this.changeEvent);
|
|
3652
|
+
}
|
|
3653
|
+
}
|
|
3654
|
+
};
|
|
3655
|
+
dispose = () => this.disconnect();
|
|
3656
|
+
};
|
|
3657
|
+
|
|
3572
3658
|
const DeviceOrientationControls = /* @__PURE__ */ React.forwardRef(
|
|
3573
3659
|
(props, ref) => {
|
|
3574
3660
|
const { camera, onChange, makeDefault, ...rest } = props;
|
|
@@ -3638,8 +3724,9 @@ const DragControls = React.forwardRef(
|
|
|
3638
3724
|
onDragStart && onDragStart(initialModelPosition);
|
|
3639
3725
|
invalidate();
|
|
3640
3726
|
},
|
|
3641
|
-
onDrag: ({ xy: [dragX, dragY], intentional }) => {
|
|
3727
|
+
onDrag: ({ xy: [dragX, dragY], intentional, event }) => {
|
|
3642
3728
|
if (!intentional) return;
|
|
3729
|
+
if (dragConfig && dragConfig.preventOverlap) event.preventDefault();
|
|
3643
3730
|
const normalizedMouseX = (dragX - size.left) / size.width * 2 - 1;
|
|
3644
3731
|
const normalizedMouseY = -((dragY - size.top) / size.height) * 2 + 1;
|
|
3645
3732
|
mousePosition2D.set(normalizedMouseX, normalizedMouseY);
|
|
@@ -3808,12 +3895,21 @@ function KeyboardControls({ map, children, onChange, domElement }) {
|
|
|
3808
3895
|
obj.pressed = false;
|
|
3809
3896
|
if (up) fn(false);
|
|
3810
3897
|
};
|
|
3898
|
+
const blurHandler = () => {
|
|
3899
|
+
const resetState = map.reduce((prev, cur) => ({ ...prev, [cur.name]: false }), {});
|
|
3900
|
+
set(resetState);
|
|
3901
|
+
Object.values(keyMap).forEach((obj) => {
|
|
3902
|
+
obj.pressed = false;
|
|
3903
|
+
});
|
|
3904
|
+
};
|
|
3811
3905
|
const source = domElement || window;
|
|
3812
3906
|
source.addEventListener("keydown", downHandler, { passive: true });
|
|
3813
3907
|
source.addEventListener("keyup", upHandler, { passive: true });
|
|
3908
|
+
window.addEventListener("blur", blurHandler);
|
|
3814
3909
|
return () => {
|
|
3815
3910
|
source.removeEventListener("keydown", downHandler);
|
|
3816
3911
|
source.removeEventListener("keyup", upHandler);
|
|
3912
|
+
window.removeEventListener("blur", blurHandler);
|
|
3817
3913
|
};
|
|
3818
3914
|
}, [domElement, key]);
|
|
3819
3915
|
return /* @__PURE__ */ React.createElement(context$8.Provider, { value: api, children });
|
|
@@ -4164,7 +4260,13 @@ function PresentationControls({
|
|
|
4164
4260
|
return /* @__PURE__ */ React.createElement("group", { ref, ...bind?.() }, children);
|
|
4165
4261
|
}
|
|
4166
4262
|
|
|
4263
|
+
function roundToPixelRatio(value) {
|
|
4264
|
+
const ratio = window.devicePixelRatio || 1;
|
|
4265
|
+
return Math.round(value * ratio) / ratio;
|
|
4266
|
+
}
|
|
4267
|
+
|
|
4167
4268
|
const context$7 = /* @__PURE__ */ React.createContext(null);
|
|
4269
|
+
const rootCache = /* @__PURE__ */ new WeakMap();
|
|
4168
4270
|
function useScroll() {
|
|
4169
4271
|
return React.useContext(context$7);
|
|
4170
4272
|
}
|
|
@@ -4178,6 +4280,7 @@ function ScrollControls({
|
|
|
4178
4280
|
damping = 0.25,
|
|
4179
4281
|
maxSpeed = Infinity,
|
|
4180
4282
|
prepend = false,
|
|
4283
|
+
pixelPerfect = true,
|
|
4181
4284
|
style = {},
|
|
4182
4285
|
children
|
|
4183
4286
|
}) {
|
|
@@ -4199,6 +4302,7 @@ function ScrollControls({
|
|
|
4199
4302
|
delta: 0,
|
|
4200
4303
|
scroll,
|
|
4201
4304
|
pages,
|
|
4305
|
+
pixelPerfect,
|
|
4202
4306
|
// 0-1 for a range between from -> from + distance
|
|
4203
4307
|
range(from, distance2, margin = 0) {
|
|
4204
4308
|
const start = from - margin;
|
|
@@ -4217,7 +4321,7 @@ function ScrollControls({
|
|
|
4217
4321
|
}
|
|
4218
4322
|
};
|
|
4219
4323
|
return state2;
|
|
4220
|
-
}, [eps, damping, horizontal, pages]);
|
|
4324
|
+
}, [eps, damping, horizontal, pages, pixelPerfect]);
|
|
4221
4325
|
React.useEffect(() => {
|
|
4222
4326
|
el.style.position = "absolute";
|
|
4223
4327
|
el.style.width = "100%";
|
|
@@ -4330,10 +4434,23 @@ const ScrollHtml = React.forwardRef(
|
|
|
4330
4434
|
React.useImperativeHandle(ref, () => group.current, []);
|
|
4331
4435
|
const { width, height } = useThree((state2) => state2.size);
|
|
4332
4436
|
const fiberState = React.useContext(context$a);
|
|
4333
|
-
const root = React.useMemo(() =>
|
|
4437
|
+
const root = React.useMemo(() => {
|
|
4438
|
+
let root2 = rootCache.get(state.fixed);
|
|
4439
|
+
if (!root2) {
|
|
4440
|
+
root2 = ReactDOM.createRoot(state.fixed);
|
|
4441
|
+
rootCache.set(state.fixed, root2);
|
|
4442
|
+
}
|
|
4443
|
+
return root2;
|
|
4444
|
+
}, [state.fixed]);
|
|
4334
4445
|
useFrame(() => {
|
|
4335
4446
|
if (state.delta > state.eps) {
|
|
4336
|
-
|
|
4447
|
+
let x = state.horizontal ? -width * (state.pages - 1) * state.offset : 0;
|
|
4448
|
+
let y = state.horizontal ? 0 : height * (state.pages - 1) * -state.offset;
|
|
4449
|
+
if (state.pixelPerfect) {
|
|
4450
|
+
x = roundToPixelRatio(x);
|
|
4451
|
+
y = roundToPixelRatio(y);
|
|
4452
|
+
}
|
|
4453
|
+
group.current.style.transform = `translate3d(${x}px,${y}px,0)`;
|
|
4337
4454
|
}
|
|
4338
4455
|
});
|
|
4339
4456
|
root.render(
|
|
@@ -5262,460 +5379,89 @@ const Text3D = /* @__PURE__ */ React.forwardRef(
|
|
|
5262
5379
|
}
|
|
5263
5380
|
);
|
|
5264
5381
|
|
|
5265
|
-
const
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
)
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
if (barycentric.y < barycentric.x && barycentric.y < barycentric.z) {
|
|
5349
|
-
positionAlong = 1.0 - positionAlong;
|
|
5350
|
-
}
|
|
5351
|
-
|
|
5352
|
-
// the thickness of the stroke
|
|
5353
|
-
float computedThickness = wireframe_map(thickness, 0.0, 1.0, 0.0, 0.34);
|
|
5354
|
-
|
|
5355
|
-
// if we want to shrink the thickness toward the center of the line segment
|
|
5356
|
-
if (squeeze) {
|
|
5357
|
-
computedThickness *= mix(squeezeMin, squeezeMax, (1.0 - sin(positionAlong * PI)));
|
|
5358
|
-
}
|
|
5359
|
-
|
|
5360
|
-
// Create dash pattern
|
|
5361
|
-
if (dash) {
|
|
5362
|
-
// here we offset the stroke position depending on whether it
|
|
5363
|
-
// should overlap or not
|
|
5364
|
-
float offset = 1.0 / dashRepeats * dashLength / 2.0;
|
|
5365
|
-
if (!dashInvert) {
|
|
5366
|
-
offset += 1.0 / dashRepeats / 2.0;
|
|
5367
|
-
}
|
|
5368
|
-
|
|
5369
|
-
// if we should animate the dash or not
|
|
5370
|
-
// if (dashAnimate) {
|
|
5371
|
-
// offset += time * 0.22;
|
|
5372
|
-
// }
|
|
5373
|
-
|
|
5374
|
-
// create the repeating dash pattern
|
|
5375
|
-
float pattern = fract((positionAlong + offset) * dashRepeats);
|
|
5376
|
-
computedThickness *= 1.0 - wireframe_aastep(dashLength, pattern);
|
|
5377
|
-
}
|
|
5378
|
-
|
|
5379
|
-
// compute the anti-aliased stroke edge
|
|
5380
|
-
float edge = 1.0 - wireframe_aastep(computedThickness, d);
|
|
5381
|
-
|
|
5382
|
-
return edge;
|
|
5383
|
-
}
|
|
5384
|
-
`
|
|
5385
|
-
)
|
|
5386
|
-
};
|
|
5387
|
-
const WireframeMaterial = /* @__PURE__ */ shaderMaterial(
|
|
5388
|
-
WireframeMaterialShaders.uniforms,
|
|
5389
|
-
WireframeMaterialShaders.vertex + /* glsl */
|
|
5390
|
-
`
|
|
5391
|
-
void main() {
|
|
5392
|
-
initWireframe();
|
|
5393
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
5394
|
-
}
|
|
5395
|
-
`,
|
|
5396
|
-
WireframeMaterialShaders.fragment + /* glsl */
|
|
5397
|
-
`
|
|
5398
|
-
void main () {
|
|
5399
|
-
// Compute color
|
|
5400
|
-
|
|
5401
|
-
float edge = getWireframe();
|
|
5402
|
-
vec4 colorStroke = vec4(stroke, edge);
|
|
5403
|
-
|
|
5404
|
-
#ifdef FLIP_SIDED
|
|
5405
|
-
colorStroke.rgb = backfaceStroke;
|
|
5406
|
-
#endif
|
|
5407
|
-
|
|
5408
|
-
vec4 colorFill = vec4(fill, fillOpacity);
|
|
5409
|
-
vec4 outColor = mix(colorFill, colorStroke, edge * strokeOpacity);
|
|
5410
|
-
|
|
5411
|
-
gl_FragColor = outColor;
|
|
5412
|
-
}
|
|
5413
|
-
`
|
|
5414
|
-
);
|
|
5415
|
-
function setWireframeOverride(material, uniforms) {
|
|
5416
|
-
material.onBeforeCompile = (shader) => {
|
|
5417
|
-
shader.uniforms = {
|
|
5418
|
-
...shader.uniforms,
|
|
5419
|
-
...uniforms
|
|
5420
|
-
};
|
|
5421
|
-
shader.vertexShader = shader.vertexShader.replace(
|
|
5422
|
-
"void main() {",
|
|
5423
|
-
`
|
|
5424
|
-
${WireframeMaterialShaders.vertex}
|
|
5425
|
-
void main() {
|
|
5426
|
-
initWireframe();
|
|
5427
|
-
`
|
|
5428
|
-
);
|
|
5429
|
-
shader.fragmentShader = shader.fragmentShader.replace(
|
|
5430
|
-
"void main() {",
|
|
5431
|
-
`
|
|
5432
|
-
${WireframeMaterialShaders.fragment}
|
|
5433
|
-
void main() {
|
|
5434
|
-
`
|
|
5435
|
-
);
|
|
5436
|
-
shader.fragmentShader = shader.fragmentShader.replace(
|
|
5437
|
-
"#include <color_fragment>",
|
|
5438
|
-
/* glsl */
|
|
5439
|
-
`
|
|
5440
|
-
#include <color_fragment>
|
|
5441
|
-
float edge = getWireframe();
|
|
5442
|
-
vec4 colorStroke = vec4(stroke, edge);
|
|
5443
|
-
#ifdef FLIP_SIDED
|
|
5444
|
-
colorStroke.rgb = backfaceStroke;
|
|
5445
|
-
#endif
|
|
5446
|
-
vec4 colorFill = vec4(mix(diffuseColor.rgb, fill, fillMix), mix(diffuseColor.a, fillOpacity, fillMix));
|
|
5447
|
-
vec4 outColor = mix(colorFill, colorStroke, edge * strokeOpacity);
|
|
5448
|
-
|
|
5449
|
-
diffuseColor.rgb = outColor.rgb;
|
|
5450
|
-
diffuseColor.a *= outColor.a;
|
|
5451
|
-
`
|
|
5452
|
-
);
|
|
5453
|
-
};
|
|
5454
|
-
material.side = THREE.DoubleSide;
|
|
5455
|
-
material.transparent = true;
|
|
5456
|
-
}
|
|
5457
|
-
function useWireframeUniforms(uniforms, props) {
|
|
5458
|
-
React.useEffect(
|
|
5459
|
-
() => void (uniforms.fillOpacity.value = props.fillOpacity ?? uniforms.fillOpacity.value),
|
|
5460
|
-
[props.fillOpacity]
|
|
5461
|
-
);
|
|
5462
|
-
React.useEffect(() => void (uniforms.fillMix.value = props.fillMix ?? uniforms.fillMix.value), [props.fillMix]);
|
|
5463
|
-
React.useEffect(
|
|
5464
|
-
() => void (uniforms.strokeOpacity.value = props.strokeOpacity ?? uniforms.strokeOpacity.value),
|
|
5465
|
-
[props.strokeOpacity]
|
|
5466
|
-
);
|
|
5467
|
-
React.useEffect(
|
|
5468
|
-
() => void (uniforms.thickness.value = props.thickness ?? uniforms.thickness.value),
|
|
5469
|
-
[props.thickness]
|
|
5470
|
-
);
|
|
5471
|
-
React.useEffect(() => void (uniforms.colorBackfaces.value = !!props.colorBackfaces), [props.colorBackfaces]);
|
|
5472
|
-
React.useEffect(() => void (uniforms.dash.value = !!props.dash), [props.dash]);
|
|
5473
|
-
React.useEffect(() => void (uniforms.dashInvert.value = !!props.dashInvert), [props.dashInvert]);
|
|
5474
|
-
React.useEffect(
|
|
5475
|
-
() => void (uniforms.dashRepeats.value = props.dashRepeats ?? uniforms.dashRepeats.value),
|
|
5476
|
-
[props.dashRepeats]
|
|
5477
|
-
);
|
|
5478
|
-
React.useEffect(
|
|
5479
|
-
() => void (uniforms.dashLength.value = props.dashLength ?? uniforms.dashLength.value),
|
|
5480
|
-
[props.dashLength]
|
|
5481
|
-
);
|
|
5482
|
-
React.useEffect(() => void (uniforms.squeeze.value = !!props.squeeze), [props.squeeze]);
|
|
5483
|
-
React.useEffect(
|
|
5484
|
-
() => void (uniforms.squeezeMin.value = props.squeezeMin ?? uniforms.squeezeMin.value),
|
|
5485
|
-
[props.squeezeMin]
|
|
5486
|
-
);
|
|
5487
|
-
React.useEffect(
|
|
5488
|
-
() => void (uniforms.squeezeMax.value = props.squeezeMax ?? uniforms.squeezeMax.value),
|
|
5489
|
-
[props.squeezeMax]
|
|
5490
|
-
);
|
|
5491
|
-
React.useEffect(
|
|
5492
|
-
() => void (uniforms.stroke.value = props.stroke ? new THREE.Color(props.stroke) : uniforms.stroke.value),
|
|
5493
|
-
[props.stroke]
|
|
5494
|
-
);
|
|
5495
|
-
React.useEffect(
|
|
5496
|
-
() => void (uniforms.fill.value = props.fill ? new THREE.Color(props.fill) : uniforms.fill.value),
|
|
5497
|
-
[props.fill]
|
|
5498
|
-
);
|
|
5499
|
-
React.useEffect(
|
|
5500
|
-
() => void (uniforms.backfaceStroke.value = props.backfaceStroke ? new THREE.Color(props.backfaceStroke) : uniforms.backfaceStroke.value),
|
|
5501
|
-
[props.backfaceStroke]
|
|
5502
|
-
);
|
|
5503
|
-
}
|
|
5504
|
-
|
|
5505
|
-
function isWithGeometry(object) {
|
|
5506
|
-
return !!object?.geometry;
|
|
5507
|
-
}
|
|
5508
|
-
function isGeometry(object) {
|
|
5509
|
-
return !!object?.isBufferGeometry;
|
|
5510
|
-
}
|
|
5511
|
-
function isRefObject$1(object) {
|
|
5512
|
-
return !!object?.current;
|
|
5513
|
-
}
|
|
5514
|
-
function isRef$1(object) {
|
|
5515
|
-
return object?.current !== void 0;
|
|
5516
|
-
}
|
|
5517
|
-
function isWireframeGeometry(geometry) {
|
|
5518
|
-
return geometry.type === "WireframeGeometry";
|
|
5519
|
-
}
|
|
5520
|
-
function getUniforms() {
|
|
5521
|
-
const u = {};
|
|
5522
|
-
for (const key in WireframeMaterialShaders.uniforms) {
|
|
5523
|
-
u[key] = { value: WireframeMaterialShaders.uniforms[key] };
|
|
5524
|
-
}
|
|
5525
|
-
return u;
|
|
5526
|
-
}
|
|
5527
|
-
function getBarycentricCoordinates(geometry, removeEdge) {
|
|
5528
|
-
const position = geometry.getAttribute("position");
|
|
5529
|
-
const count = position.count;
|
|
5530
|
-
const barycentric = [];
|
|
5531
|
-
for (let i = 0; i < count; i++) {
|
|
5532
|
-
const even = i % 2 === 0;
|
|
5533
|
-
const Q = removeEdge ? 1 : 0;
|
|
5534
|
-
if (even) {
|
|
5535
|
-
barycentric.push(0, 0, 1, 0, 1, 0, 1, 0, Q);
|
|
5536
|
-
} else {
|
|
5537
|
-
barycentric.push(0, 1, 0, 0, 0, 1, 1, 0, Q);
|
|
5538
|
-
}
|
|
5539
|
-
}
|
|
5540
|
-
return new THREE.BufferAttribute(Float32Array.from(barycentric), 3);
|
|
5541
|
-
}
|
|
5542
|
-
function getInputGeometry(inputGeometry) {
|
|
5543
|
-
const geo = isRefObject$1(inputGeometry) ? inputGeometry.current : inputGeometry;
|
|
5544
|
-
if (!isGeometry(geo)) {
|
|
5545
|
-
if (isWireframeGeometry(geo)) {
|
|
5546
|
-
throw new Error("Wireframe: WireframeGeometry is not supported.");
|
|
5547
|
-
}
|
|
5548
|
-
const parent = geo.parent;
|
|
5549
|
-
if (isWithGeometry(parent)) {
|
|
5550
|
-
if (isWireframeGeometry(parent.geometry)) {
|
|
5551
|
-
throw new Error("Wireframe: WireframeGeometry is not supported.");
|
|
5552
|
-
}
|
|
5553
|
-
return parent.geometry;
|
|
5554
|
-
}
|
|
5555
|
-
} else {
|
|
5556
|
-
return geo;
|
|
5557
|
-
}
|
|
5558
|
-
}
|
|
5559
|
-
function setBarycentricCoordinates(geometry, simplify) {
|
|
5560
|
-
if (geometry.index) {
|
|
5561
|
-
console.warn("Wireframe: Requires non-indexed geometry, converting to non-indexed geometry.");
|
|
5562
|
-
const nonIndexedGeo = geometry.toNonIndexed();
|
|
5563
|
-
geometry.copy(nonIndexedGeo);
|
|
5564
|
-
geometry.setIndex(null);
|
|
5565
|
-
}
|
|
5566
|
-
const newBarycentric = getBarycentricCoordinates(geometry, simplify);
|
|
5567
|
-
geometry.setAttribute("barycentric", newBarycentric);
|
|
5568
|
-
}
|
|
5569
|
-
function WireframeWithCustomGeo({
|
|
5570
|
-
geometry: customGeometry,
|
|
5571
|
-
simplify = false,
|
|
5572
|
-
...props
|
|
5573
|
-
}) {
|
|
5574
|
-
extend({ MeshWireframeMaterial: WireframeMaterial });
|
|
5575
|
-
const [geometry, setGeometry] = React.useState(null);
|
|
5576
|
-
React.useLayoutEffect(() => {
|
|
5577
|
-
const geom = getInputGeometry(customGeometry);
|
|
5578
|
-
if (!geom) {
|
|
5579
|
-
throw new Error("Wireframe: geometry prop must be a BufferGeometry or a ref to a BufferGeometry.");
|
|
5580
|
-
}
|
|
5581
|
-
setBarycentricCoordinates(geom, simplify);
|
|
5582
|
-
if (isRef$1(customGeometry)) {
|
|
5583
|
-
setGeometry(geom);
|
|
5584
|
-
}
|
|
5585
|
-
}, [simplify, customGeometry]);
|
|
5586
|
-
const drawnGeo = isRef$1(customGeometry) ? geometry : customGeometry;
|
|
5587
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, drawnGeo && /* @__PURE__ */ React.createElement("mesh", { geometry: drawnGeo }, /* @__PURE__ */ React.createElement(
|
|
5588
|
-
"meshWireframeMaterial",
|
|
5589
|
-
{
|
|
5590
|
-
attach: "material",
|
|
5591
|
-
transparent: true,
|
|
5592
|
-
side: THREE.DoubleSide,
|
|
5593
|
-
polygonOffset: true,
|
|
5594
|
-
polygonOffsetFactor: -4,
|
|
5595
|
-
...props
|
|
5596
|
-
}
|
|
5597
|
-
)));
|
|
5598
|
-
}
|
|
5599
|
-
function WireframeWithoutCustomGeo({
|
|
5600
|
-
simplify = false,
|
|
5601
|
-
...props
|
|
5602
|
-
}) {
|
|
5603
|
-
const objectRef = React.useRef(null);
|
|
5604
|
-
const uniforms = React.useMemo(() => getUniforms(), [WireframeMaterialShaders.uniforms]);
|
|
5605
|
-
useWireframeUniforms(uniforms, props);
|
|
5606
|
-
React.useLayoutEffect(() => {
|
|
5607
|
-
const geom = getInputGeometry(objectRef);
|
|
5608
|
-
if (!geom) {
|
|
5609
|
-
throw new Error("Wireframe: Must be a child of a Mesh, Line or Points object or specify a geometry prop.");
|
|
5610
|
-
}
|
|
5611
|
-
const og = geom.clone();
|
|
5612
|
-
setBarycentricCoordinates(geom, simplify);
|
|
5613
|
-
return () => {
|
|
5614
|
-
geom.copy(og);
|
|
5615
|
-
og.dispose();
|
|
5616
|
-
};
|
|
5617
|
-
}, [simplify]);
|
|
5618
|
-
React.useLayoutEffect(() => {
|
|
5619
|
-
const parentMesh = objectRef.current.parent;
|
|
5620
|
-
const og = parentMesh.material.clone();
|
|
5621
|
-
setWireframeOverride(parentMesh.material, uniforms);
|
|
5622
|
-
return () => {
|
|
5623
|
-
parentMesh.material.dispose();
|
|
5624
|
-
parentMesh.material = og;
|
|
5625
|
-
};
|
|
5626
|
-
}, []);
|
|
5627
|
-
return /* @__PURE__ */ React.createElement("object3D", { ref: objectRef });
|
|
5628
|
-
}
|
|
5629
|
-
function Wireframe({ geometry: customGeometry, ...props }) {
|
|
5630
|
-
if (customGeometry) {
|
|
5631
|
-
return /* @__PURE__ */ React.createElement(WireframeWithCustomGeo, { geometry: customGeometry, ...props });
|
|
5632
|
-
}
|
|
5633
|
-
return /* @__PURE__ */ React.createElement(WireframeWithoutCustomGeo, { ...props });
|
|
5634
|
-
}
|
|
5635
|
-
|
|
5636
|
-
const Context = /* @__PURE__ */ React.createContext({});
|
|
5637
|
-
const useGizmoContext = () => {
|
|
5638
|
-
return React.useContext(Context);
|
|
5639
|
-
};
|
|
5640
|
-
const turnRate = 2 * Math.PI;
|
|
5641
|
-
const dummy = /* @__PURE__ */ new Object3D();
|
|
5642
|
-
const matrix = /* @__PURE__ */ new Matrix4();
|
|
5643
|
-
const [q1, q2] = [/* @__PURE__ */ new Quaternion(), /* @__PURE__ */ new Quaternion()];
|
|
5644
|
-
const target = /* @__PURE__ */ new Vector3();
|
|
5645
|
-
const targetPosition = /* @__PURE__ */ new Vector3();
|
|
5646
|
-
const isOrbitControls = (controls) => {
|
|
5647
|
-
return "minPolarAngle" in controls;
|
|
5648
|
-
};
|
|
5649
|
-
const isCameraControls = (controls) => {
|
|
5650
|
-
return "getTarget" in controls;
|
|
5651
|
-
};
|
|
5652
|
-
const GizmoHelper = ({
|
|
5653
|
-
alignment = "bottom-right",
|
|
5654
|
-
margin = [80, 80],
|
|
5655
|
-
renderPriority = 1,
|
|
5656
|
-
onUpdate,
|
|
5657
|
-
onTarget,
|
|
5658
|
-
children
|
|
5659
|
-
}) => {
|
|
5660
|
-
const size = useThree((state) => state.size);
|
|
5661
|
-
const mainCamera = useThree((state) => state.camera);
|
|
5662
|
-
const defaultControls = useThree((state) => state.controls);
|
|
5663
|
-
const invalidate = useThree((state) => state.invalidate);
|
|
5664
|
-
const gizmoRef = React.useRef(null);
|
|
5665
|
-
const virtualCam = React.useRef(null);
|
|
5666
|
-
const animating = React.useRef(false);
|
|
5667
|
-
const radius = React.useRef(0);
|
|
5668
|
-
const focusPoint = React.useRef(new Vector3(0, 0, 0));
|
|
5669
|
-
const defaultUp = React.useRef(new Vector3(0, 0, 0));
|
|
5670
|
-
React.useEffect(() => {
|
|
5671
|
-
defaultUp.current.copy(mainCamera.up);
|
|
5672
|
-
dummy.up.copy(mainCamera.up);
|
|
5673
|
-
}, [mainCamera]);
|
|
5674
|
-
const tweenCamera = React.useCallback(
|
|
5675
|
-
(direction) => {
|
|
5676
|
-
animating.current = true;
|
|
5677
|
-
if (defaultControls || onTarget) {
|
|
5678
|
-
focusPoint.current = onTarget?.() || (isCameraControls(defaultControls) ? defaultControls.getTarget(focusPoint.current) : defaultControls?.target);
|
|
5679
|
-
}
|
|
5680
|
-
radius.current = mainCamera.position.distanceTo(target);
|
|
5681
|
-
q1.copy(mainCamera.quaternion);
|
|
5682
|
-
targetPosition.copy(direction).multiplyScalar(radius.current).add(target);
|
|
5683
|
-
dummy.lookAt(targetPosition);
|
|
5684
|
-
q2.copy(dummy.quaternion);
|
|
5685
|
-
invalidate();
|
|
5686
|
-
},
|
|
5687
|
-
[defaultControls, mainCamera, onTarget, invalidate]
|
|
5688
|
-
);
|
|
5689
|
-
useFrame((_, delta) => {
|
|
5690
|
-
if (virtualCam.current && gizmoRef.current) {
|
|
5691
|
-
if (animating.current) {
|
|
5692
|
-
if (q1.angleTo(q2) < 0.01) {
|
|
5693
|
-
animating.current = false;
|
|
5694
|
-
if (isOrbitControls(defaultControls)) {
|
|
5695
|
-
mainCamera.up.copy(defaultUp.current);
|
|
5696
|
-
}
|
|
5697
|
-
} else {
|
|
5698
|
-
const step = delta * turnRate;
|
|
5699
|
-
q1.rotateTowards(q2, step);
|
|
5700
|
-
mainCamera.position.set(0, 0, 1).applyQuaternion(q1).multiplyScalar(radius.current).add(focusPoint.current);
|
|
5701
|
-
mainCamera.up.set(0, 1, 0).applyQuaternion(q1).normalize();
|
|
5702
|
-
mainCamera.quaternion.copy(q1);
|
|
5703
|
-
if (isCameraControls(defaultControls))
|
|
5704
|
-
defaultControls.setPosition(mainCamera.position.x, mainCamera.position.y, mainCamera.position.z);
|
|
5705
|
-
if (onUpdate) onUpdate();
|
|
5706
|
-
else if (defaultControls) defaultControls.update(delta);
|
|
5707
|
-
invalidate();
|
|
5708
|
-
}
|
|
5709
|
-
}
|
|
5710
|
-
matrix.copy(mainCamera.matrix).invert();
|
|
5711
|
-
gizmoRef.current?.quaternion.setFromRotationMatrix(matrix);
|
|
5712
|
-
}
|
|
5713
|
-
});
|
|
5714
|
-
const gizmoHelperContext = React.useMemo(() => ({ tweenCamera }), [tweenCamera]);
|
|
5715
|
-
const [marginX, marginY] = margin;
|
|
5716
|
-
const x = alignment.endsWith("-center") ? 0 : alignment.endsWith("-left") ? -size.width / 2 + marginX : size.width / 2 - marginX;
|
|
5717
|
-
const y = alignment.startsWith("center-") ? 0 : alignment.startsWith("top-") ? size.height / 2 - marginY : -size.height / 2 + marginY;
|
|
5718
|
-
return /* @__PURE__ */ React.createElement(Hud$1, { renderPriority }, /* @__PURE__ */ React.createElement(Context.Provider, { value: gizmoHelperContext }, /* @__PURE__ */ React.createElement(OrthographicCamera, { makeDefault: true, ref: virtualCam, position: [0, 0, 200] }), /* @__PURE__ */ React.createElement("group", { ref: gizmoRef, position: [x, y, 0] }, children)));
|
|
5382
|
+
const Context = /* @__PURE__ */ React.createContext({});
|
|
5383
|
+
const useGizmoContext = () => {
|
|
5384
|
+
return React.useContext(Context);
|
|
5385
|
+
};
|
|
5386
|
+
const turnRate = 2 * Math.PI;
|
|
5387
|
+
const dummy = /* @__PURE__ */ new Object3D();
|
|
5388
|
+
const matrix = /* @__PURE__ */ new Matrix4();
|
|
5389
|
+
const [q1, q2] = [/* @__PURE__ */ new Quaternion(), /* @__PURE__ */ new Quaternion()];
|
|
5390
|
+
const target = /* @__PURE__ */ new Vector3();
|
|
5391
|
+
const targetPosition = /* @__PURE__ */ new Vector3();
|
|
5392
|
+
const isOrbitControls = (controls) => {
|
|
5393
|
+
return "minPolarAngle" in controls;
|
|
5394
|
+
};
|
|
5395
|
+
const isCameraControls = (controls) => {
|
|
5396
|
+
return "getTarget" in controls;
|
|
5397
|
+
};
|
|
5398
|
+
const GizmoHelper = ({
|
|
5399
|
+
alignment = "bottom-right",
|
|
5400
|
+
margin = [80, 80],
|
|
5401
|
+
renderPriority = 1,
|
|
5402
|
+
onUpdate,
|
|
5403
|
+
onTarget,
|
|
5404
|
+
children
|
|
5405
|
+
}) => {
|
|
5406
|
+
const size = useThree((state) => state.size);
|
|
5407
|
+
const mainCamera = useThree((state) => state.camera);
|
|
5408
|
+
const defaultControls = useThree((state) => state.controls);
|
|
5409
|
+
const invalidate = useThree((state) => state.invalidate);
|
|
5410
|
+
const gizmoRef = React.useRef(null);
|
|
5411
|
+
const virtualCam = React.useRef(null);
|
|
5412
|
+
const animating = React.useRef(false);
|
|
5413
|
+
const radius = React.useRef(0);
|
|
5414
|
+
const focusPoint = React.useRef(new Vector3(0, 0, 0));
|
|
5415
|
+
const defaultUp = React.useRef(new Vector3(0, 0, 0));
|
|
5416
|
+
React.useEffect(() => {
|
|
5417
|
+
defaultUp.current.copy(mainCamera.up);
|
|
5418
|
+
dummy.up.copy(mainCamera.up);
|
|
5419
|
+
}, [mainCamera]);
|
|
5420
|
+
const tweenCamera = React.useCallback(
|
|
5421
|
+
(direction) => {
|
|
5422
|
+
animating.current = true;
|
|
5423
|
+
if (defaultControls || onTarget) {
|
|
5424
|
+
focusPoint.current = onTarget?.() || (isCameraControls(defaultControls) ? defaultControls.getTarget(focusPoint.current) : defaultControls?.target);
|
|
5425
|
+
}
|
|
5426
|
+
radius.current = mainCamera.position.distanceTo(target);
|
|
5427
|
+
q1.copy(mainCamera.quaternion);
|
|
5428
|
+
targetPosition.copy(direction).multiplyScalar(radius.current).add(target);
|
|
5429
|
+
dummy.lookAt(targetPosition);
|
|
5430
|
+
q2.copy(dummy.quaternion);
|
|
5431
|
+
invalidate();
|
|
5432
|
+
},
|
|
5433
|
+
[defaultControls, mainCamera, onTarget, invalidate]
|
|
5434
|
+
);
|
|
5435
|
+
useFrame((_, delta) => {
|
|
5436
|
+
if (virtualCam.current && gizmoRef.current) {
|
|
5437
|
+
if (animating.current) {
|
|
5438
|
+
if (q1.angleTo(q2) < 0.01) {
|
|
5439
|
+
animating.current = false;
|
|
5440
|
+
if (isOrbitControls(defaultControls)) {
|
|
5441
|
+
mainCamera.up.copy(defaultUp.current);
|
|
5442
|
+
}
|
|
5443
|
+
} else {
|
|
5444
|
+
const step = delta * turnRate;
|
|
5445
|
+
q1.rotateTowards(q2, step);
|
|
5446
|
+
mainCamera.position.set(0, 0, 1).applyQuaternion(q1).multiplyScalar(radius.current).add(focusPoint.current);
|
|
5447
|
+
mainCamera.up.set(0, 1, 0).applyQuaternion(q1).normalize();
|
|
5448
|
+
mainCamera.quaternion.copy(q1);
|
|
5449
|
+
if (isCameraControls(defaultControls))
|
|
5450
|
+
defaultControls.setPosition(mainCamera.position.x, mainCamera.position.y, mainCamera.position.z);
|
|
5451
|
+
if (onUpdate) onUpdate();
|
|
5452
|
+
else if (defaultControls) defaultControls.update(delta);
|
|
5453
|
+
invalidate();
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5456
|
+
matrix.copy(mainCamera.matrix).invert();
|
|
5457
|
+
gizmoRef.current?.quaternion.setFromRotationMatrix(matrix);
|
|
5458
|
+
}
|
|
5459
|
+
});
|
|
5460
|
+
const gizmoHelperContext = React.useMemo(() => ({ tweenCamera }), [tweenCamera]);
|
|
5461
|
+
const [marginX, marginY] = margin;
|
|
5462
|
+
const x = alignment.endsWith("-center") ? 0 : alignment.endsWith("-left") ? -size.width / 2 + marginX : size.width / 2 - marginX;
|
|
5463
|
+
const y = alignment.startsWith("center-") ? 0 : alignment.startsWith("top-") ? size.height / 2 - marginY : -size.height / 2 + marginY;
|
|
5464
|
+
return /* @__PURE__ */ React.createElement(Hud$1, { renderPriority }, /* @__PURE__ */ React.createElement(Context.Provider, { value: gizmoHelperContext }, /* @__PURE__ */ React.createElement(OrthographicCamera, { makeDefault: true, ref: virtualCam, position: [0, 0, 200] }), /* @__PURE__ */ React.createElement("group", { ref: gizmoRef, position: [x, y, 0] }, children)));
|
|
5719
5465
|
};
|
|
5720
5466
|
|
|
5721
5467
|
const colors = { bg: "#f0f0f0", hover: "#999", text: "black", stroke: "black" };
|
|
@@ -5928,6 +5674,11 @@ const GizmoViewport = ({
|
|
|
5928
5674
|
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 }))));
|
|
5929
5675
|
};
|
|
5930
5676
|
|
|
5677
|
+
const roundEven = (n) => {
|
|
5678
|
+
const rounded = Math.ceil(n);
|
|
5679
|
+
return rounded % 2 === 0 ? rounded : rounded + 1;
|
|
5680
|
+
};
|
|
5681
|
+
|
|
5931
5682
|
const v1 = /* @__PURE__ */ new Vector3();
|
|
5932
5683
|
const v2 = /* @__PURE__ */ new Vector3();
|
|
5933
5684
|
const v3 = /* @__PURE__ */ new Vector3();
|
|
@@ -5999,7 +5750,7 @@ const getCameraCSSMatrix = /* @__PURE__ */ ((multipliers) => {
|
|
|
5999
5750
|
const getObjectCSSMatrix = /* @__PURE__ */ ((scaleMultipliers) => {
|
|
6000
5751
|
return (matrix, factor) => getCSSMatrix(matrix, scaleMultipliers(factor), "translate(-50%,-50%)");
|
|
6001
5752
|
})((f) => [1 / f, 1 / f, 1 / f, 1, -1 / f, -1 / f, -1 / f, -1, 1 / f, 1 / f, 1 / f, 1, 1, 1, 1, 1]);
|
|
6002
|
-
function isRefObject(ref) {
|
|
5753
|
+
function isRefObject$1(ref) {
|
|
6003
5754
|
return ref && typeof ref === "object" && "current" in ref;
|
|
6004
5755
|
}
|
|
6005
5756
|
const Html = /* @__PURE__ */ React.forwardRef(
|
|
@@ -6026,9 +5777,11 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
6026
5777
|
as = "div",
|
|
6027
5778
|
wrapperClass,
|
|
6028
5779
|
pointerEvents = "auto",
|
|
5780
|
+
pixelPerfect = true,
|
|
6029
5781
|
...props
|
|
6030
5782
|
}, ref) => {
|
|
6031
5783
|
const { gl, camera, scene, size, raycaster, events, viewport } = useThree();
|
|
5784
|
+
const forceEven = useThree((state) => state.internal.forceEven);
|
|
6032
5785
|
const [el] = React.useState(() => document.createElement(as));
|
|
6033
5786
|
const root = React.useRef(null);
|
|
6034
5787
|
const group = React.useRef(null);
|
|
@@ -6040,7 +5793,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
6040
5793
|
const occlusionMeshRef = React.useRef(null);
|
|
6041
5794
|
const isMeshSizeSet = React.useRef(false);
|
|
6042
5795
|
const isRayCastOcclusion = React.useMemo(() => {
|
|
6043
|
-
return occlude && occlude !== "blending" || Array.isArray(occlude) && occlude.length && isRefObject(occlude[0]);
|
|
5796
|
+
return occlude && occlude !== "blending" || Array.isArray(occlude) && occlude.length && isRefObject$1(occlude[0]);
|
|
6044
5797
|
}, [occlude]);
|
|
6045
5798
|
React.useLayoutEffect(() => {
|
|
6046
5799
|
const el2 = gl.domElement;
|
|
@@ -6053,38 +5806,54 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
6053
5806
|
el2.style.position = null;
|
|
6054
5807
|
el2.style.pointerEvents = null;
|
|
6055
5808
|
}
|
|
6056
|
-
}, [occlude]);
|
|
5809
|
+
}, [occlude, zIndexRange, gl.domElement]);
|
|
6057
5810
|
React.useLayoutEffect(() => {
|
|
6058
5811
|
if (group.current) {
|
|
6059
|
-
|
|
5812
|
+
if (!root.current) {
|
|
5813
|
+
root.current = ReactDOM.createRoot(el);
|
|
5814
|
+
}
|
|
6060
5815
|
scene.updateMatrixWorld();
|
|
6061
5816
|
if (transform) {
|
|
6062
5817
|
el.style.cssText = `position:absolute;top:0;left:0;pointer-events:none;overflow:hidden;`;
|
|
6063
5818
|
} else {
|
|
6064
|
-
|
|
6065
|
-
el.style.cssText = `position:absolute;top:0;left:0;transform:translate3d(${vec[0]}px,${vec[1]}px,0);transform-origin:0 0;`;
|
|
5819
|
+
el.style.cssText = `position:absolute;top:0;left:0;transform:translate3d(0,-9999px,0);transform-origin:0 0;`;
|
|
6066
5820
|
}
|
|
6067
5821
|
if (target) {
|
|
6068
5822
|
if (prepend) target.prepend(el);
|
|
6069
5823
|
else target.appendChild(el);
|
|
6070
5824
|
}
|
|
6071
5825
|
return () => {
|
|
6072
|
-
if (
|
|
6073
|
-
|
|
5826
|
+
if (root.current) {
|
|
5827
|
+
root.current.unmount();
|
|
5828
|
+
root.current = null;
|
|
5829
|
+
}
|
|
5830
|
+
if (target && target.contains(el)) {
|
|
5831
|
+
target.removeChild(el);
|
|
5832
|
+
}
|
|
6074
5833
|
};
|
|
6075
5834
|
}
|
|
6076
|
-
}, [target, transform]);
|
|
5835
|
+
}, [target, transform, el, prepend, scene]);
|
|
6077
5836
|
React.useLayoutEffect(() => {
|
|
6078
5837
|
if (wrapperClass) el.className = wrapperClass;
|
|
6079
|
-
}, [wrapperClass]);
|
|
5838
|
+
}, [wrapperClass, el]);
|
|
5839
|
+
React.useLayoutEffect(() => {
|
|
5840
|
+
return () => {
|
|
5841
|
+
if (root.current) {
|
|
5842
|
+
root.current.unmount();
|
|
5843
|
+
root.current = null;
|
|
5844
|
+
}
|
|
5845
|
+
};
|
|
5846
|
+
}, []);
|
|
6080
5847
|
const styles = React.useMemo(() => {
|
|
5848
|
+
const width = forceEven ? roundEven(size.width) : size.width;
|
|
5849
|
+
const height = forceEven ? roundEven(size.height) : size.height;
|
|
6081
5850
|
if (transform) {
|
|
6082
5851
|
return {
|
|
6083
5852
|
position: "absolute",
|
|
6084
5853
|
top: 0,
|
|
6085
5854
|
left: 0,
|
|
6086
|
-
width
|
|
6087
|
-
height
|
|
5855
|
+
width,
|
|
5856
|
+
height,
|
|
6088
5857
|
transformStyle: "preserve-3d",
|
|
6089
5858
|
pointerEvents: "none"
|
|
6090
5859
|
};
|
|
@@ -6093,15 +5862,15 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
6093
5862
|
position: "absolute",
|
|
6094
5863
|
transform: center ? "translate3d(-50%,-50%,0)" : "none",
|
|
6095
5864
|
...fullscreen && {
|
|
6096
|
-
top: -size.height / 2,
|
|
6097
|
-
left: -size.width / 2,
|
|
6098
|
-
width
|
|
6099
|
-
height
|
|
5865
|
+
top: forceEven ? roundEven(-size.height / 2) : -size.height / 2,
|
|
5866
|
+
left: forceEven ? roundEven(-size.width / 2) : -size.width / 2,
|
|
5867
|
+
width,
|
|
5868
|
+
height
|
|
6100
5869
|
},
|
|
6101
5870
|
...style
|
|
6102
5871
|
};
|
|
6103
5872
|
}
|
|
6104
|
-
}, [style, center, fullscreen, size, transform]);
|
|
5873
|
+
}, [style, center, fullscreen, size, transform, forceEven]);
|
|
6105
5874
|
const transformInnerStyles = React.useMemo(
|
|
6106
5875
|
() => ({ position: "absolute", pointerEvents }),
|
|
6107
5876
|
[pointerEvents]
|
|
@@ -6115,7 +5884,7 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
6115
5884
|
} else {
|
|
6116
5885
|
root.current?.render(/* @__PURE__ */ React.createElement("div", { ref, style: styles, className, children }));
|
|
6117
5886
|
}
|
|
6118
|
-
});
|
|
5887
|
+
}, [transform, styles, transformInnerStyles, ref, className, style, children]);
|
|
6119
5888
|
const visible = React.useRef(true);
|
|
6120
5889
|
useFrame((gl2) => {
|
|
6121
5890
|
if (group.current) {
|
|
@@ -6147,7 +5916,12 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
6147
5916
|
const zRange = occlude ? isRayCastOcclusion ? [zIndexRange[0], halfRange] : [halfRange - 1, 0] : zIndexRange;
|
|
6148
5917
|
el.style.zIndex = `${objectZIndex(group.current, camera, zRange)}`;
|
|
6149
5918
|
if (transform) {
|
|
6150
|
-
|
|
5919
|
+
let widthHalf = forceEven ? roundEven(size.width / 2) : size.width / 2;
|
|
5920
|
+
let heightHalf = forceEven ? roundEven(size.height / 2) : size.height / 2;
|
|
5921
|
+
if (pixelPerfect) {
|
|
5922
|
+
widthHalf = roundToPixelRatio(widthHalf);
|
|
5923
|
+
heightHalf = roundToPixelRatio(heightHalf);
|
|
5924
|
+
}
|
|
6151
5925
|
const fov = camera.projectionMatrix.elements[5] * heightHalf;
|
|
6152
5926
|
const { isOrthographicCamera, top, left, bottom, right } = camera;
|
|
6153
5927
|
const cameraMatrix = getCameraCSSMatrix(camera.matrixWorldInverse);
|
|
@@ -6158,8 +5932,10 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
6158
5932
|
matrix.elements[3] = matrix.elements[7] = matrix.elements[11] = 0;
|
|
6159
5933
|
matrix.elements[15] = 1;
|
|
6160
5934
|
}
|
|
6161
|
-
|
|
6162
|
-
|
|
5935
|
+
const elWidth = forceEven ? roundEven(size.width) : size.width;
|
|
5936
|
+
const elHeight = forceEven ? roundEven(size.height) : size.height;
|
|
5937
|
+
el.style.width = elWidth + "px";
|
|
5938
|
+
el.style.height = elHeight + "px";
|
|
6163
5939
|
el.style.perspective = isOrthographicCamera ? "" : `${fov}px`;
|
|
6164
5940
|
if (transformOuterRef.current && transformInnerRef.current) {
|
|
6165
5941
|
transformOuterRef.current.style.transform = `${cameraTransform}${cameraMatrix}translate(${widthHalf}px,${heightHalf}px)`;
|
|
@@ -6167,7 +5943,13 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
6167
5943
|
}
|
|
6168
5944
|
} else {
|
|
6169
5945
|
const scale = distanceFactor === void 0 ? 1 : objectScale(group.current, camera) * distanceFactor;
|
|
6170
|
-
|
|
5946
|
+
let x = forceEven ? roundEven(vec[0]) : vec[0];
|
|
5947
|
+
let y = forceEven ? roundEven(vec[1]) : vec[1];
|
|
5948
|
+
if (pixelPerfect) {
|
|
5949
|
+
x = roundToPixelRatio(x);
|
|
5950
|
+
y = roundToPixelRatio(y);
|
|
5951
|
+
}
|
|
5952
|
+
el.style.transform = `translate3d(${x}px,${y}px,0) scale(${scale})`;
|
|
6171
5953
|
}
|
|
6172
5954
|
oldPosition.current = vec;
|
|
6173
5955
|
oldZoom.current = camera.zoom;
|
|
@@ -6273,6 +6055,11 @@ const Html = /* @__PURE__ */ React.forwardRef(
|
|
|
6273
6055
|
);
|
|
6274
6056
|
|
|
6275
6057
|
const context$4 = /* @__PURE__ */ React.createContext(null);
|
|
6058
|
+
const resolveObject = (object, fallback) => {
|
|
6059
|
+
if (!object) return fallback;
|
|
6060
|
+
if ("current" in object) return object.current;
|
|
6061
|
+
return object;
|
|
6062
|
+
};
|
|
6276
6063
|
|
|
6277
6064
|
const vec1$1 = /* @__PURE__ */ new THREE.Vector3();
|
|
6278
6065
|
const vec2$1 = /* @__PURE__ */ new THREE.Vector3();
|
|
@@ -6307,6 +6094,8 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
6307
6094
|
onDragStart,
|
|
6308
6095
|
onDrag,
|
|
6309
6096
|
onDragEnd,
|
|
6097
|
+
onHover,
|
|
6098
|
+
dragState,
|
|
6310
6099
|
userData,
|
|
6311
6100
|
LineComponent: Line
|
|
6312
6101
|
} = React.useContext(context$4);
|
|
@@ -6338,7 +6127,13 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
6338
6127
|
const onPointerMove = React.useCallback(
|
|
6339
6128
|
(e) => {
|
|
6340
6129
|
e.stopPropagation();
|
|
6341
|
-
if (!isHovered)
|
|
6130
|
+
if (!isHovered) {
|
|
6131
|
+
const drag = dragState.current;
|
|
6132
|
+
if (drag === null || drag.component === "Arrow" && drag.axis === axis) {
|
|
6133
|
+
setIsHovered(true);
|
|
6134
|
+
onHover({ component: "Arrow", axis, hovering: true });
|
|
6135
|
+
}
|
|
6136
|
+
}
|
|
6342
6137
|
if (clickInfo.current) {
|
|
6343
6138
|
const { clickPoint, dir } = clickInfo.current;
|
|
6344
6139
|
const [min, max] = translationLimits?.[axis] || [void 0, void 0];
|
|
@@ -6357,7 +6152,7 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
6357
6152
|
onDrag(offsetMatrix$1);
|
|
6358
6153
|
}
|
|
6359
6154
|
},
|
|
6360
|
-
[annotations, onDrag, isHovered, translation, translationLimits, axis]
|
|
6155
|
+
[annotations, onDrag, onHover, dragState, isHovered, translation, translationLimits, axis]
|
|
6361
6156
|
);
|
|
6362
6157
|
const onPointerUp = React.useCallback(
|
|
6363
6158
|
(e) => {
|
|
@@ -6372,10 +6167,16 @@ const AxisArrow = ({ direction, axis }) => {
|
|
|
6372
6167
|
},
|
|
6373
6168
|
[annotations, camControls, onDragEnd]
|
|
6374
6169
|
);
|
|
6375
|
-
const onPointerOut = React.useCallback(
|
|
6376
|
-
e
|
|
6377
|
-
|
|
6378
|
-
|
|
6170
|
+
const onPointerOut = React.useCallback(
|
|
6171
|
+
(e) => {
|
|
6172
|
+
e.stopPropagation();
|
|
6173
|
+
if (isHovered) {
|
|
6174
|
+
setIsHovered(false);
|
|
6175
|
+
onHover({ component: "Arrow", axis, hovering: false });
|
|
6176
|
+
}
|
|
6177
|
+
},
|
|
6178
|
+
[onHover, axis, isHovered]
|
|
6179
|
+
);
|
|
6379
6180
|
const { cylinderLength, coneWidth, coneLength, matrixL } = React.useMemo(() => {
|
|
6380
6181
|
const coneWidth2 = fixed ? lineWidth / scale * 1.6 : scale / 20;
|
|
6381
6182
|
const coneLength2 = fixed ? 0.2 : scale / 5;
|
|
@@ -6479,6 +6280,8 @@ const rotMatrix = /* @__PURE__ */ new THREE.Matrix4();
|
|
|
6479
6280
|
const posNew = /* @__PURE__ */ new THREE.Vector3();
|
|
6480
6281
|
const ray$1 = /* @__PURE__ */ new THREE.Ray();
|
|
6481
6282
|
const intersection$1 = /* @__PURE__ */ new THREE.Vector3();
|
|
6283
|
+
const viewPlane = /* @__PURE__ */ new THREE.Plane();
|
|
6284
|
+
const viewIntersection = /* @__PURE__ */ new THREE.Vector3();
|
|
6482
6285
|
const AxisRotator = ({
|
|
6483
6286
|
dir1,
|
|
6484
6287
|
dir2,
|
|
@@ -6499,6 +6302,8 @@ const AxisRotator = ({
|
|
|
6499
6302
|
onDragStart,
|
|
6500
6303
|
onDrag,
|
|
6501
6304
|
onDragEnd,
|
|
6305
|
+
onHover,
|
|
6306
|
+
dragState,
|
|
6502
6307
|
userData,
|
|
6503
6308
|
LineComponent: Line
|
|
6504
6309
|
} = React.useContext(context$4);
|
|
@@ -6532,14 +6337,29 @@ const AxisRotator = ({
|
|
|
6532
6337
|
const onPointerMove = React.useCallback(
|
|
6533
6338
|
(e) => {
|
|
6534
6339
|
e.stopPropagation();
|
|
6535
|
-
if (!isHovered)
|
|
6340
|
+
if (!isHovered) {
|
|
6341
|
+
const drag = dragState.current;
|
|
6342
|
+
if (drag === null || drag.component === "Rotator" && drag.axis === axis) {
|
|
6343
|
+
setIsHovered(true);
|
|
6344
|
+
onHover({ component: "Rotator", axis, hovering: true });
|
|
6345
|
+
}
|
|
6346
|
+
}
|
|
6536
6347
|
if (clickInfo.current) {
|
|
6537
6348
|
const { clickPoint, origin, e1, e2, normal, plane } = clickInfo.current;
|
|
6538
6349
|
const [min, max] = rotationLimits?.[axis] || [void 0, void 0];
|
|
6539
6350
|
ray$1.copy(e.ray);
|
|
6540
|
-
ray$1.
|
|
6541
|
-
|
|
6542
|
-
|
|
6351
|
+
const dotProduct = Math.abs(ray$1.direction.dot(normal));
|
|
6352
|
+
if (dotProduct < 0.1) {
|
|
6353
|
+
viewPlane.setFromNormalAndCoplanarPoint(ray$1.direction.clone().negate(), origin);
|
|
6354
|
+
ray$1.intersectPlane(viewPlane, viewIntersection);
|
|
6355
|
+
const toIntersection = viewIntersection.clone().sub(origin);
|
|
6356
|
+
const projectedDist = toIntersection.dot(normal);
|
|
6357
|
+
intersection$1.copy(viewIntersection).sub(normal.clone().multiplyScalar(projectedDist));
|
|
6358
|
+
} else {
|
|
6359
|
+
ray$1.intersectPlane(plane, intersection$1);
|
|
6360
|
+
ray$1.direction.negate();
|
|
6361
|
+
ray$1.intersectPlane(plane, intersection$1);
|
|
6362
|
+
}
|
|
6543
6363
|
let deltaAngle = calculateAngle(clickPoint, intersection$1, origin, e1, e2);
|
|
6544
6364
|
let degrees = toDegrees(deltaAngle);
|
|
6545
6365
|
if (e.shiftKey) {
|
|
@@ -6565,7 +6385,7 @@ const AxisRotator = ({
|
|
|
6565
6385
|
onDrag(rotMatrix);
|
|
6566
6386
|
}
|
|
6567
6387
|
},
|
|
6568
|
-
[annotations, onDrag, isHovered, rotationLimits, axis]
|
|
6388
|
+
[annotations, onDrag, onHover, dragState, isHovered, rotationLimits, axis]
|
|
6569
6389
|
);
|
|
6570
6390
|
const onPointerUp = React.useCallback(
|
|
6571
6391
|
(e) => {
|
|
@@ -6581,10 +6401,16 @@ const AxisRotator = ({
|
|
|
6581
6401
|
},
|
|
6582
6402
|
[annotations, camControls, onDragEnd]
|
|
6583
6403
|
);
|
|
6584
|
-
const onPointerOut = React.useCallback(
|
|
6585
|
-
e
|
|
6586
|
-
|
|
6587
|
-
|
|
6404
|
+
const onPointerOut = React.useCallback(
|
|
6405
|
+
(e) => {
|
|
6406
|
+
e.stopPropagation();
|
|
6407
|
+
if (isHovered) {
|
|
6408
|
+
setIsHovered(false);
|
|
6409
|
+
onHover({ component: "Rotator", axis, hovering: false });
|
|
6410
|
+
}
|
|
6411
|
+
},
|
|
6412
|
+
[onHover, axis, isHovered]
|
|
6413
|
+
);
|
|
6588
6414
|
const matrixL = React.useMemo(() => {
|
|
6589
6415
|
const dir1N = dir1.clone().normalize();
|
|
6590
6416
|
const dir2N = dir2.clone().normalize();
|
|
@@ -6685,6 +6511,8 @@ const PlaneSlider = ({
|
|
|
6685
6511
|
onDragStart,
|
|
6686
6512
|
onDrag,
|
|
6687
6513
|
onDragEnd,
|
|
6514
|
+
onHover,
|
|
6515
|
+
dragState,
|
|
6688
6516
|
userData,
|
|
6689
6517
|
LineComponent: Line
|
|
6690
6518
|
} = React.useContext(context$4);
|
|
@@ -6720,7 +6548,13 @@ const PlaneSlider = ({
|
|
|
6720
6548
|
const onPointerMove = React.useCallback(
|
|
6721
6549
|
(e) => {
|
|
6722
6550
|
e.stopPropagation();
|
|
6723
|
-
if (!isHovered)
|
|
6551
|
+
if (!isHovered) {
|
|
6552
|
+
const drag = dragState.current;
|
|
6553
|
+
if (drag === null || drag.component === "Slider" && drag.axis === axis) {
|
|
6554
|
+
setIsHovered(true);
|
|
6555
|
+
onHover({ component: "Slider", axis, hovering: true });
|
|
6556
|
+
}
|
|
6557
|
+
}
|
|
6724
6558
|
if (clickInfo.current) {
|
|
6725
6559
|
const { clickPoint, e1, e2, plane } = clickInfo.current;
|
|
6726
6560
|
const [minX, maxX] = translationLimits?.[(axis + 1) % 3] || [void 0, void 0];
|
|
@@ -6756,7 +6590,7 @@ const PlaneSlider = ({
|
|
|
6756
6590
|
onDrag(offsetMatrix);
|
|
6757
6591
|
}
|
|
6758
6592
|
},
|
|
6759
|
-
[annotations, onDrag, isHovered, translation, translationLimits, axis]
|
|
6593
|
+
[annotations, onDrag, onHover, dragState, isHovered, translation, translationLimits, axis]
|
|
6760
6594
|
);
|
|
6761
6595
|
const onPointerUp = React.useCallback(
|
|
6762
6596
|
(e) => {
|
|
@@ -6771,10 +6605,16 @@ const PlaneSlider = ({
|
|
|
6771
6605
|
},
|
|
6772
6606
|
[annotations, camControls, onDragEnd]
|
|
6773
6607
|
);
|
|
6774
|
-
const onPointerOut = React.useCallback(
|
|
6775
|
-
e
|
|
6776
|
-
|
|
6777
|
-
|
|
6608
|
+
const onPointerOut = React.useCallback(
|
|
6609
|
+
(e) => {
|
|
6610
|
+
e.stopPropagation();
|
|
6611
|
+
if (isHovered) {
|
|
6612
|
+
setIsHovered(false);
|
|
6613
|
+
onHover({ component: "Slider", axis, hovering: false });
|
|
6614
|
+
}
|
|
6615
|
+
},
|
|
6616
|
+
[onHover, axis, isHovered]
|
|
6617
|
+
);
|
|
6778
6618
|
const matrixL = React.useMemo(() => {
|
|
6779
6619
|
const dir1N = dir1.clone().normalize();
|
|
6780
6620
|
const dir2N = dir2.clone().normalize();
|
|
@@ -6912,6 +6752,8 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
6912
6752
|
onDragStart,
|
|
6913
6753
|
onDrag,
|
|
6914
6754
|
onDragEnd,
|
|
6755
|
+
onHover,
|
|
6756
|
+
dragState,
|
|
6915
6757
|
userData
|
|
6916
6758
|
} = React.useContext(context$4);
|
|
6917
6759
|
const size = useThree((state) => state.size);
|
|
@@ -6948,7 +6790,13 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
6948
6790
|
const onPointerMove = React.useCallback(
|
|
6949
6791
|
(e) => {
|
|
6950
6792
|
e.stopPropagation();
|
|
6951
|
-
if (!isHovered)
|
|
6793
|
+
if (!isHovered) {
|
|
6794
|
+
const drag = dragState.current;
|
|
6795
|
+
if (drag === null || drag.component === "Sphere" && drag.axis === axis) {
|
|
6796
|
+
setIsHovered(true);
|
|
6797
|
+
onHover({ component: "Sphere", axis, hovering: true });
|
|
6798
|
+
}
|
|
6799
|
+
}
|
|
6952
6800
|
if (clickInfo.current) {
|
|
6953
6801
|
const { clickPoint, dir, mPLG, mPLGInv, offsetMultiplier } = clickInfo.current;
|
|
6954
6802
|
const [min, max] = scaleLimits?.[axis] || [1e-5, void 0];
|
|
@@ -6974,7 +6822,7 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
6974
6822
|
onDrag(scaleMatrix);
|
|
6975
6823
|
}
|
|
6976
6824
|
},
|
|
6977
|
-
[annotations, position, onDrag, isHovered, scaleLimits, axis]
|
|
6825
|
+
[annotations, position, onDrag, onHover, dragState, isHovered, scaleLimits, axis]
|
|
6978
6826
|
);
|
|
6979
6827
|
const onPointerUp = React.useCallback(
|
|
6980
6828
|
(e) => {
|
|
@@ -6991,10 +6839,16 @@ const ScalingSphere = ({ direction, axis }) => {
|
|
|
6991
6839
|
},
|
|
6992
6840
|
[annotations, camControls, onDragEnd, position]
|
|
6993
6841
|
);
|
|
6994
|
-
const onPointerOut = React.useCallback(
|
|
6995
|
-
e
|
|
6996
|
-
|
|
6997
|
-
|
|
6842
|
+
const onPointerOut = React.useCallback(
|
|
6843
|
+
(e) => {
|
|
6844
|
+
e.stopPropagation();
|
|
6845
|
+
if (isHovered) {
|
|
6846
|
+
setIsHovered(false);
|
|
6847
|
+
onHover({ component: "Sphere", axis, hovering: false });
|
|
6848
|
+
}
|
|
6849
|
+
},
|
|
6850
|
+
[onHover, axis, isHovered]
|
|
6851
|
+
);
|
|
6998
6852
|
const { radius, matrixL } = React.useMemo(() => {
|
|
6999
6853
|
const radius2 = fixed ? lineWidth / scale * 1.8 : scale / 22.5;
|
|
7000
6854
|
const quaternion = new THREE.Quaternion().setFromUnitVectors(upV, direction.clone().normalize());
|
|
@@ -7064,9 +6918,11 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
7064
6918
|
({
|
|
7065
6919
|
enabled = true,
|
|
7066
6920
|
matrix,
|
|
6921
|
+
object,
|
|
7067
6922
|
onDragStart,
|
|
7068
6923
|
onDrag,
|
|
7069
6924
|
onDragEnd,
|
|
6925
|
+
onHover,
|
|
7070
6926
|
autoTransform = true,
|
|
7071
6927
|
anchor,
|
|
7072
6928
|
disableAxes = false,
|
|
@@ -7102,14 +6958,35 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
7102
6958
|
const gizmoRef = React.useRef(null);
|
|
7103
6959
|
const childrenRef = React.useRef(null);
|
|
7104
6960
|
const translation = React.useRef([0, 0, 0]);
|
|
6961
|
+
const dragState = React.useRef(null);
|
|
7105
6962
|
const cameraScale = React.useRef(new THREE.Vector3(1, 1, 1));
|
|
7106
6963
|
const gizmoScale = React.useRef(new THREE.Vector3(1, 1, 1));
|
|
6964
|
+
React.useEffect(() => {
|
|
6965
|
+
if (object) {
|
|
6966
|
+
const target = resolveObject(object);
|
|
6967
|
+
if (target) {
|
|
6968
|
+
const pivot = ref.current;
|
|
6969
|
+
const didAutoUpdate = target.matrixAutoUpdate;
|
|
6970
|
+
target.updateWorldMatrix(true, true);
|
|
6971
|
+
target.matrixAutoUpdate = false;
|
|
6972
|
+
pivot.matrix.copy(target.matrix);
|
|
6973
|
+
return () => {
|
|
6974
|
+
if (didAutoUpdate) {
|
|
6975
|
+
target.matrixAutoUpdate = true;
|
|
6976
|
+
target.matrix.decompose(target.position, target.quaternion, target.scale);
|
|
6977
|
+
}
|
|
6978
|
+
};
|
|
6979
|
+
}
|
|
6980
|
+
}
|
|
6981
|
+
}, [object]);
|
|
7107
6982
|
React.useLayoutEffect(() => {
|
|
7108
6983
|
if (!anchor) return;
|
|
7109
|
-
childrenRef.current
|
|
7110
|
-
|
|
6984
|
+
const anchorTarget = resolveObject(object, childrenRef.current);
|
|
6985
|
+
if (!anchorTarget) return;
|
|
6986
|
+
anchorTarget.updateWorldMatrix(true, true);
|
|
6987
|
+
mPInv.copy(anchorTarget.matrixWorld).invert();
|
|
7111
6988
|
bb.makeEmpty();
|
|
7112
|
-
|
|
6989
|
+
anchorTarget.traverse((obj) => {
|
|
7113
6990
|
if (!obj.geometry) return;
|
|
7114
6991
|
if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
|
|
7115
6992
|
mL.copy(obj.matrixWorld).premultiply(mPInv);
|
|
@@ -7124,9 +7001,17 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
7124
7001
|
gizmoRef.current.position.copy(vPosition);
|
|
7125
7002
|
invalidate();
|
|
7126
7003
|
});
|
|
7004
|
+
const mergedUserData = React.useMemo(
|
|
7005
|
+
() => ({
|
|
7006
|
+
...userData,
|
|
7007
|
+
...depthTest === false && { interactivePriority: 1 }
|
|
7008
|
+
}),
|
|
7009
|
+
[userData, depthTest]
|
|
7010
|
+
);
|
|
7127
7011
|
const config = React.useMemo(
|
|
7128
7012
|
() => ({
|
|
7129
7013
|
onDragStart: (props2) => {
|
|
7014
|
+
dragState.current = props2;
|
|
7130
7015
|
mL0.copy(ref.current.matrix);
|
|
7131
7016
|
mW0.copy(ref.current.matrixWorld);
|
|
7132
7017
|
onDragStart && onDragStart(props2);
|
|
@@ -7142,13 +7027,20 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
7142
7027
|
if (autoTransform) {
|
|
7143
7028
|
ref.current.matrix.copy(mL);
|
|
7144
7029
|
}
|
|
7030
|
+
const target = resolveObject(object);
|
|
7031
|
+
if (target) target.matrix.copy(mL);
|
|
7145
7032
|
onDrag && onDrag(mL, mdL, mW, mdW);
|
|
7146
7033
|
invalidate();
|
|
7147
7034
|
},
|
|
7148
7035
|
onDragEnd: () => {
|
|
7036
|
+
dragState.current = null;
|
|
7149
7037
|
if (onDragEnd) onDragEnd();
|
|
7150
7038
|
invalidate();
|
|
7151
7039
|
},
|
|
7040
|
+
onHover: (props2) => {
|
|
7041
|
+
if (onHover) onHover(props2);
|
|
7042
|
+
},
|
|
7043
|
+
dragState,
|
|
7152
7044
|
translation,
|
|
7153
7045
|
translationLimits,
|
|
7154
7046
|
rotationLimits,
|
|
@@ -7160,7 +7052,7 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
7160
7052
|
fixed,
|
|
7161
7053
|
depthTest,
|
|
7162
7054
|
renderOrder,
|
|
7163
|
-
userData,
|
|
7055
|
+
userData: mergedUserData,
|
|
7164
7056
|
annotations,
|
|
7165
7057
|
annotationsClass,
|
|
7166
7058
|
LineComponent: LineComp
|
|
@@ -7169,6 +7061,7 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
7169
7061
|
onDragStart,
|
|
7170
7062
|
onDrag,
|
|
7171
7063
|
onDragEnd,
|
|
7064
|
+
onHover,
|
|
7172
7065
|
translation,
|
|
7173
7066
|
translationLimits,
|
|
7174
7067
|
rotationLimits,
|
|
@@ -7180,11 +7073,12 @@ const PivotControls = /* @__PURE__ */ React.forwardRef(
|
|
|
7180
7073
|
...axisColors,
|
|
7181
7074
|
hoveredColor,
|
|
7182
7075
|
opacity,
|
|
7183
|
-
|
|
7076
|
+
mergedUserData,
|
|
7184
7077
|
autoTransform,
|
|
7185
7078
|
annotations,
|
|
7186
7079
|
annotationsClass,
|
|
7187
|
-
LineComp
|
|
7080
|
+
LineComp,
|
|
7081
|
+
object
|
|
7188
7082
|
]
|
|
7189
7083
|
);
|
|
7190
7084
|
const vec = new THREE.Vector3();
|
|
@@ -7546,7 +7440,7 @@ function createInstances() {
|
|
|
7546
7440
|
];
|
|
7547
7441
|
}
|
|
7548
7442
|
const InstancedAttribute = React.forwardRef(
|
|
7549
|
-
({ name, defaultValue, normalized, usage = THREE.DynamicDrawUsage }, fref) => {
|
|
7443
|
+
({ name, defaultValue, normalized, usage = THREE.DynamicDrawUsage, type = "float" }, fref) => {
|
|
7550
7444
|
const ref = React.useRef(null);
|
|
7551
7445
|
React.useImperativeHandle(fref, () => ref.current, []);
|
|
7552
7446
|
React.useLayoutEffect(() => {
|
|
@@ -7554,7 +7448,26 @@ const InstancedAttribute = React.forwardRef(
|
|
|
7554
7448
|
parent.geometry.attributes[name] = ref.current;
|
|
7555
7449
|
const value = Array.isArray(defaultValue) ? defaultValue : [defaultValue];
|
|
7556
7450
|
const array = Array.from({ length: parent.userData.limit }, () => value).flat();
|
|
7557
|
-
|
|
7451
|
+
switch (type) {
|
|
7452
|
+
case "float":
|
|
7453
|
+
ref.current.array = new Float32Array(array);
|
|
7454
|
+
break;
|
|
7455
|
+
case "int":
|
|
7456
|
+
ref.current.array = new Int32Array(array);
|
|
7457
|
+
break;
|
|
7458
|
+
case "uint":
|
|
7459
|
+
ref.current.array = new Uint32Array(array);
|
|
7460
|
+
break;
|
|
7461
|
+
case "short":
|
|
7462
|
+
ref.current.array = new Int16Array(array);
|
|
7463
|
+
break;
|
|
7464
|
+
case "ushort":
|
|
7465
|
+
ref.current.array = new Uint16Array(array);
|
|
7466
|
+
break;
|
|
7467
|
+
case "byte":
|
|
7468
|
+
ref.current.array = new Uint8Array(array);
|
|
7469
|
+
break;
|
|
7470
|
+
}
|
|
7558
7471
|
ref.current.itemSize = value.length;
|
|
7559
7472
|
ref.current.count = array.length / ref.current.itemSize;
|
|
7560
7473
|
return () => {
|
|
@@ -9079,12 +8992,17 @@ const Gltf = /* @__PURE__ */ React.forwardRef(
|
|
|
9079
8992
|
}
|
|
9080
8993
|
);
|
|
9081
8994
|
|
|
9082
|
-
|
|
9083
|
-
function useKTX2(input, basisPath =
|
|
8995
|
+
let transcoderPath = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/basis/";
|
|
8996
|
+
function useKTX2(input, basisPath = true, extendLoader) {
|
|
9084
8997
|
const renderer = useThree((state) => state.renderer);
|
|
9085
8998
|
const textures = useLoader(KTX2Loader, IsObject(input) ? Object.values(input) : input, (loader) => {
|
|
8999
|
+
if (extendLoader) {
|
|
9000
|
+
extendLoader(loader);
|
|
9001
|
+
}
|
|
9002
|
+
if (basisPath) {
|
|
9003
|
+
loader.setTranscoderPath(typeof basisPath === "string" ? basisPath : transcoderPath);
|
|
9004
|
+
}
|
|
9086
9005
|
loader.detectSupport(renderer);
|
|
9087
|
-
loader.setTranscoderPath(basisPath);
|
|
9088
9006
|
});
|
|
9089
9007
|
useEffect(() => {
|
|
9090
9008
|
const array = Array.isArray(textures) ? textures : [textures];
|
|
@@ -9099,16 +9017,20 @@ function useKTX2(input, basisPath = `${cdn}/basis/`) {
|
|
|
9099
9017
|
return textures;
|
|
9100
9018
|
}
|
|
9101
9019
|
}
|
|
9102
|
-
useKTX2.preload = (url, basisPath =
|
|
9103
|
-
|
|
9020
|
+
useKTX2.preload = (url, basisPath = true, extendLoader) => useLoader.preload(KTX2Loader, url, (loader) => {
|
|
9021
|
+
if (extendLoader) {
|
|
9022
|
+
extendLoader(loader);
|
|
9023
|
+
}
|
|
9024
|
+
if (basisPath) {
|
|
9025
|
+
loader.setTranscoderPath(typeof basisPath === "string" ? basisPath : transcoderPath);
|
|
9026
|
+
}
|
|
9104
9027
|
});
|
|
9105
9028
|
useKTX2.clear = (input) => useLoader.clear(KTX2Loader, input);
|
|
9106
|
-
|
|
9107
|
-
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
const texture = useKTX2(input, basisPath);
|
|
9029
|
+
useKTX2.setTranscoderPath = (path) => {
|
|
9030
|
+
transcoderPath = path;
|
|
9031
|
+
};
|
|
9032
|
+
const Ktx2 = ({ children, input, basisPath, extendLoader }) => {
|
|
9033
|
+
const texture = useKTX2(input, basisPath, extendLoader);
|
|
9112
9034
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, children?.(texture));
|
|
9113
9035
|
};
|
|
9114
9036
|
|
|
@@ -9584,18 +9506,21 @@ function Fisheye({
|
|
|
9584
9506
|
const normal = new THREE.Vector3();
|
|
9585
9507
|
const sph = new THREE.Sphere(new THREE.Vector3(), radius);
|
|
9586
9508
|
const normalMatrix = new THREE.Matrix3();
|
|
9587
|
-
const compute = React.useCallback(
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9509
|
+
const compute = React.useCallback(
|
|
9510
|
+
(event, state, prev) => {
|
|
9511
|
+
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
9512
|
+
state.raycaster.setFromCamera(state.pointer, orthoC);
|
|
9513
|
+
if (!state.raycaster.ray.intersectSphere(sph, normal)) return;
|
|
9514
|
+
else normal.normalize();
|
|
9515
|
+
normalMatrix.getNormalMatrix(cubeApi.current.camera.matrixWorld);
|
|
9516
|
+
cubeApi.current.camera.getWorldPosition(state.raycaster.ray.origin);
|
|
9517
|
+
state.raycaster.ray.direction.set(0, 0, 1).reflect(normal);
|
|
9518
|
+
state.raycaster.ray.direction.x *= -1;
|
|
9519
|
+
state.raycaster.ray.direction.applyNormalMatrix(normalMatrix).multiplyScalar(-1);
|
|
9520
|
+
return void 0;
|
|
9521
|
+
},
|
|
9522
|
+
[width, height]
|
|
9523
|
+
);
|
|
9599
9524
|
useFrame(
|
|
9600
9525
|
({ gl }) => {
|
|
9601
9526
|
if (renderPriority) gl.render(sphere.current, orthoC);
|
|
@@ -9730,14 +9655,22 @@ const isWebGPURenderer = (def) => !!def.isWebGPURenderer;
|
|
|
9730
9655
|
const col = /* @__PURE__ */ new THREE.Color();
|
|
9731
9656
|
const TUNNEL_KEY = "__drei_view_tunnel__";
|
|
9732
9657
|
const tracked = globalThis[TUNNEL_KEY] || (globalThis[TUNNEL_KEY] = tunnel());
|
|
9733
|
-
function computeContainerPosition(canvasSize, trackRect) {
|
|
9658
|
+
function computeContainerPosition(canvasSize, trackRect, forceEven) {
|
|
9734
9659
|
const { right, top: trackTop, left: trackLeft, bottom: trackBottom, width, height } = trackRect;
|
|
9735
9660
|
const isOffscreen = trackRect.bottom < 0 || trackTop > canvasSize.height || right < 0 || trackRect.left > canvasSize.width;
|
|
9736
9661
|
const canvasBottom = canvasSize.top + canvasSize.height;
|
|
9737
|
-
const
|
|
9738
|
-
const
|
|
9739
|
-
const
|
|
9740
|
-
|
|
9662
|
+
const rawBottom = canvasBottom - trackBottom;
|
|
9663
|
+
const rawLeft = trackLeft - canvasSize.left;
|
|
9664
|
+
const rawTop = trackTop - canvasSize.top;
|
|
9665
|
+
const position = forceEven ? {
|
|
9666
|
+
width: roundEven(width),
|
|
9667
|
+
height: roundEven(height),
|
|
9668
|
+
left: roundEven(rawLeft),
|
|
9669
|
+
top: roundEven(rawTop),
|
|
9670
|
+
bottom: roundEven(rawBottom),
|
|
9671
|
+
right: roundEven(right)
|
|
9672
|
+
} : { width, height, left: rawLeft, top: rawTop, bottom: rawBottom, right };
|
|
9673
|
+
return { position, isOffscreen };
|
|
9741
9674
|
}
|
|
9742
9675
|
function prepareSkissor(renderer, camera, {
|
|
9743
9676
|
left,
|
|
@@ -9777,6 +9710,7 @@ function clear(renderer) {
|
|
|
9777
9710
|
}
|
|
9778
9711
|
function Container({ visible = true, canvasSize, scene, index, children, frames, rect, track }) {
|
|
9779
9712
|
const { scene: portalScene, camera: portalCamera, renderer, get, setEvents } = useThree();
|
|
9713
|
+
const forceEven = useThree((state) => state.internal.forceEven);
|
|
9780
9714
|
const [isOffscreen, setOffscreen] = React.useState(false);
|
|
9781
9715
|
const mountedRef = React.useRef(true);
|
|
9782
9716
|
React.useEffect(() => {
|
|
@@ -9794,7 +9728,7 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
9794
9728
|
frameCount++;
|
|
9795
9729
|
}
|
|
9796
9730
|
if (rect.current) {
|
|
9797
|
-
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, rect.current);
|
|
9731
|
+
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, rect.current, forceEven);
|
|
9798
9732
|
if (isOffscreen !== _isOffscreen) setOffscreen(_isOffscreen);
|
|
9799
9733
|
if (visible && !_isOffscreen && rect.current) {
|
|
9800
9734
|
const targetScene = children ? portalScene : scene;
|
|
@@ -9816,14 +9750,14 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
9816
9750
|
React.useLayoutEffect(() => {
|
|
9817
9751
|
const curRect = rect.current;
|
|
9818
9752
|
if (curRect && (!visible || !isOffscreen)) {
|
|
9819
|
-
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect);
|
|
9753
|
+
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect, forceEven);
|
|
9820
9754
|
if (!_isOffscreen) {
|
|
9821
9755
|
const autoClear = prepareSkissor(renderer, portalCamera, position);
|
|
9822
9756
|
clear(renderer);
|
|
9823
9757
|
finishSkissor(renderer, autoClear);
|
|
9824
9758
|
}
|
|
9825
9759
|
}
|
|
9826
|
-
}, [visible, isOffscreen, renderer, portalCamera, canvasSize]);
|
|
9760
|
+
}, [visible, isOffscreen, renderer, portalCamera, canvasSize, forceEven]);
|
|
9827
9761
|
React.useEffect(() => {
|
|
9828
9762
|
if (!track) return;
|
|
9829
9763
|
const curRect = rect.current;
|
|
@@ -9831,7 +9765,7 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
9831
9765
|
setEvents({ connected: track.current });
|
|
9832
9766
|
return () => {
|
|
9833
9767
|
if (curRect) {
|
|
9834
|
-
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect);
|
|
9768
|
+
const { position, isOffscreen: _isOffscreen } = computeContainerPosition(canvasSize, curRect, forceEven);
|
|
9835
9769
|
if (!_isOffscreen) {
|
|
9836
9770
|
const autoClear = prepareSkissor(renderer, portalCamera, position);
|
|
9837
9771
|
clear(renderer);
|
|
@@ -9840,13 +9774,14 @@ function Container({ visible = true, canvasSize, scene, index, children, frames,
|
|
|
9840
9774
|
}
|
|
9841
9775
|
setEvents({ connected: old });
|
|
9842
9776
|
};
|
|
9843
|
-
}, [track, renderer, portalCamera, canvasSize, get, setEvents]);
|
|
9777
|
+
}, [track, renderer, portalCamera, canvasSize, get, setEvents, forceEven]);
|
|
9844
9778
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, children, /* @__PURE__ */ React.createElement("group", { onPointerOver: () => null }));
|
|
9845
9779
|
}
|
|
9846
9780
|
const CanvasView = /* @__PURE__ */ React.forwardRef(
|
|
9847
9781
|
({ track, visible = true, index = 1, id, style, className, frames = Infinity, children, ...props }, fref) => {
|
|
9848
9782
|
const rect = React.useRef(null);
|
|
9849
9783
|
const { size, scene } = useThree();
|
|
9784
|
+
const forceEven = useThree((state) => state.internal.forceEven);
|
|
9850
9785
|
const [virtualScene] = React.useState(() => new THREE.Scene());
|
|
9851
9786
|
const [ready, toggle] = React.useReducer(() => true, false);
|
|
9852
9787
|
const compute = React.useCallback(
|
|
@@ -9883,12 +9818,12 @@ const CanvasView = /* @__PURE__ */ React.forwardRef(
|
|
|
9883
9818
|
{
|
|
9884
9819
|
events: { compute, priority: index },
|
|
9885
9820
|
size: {
|
|
9886
|
-
width: rect.current?.width,
|
|
9887
|
-
height: rect.current?.height,
|
|
9821
|
+
width: forceEven && rect.current?.width ? roundEven(rect.current.width) : rect.current?.width,
|
|
9822
|
+
height: forceEven && rect.current?.height ? roundEven(rect.current.height) : rect.current?.height,
|
|
9888
9823
|
// @ts-ignore
|
|
9889
|
-
top: rect.current?.top,
|
|
9824
|
+
top: forceEven && rect.current?.top ? roundEven(rect.current.top) : rect.current?.top,
|
|
9890
9825
|
// @ts-ignore
|
|
9891
|
-
left: rect.current?.left
|
|
9826
|
+
left: forceEven && rect.current?.left ? roundEven(rect.current.left) : rect.current?.left
|
|
9892
9827
|
}
|
|
9893
9828
|
}
|
|
9894
9829
|
));
|
|
@@ -10315,8 +10250,8 @@ function getLoader(extension) {
|
|
|
10315
10250
|
return loader;
|
|
10316
10251
|
}
|
|
10317
10252
|
|
|
10318
|
-
const isRef = (obj) => obj.current && obj.current.isScene;
|
|
10319
|
-
const resolveScene = (scene) => isRef(scene) ? scene.current : scene;
|
|
10253
|
+
const isRef$1 = (obj) => obj.current && obj.current.isScene;
|
|
10254
|
+
const resolveScene = (scene) => isRef$1(scene) ? scene.current : scene;
|
|
10320
10255
|
function setEnvProps(background, scene, defaultScene, texture, sceneProps = {}) {
|
|
10321
10256
|
sceneProps = {
|
|
10322
10257
|
backgroundBlurriness: 0,
|
|
@@ -10673,433 +10608,804 @@ const Sky = /* @__PURE__ */ React.forwardRef(
|
|
|
10673
10608
|
}
|
|
10674
10609
|
);
|
|
10675
10610
|
|
|
10676
|
-
const presets = {
|
|
10677
|
-
rembrandt: {
|
|
10678
|
-
main: [1, 2, 1],
|
|
10679
|
-
fill: [-2, -0.5, -2]
|
|
10680
|
-
},
|
|
10681
|
-
portrait: {
|
|
10682
|
-
main: [-1, 2, 0.5],
|
|
10683
|
-
fill: [-1, 0.5, -1.5]
|
|
10684
|
-
},
|
|
10685
|
-
upfront: {
|
|
10686
|
-
main: [0, 2, 1],
|
|
10687
|
-
fill: [-1, 0.5, -1.5]
|
|
10688
|
-
},
|
|
10689
|
-
soft: {
|
|
10690
|
-
main: [-2, 4, 4],
|
|
10691
|
-
fill: [-1, 0.5, -1.5]
|
|
10692
|
-
}
|
|
10611
|
+
const presets = {
|
|
10612
|
+
rembrandt: {
|
|
10613
|
+
main: [1, 2, 1],
|
|
10614
|
+
fill: [-2, -0.5, -2]
|
|
10615
|
+
},
|
|
10616
|
+
portrait: {
|
|
10617
|
+
main: [-1, 2, 0.5],
|
|
10618
|
+
fill: [-1, 0.5, -1.5]
|
|
10619
|
+
},
|
|
10620
|
+
upfront: {
|
|
10621
|
+
main: [0, 2, 1],
|
|
10622
|
+
fill: [-1, 0.5, -1.5]
|
|
10623
|
+
},
|
|
10624
|
+
soft: {
|
|
10625
|
+
main: [-2, 4, 4],
|
|
10626
|
+
fill: [-1, 0.5, -1.5]
|
|
10627
|
+
}
|
|
10628
|
+
};
|
|
10629
|
+
function Refit({ radius, adjustCamera }) {
|
|
10630
|
+
const api = useBounds();
|
|
10631
|
+
React.useEffect(() => {
|
|
10632
|
+
if (adjustCamera) api.refresh().clip().fit();
|
|
10633
|
+
}, [radius, adjustCamera]);
|
|
10634
|
+
return null;
|
|
10635
|
+
}
|
|
10636
|
+
function Stage({
|
|
10637
|
+
children,
|
|
10638
|
+
center,
|
|
10639
|
+
adjustCamera = true,
|
|
10640
|
+
intensity = 0.5,
|
|
10641
|
+
shadows = "contact",
|
|
10642
|
+
environment = "city",
|
|
10643
|
+
preset = "rembrandt",
|
|
10644
|
+
...props
|
|
10645
|
+
}) {
|
|
10646
|
+
const config = typeof preset === "string" ? presets[preset] : preset;
|
|
10647
|
+
const [{ radius, height }, set] = React.useState({ radius: 0, width: 0, height: 0, depth: 0 });
|
|
10648
|
+
const shadowBias = shadows?.bias ?? -1e-4;
|
|
10649
|
+
const normalBias = shadows?.normalBias ?? 0;
|
|
10650
|
+
const shadowSize = shadows?.size ?? 1024;
|
|
10651
|
+
const shadowOffset = shadows?.offset ?? 0;
|
|
10652
|
+
const contactShadow = shadows === "contact" || shadows?.type === "contact";
|
|
10653
|
+
const accumulativeShadow = shadows === "accumulative" || shadows?.type === "accumulative";
|
|
10654
|
+
const shadowSpread = { ...typeof shadows === "object" ? shadows : {} };
|
|
10655
|
+
const environmentProps = !environment ? null : typeof environment === "string" ? { preset: environment } : environment;
|
|
10656
|
+
const onCentered = React.useCallback((props2) => {
|
|
10657
|
+
const { width, height: height2, depth, boundingSphere } = props2;
|
|
10658
|
+
set({ radius: boundingSphere.radius, width, height: height2, depth });
|
|
10659
|
+
if (center?.onCentered) center.onCentered(props2);
|
|
10660
|
+
}, []);
|
|
10661
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("ambientLight", { intensity: intensity / 3 }), /* @__PURE__ */ React.createElement(
|
|
10662
|
+
"spotLight",
|
|
10663
|
+
{
|
|
10664
|
+
penumbra: 1,
|
|
10665
|
+
position: [config.main[0] * radius, config.main[1] * radius, config.main[2] * radius],
|
|
10666
|
+
intensity: intensity * 2,
|
|
10667
|
+
castShadow: !!shadows,
|
|
10668
|
+
"shadow-bias": shadowBias,
|
|
10669
|
+
"shadow-normalBias": normalBias,
|
|
10670
|
+
"shadow-mapSize": shadowSize
|
|
10671
|
+
}
|
|
10672
|
+
), /* @__PURE__ */ React.createElement(
|
|
10673
|
+
"pointLight",
|
|
10674
|
+
{
|
|
10675
|
+
position: [config.fill[0] * radius, config.fill[1] * radius, config.fill[2] * radius],
|
|
10676
|
+
intensity
|
|
10677
|
+
}
|
|
10678
|
+
), /* @__PURE__ */ React.createElement(Bounds, { fit: !!adjustCamera, clip: !!adjustCamera, margin: Number(adjustCamera), observe: true, ...props }, /* @__PURE__ */ React.createElement(Refit, { radius, adjustCamera }), /* @__PURE__ */ React.createElement(Center, { ...center, position: [0, shadowOffset / 2, 0], onCentered }, children)), /* @__PURE__ */ React.createElement("group", { position: [0, -height / 2 - shadowOffset / 2, 0] }, contactShadow && /* @__PURE__ */ React.createElement(ContactShadows, { scale: radius * 4, far: radius, blur: 2, ...shadowSpread }), accumulativeShadow && /* @__PURE__ */ React.createElement(
|
|
10679
|
+
AccumulativeShadows,
|
|
10680
|
+
{
|
|
10681
|
+
temporal: true,
|
|
10682
|
+
frames: 100,
|
|
10683
|
+
alphaTest: 0.9,
|
|
10684
|
+
toneMapped: true,
|
|
10685
|
+
scale: radius * 4,
|
|
10686
|
+
...shadowSpread
|
|
10687
|
+
},
|
|
10688
|
+
/* @__PURE__ */ React.createElement(
|
|
10689
|
+
RandomizedLight,
|
|
10690
|
+
{
|
|
10691
|
+
amount: shadowSpread.amount ?? 8,
|
|
10692
|
+
radius: shadowSpread.radius ?? radius,
|
|
10693
|
+
ambient: shadowSpread.ambient ?? 0.5,
|
|
10694
|
+
intensity: shadowSpread.intensity ?? 1,
|
|
10695
|
+
position: [config.main[0] * radius, config.main[1] * radius, config.main[2] * radius],
|
|
10696
|
+
size: radius * 4,
|
|
10697
|
+
bias: -shadowBias,
|
|
10698
|
+
mapSize: shadowSize
|
|
10699
|
+
}
|
|
10700
|
+
)
|
|
10701
|
+
)), environment && /* @__PURE__ */ React.createElement(Environment, { ...environmentProps }));
|
|
10702
|
+
}
|
|
10703
|
+
|
|
10704
|
+
function getFormatString(format) {
|
|
10705
|
+
switch (format) {
|
|
10706
|
+
case 64:
|
|
10707
|
+
return "-64px";
|
|
10708
|
+
case 128:
|
|
10709
|
+
return "-128px";
|
|
10710
|
+
case 256:
|
|
10711
|
+
return "-256px";
|
|
10712
|
+
case 512:
|
|
10713
|
+
return "-512px";
|
|
10714
|
+
default:
|
|
10715
|
+
return "";
|
|
10716
|
+
}
|
|
10717
|
+
}
|
|
10718
|
+
const LIST_URL$1 = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/matcaps.json";
|
|
10719
|
+
const MATCAP_ROOT = "https://rawcdn.githack.com/emmelleppi/matcaps/9b36ccaaf0a24881a39062d05566c9e92be4aa0d";
|
|
10720
|
+
function useMatcapTexture(id = 0, format = 1024, onLoad) {
|
|
10721
|
+
const matcapList = suspend(() => fetch(LIST_URL$1).then((res) => res.json()), ["matcapList"]);
|
|
10722
|
+
const DEFAULT_MATCAP = matcapList[0];
|
|
10723
|
+
const numTot = React.useMemo(() => Object.keys(matcapList).length, []);
|
|
10724
|
+
const fileHash = React.useMemo(() => {
|
|
10725
|
+
if (typeof id === "string") {
|
|
10726
|
+
return id;
|
|
10727
|
+
} else if (typeof id === "number") {
|
|
10728
|
+
return matcapList[id];
|
|
10729
|
+
}
|
|
10730
|
+
return null;
|
|
10731
|
+
}, [id]);
|
|
10732
|
+
const fileName = `${fileHash || DEFAULT_MATCAP}${getFormatString(format)}.png`;
|
|
10733
|
+
const url = `${MATCAP_ROOT}/${format}/${fileName}`;
|
|
10734
|
+
const matcapTexture = useTexture(url, onLoad);
|
|
10735
|
+
return [matcapTexture, url, numTot];
|
|
10736
|
+
}
|
|
10737
|
+
const MatcapTexture = ({
|
|
10738
|
+
children,
|
|
10739
|
+
id,
|
|
10740
|
+
format,
|
|
10741
|
+
onLoad
|
|
10742
|
+
}) => {
|
|
10743
|
+
const texture = useMatcapTexture(id, format, onLoad);
|
|
10744
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, children?.(texture));
|
|
10745
|
+
};
|
|
10746
|
+
|
|
10747
|
+
const NORMAL_ROOT = "https://rawcdn.githack.com/pmndrs/drei-assets/7a3104997e1576f83472829815b00880d88b32fb";
|
|
10748
|
+
const LIST_URL = "https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/normals/normals.json";
|
|
10749
|
+
function useNormalTexture(id = 0, settings = {}, onLoad) {
|
|
10750
|
+
const { repeat = [1, 1], anisotropy = 1, offset = [0, 0] } = settings;
|
|
10751
|
+
const normalsList = suspend(() => fetch(LIST_URL).then((res) => res.json()), ["normalsList"]);
|
|
10752
|
+
const numTot = React.useMemo(() => Object.keys(normalsList).length, []);
|
|
10753
|
+
const DEFAULT_NORMAL = normalsList[0];
|
|
10754
|
+
const imageName = normalsList[id] || DEFAULT_NORMAL;
|
|
10755
|
+
const url = `${NORMAL_ROOT}/normals/${imageName}`;
|
|
10756
|
+
const normalTexture = useTexture(url, onLoad);
|
|
10757
|
+
React.useLayoutEffect(() => {
|
|
10758
|
+
if (!normalTexture) return;
|
|
10759
|
+
normalTexture.wrapS = normalTexture.wrapT = RepeatWrapping;
|
|
10760
|
+
normalTexture.repeat = new Vector2(repeat[0], repeat[1]);
|
|
10761
|
+
normalTexture.offset = new Vector2(offset[0], offset[1]);
|
|
10762
|
+
normalTexture.anisotropy = anisotropy;
|
|
10763
|
+
}, [normalTexture, anisotropy, repeat, offset]);
|
|
10764
|
+
return [normalTexture, url, numTot];
|
|
10765
|
+
}
|
|
10766
|
+
const NormalTexture = ({
|
|
10767
|
+
children,
|
|
10768
|
+
id,
|
|
10769
|
+
onLoad,
|
|
10770
|
+
...settings
|
|
10771
|
+
}) => {
|
|
10772
|
+
const ret = useNormalTexture(id, settings, onLoad);
|
|
10773
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, children?.(ret));
|
|
10693
10774
|
};
|
|
10694
|
-
|
|
10695
|
-
|
|
10775
|
+
|
|
10776
|
+
function CycleRaycast({
|
|
10777
|
+
onChanged,
|
|
10778
|
+
portal,
|
|
10779
|
+
preventDefault = true,
|
|
10780
|
+
scroll = true,
|
|
10781
|
+
keyCode = 9
|
|
10782
|
+
}) {
|
|
10783
|
+
const cycle = React.useRef(0);
|
|
10784
|
+
const setEvents = useThree((state) => state.setEvents);
|
|
10785
|
+
const get = useThree((state) => state.get);
|
|
10786
|
+
const gl = useThree((state) => state.gl);
|
|
10696
10787
|
React.useEffect(() => {
|
|
10697
|
-
|
|
10698
|
-
|
|
10788
|
+
let hits = [];
|
|
10789
|
+
let lastEvent = void 0;
|
|
10790
|
+
const prev = get().events.filter;
|
|
10791
|
+
const target = portal?.current ?? gl.domElement.parentNode;
|
|
10792
|
+
const renderStatus = () => target && onChanged && onChanged(hits, Math.round(cycle.current) % hits.length);
|
|
10793
|
+
setEvents({
|
|
10794
|
+
filter: (intersections, state) => {
|
|
10795
|
+
let clone = [...intersections];
|
|
10796
|
+
if (clone.length !== hits.length || !hits.every((hit) => clone.map((e) => e.object.uuid).includes(hit.object.uuid))) {
|
|
10797
|
+
cycle.current = 0;
|
|
10798
|
+
hits = clone;
|
|
10799
|
+
renderStatus();
|
|
10800
|
+
}
|
|
10801
|
+
if (prev) clone = prev(clone, state);
|
|
10802
|
+
for (let i = 0; i < Math.round(cycle.current) % clone.length; i++) {
|
|
10803
|
+
const first = clone.shift();
|
|
10804
|
+
clone = [...clone, first];
|
|
10805
|
+
}
|
|
10806
|
+
return clone;
|
|
10807
|
+
}
|
|
10808
|
+
});
|
|
10809
|
+
const refresh = (fn) => {
|
|
10810
|
+
cycle.current = fn(cycle.current);
|
|
10811
|
+
get().events.handlers?.onPointerCancel(void 0);
|
|
10812
|
+
get().events.handlers?.onPointerMove(lastEvent);
|
|
10813
|
+
renderStatus();
|
|
10814
|
+
};
|
|
10815
|
+
const tabEvent = (event) => {
|
|
10816
|
+
if ((event.keyCode || event.which) === keyCode) {
|
|
10817
|
+
if (preventDefault) event.preventDefault();
|
|
10818
|
+
if (hits.length > 1) refresh((current) => current + 1);
|
|
10819
|
+
}
|
|
10820
|
+
};
|
|
10821
|
+
const wheelEvent = (event) => {
|
|
10822
|
+
if (preventDefault) event.preventDefault();
|
|
10823
|
+
let delta = 0;
|
|
10824
|
+
if (!event) event = window.event;
|
|
10825
|
+
if (event.wheelDelta) delta = event.wheelDelta / 120;
|
|
10826
|
+
else if (event.detail) delta = -event.detail / 3;
|
|
10827
|
+
if (hits.length > 1) refresh((current) => Math.abs(current - delta));
|
|
10828
|
+
};
|
|
10829
|
+
const moveEvent = (event) => lastEvent = event;
|
|
10830
|
+
document.addEventListener("pointermove", moveEvent, { passive: true });
|
|
10831
|
+
if (scroll) document.addEventListener("wheel", wheelEvent);
|
|
10832
|
+
if (keyCode !== void 0) document.addEventListener("keydown", tabEvent);
|
|
10833
|
+
return () => {
|
|
10834
|
+
setEvents({ filter: prev });
|
|
10835
|
+
if (keyCode !== void 0) document.removeEventListener("keydown", tabEvent);
|
|
10836
|
+
if (scroll) document.removeEventListener("wheel", wheelEvent);
|
|
10837
|
+
document.removeEventListener("pointermove", moveEvent);
|
|
10838
|
+
};
|
|
10839
|
+
}, [gl, get, setEvents, preventDefault, scroll, keyCode]);
|
|
10699
10840
|
return null;
|
|
10700
10841
|
}
|
|
10701
|
-
|
|
10842
|
+
|
|
10843
|
+
function useAspect(width, height, factor = 1) {
|
|
10844
|
+
const v = useThree((state) => state.viewport);
|
|
10845
|
+
const adaptedHeight = height * (v.aspect > width / height ? v.width / width : v.height / height);
|
|
10846
|
+
const adaptedWidth = width * (v.aspect > width / height ? v.width / width : v.height / height);
|
|
10847
|
+
return [adaptedWidth * factor, adaptedHeight * factor, 1];
|
|
10848
|
+
}
|
|
10849
|
+
|
|
10850
|
+
function useCursor(hovered, onPointerOver = "pointer", onPointerOut = "auto", container = document.body) {
|
|
10851
|
+
React.useEffect(() => {
|
|
10852
|
+
if (hovered) {
|
|
10853
|
+
container.style.cursor = onPointerOver;
|
|
10854
|
+
return () => void (container.style.cursor = onPointerOut);
|
|
10855
|
+
}
|
|
10856
|
+
}, [hovered]);
|
|
10857
|
+
}
|
|
10858
|
+
|
|
10859
|
+
const ScreenSpace = /* @__PURE__ */ React.forwardRef(({ children, depth = -1, ...rest }, ref) => {
|
|
10860
|
+
const localRef = React.useRef(null);
|
|
10861
|
+
React.useImperativeHandle(ref, () => localRef.current, []);
|
|
10862
|
+
useFrame(({ camera }) => {
|
|
10863
|
+
localRef.current.quaternion.copy(camera.quaternion);
|
|
10864
|
+
localRef.current.position.copy(camera.position);
|
|
10865
|
+
});
|
|
10866
|
+
return /* @__PURE__ */ React.createElement("group", { ref: localRef, ...rest }, /* @__PURE__ */ React.createElement("group", { "position-z": -depth }, children));
|
|
10867
|
+
});
|
|
10868
|
+
|
|
10869
|
+
const context = /* @__PURE__ */ React.createContext([]);
|
|
10870
|
+
function Select({
|
|
10871
|
+
box,
|
|
10872
|
+
multiple,
|
|
10702
10873
|
children,
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
preset = "rembrandt",
|
|
10874
|
+
onChange,
|
|
10875
|
+
onChangePointerUp,
|
|
10876
|
+
border = "1px solid #55aaff",
|
|
10877
|
+
backgroundColor = "rgba(75, 160, 255, 0.1)",
|
|
10878
|
+
filter: customFilter = (item) => item,
|
|
10709
10879
|
...props
|
|
10710
10880
|
}) {
|
|
10711
|
-
const
|
|
10712
|
-
const
|
|
10713
|
-
const
|
|
10714
|
-
const
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
|
|
10881
|
+
const [downed, down] = React.useState(false);
|
|
10882
|
+
const { setEvents, camera, raycaster, gl, controls, size, get } = useThree();
|
|
10883
|
+
const [hovered, hover] = React.useState(false);
|
|
10884
|
+
const [active, dispatch] = React.useReducer(
|
|
10885
|
+
// @ts-expect-error
|
|
10886
|
+
(state, { object, shift }) => {
|
|
10887
|
+
if (object === void 0) return [];
|
|
10888
|
+
else if (Array.isArray(object)) return object;
|
|
10889
|
+
else if (!shift) return state[0] === object ? [] : [object];
|
|
10890
|
+
else if (state.includes(object)) return state.filter((o) => o !== object);
|
|
10891
|
+
else return [object, ...state];
|
|
10892
|
+
},
|
|
10893
|
+
[]
|
|
10894
|
+
);
|
|
10895
|
+
React.useEffect(() => {
|
|
10896
|
+
if (downed) onChange?.(active);
|
|
10897
|
+
else onChangePointerUp?.(active);
|
|
10898
|
+
}, [active, downed]);
|
|
10899
|
+
const onClick = React.useCallback((e) => {
|
|
10900
|
+
e.stopPropagation();
|
|
10901
|
+
dispatch({ object: customFilter([e.object])[0], shift: multiple && e.shiftKey });
|
|
10725
10902
|
}, []);
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
|
|
10730
|
-
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
|
|
10903
|
+
const onPointerMissed = React.useCallback((e) => !hovered && dispatch({}), [hovered]);
|
|
10904
|
+
const ref = React.useRef(null);
|
|
10905
|
+
React.useEffect(() => {
|
|
10906
|
+
if (!box || !multiple) return;
|
|
10907
|
+
const selBox = new SelectionBox(camera, ref.current);
|
|
10908
|
+
const element = document.createElement("div");
|
|
10909
|
+
element.style.pointerEvents = "none";
|
|
10910
|
+
element.style.border = border;
|
|
10911
|
+
element.style.backgroundColor = backgroundColor;
|
|
10912
|
+
element.style.position = "fixed";
|
|
10913
|
+
const startPoint = new THREE.Vector2();
|
|
10914
|
+
const pointTopLeft = new THREE.Vector2();
|
|
10915
|
+
const pointBottomRight = new THREE.Vector2();
|
|
10916
|
+
const oldRaycasterEnabled = get().events.enabled;
|
|
10917
|
+
const oldControlsEnabled = controls?.enabled;
|
|
10918
|
+
let isDown = false;
|
|
10919
|
+
function prepareRay(event, vec) {
|
|
10920
|
+
const { offsetX, offsetY } = event;
|
|
10921
|
+
const { width, height } = size;
|
|
10922
|
+
vec.set(offsetX / width * 2 - 1, -(offsetY / height) * 2 + 1);
|
|
10923
|
+
}
|
|
10924
|
+
function onSelectStart(event) {
|
|
10925
|
+
if (controls) controls.enabled = false;
|
|
10926
|
+
setEvents({ enabled: false });
|
|
10927
|
+
down(isDown = true);
|
|
10928
|
+
gl.domElement.parentElement?.appendChild(element);
|
|
10929
|
+
element.style.left = `${event.clientX}px`;
|
|
10930
|
+
element.style.top = `${event.clientY}px`;
|
|
10931
|
+
element.style.width = "0px";
|
|
10932
|
+
element.style.height = "0px";
|
|
10933
|
+
startPoint.x = event.clientX;
|
|
10934
|
+
startPoint.y = event.clientY;
|
|
10935
|
+
}
|
|
10936
|
+
function onSelectMove(event) {
|
|
10937
|
+
pointBottomRight.x = Math.max(startPoint.x, event.clientX);
|
|
10938
|
+
pointBottomRight.y = Math.max(startPoint.y, event.clientY);
|
|
10939
|
+
pointTopLeft.x = Math.min(startPoint.x, event.clientX);
|
|
10940
|
+
pointTopLeft.y = Math.min(startPoint.y, event.clientY);
|
|
10941
|
+
element.style.left = `${pointTopLeft.x}px`;
|
|
10942
|
+
element.style.top = `${pointTopLeft.y}px`;
|
|
10943
|
+
element.style.width = `${pointBottomRight.x - pointTopLeft.x}px`;
|
|
10944
|
+
element.style.height = `${pointBottomRight.y - pointTopLeft.y}px`;
|
|
10945
|
+
}
|
|
10946
|
+
function onSelectOver() {
|
|
10947
|
+
if (isDown) {
|
|
10948
|
+
if (controls) controls.enabled = oldControlsEnabled;
|
|
10949
|
+
setEvents({ enabled: oldRaycasterEnabled });
|
|
10950
|
+
down(isDown = false);
|
|
10951
|
+
element.parentElement?.removeChild(element);
|
|
10952
|
+
}
|
|
10736
10953
|
}
|
|
10737
|
-
|
|
10738
|
-
|
|
10739
|
-
|
|
10740
|
-
|
|
10741
|
-
|
|
10954
|
+
function pointerDown(event) {
|
|
10955
|
+
if (event.shiftKey) {
|
|
10956
|
+
onSelectStart(event);
|
|
10957
|
+
prepareRay(event, selBox.startPoint);
|
|
10958
|
+
}
|
|
10742
10959
|
}
|
|
10743
|
-
|
|
10744
|
-
|
|
10960
|
+
let previous = [];
|
|
10961
|
+
function pointerMove(event) {
|
|
10962
|
+
if (isDown) {
|
|
10963
|
+
onSelectMove(event);
|
|
10964
|
+
prepareRay(event, selBox.endPoint);
|
|
10965
|
+
const allSelected = selBox.select().sort((o) => o.uuid).filter((o) => o.isMesh);
|
|
10966
|
+
if (!shallow(allSelected, previous)) {
|
|
10967
|
+
previous = allSelected;
|
|
10968
|
+
dispatch({ object: customFilter(allSelected) });
|
|
10969
|
+
}
|
|
10970
|
+
}
|
|
10971
|
+
}
|
|
10972
|
+
function pointerUp(event) {
|
|
10973
|
+
if (isDown) onSelectOver();
|
|
10974
|
+
}
|
|
10975
|
+
document.addEventListener("pointerdown", pointerDown, { passive: true });
|
|
10976
|
+
document.addEventListener("pointermove", pointerMove, { passive: true, capture: true });
|
|
10977
|
+
document.addEventListener("pointerup", pointerUp, { passive: true });
|
|
10978
|
+
return () => {
|
|
10979
|
+
document.removeEventListener("pointerdown", pointerDown);
|
|
10980
|
+
document.removeEventListener("pointermove", pointerMove, true);
|
|
10981
|
+
document.removeEventListener("pointerup", pointerUp);
|
|
10982
|
+
};
|
|
10983
|
+
}, [size.width, size.height, raycaster, camera, controls, gl]);
|
|
10984
|
+
return /* @__PURE__ */ React.createElement(
|
|
10985
|
+
"group",
|
|
10745
10986
|
{
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
...
|
|
10987
|
+
ref,
|
|
10988
|
+
onClick,
|
|
10989
|
+
onPointerOver: () => hover(true),
|
|
10990
|
+
onPointerOut: () => hover(false),
|
|
10991
|
+
onPointerMissed,
|
|
10992
|
+
...props
|
|
10752
10993
|
},
|
|
10753
|
-
/* @__PURE__ */ React.createElement(
|
|
10754
|
-
|
|
10755
|
-
{
|
|
10756
|
-
amount: shadowSpread.amount ?? 8,
|
|
10757
|
-
radius: shadowSpread.radius ?? radius,
|
|
10758
|
-
ambient: shadowSpread.ambient ?? 0.5,
|
|
10759
|
-
intensity: shadowSpread.intensity ?? 1,
|
|
10760
|
-
position: [config.main[0] * radius, config.main[1] * radius, config.main[2] * radius],
|
|
10761
|
-
size: radius * 4,
|
|
10762
|
-
bias: -shadowBias,
|
|
10763
|
-
mapSize: shadowSize
|
|
10764
|
-
}
|
|
10765
|
-
)
|
|
10766
|
-
)), environment && /* @__PURE__ */ React.createElement(Environment, { ...environmentProps }));
|
|
10994
|
+
/* @__PURE__ */ React.createElement(context.Provider, { value: active }, children)
|
|
10995
|
+
);
|
|
10767
10996
|
}
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
switch (format) {
|
|
10771
|
-
case 64:
|
|
10772
|
-
return "-64px";
|
|
10773
|
-
case 128:
|
|
10774
|
-
return "-128px";
|
|
10775
|
-
case 256:
|
|
10776
|
-
return "-256px";
|
|
10777
|
-
case 512:
|
|
10778
|
-
return "-512px";
|
|
10779
|
-
default:
|
|
10780
|
-
return "";
|
|
10781
|
-
}
|
|
10997
|
+
function useSelect() {
|
|
10998
|
+
return React.useContext(context);
|
|
10782
10999
|
}
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
|
|
10786
|
-
|
|
10787
|
-
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10797
|
-
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
|
|
11000
|
+
|
|
11001
|
+
function AsciiRenderer({
|
|
11002
|
+
renderIndex = 1,
|
|
11003
|
+
bgColor = "black",
|
|
11004
|
+
fgColor = "white",
|
|
11005
|
+
characters = " .:-+*=%@#",
|
|
11006
|
+
invert = true,
|
|
11007
|
+
color = false,
|
|
11008
|
+
resolution = 0.15
|
|
11009
|
+
}) {
|
|
11010
|
+
const { size, gl, scene, camera } = useThree();
|
|
11011
|
+
const effect = React.useMemo(() => {
|
|
11012
|
+
const effect2 = new AsciiEffect(gl, characters, { invert, color, resolution });
|
|
11013
|
+
effect2.domElement.style.position = "absolute";
|
|
11014
|
+
effect2.domElement.style.top = "0px";
|
|
11015
|
+
effect2.domElement.style.left = "0px";
|
|
11016
|
+
effect2.domElement.style.pointerEvents = "none";
|
|
11017
|
+
return effect2;
|
|
11018
|
+
}, [characters, invert, color, resolution]);
|
|
11019
|
+
React.useLayoutEffect(() => {
|
|
11020
|
+
effect.domElement.style.color = fgColor;
|
|
11021
|
+
effect.domElement.style.backgroundColor = bgColor;
|
|
11022
|
+
}, [fgColor, bgColor]);
|
|
11023
|
+
React.useEffect(() => {
|
|
11024
|
+
gl.domElement.style.opacity = "0";
|
|
11025
|
+
gl.domElement.parentNode.appendChild(effect.domElement);
|
|
11026
|
+
return () => {
|
|
11027
|
+
gl.domElement.style.opacity = "1";
|
|
11028
|
+
gl.domElement.parentNode.removeChild(effect.domElement);
|
|
11029
|
+
};
|
|
11030
|
+
}, [effect]);
|
|
11031
|
+
React.useEffect(() => {
|
|
11032
|
+
effect.setSize(size.width, size.height);
|
|
11033
|
+
}, [effect, size]);
|
|
11034
|
+
useFrame((state) => {
|
|
11035
|
+
effect.render(scene, camera);
|
|
11036
|
+
}, renderIndex);
|
|
11037
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
10801
11038
|
}
|
|
10802
|
-
const MatcapTexture = ({
|
|
10803
|
-
children,
|
|
10804
|
-
id,
|
|
10805
|
-
format,
|
|
10806
|
-
onLoad
|
|
10807
|
-
}) => {
|
|
10808
|
-
const texture = useMatcapTexture(id, format, onLoad);
|
|
10809
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, children?.(texture));
|
|
10810
|
-
};
|
|
10811
11039
|
|
|
10812
|
-
const
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
10818
|
-
|
|
10819
|
-
|
|
10820
|
-
|
|
10821
|
-
|
|
10822
|
-
|
|
10823
|
-
|
|
10824
|
-
|
|
10825
|
-
|
|
10826
|
-
|
|
10827
|
-
|
|
10828
|
-
|
|
10829
|
-
|
|
10830
|
-
|
|
10831
|
-
|
|
10832
|
-
|
|
10833
|
-
|
|
10834
|
-
|
|
10835
|
-
|
|
10836
|
-
|
|
10837
|
-
|
|
10838
|
-
|
|
10839
|
-
|
|
11040
|
+
const WireframeMaterialShaders = {
|
|
11041
|
+
uniforms: {
|
|
11042
|
+
strokeOpacity: 1,
|
|
11043
|
+
fillOpacity: 0.25,
|
|
11044
|
+
fillMix: 0,
|
|
11045
|
+
thickness: 0.05,
|
|
11046
|
+
colorBackfaces: false,
|
|
11047
|
+
dashInvert: true,
|
|
11048
|
+
dash: false,
|
|
11049
|
+
dashRepeats: 4,
|
|
11050
|
+
dashLength: 0.5,
|
|
11051
|
+
squeeze: false,
|
|
11052
|
+
squeezeMin: 0.2,
|
|
11053
|
+
squeezeMax: 1,
|
|
11054
|
+
stroke: /* @__PURE__ */ new THREE.Color("#ff0000"),
|
|
11055
|
+
backfaceStroke: /* @__PURE__ */ new THREE.Color("#0000ff"),
|
|
11056
|
+
fill: /* @__PURE__ */ new THREE.Color("#00ff00")
|
|
11057
|
+
},
|
|
11058
|
+
vertex: (
|
|
11059
|
+
/* glsl */
|
|
11060
|
+
`
|
|
11061
|
+
attribute vec3 barycentric;
|
|
11062
|
+
|
|
11063
|
+
varying vec3 v_edges_Barycentric;
|
|
11064
|
+
varying vec3 v_edges_Position;
|
|
11065
|
+
|
|
11066
|
+
void initWireframe() {
|
|
11067
|
+
v_edges_Barycentric = barycentric;
|
|
11068
|
+
v_edges_Position = position.xyz;
|
|
11069
|
+
}
|
|
11070
|
+
`
|
|
11071
|
+
),
|
|
11072
|
+
fragment: (
|
|
11073
|
+
/* glsl */
|
|
11074
|
+
`
|
|
11075
|
+
#ifndef PI
|
|
11076
|
+
#define PI 3.1415926535897932384626433832795
|
|
11077
|
+
#endif
|
|
11078
|
+
|
|
11079
|
+
varying vec3 v_edges_Barycentric;
|
|
11080
|
+
varying vec3 v_edges_Position;
|
|
11081
|
+
|
|
11082
|
+
uniform float strokeOpacity;
|
|
11083
|
+
uniform float fillOpacity;
|
|
11084
|
+
uniform float fillMix;
|
|
11085
|
+
uniform float thickness;
|
|
11086
|
+
uniform bool colorBackfaces;
|
|
11087
|
+
|
|
11088
|
+
// Dash
|
|
11089
|
+
uniform bool dashInvert;
|
|
11090
|
+
uniform bool dash;
|
|
11091
|
+
uniform bool dashOnly;
|
|
11092
|
+
uniform float dashRepeats;
|
|
11093
|
+
uniform float dashLength;
|
|
11094
|
+
|
|
11095
|
+
// Squeeze
|
|
11096
|
+
uniform bool squeeze;
|
|
11097
|
+
uniform float squeezeMin;
|
|
11098
|
+
uniform float squeezeMax;
|
|
11099
|
+
|
|
11100
|
+
// Colors
|
|
11101
|
+
uniform vec3 stroke;
|
|
11102
|
+
uniform vec3 backfaceStroke;
|
|
11103
|
+
uniform vec3 fill;
|
|
11104
|
+
|
|
11105
|
+
// This is like
|
|
11106
|
+
float wireframe_aastep(float threshold, float dist) {
|
|
11107
|
+
float afwidth = fwidth(dist) * 0.5;
|
|
11108
|
+
return smoothstep(threshold - afwidth, threshold + afwidth, dist);
|
|
11109
|
+
}
|
|
11110
|
+
|
|
11111
|
+
float wireframe_map(float value, float min1, float max1, float min2, float max2) {
|
|
11112
|
+
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
|
11113
|
+
}
|
|
11114
|
+
|
|
11115
|
+
float getWireframe() {
|
|
11116
|
+
vec3 barycentric = v_edges_Barycentric;
|
|
11117
|
+
|
|
11118
|
+
// Distance from center of each triangle to its edges.
|
|
11119
|
+
float d = min(min(barycentric.x, barycentric.y), barycentric.z);
|
|
11120
|
+
|
|
11121
|
+
// for dashed rendering, we can use this to get the 0 .. 1 value of the line length
|
|
11122
|
+
float positionAlong = max(barycentric.x, barycentric.y);
|
|
11123
|
+
if (barycentric.y < barycentric.x && barycentric.y < barycentric.z) {
|
|
11124
|
+
positionAlong = 1.0 - positionAlong;
|
|
11125
|
+
}
|
|
11126
|
+
|
|
11127
|
+
// the thickness of the stroke
|
|
11128
|
+
float computedThickness = wireframe_map(thickness, 0.0, 1.0, 0.0, 0.34);
|
|
11129
|
+
|
|
11130
|
+
// if we want to shrink the thickness toward the center of the line segment
|
|
11131
|
+
if (squeeze) {
|
|
11132
|
+
computedThickness *= mix(squeezeMin, squeezeMax, (1.0 - sin(positionAlong * PI)));
|
|
11133
|
+
}
|
|
11134
|
+
|
|
11135
|
+
// Create dash pattern
|
|
11136
|
+
if (dash) {
|
|
11137
|
+
// here we offset the stroke position depending on whether it
|
|
11138
|
+
// should overlap or not
|
|
11139
|
+
float offset = 1.0 / dashRepeats * dashLength / 2.0;
|
|
11140
|
+
if (!dashInvert) {
|
|
11141
|
+
offset += 1.0 / dashRepeats / 2.0;
|
|
11142
|
+
}
|
|
11143
|
+
|
|
11144
|
+
// if we should animate the dash or not
|
|
11145
|
+
// if (dashAnimate) {
|
|
11146
|
+
// offset += time * 0.22;
|
|
11147
|
+
// }
|
|
11148
|
+
|
|
11149
|
+
// create the repeating dash pattern
|
|
11150
|
+
float pattern = fract((positionAlong + offset) * dashRepeats);
|
|
11151
|
+
computedThickness *= 1.0 - wireframe_aastep(dashLength, pattern);
|
|
11152
|
+
}
|
|
10840
11153
|
|
|
10841
|
-
|
|
10842
|
-
|
|
10843
|
-
portal,
|
|
10844
|
-
preventDefault = true,
|
|
10845
|
-
scroll = true,
|
|
10846
|
-
keyCode = 9
|
|
10847
|
-
}) {
|
|
10848
|
-
const cycle = React.useRef(0);
|
|
10849
|
-
const setEvents = useThree((state) => state.setEvents);
|
|
10850
|
-
const get = useThree((state) => state.get);
|
|
10851
|
-
const gl = useThree((state) => state.gl);
|
|
10852
|
-
React.useEffect(() => {
|
|
10853
|
-
let hits = [];
|
|
10854
|
-
let lastEvent = void 0;
|
|
10855
|
-
const prev = get().events.filter;
|
|
10856
|
-
const target = portal?.current ?? gl.domElement.parentNode;
|
|
10857
|
-
const renderStatus = () => target && onChanged && onChanged(hits, Math.round(cycle.current) % hits.length);
|
|
10858
|
-
setEvents({
|
|
10859
|
-
filter: (intersections, state) => {
|
|
10860
|
-
let clone = [...intersections];
|
|
10861
|
-
if (clone.length !== hits.length || !hits.every((hit) => clone.map((e) => e.object.uuid).includes(hit.object.uuid))) {
|
|
10862
|
-
cycle.current = 0;
|
|
10863
|
-
hits = clone;
|
|
10864
|
-
renderStatus();
|
|
10865
|
-
}
|
|
10866
|
-
if (prev) clone = prev(clone, state);
|
|
10867
|
-
for (let i = 0; i < Math.round(cycle.current) % clone.length; i++) {
|
|
10868
|
-
const first = clone.shift();
|
|
10869
|
-
clone = [...clone, first];
|
|
10870
|
-
}
|
|
10871
|
-
return clone;
|
|
10872
|
-
}
|
|
10873
|
-
});
|
|
10874
|
-
const refresh = (fn) => {
|
|
10875
|
-
cycle.current = fn(cycle.current);
|
|
10876
|
-
get().events.handlers?.onPointerCancel(void 0);
|
|
10877
|
-
get().events.handlers?.onPointerMove(lastEvent);
|
|
10878
|
-
renderStatus();
|
|
10879
|
-
};
|
|
10880
|
-
const tabEvent = (event) => {
|
|
10881
|
-
if ((event.keyCode || event.which) === keyCode) {
|
|
10882
|
-
if (preventDefault) event.preventDefault();
|
|
10883
|
-
if (hits.length > 1) refresh((current) => current + 1);
|
|
10884
|
-
}
|
|
10885
|
-
};
|
|
10886
|
-
const wheelEvent = (event) => {
|
|
10887
|
-
if (preventDefault) event.preventDefault();
|
|
10888
|
-
let delta = 0;
|
|
10889
|
-
if (!event) event = window.event;
|
|
10890
|
-
if (event.wheelDelta) delta = event.wheelDelta / 120;
|
|
10891
|
-
else if (event.detail) delta = -event.detail / 3;
|
|
10892
|
-
if (hits.length > 1) refresh((current) => Math.abs(current - delta));
|
|
10893
|
-
};
|
|
10894
|
-
const moveEvent = (event) => lastEvent = event;
|
|
10895
|
-
document.addEventListener("pointermove", moveEvent, { passive: true });
|
|
10896
|
-
if (scroll) document.addEventListener("wheel", wheelEvent);
|
|
10897
|
-
if (keyCode !== void 0) document.addEventListener("keydown", tabEvent);
|
|
10898
|
-
return () => {
|
|
10899
|
-
setEvents({ filter: prev });
|
|
10900
|
-
if (keyCode !== void 0) document.removeEventListener("keydown", tabEvent);
|
|
10901
|
-
if (scroll) document.removeEventListener("wheel", wheelEvent);
|
|
10902
|
-
document.removeEventListener("pointermove", moveEvent);
|
|
10903
|
-
};
|
|
10904
|
-
}, [gl, get, setEvents, preventDefault, scroll, keyCode]);
|
|
10905
|
-
return null;
|
|
10906
|
-
}
|
|
11154
|
+
// compute the anti-aliased stroke edge
|
|
11155
|
+
float edge = 1.0 - wireframe_aastep(computedThickness, d);
|
|
10907
11156
|
|
|
10908
|
-
|
|
10909
|
-
|
|
10910
|
-
|
|
10911
|
-
|
|
10912
|
-
|
|
10913
|
-
|
|
11157
|
+
return edge;
|
|
11158
|
+
}
|
|
11159
|
+
`
|
|
11160
|
+
)
|
|
11161
|
+
};
|
|
11162
|
+
const WireframeMaterial = /* @__PURE__ */ shaderMaterial(
|
|
11163
|
+
WireframeMaterialShaders.uniforms,
|
|
11164
|
+
WireframeMaterialShaders.vertex + /* glsl */
|
|
11165
|
+
`
|
|
11166
|
+
void main() {
|
|
11167
|
+
initWireframe();
|
|
11168
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
11169
|
+
}
|
|
11170
|
+
`,
|
|
11171
|
+
WireframeMaterialShaders.fragment + /* glsl */
|
|
11172
|
+
`
|
|
11173
|
+
void main () {
|
|
11174
|
+
// Compute color
|
|
10914
11175
|
|
|
10915
|
-
|
|
10916
|
-
|
|
10917
|
-
if (hovered) {
|
|
10918
|
-
container.style.cursor = onPointerOver;
|
|
10919
|
-
return () => void (container.style.cursor = onPointerOut);
|
|
10920
|
-
}
|
|
10921
|
-
}, [hovered]);
|
|
10922
|
-
}
|
|
11176
|
+
float edge = getWireframe();
|
|
11177
|
+
vec4 colorStroke = vec4(stroke, edge);
|
|
10923
11178
|
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
|
|
10928
|
-
|
|
10929
|
-
|
|
10930
|
-
});
|
|
10931
|
-
return /* @__PURE__ */ React.createElement("group", { ref: localRef, ...rest }, /* @__PURE__ */ React.createElement("group", { "position-z": -depth }, children));
|
|
10932
|
-
});
|
|
11179
|
+
#ifdef FLIP_SIDED
|
|
11180
|
+
colorStroke.rgb = backfaceStroke;
|
|
11181
|
+
#endif
|
|
11182
|
+
|
|
11183
|
+
vec4 colorFill = vec4(fill, fillOpacity);
|
|
11184
|
+
vec4 outColor = mix(colorFill, colorStroke, edge * strokeOpacity);
|
|
10933
11185
|
|
|
10934
|
-
|
|
10935
|
-
|
|
10936
|
-
|
|
10937
|
-
|
|
10938
|
-
|
|
10939
|
-
|
|
10940
|
-
|
|
10941
|
-
|
|
10942
|
-
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
|
|
10947
|
-
|
|
10948
|
-
|
|
10949
|
-
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
11186
|
+
gl_FragColor = outColor;
|
|
11187
|
+
}
|
|
11188
|
+
`
|
|
11189
|
+
);
|
|
11190
|
+
function setWireframeOverride(material, uniforms) {
|
|
11191
|
+
material.onBeforeCompile = (shader) => {
|
|
11192
|
+
shader.uniforms = {
|
|
11193
|
+
...shader.uniforms,
|
|
11194
|
+
...uniforms
|
|
11195
|
+
};
|
|
11196
|
+
shader.vertexShader = shader.vertexShader.replace(
|
|
11197
|
+
"void main() {",
|
|
11198
|
+
`
|
|
11199
|
+
${WireframeMaterialShaders.vertex}
|
|
11200
|
+
void main() {
|
|
11201
|
+
initWireframe();
|
|
11202
|
+
`
|
|
11203
|
+
);
|
|
11204
|
+
shader.fragmentShader = shader.fragmentShader.replace(
|
|
11205
|
+
"void main() {",
|
|
11206
|
+
`
|
|
11207
|
+
${WireframeMaterialShaders.fragment}
|
|
11208
|
+
void main() {
|
|
11209
|
+
`
|
|
11210
|
+
);
|
|
11211
|
+
shader.fragmentShader = shader.fragmentShader.replace(
|
|
11212
|
+
"#include <color_fragment>",
|
|
11213
|
+
/* glsl */
|
|
11214
|
+
`
|
|
11215
|
+
#include <color_fragment>
|
|
11216
|
+
float edge = getWireframe();
|
|
11217
|
+
vec4 colorStroke = vec4(stroke, edge);
|
|
11218
|
+
#ifdef FLIP_SIDED
|
|
11219
|
+
colorStroke.rgb = backfaceStroke;
|
|
11220
|
+
#endif
|
|
11221
|
+
vec4 colorFill = vec4(mix(diffuseColor.rgb, fill, fillMix), mix(diffuseColor.a, fillOpacity, fillMix));
|
|
11222
|
+
vec4 outColor = mix(colorFill, colorStroke, edge * strokeOpacity);
|
|
11223
|
+
|
|
11224
|
+
diffuseColor.rgb = outColor.rgb;
|
|
11225
|
+
diffuseColor.a *= outColor.a;
|
|
11226
|
+
`
|
|
11227
|
+
);
|
|
11228
|
+
};
|
|
11229
|
+
material.side = THREE.DoubleSide;
|
|
11230
|
+
material.transparent = true;
|
|
11231
|
+
}
|
|
11232
|
+
function useWireframeUniforms(uniforms, props) {
|
|
11233
|
+
React.useEffect(
|
|
11234
|
+
() => void (uniforms.fillOpacity.value = props.fillOpacity ?? uniforms.fillOpacity.value),
|
|
11235
|
+
[props.fillOpacity]
|
|
11236
|
+
);
|
|
11237
|
+
React.useEffect(() => void (uniforms.fillMix.value = props.fillMix ?? uniforms.fillMix.value), [props.fillMix]);
|
|
11238
|
+
React.useEffect(
|
|
11239
|
+
() => void (uniforms.strokeOpacity.value = props.strokeOpacity ?? uniforms.strokeOpacity.value),
|
|
11240
|
+
[props.strokeOpacity]
|
|
11241
|
+
);
|
|
11242
|
+
React.useEffect(
|
|
11243
|
+
() => void (uniforms.thickness.value = props.thickness ?? uniforms.thickness.value),
|
|
11244
|
+
[props.thickness]
|
|
11245
|
+
);
|
|
11246
|
+
React.useEffect(() => void (uniforms.colorBackfaces.value = !!props.colorBackfaces), [props.colorBackfaces]);
|
|
11247
|
+
React.useEffect(() => void (uniforms.dash.value = !!props.dash), [props.dash]);
|
|
11248
|
+
React.useEffect(() => void (uniforms.dashInvert.value = !!props.dashInvert), [props.dashInvert]);
|
|
11249
|
+
React.useEffect(
|
|
11250
|
+
() => void (uniforms.dashRepeats.value = props.dashRepeats ?? uniforms.dashRepeats.value),
|
|
11251
|
+
[props.dashRepeats]
|
|
11252
|
+
);
|
|
11253
|
+
React.useEffect(
|
|
11254
|
+
() => void (uniforms.dashLength.value = props.dashLength ?? uniforms.dashLength.value),
|
|
11255
|
+
[props.dashLength]
|
|
11256
|
+
);
|
|
11257
|
+
React.useEffect(() => void (uniforms.squeeze.value = !!props.squeeze), [props.squeeze]);
|
|
11258
|
+
React.useEffect(
|
|
11259
|
+
() => void (uniforms.squeezeMin.value = props.squeezeMin ?? uniforms.squeezeMin.value),
|
|
11260
|
+
[props.squeezeMin]
|
|
11261
|
+
);
|
|
11262
|
+
React.useEffect(
|
|
11263
|
+
() => void (uniforms.squeezeMax.value = props.squeezeMax ?? uniforms.squeezeMax.value),
|
|
11264
|
+
[props.squeezeMax]
|
|
10959
11265
|
);
|
|
10960
|
-
React.useEffect(
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
10964
|
-
|
|
10965
|
-
|
|
10966
|
-
|
|
10967
|
-
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
|
|
10980
|
-
|
|
10981
|
-
|
|
10982
|
-
|
|
10983
|
-
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
|
|
11001
|
-
|
|
11002
|
-
|
|
11003
|
-
|
|
11004
|
-
|
|
11005
|
-
|
|
11006
|
-
|
|
11007
|
-
element.style.top = `${pointTopLeft.y}px`;
|
|
11008
|
-
element.style.width = `${pointBottomRight.x - pointTopLeft.x}px`;
|
|
11009
|
-
element.style.height = `${pointBottomRight.y - pointTopLeft.y}px`;
|
|
11266
|
+
React.useEffect(
|
|
11267
|
+
() => void (uniforms.stroke.value = props.stroke ? new THREE.Color(props.stroke) : uniforms.stroke.value),
|
|
11268
|
+
[props.stroke]
|
|
11269
|
+
);
|
|
11270
|
+
React.useEffect(
|
|
11271
|
+
() => void (uniforms.fill.value = props.fill ? new THREE.Color(props.fill) : uniforms.fill.value),
|
|
11272
|
+
[props.fill]
|
|
11273
|
+
);
|
|
11274
|
+
React.useEffect(
|
|
11275
|
+
() => void (uniforms.backfaceStroke.value = props.backfaceStroke ? new THREE.Color(props.backfaceStroke) : uniforms.backfaceStroke.value),
|
|
11276
|
+
[props.backfaceStroke]
|
|
11277
|
+
);
|
|
11278
|
+
}
|
|
11279
|
+
|
|
11280
|
+
function isWithGeometry(object) {
|
|
11281
|
+
return !!object?.geometry;
|
|
11282
|
+
}
|
|
11283
|
+
function isGeometry(object) {
|
|
11284
|
+
return !!object?.isBufferGeometry;
|
|
11285
|
+
}
|
|
11286
|
+
function isRefObject(object) {
|
|
11287
|
+
return !!object?.current;
|
|
11288
|
+
}
|
|
11289
|
+
function isRef(object) {
|
|
11290
|
+
return object?.current !== void 0;
|
|
11291
|
+
}
|
|
11292
|
+
function isWireframeGeometry(geometry) {
|
|
11293
|
+
return geometry.type === "WireframeGeometry";
|
|
11294
|
+
}
|
|
11295
|
+
function getUniforms() {
|
|
11296
|
+
const u = {};
|
|
11297
|
+
for (const key in WireframeMaterialShaders.uniforms) {
|
|
11298
|
+
u[key] = { value: WireframeMaterialShaders.uniforms[key] };
|
|
11299
|
+
}
|
|
11300
|
+
return u;
|
|
11301
|
+
}
|
|
11302
|
+
function getBarycentricCoordinates(geometry, removeEdge) {
|
|
11303
|
+
const position = geometry.getAttribute("position");
|
|
11304
|
+
const count = position.count;
|
|
11305
|
+
const barycentric = [];
|
|
11306
|
+
for (let i = 0; i < count; i++) {
|
|
11307
|
+
const even = i % 2 === 0;
|
|
11308
|
+
const Q = removeEdge ? 1 : 0;
|
|
11309
|
+
if (even) {
|
|
11310
|
+
barycentric.push(0, 0, 1, 0, 1, 0, 1, 0, Q);
|
|
11311
|
+
} else {
|
|
11312
|
+
barycentric.push(0, 1, 0, 0, 0, 1, 1, 0, Q);
|
|
11010
11313
|
}
|
|
11011
|
-
|
|
11012
|
-
|
|
11013
|
-
|
|
11014
|
-
|
|
11015
|
-
|
|
11016
|
-
|
|
11017
|
-
|
|
11314
|
+
}
|
|
11315
|
+
return new THREE.BufferAttribute(Float32Array.from(barycentric), 3);
|
|
11316
|
+
}
|
|
11317
|
+
function getInputGeometry(inputGeometry) {
|
|
11318
|
+
const geo = isRefObject(inputGeometry) ? inputGeometry.current : inputGeometry;
|
|
11319
|
+
if (!isGeometry(geo)) {
|
|
11320
|
+
if (isWireframeGeometry(geo)) {
|
|
11321
|
+
throw new Error("Wireframe: WireframeGeometry is not supported.");
|
|
11018
11322
|
}
|
|
11019
|
-
|
|
11020
|
-
|
|
11021
|
-
|
|
11022
|
-
|
|
11323
|
+
const parent = geo.parent;
|
|
11324
|
+
if (isWithGeometry(parent)) {
|
|
11325
|
+
if (isWireframeGeometry(parent.geometry)) {
|
|
11326
|
+
throw new Error("Wireframe: WireframeGeometry is not supported.");
|
|
11023
11327
|
}
|
|
11328
|
+
return parent.geometry;
|
|
11024
11329
|
}
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11330
|
+
} else {
|
|
11331
|
+
return geo;
|
|
11332
|
+
}
|
|
11333
|
+
}
|
|
11334
|
+
function setBarycentricCoordinates(geometry, simplify) {
|
|
11335
|
+
if (geometry.index) {
|
|
11336
|
+
console.warn("Wireframe: Requires non-indexed geometry, converting to non-indexed geometry.");
|
|
11337
|
+
const nonIndexedGeo = geometry.toNonIndexed();
|
|
11338
|
+
geometry.copy(nonIndexedGeo);
|
|
11339
|
+
geometry.setIndex(null);
|
|
11340
|
+
}
|
|
11341
|
+
const newBarycentric = getBarycentricCoordinates(geometry, simplify);
|
|
11342
|
+
geometry.setAttribute("barycentric", newBarycentric);
|
|
11343
|
+
}
|
|
11344
|
+
function WireframeWithCustomGeo({
|
|
11345
|
+
geometry: customGeometry,
|
|
11346
|
+
simplify = false,
|
|
11347
|
+
...props
|
|
11348
|
+
}) {
|
|
11349
|
+
extend({ MeshWireframeMaterial: WireframeMaterial });
|
|
11350
|
+
const [geometry, setGeometry] = React.useState(null);
|
|
11351
|
+
React.useLayoutEffect(() => {
|
|
11352
|
+
const geom = getInputGeometry(customGeometry);
|
|
11353
|
+
if (!geom) {
|
|
11354
|
+
throw new Error("Wireframe: geometry prop must be a BufferGeometry or a ref to a BufferGeometry.");
|
|
11036
11355
|
}
|
|
11037
|
-
|
|
11038
|
-
|
|
11356
|
+
setBarycentricCoordinates(geom, simplify);
|
|
11357
|
+
if (isRef(customGeometry)) {
|
|
11358
|
+
setGeometry(geom);
|
|
11039
11359
|
}
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
11043
|
-
|
|
11044
|
-
document.removeEventListener("pointerdown", pointerDown);
|
|
11045
|
-
document.removeEventListener("pointermove", pointerMove, true);
|
|
11046
|
-
document.removeEventListener("pointerup", pointerUp);
|
|
11047
|
-
};
|
|
11048
|
-
}, [size.width, size.height, raycaster, camera, controls, gl]);
|
|
11049
|
-
return /* @__PURE__ */ React.createElement(
|
|
11050
|
-
"group",
|
|
11360
|
+
}, [simplify, customGeometry]);
|
|
11361
|
+
const drawnGeo = isRef(customGeometry) ? geometry : customGeometry;
|
|
11362
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, drawnGeo && /* @__PURE__ */ React.createElement("mesh", { geometry: drawnGeo }, /* @__PURE__ */ React.createElement(
|
|
11363
|
+
"meshWireframeMaterial",
|
|
11051
11364
|
{
|
|
11052
|
-
|
|
11053
|
-
|
|
11054
|
-
|
|
11055
|
-
|
|
11056
|
-
|
|
11365
|
+
attach: "material",
|
|
11366
|
+
transparent: true,
|
|
11367
|
+
side: THREE.DoubleSide,
|
|
11368
|
+
polygonOffset: true,
|
|
11369
|
+
polygonOffsetFactor: -4,
|
|
11057
11370
|
...props
|
|
11058
|
-
}
|
|
11059
|
-
|
|
11060
|
-
);
|
|
11061
|
-
}
|
|
11062
|
-
function useSelect() {
|
|
11063
|
-
return React.useContext(context);
|
|
11371
|
+
}
|
|
11372
|
+
)));
|
|
11064
11373
|
}
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
bgColor = "black",
|
|
11069
|
-
fgColor = "white",
|
|
11070
|
-
characters = " .:-+*=%@#",
|
|
11071
|
-
invert = true,
|
|
11072
|
-
color = false,
|
|
11073
|
-
resolution = 0.15
|
|
11374
|
+
function WireframeWithoutCustomGeo({
|
|
11375
|
+
simplify = false,
|
|
11376
|
+
...props
|
|
11074
11377
|
}) {
|
|
11075
|
-
const
|
|
11076
|
-
const
|
|
11077
|
-
|
|
11078
|
-
effect2.domElement.style.position = "absolute";
|
|
11079
|
-
effect2.domElement.style.top = "0px";
|
|
11080
|
-
effect2.domElement.style.left = "0px";
|
|
11081
|
-
effect2.domElement.style.pointerEvents = "none";
|
|
11082
|
-
return effect2;
|
|
11083
|
-
}, [characters, invert, color, resolution]);
|
|
11378
|
+
const objectRef = React.useRef(null);
|
|
11379
|
+
const uniforms = React.useMemo(() => getUniforms(), [WireframeMaterialShaders.uniforms]);
|
|
11380
|
+
useWireframeUniforms(uniforms, props);
|
|
11084
11381
|
React.useLayoutEffect(() => {
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
11382
|
+
const geom = getInputGeometry(objectRef);
|
|
11383
|
+
if (!geom) {
|
|
11384
|
+
throw new Error("Wireframe: Must be a child of a Mesh, Line or Points object or specify a geometry prop.");
|
|
11385
|
+
}
|
|
11386
|
+
const og = geom.clone();
|
|
11387
|
+
setBarycentricCoordinates(geom, simplify);
|
|
11091
11388
|
return () => {
|
|
11092
|
-
|
|
11093
|
-
|
|
11389
|
+
geom.copy(og);
|
|
11390
|
+
og.dispose();
|
|
11094
11391
|
};
|
|
11095
|
-
}, [
|
|
11096
|
-
React.
|
|
11097
|
-
|
|
11098
|
-
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11392
|
+
}, [simplify]);
|
|
11393
|
+
React.useLayoutEffect(() => {
|
|
11394
|
+
const parentMesh = objectRef.current.parent;
|
|
11395
|
+
const og = parentMesh.material.clone();
|
|
11396
|
+
setWireframeOverride(parentMesh.material, uniforms);
|
|
11397
|
+
return () => {
|
|
11398
|
+
parentMesh.material.dispose();
|
|
11399
|
+
parentMesh.material = og;
|
|
11400
|
+
};
|
|
11401
|
+
}, []);
|
|
11402
|
+
return /* @__PURE__ */ React.createElement("object3D", { ref: objectRef });
|
|
11403
|
+
}
|
|
11404
|
+
function Wireframe({ geometry: customGeometry, ...props }) {
|
|
11405
|
+
if (customGeometry) {
|
|
11406
|
+
return /* @__PURE__ */ React.createElement(WireframeWithCustomGeo, { geometry: customGeometry, ...props });
|
|
11407
|
+
}
|
|
11408
|
+
return /* @__PURE__ */ React.createElement(WireframeWithoutCustomGeo, { ...props });
|
|
11103
11409
|
}
|
|
11104
11410
|
|
|
11105
11411
|
function BakeShadows() {
|