Initial project import
This commit is contained in:
192
node_modules/@react-three/drei/web/pivotControls/ScalingSphere.js
generated
vendored
Normal file
192
node_modules/@react-three/drei/web/pivotControls/ScalingSphere.js
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
import * as React from 'react';
|
||||
import * as THREE from 'three';
|
||||
import { useThree } from '@react-three/fiber';
|
||||
import { Html } from '../Html.js';
|
||||
import { context } from './context.js';
|
||||
import { calculateScaleFactor } from '../../core/calculateScaleFactor.js';
|
||||
|
||||
const vec1 = /* @__PURE__ */new THREE.Vector3();
|
||||
const vec2 = /* @__PURE__ */new THREE.Vector3();
|
||||
const calculateOffset = (clickPoint, normal, rayStart, rayDir) => {
|
||||
const e1 = normal.dot(normal);
|
||||
const e2 = normal.dot(clickPoint) - normal.dot(rayStart);
|
||||
const e3 = normal.dot(rayDir);
|
||||
if (e3 === 0) {
|
||||
return -e2 / e1;
|
||||
}
|
||||
vec1.copy(rayDir).multiplyScalar(e1 / e3).sub(normal);
|
||||
vec2.copy(rayDir).multiplyScalar(e2 / e3).add(rayStart).sub(clickPoint);
|
||||
const offset = -vec1.dot(vec2) / vec1.dot(vec1);
|
||||
return offset;
|
||||
};
|
||||
const upV = /* @__PURE__ */new THREE.Vector3(0, 1, 0);
|
||||
const scaleV = /* @__PURE__ */new THREE.Vector3();
|
||||
const scaleMatrix = /* @__PURE__ */new THREE.Matrix4();
|
||||
const ScalingSphere = ({
|
||||
direction,
|
||||
axis
|
||||
}) => {
|
||||
const {
|
||||
scaleLimits,
|
||||
annotations,
|
||||
annotationsClass,
|
||||
depthTest,
|
||||
scale,
|
||||
lineWidth,
|
||||
fixed,
|
||||
axisColors,
|
||||
hoveredColor,
|
||||
opacity,
|
||||
renderOrder,
|
||||
onDragStart,
|
||||
onDrag,
|
||||
onDragEnd,
|
||||
userData
|
||||
} = React.useContext(context);
|
||||
const size = useThree(state => state.size);
|
||||
const camControls = useThree(state => state.controls);
|
||||
const divRef = React.useRef(null);
|
||||
const objRef = React.useRef(null);
|
||||
const meshRef = React.useRef(null);
|
||||
const scale0 = React.useRef(1);
|
||||
const scaleCur = React.useRef(1);
|
||||
const clickInfo = React.useRef(null);
|
||||
const [isHovered, setIsHovered] = React.useState(false);
|
||||
const position = fixed ? 1.2 : 1.2 * scale;
|
||||
const onPointerDown = React.useCallback(e => {
|
||||
if (annotations) {
|
||||
divRef.current.innerText = `${scaleCur.current.toFixed(2)}`;
|
||||
divRef.current.style.display = 'block';
|
||||
}
|
||||
e.stopPropagation();
|
||||
const rotation = new THREE.Matrix4().extractRotation(objRef.current.matrixWorld);
|
||||
const clickPoint = e.point.clone();
|
||||
const origin = new THREE.Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
|
||||
const dir = direction.clone().applyMatrix4(rotation).normalize();
|
||||
const mPLG = objRef.current.matrixWorld.clone();
|
||||
const mPLGInv = mPLG.clone().invert();
|
||||
const offsetMultiplier = fixed ? 1 / calculateScaleFactor(objRef.current.getWorldPosition(vec1), scale, e.camera, size) : 1;
|
||||
clickInfo.current = {
|
||||
clickPoint,
|
||||
dir,
|
||||
mPLG,
|
||||
mPLGInv,
|
||||
offsetMultiplier
|
||||
};
|
||||
onDragStart({
|
||||
component: 'Sphere',
|
||||
axis,
|
||||
origin,
|
||||
directions: [dir]
|
||||
});
|
||||
camControls && (camControls.enabled = false);
|
||||
// @ts-ignore - setPointerCapture is not in the type definition
|
||||
e.target.setPointerCapture(e.pointerId);
|
||||
}, [annotations, camControls, direction, onDragStart, axis, fixed, scale, size]);
|
||||
const onPointerMove = React.useCallback(e => {
|
||||
e.stopPropagation();
|
||||
if (!isHovered) setIsHovered(true);
|
||||
if (clickInfo.current) {
|
||||
const {
|
||||
clickPoint,
|
||||
dir,
|
||||
mPLG,
|
||||
mPLGInv,
|
||||
offsetMultiplier
|
||||
} = clickInfo.current;
|
||||
const [min, max] = (scaleLimits == null ? void 0 : scaleLimits[axis]) || [1e-5, undefined]; // always limit the minimal value, since setting it very low might break the transform
|
||||
|
||||
const offsetW = calculateOffset(clickPoint, dir, e.ray.origin, e.ray.direction);
|
||||
const offsetL = offsetW * offsetMultiplier;
|
||||
const offsetH = fixed ? offsetL : offsetL / scale;
|
||||
let upscale = Math.pow(2, offsetH * 0.2);
|
||||
|
||||
// @ts-ignore
|
||||
if (e.shiftKey) {
|
||||
upscale = Math.round(upscale * 10) / 10;
|
||||
}
|
||||
upscale = Math.max(upscale, min / scale0.current);
|
||||
if (max !== undefined) {
|
||||
upscale = Math.min(upscale, max / scale0.current);
|
||||
}
|
||||
scaleCur.current = scale0.current * upscale;
|
||||
meshRef.current.position.set(0, position + offsetL, 0);
|
||||
if (annotations) {
|
||||
divRef.current.innerText = `${scaleCur.current.toFixed(2)}`;
|
||||
}
|
||||
scaleV.set(1, 1, 1);
|
||||
scaleV.setComponent(axis, upscale);
|
||||
scaleMatrix.makeScale(scaleV.x, scaleV.y, scaleV.z).premultiply(mPLG).multiply(mPLGInv);
|
||||
onDrag(scaleMatrix);
|
||||
}
|
||||
}, [annotations, position, onDrag, isHovered, scaleLimits, axis]);
|
||||
const onPointerUp = React.useCallback(e => {
|
||||
if (annotations) {
|
||||
divRef.current.style.display = 'none';
|
||||
}
|
||||
e.stopPropagation();
|
||||
scale0.current = scaleCur.current;
|
||||
clickInfo.current = null;
|
||||
meshRef.current.position.set(0, position, 0);
|
||||
onDragEnd();
|
||||
camControls && (camControls.enabled = true);
|
||||
// @ts-ignore - releasePointerCapture & PointerEvent#pointerId is not in the type definition
|
||||
e.target.releasePointerCapture(e.pointerId);
|
||||
}, [annotations, camControls, onDragEnd, position]);
|
||||
const onPointerOut = React.useCallback(e => {
|
||||
e.stopPropagation();
|
||||
setIsHovered(false);
|
||||
}, []);
|
||||
const {
|
||||
radius,
|
||||
matrixL
|
||||
} = React.useMemo(() => {
|
||||
const radius = fixed ? lineWidth / scale * 1.8 : scale / 22.5;
|
||||
const quaternion = new THREE.Quaternion().setFromUnitVectors(upV, direction.clone().normalize());
|
||||
const matrixL = new THREE.Matrix4().makeRotationFromQuaternion(quaternion);
|
||||
return {
|
||||
radius,
|
||||
matrixL
|
||||
};
|
||||
}, [direction, scale, lineWidth, fixed]);
|
||||
const color = isHovered ? hoveredColor : axisColors[axis];
|
||||
return /*#__PURE__*/React.createElement("group", {
|
||||
ref: objRef
|
||||
}, /*#__PURE__*/React.createElement("group", {
|
||||
matrix: matrixL,
|
||||
matrixAutoUpdate: false,
|
||||
onPointerDown: onPointerDown,
|
||||
onPointerMove: onPointerMove,
|
||||
onPointerUp: onPointerUp,
|
||||
onPointerOut: onPointerOut
|
||||
}, annotations && /*#__PURE__*/React.createElement(Html, {
|
||||
position: [0, position / 2, 0]
|
||||
}, /*#__PURE__*/React.createElement("div", {
|
||||
style: {
|
||||
display: 'none',
|
||||
background: '#151520',
|
||||
color: 'white',
|
||||
padding: '6px 8px',
|
||||
borderRadius: 7,
|
||||
whiteSpace: 'nowrap'
|
||||
},
|
||||
className: annotationsClass,
|
||||
ref: divRef
|
||||
})), /*#__PURE__*/React.createElement("mesh", {
|
||||
ref: meshRef,
|
||||
position: [0, position, 0],
|
||||
renderOrder: renderOrder,
|
||||
userData: userData
|
||||
}, /*#__PURE__*/React.createElement("sphereGeometry", {
|
||||
args: [radius, 12, 12]
|
||||
}), /*#__PURE__*/React.createElement("meshBasicMaterial", {
|
||||
transparent: true,
|
||||
depthTest: depthTest,
|
||||
color: color,
|
||||
opacity: opacity,
|
||||
polygonOffset: true,
|
||||
polygonOffsetFactor: -10
|
||||
}))));
|
||||
};
|
||||
|
||||
export { ScalingSphere, calculateOffset };
|
||||
Reference in New Issue
Block a user