Favivon - Correção

This commit is contained in:
2026-05-30 19:59:39 -03:00
parent 76ddaa815d
commit d7dfd221f0
32859 changed files with 5459654 additions and 404 deletions
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("three"),r=require("@react-three/fiber"),n=require("../../core/Line.cjs.js"),o=require("../Html.cjs.js"),a=require("./context.cjs.js");function i(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}require("@babel/runtime/helpers/extends"),require("three-stdlib"),require("react-dom/client");var c=i(e),l=i(t);const s=new l.Vector3,u=new l.Vector3,d=(e,t,r,n)=>{const o=t.dot(t),a=t.dot(e)-t.dot(r),i=t.dot(n);if(0===i)return-a/o;s.copy(n).multiplyScalar(o/i).sub(t),u.copy(n).multiplyScalar(a/i).add(r).sub(e);return-s.dot(u)/s.dot(s)},p=new l.Vector3(0,1,0),m=new l.Matrix4;exports.AxisArrow=({direction:e,axis:t})=>{const{translation:i,translationLimits:s,annotations:u,annotationsClass:f,depthTest:x,scale:y,lineWidth:g,fixed:h,axisColors:b,hoveredColor:O,opacity:P,renderOrder:w,onDragStart:v,onDrag:j,onDragEnd:E,userData:M}=c.useContext(a.context),k=r.useThree((e=>e.controls)),C=c.useRef(null),q=c.useRef(null),L=c.useRef(null),D=c.useRef(0),[F,R]=c.useState(!1),T=c.useCallback((r=>{u&&(C.current.innerText=`${i.current[t].toFixed(2)}`,C.current.style.display="block"),r.stopPropagation();const n=(new l.Matrix4).extractRotation(q.current.matrixWorld),o=r.point.clone(),a=(new l.Vector3).setFromMatrixPosition(q.current.matrixWorld),c=e.clone().applyMatrix4(n).normalize();L.current={clickPoint:o,dir:c},D.current=i.current[t],v({component:"Arrow",axis:t,origin:a,directions:[c]}),k&&(k.enabled=!1),r.target.setPointerCapture(r.pointerId)}),[u,e,k,v,i,t]),S=c.useCallback((e=>{if(e.stopPropagation(),F||R(!0),L.current){const{clickPoint:r,dir:n}=L.current,[o,a]=(null==s?void 0:s[t])||[void 0,void 0];let c=d(r,n,e.ray.origin,e.ray.direction);void 0!==o&&(c=Math.max(c,o-D.current)),void 0!==a&&(c=Math.min(c,a-D.current)),i.current[t]=D.current+c,u&&(C.current.innerText=`${i.current[t].toFixed(2)}`),m.makeTranslation(n.x*c,n.y*c,n.z*c),j(m)}}),[u,j,F,i,s,t]),W=c.useCallback((e=>{u&&(C.current.style.display="none"),e.stopPropagation(),L.current=null,E(),k&&(k.enabled=!0),e.target.releasePointerCapture(e.pointerId)}),[u,k,E]),V=c.useCallback((e=>{e.stopPropagation(),R(!1)}),[]),{cylinderLength:z,coneWidth:A,coneLength:_,matrixL:U}=c.useMemo((()=>{const t=h?g/y*1.6:y/20,r=h?.2:y/5,n=h?1-r:y-r,o=(new l.Quaternion).setFromUnitVectors(p,e.clone().normalize());return{cylinderLength:n,coneWidth:t,coneLength:r,matrixL:(new l.Matrix4).makeRotationFromQuaternion(o)}}),[e,y,g,h]),G=F?O:b[t];return c.createElement("group",{ref:q},c.createElement("group",{matrix:U,matrixAutoUpdate:!1,onPointerDown:T,onPointerMove:S,onPointerUp:W,onPointerOut:V},u&&c.createElement(o.Html,{position:[0,-_,0]},c.createElement("div",{style:{display:"none",background:"#151520",color:"white",padding:"6px 8px",borderRadius:7,whiteSpace:"nowrap"},className:f,ref:C})),c.createElement("mesh",{visible:!1,position:[0,(z+_)/2,0],userData:M},c.createElement("cylinderGeometry",{args:[1.4*A,1.4*A,z+_,8,1]})),c.createElement(n.Line,{transparent:!0,raycast:()=>null,depthTest:x,points:[0,0,0,0,z,0],lineWidth:g,side:l.DoubleSide,color:G,opacity:P,polygonOffset:!0,renderOrder:w,polygonOffsetFactor:-10,fog:!1}),c.createElement("mesh",{raycast:()=>null,position:[0,z+_/2,0],renderOrder:w},c.createElement("coneGeometry",{args:[A,_,24,1]}),c.createElement("meshBasicMaterial",{transparent:!0,depthTest:x,color:G,opacity:P,polygonOffset:!0,polygonOffsetFactor:-10,fog:!1}))))},exports.calculateOffset=d;
+7
View File
@@ -0,0 +1,7 @@
import * as React from 'react';
import * as THREE from 'three';
export declare const calculateOffset: (clickPoint: THREE.Vector3, normal: THREE.Vector3, rayStart: THREE.Vector3, rayDir: THREE.Vector3) => number;
export declare const AxisArrow: React.FC<{
direction: THREE.Vector3;
axis: 0 | 1 | 2;
}>;
+193
View File
@@ -0,0 +1,193 @@
import * as React from 'react';
import * as THREE from 'three';
import { useThree } from '@react-three/fiber';
import { Line } from '../../core/Line.js';
import { Html } from '../Html.js';
import { context } from './context.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 offsetMatrix = /* @__PURE__ */new THREE.Matrix4();
const AxisArrow = ({
direction,
axis
}) => {
const {
translation,
translationLimits,
annotations,
annotationsClass,
depthTest,
scale,
lineWidth,
fixed,
axisColors,
hoveredColor,
opacity,
renderOrder,
onDragStart,
onDrag,
onDragEnd,
userData
} = React.useContext(context);
const camControls = useThree(state => state.controls);
const divRef = React.useRef(null);
const objRef = React.useRef(null);
const clickInfo = React.useRef(null);
const offset0 = React.useRef(0);
const [isHovered, setIsHovered] = React.useState(false);
const onPointerDown = React.useCallback(e => {
if (annotations) {
divRef.current.innerText = `${translation.current[axis].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();
clickInfo.current = {
clickPoint,
dir
};
offset0.current = translation.current[axis];
onDragStart({
component: 'Arrow',
axis,
origin,
directions: [dir]
});
camControls && (camControls.enabled = false);
// @ts-ignore - setPointerCapture is not in the type definition
e.target.setPointerCapture(e.pointerId);
}, [annotations, direction, camControls, onDragStart, translation, axis]);
const onPointerMove = React.useCallback(e => {
e.stopPropagation();
if (!isHovered) setIsHovered(true);
if (clickInfo.current) {
const {
clickPoint,
dir
} = clickInfo.current;
const [min, max] = (translationLimits == null ? void 0 : translationLimits[axis]) || [undefined, undefined];
let offset = calculateOffset(clickPoint, dir, e.ray.origin, e.ray.direction);
if (min !== undefined) {
offset = Math.max(offset, min - offset0.current);
}
if (max !== undefined) {
offset = Math.min(offset, max - offset0.current);
}
translation.current[axis] = offset0.current + offset;
if (annotations) {
divRef.current.innerText = `${translation.current[axis].toFixed(2)}`;
}
offsetMatrix.makeTranslation(dir.x * offset, dir.y * offset, dir.z * offset);
onDrag(offsetMatrix);
}
}, [annotations, onDrag, isHovered, translation, translationLimits, axis]);
const onPointerUp = React.useCallback(e => {
if (annotations) {
divRef.current.style.display = 'none';
}
e.stopPropagation();
clickInfo.current = null;
onDragEnd();
camControls && (camControls.enabled = true);
// @ts-ignore - releasePointerCapture & PointerEvent#pointerId is not in the type definition
e.target.releasePointerCapture(e.pointerId);
}, [annotations, camControls, onDragEnd]);
const onPointerOut = React.useCallback(e => {
e.stopPropagation();
setIsHovered(false);
}, []);
const {
cylinderLength,
coneWidth,
coneLength,
matrixL
} = React.useMemo(() => {
const coneWidth = fixed ? lineWidth / scale * 1.6 : scale / 20;
const coneLength = fixed ? 0.2 : scale / 5;
const cylinderLength = fixed ? 1 - coneLength : scale - coneLength;
const quaternion = new THREE.Quaternion().setFromUnitVectors(upV, direction.clone().normalize());
const matrixL = new THREE.Matrix4().makeRotationFromQuaternion(quaternion);
return {
cylinderLength,
coneWidth,
coneLength,
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, -coneLength, 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", {
visible: false,
position: [0, (cylinderLength + coneLength) / 2.0, 0],
userData: userData
}, /*#__PURE__*/React.createElement("cylinderGeometry", {
args: [coneWidth * 1.4, coneWidth * 1.4, cylinderLength + coneLength, 8, 1]
})), /*#__PURE__*/React.createElement(Line, {
transparent: true,
raycast: () => null,
depthTest: depthTest,
points: [0, 0, 0, 0, cylinderLength, 0],
lineWidth: lineWidth,
side: THREE.DoubleSide,
color: color_,
opacity: opacity,
polygonOffset: true,
renderOrder: renderOrder,
polygonOffsetFactor: -10,
fog: false
}), /*#__PURE__*/React.createElement("mesh", {
raycast: () => null,
position: [0, cylinderLength + coneLength / 2.0, 0],
renderOrder: renderOrder
}, /*#__PURE__*/React.createElement("coneGeometry", {
args: [coneWidth, coneLength, 24, 1]
}), /*#__PURE__*/React.createElement("meshBasicMaterial", {
transparent: true,
depthTest: depthTest,
color: color_,
opacity: opacity,
polygonOffset: true,
polygonOffsetFactor: -10,
fog: false
}))));
};
export { AxisArrow, calculateOffset };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("three"),r=require("@react-three/fiber"),n=require("../../core/Line.cjs.js"),o=require("../Html.cjs.js"),a=require("./context.cjs.js");function i(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}require("@babel/runtime/helpers/extends"),require("three-stdlib"),require("react-dom/client");var c=i(e),s=i(t);const l=new s.Vector3,u=new s.Vector3,d=e=>180*e/Math.PI,p=e=>{let t=((e,t)=>{let r=Math.floor(e/t);return r=r<0?r+1:r,e-r*t})(e,2*Math.PI);return Math.abs(t)<1e-6?0:(t<0&&(t+=2*Math.PI),t)},m=new s.Matrix4,h=new s.Vector3,x=new s.Ray,P=new s.Vector3;exports.AxisRotator=({dir1:e,dir2:t,axis:i})=>{const{rotationLimits:M,annotations:f,annotationsClass:b,depthTest:g,scale:y,lineWidth:w,fixed:v,axisColors:C,hoveredColor:j,renderOrder:I,opacity:O,onDragStart:k,onDrag:R,onDragEnd:q,userData:V}=c.useContext(a.context),D=r.useThree((e=>e.controls)),F=c.useRef(null),E=c.useRef(null),W=c.useRef(0),z=c.useRef(0),T=c.useRef(null),[A,L]=c.useState(!1),S=c.useCallback((e=>{f&&(F.current.innerText=`${d(z.current).toFixed(0)}º`,F.current.style.display="block"),e.stopPropagation();const t=e.point.clone(),r=(new s.Vector3).setFromMatrixPosition(E.current.matrixWorld),n=(new s.Vector3).setFromMatrixColumn(E.current.matrixWorld,0).normalize(),o=(new s.Vector3).setFromMatrixColumn(E.current.matrixWorld,1).normalize(),a=(new s.Vector3).setFromMatrixColumn(E.current.matrixWorld,2).normalize(),c=(new s.Plane).setFromNormalAndCoplanarPoint(a,r);T.current={clickPoint:t,origin:r,e1:n,e2:o,normal:a,plane:c},k({component:"Rotator",axis:i,origin:r,directions:[n,o,a]}),D&&(D.enabled=!1),e.target.setPointerCapture(e.pointerId)}),[f,D,k,i]),_=c.useCallback((e=>{if(e.stopPropagation(),A||L(!0),T.current){const{clickPoint:t,origin:r,e1:n,e2:o,normal:a,plane:c}=T.current,[b,g]=(null==M?void 0:M[i])||[void 0,void 0];x.copy(e.ray),x.intersectPlane(c,P),x.direction.negate(),x.intersectPlane(c,P);let y=((e,t,r,n,o)=>{l.copy(e).sub(r),u.copy(t).sub(r);const a=n.dot(n),i=o.dot(o),c=l.dot(n)/a,s=l.dot(o)/i,d=u.dot(n)/a,p=u.dot(o)/i,m=Math.atan2(s,c);return Math.atan2(p,d)-m})(t,P,r,n,o),w=d(y);e.shiftKey&&(w=10*Math.round(w/10),y=(e=>e*Math.PI/180)(w)),void 0!==b&&void 0!==g&&g-b<2*Math.PI?(y=p(y),y=y>Math.PI?y-2*Math.PI:y,y=s.MathUtils.clamp(y,b-W.current,g-W.current),z.current=W.current+y):(z.current=p(W.current+y),z.current=z.current>Math.PI?z.current-2*Math.PI:z.current),f&&(w=d(z.current),F.current.innerText=`${w.toFixed(0)}º`),m.makeRotationAxis(a,y),h.copy(r).applyMatrix4(m).sub(r).negate(),m.setPosition(h),R(m)}}),[f,R,A,M,i]),U=c.useCallback((e=>{f&&(F.current.style.display="none"),e.stopPropagation(),W.current=z.current,T.current=null,q(),D&&(D.enabled=!0),e.target.releasePointerCapture(e.pointerId)}),[f,D,q]),H=c.useCallback((e=>{e.stopPropagation(),L(!1)}),[]),N=c.useMemo((()=>{const r=e.clone().normalize(),n=t.clone().normalize();return(new s.Matrix4).makeBasis(r,n,r.clone().cross(n))}),[e,t]),$=v?.65:.65*y,B=c.useMemo((()=>{const e=[];for(let t=0;t<=32;t++){const r=t*(Math.PI/2)/32;e.push(new s.Vector3(Math.cos(r)*$,Math.sin(r)*$,0))}return e}),[$]);return c.createElement("group",{ref:E,onPointerDown:S,onPointerMove:_,onPointerUp:U,onPointerOut:H,matrix:N,matrixAutoUpdate:!1},f&&c.createElement(o.Html,{position:[$,$,0]},c.createElement("div",{style:{display:"none",background:"#151520",color:"white",padding:"6px 8px",borderRadius:7,whiteSpace:"nowrap"},className:b,ref:F})),c.createElement(n.Line,{points:B,lineWidth:4*w,visible:!1,userData:V}),c.createElement(n.Line,{transparent:!0,raycast:()=>null,depthTest:g,points:B,lineWidth:w,side:s.DoubleSide,color:A?j:C[i],opacity:O,polygonOffset:!0,polygonOffsetFactor:-10,renderOrder:I,fog:!1}))};
+7
View File
@@ -0,0 +1,7 @@
import * as React from 'react';
import * as THREE from 'three';
export declare const AxisRotator: React.FC<{
dir1: THREE.Vector3;
dir2: THREE.Vector3;
axis: 0 | 1 | 2;
}>;
+220
View File
@@ -0,0 +1,220 @@
import * as React from 'react';
import * as THREE from 'three';
import { useThree } from '@react-three/fiber';
import { Line } from '../../core/Line.js';
import { Html } from '../Html.js';
import { context } from './context.js';
const clickDir = /* @__PURE__ */new THREE.Vector3();
const intersectionDir = /* @__PURE__ */new THREE.Vector3();
const toDegrees = radians => radians * 180 / Math.PI;
const toRadians = degrees => degrees * Math.PI / 180;
const calculateAngle = (clickPoint, intersectionPoint, origin, e1, e2) => {
clickDir.copy(clickPoint).sub(origin);
intersectionDir.copy(intersectionPoint).sub(origin);
const dote1e1 = e1.dot(e1);
const dote2e2 = e2.dot(e2);
const uClick = clickDir.dot(e1) / dote1e1;
const vClick = clickDir.dot(e2) / dote2e2;
const uIntersection = intersectionDir.dot(e1) / dote1e1;
const vIntersection = intersectionDir.dot(e2) / dote2e2;
const angleClick = Math.atan2(vClick, uClick);
const angleIntersection = Math.atan2(vIntersection, uIntersection);
return angleIntersection - angleClick;
};
const fmod = (num, denom) => {
let k = Math.floor(num / denom);
k = k < 0 ? k + 1 : k;
return num - k * denom;
};
const minimizeAngle = angle => {
let result = fmod(angle, 2 * Math.PI);
if (Math.abs(result) < 1e-6) {
return 0.0;
}
if (result < 0.0) {
result += 2 * Math.PI;
}
return result;
};
const rotMatrix = /* @__PURE__ */new THREE.Matrix4();
const posNew = /* @__PURE__ */new THREE.Vector3();
const ray = /* @__PURE__ */new THREE.Ray();
const intersection = /* @__PURE__ */new THREE.Vector3();
const AxisRotator = ({
dir1,
dir2,
axis
}) => {
const {
rotationLimits,
annotations,
annotationsClass,
depthTest,
scale,
lineWidth,
fixed,
axisColors,
hoveredColor,
renderOrder,
opacity,
onDragStart,
onDrag,
onDragEnd,
userData
} = React.useContext(context);
const camControls = useThree(state => state.controls);
const divRef = React.useRef(null);
const objRef = React.useRef(null);
const angle0 = React.useRef(0);
const angle = React.useRef(0);
const clickInfo = React.useRef(null);
const [isHovered, setIsHovered] = React.useState(false);
const onPointerDown = React.useCallback(e => {
if (annotations) {
divRef.current.innerText = `${toDegrees(angle.current).toFixed(0)}º`;
divRef.current.style.display = 'block';
}
e.stopPropagation();
const clickPoint = e.point.clone();
const origin = new THREE.Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
const e1 = new THREE.Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 0).normalize();
const e2 = new THREE.Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 1).normalize();
const normal = new THREE.Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 2).normalize();
const plane = new THREE.Plane().setFromNormalAndCoplanarPoint(normal, origin);
clickInfo.current = {
clickPoint,
origin,
e1,
e2,
normal,
plane
};
onDragStart({
component: 'Rotator',
axis,
origin,
directions: [e1, e2, normal]
});
camControls && (camControls.enabled = false);
// @ts-ignore
e.target.setPointerCapture(e.pointerId);
}, [annotations, camControls, onDragStart, axis]);
const onPointerMove = React.useCallback(e => {
e.stopPropagation();
if (!isHovered) setIsHovered(true);
if (clickInfo.current) {
const {
clickPoint,
origin,
e1,
e2,
normal,
plane
} = clickInfo.current;
const [min, max] = (rotationLimits == null ? void 0 : rotationLimits[axis]) || [undefined, undefined];
ray.copy(e.ray);
ray.intersectPlane(plane, intersection);
ray.direction.negate();
ray.intersectPlane(plane, intersection);
let deltaAngle = calculateAngle(clickPoint, intersection, origin, e1, e2);
let degrees = toDegrees(deltaAngle);
// @ts-ignore
if (e.shiftKey) {
degrees = Math.round(degrees / 10) * 10;
deltaAngle = toRadians(degrees);
}
if (min !== undefined && max !== undefined && max - min < 2 * Math.PI) {
deltaAngle = minimizeAngle(deltaAngle);
deltaAngle = deltaAngle > Math.PI ? deltaAngle - 2 * Math.PI : deltaAngle;
deltaAngle = THREE.MathUtils.clamp(deltaAngle, min - angle0.current, max - angle0.current);
angle.current = angle0.current + deltaAngle;
} else {
angle.current = minimizeAngle(angle0.current + deltaAngle);
angle.current = angle.current > Math.PI ? angle.current - 2 * Math.PI : angle.current;
}
if (annotations) {
degrees = toDegrees(angle.current);
divRef.current.innerText = `${degrees.toFixed(0)}º`;
}
rotMatrix.makeRotationAxis(normal, deltaAngle);
posNew.copy(origin).applyMatrix4(rotMatrix).sub(origin).negate();
rotMatrix.setPosition(posNew);
onDrag(rotMatrix);
}
}, [annotations, onDrag, isHovered, rotationLimits, axis]);
const onPointerUp = React.useCallback(e => {
if (annotations) {
divRef.current.style.display = 'none';
}
e.stopPropagation();
angle0.current = angle.current;
clickInfo.current = null;
onDragEnd();
camControls && (camControls.enabled = true);
// @ts-ignore
e.target.releasePointerCapture(e.pointerId);
}, [annotations, camControls, onDragEnd]);
const onPointerOut = React.useCallback(e => {
e.stopPropagation();
setIsHovered(false);
}, []);
const matrixL = React.useMemo(() => {
const dir1N = dir1.clone().normalize();
const dir2N = dir2.clone().normalize();
return new THREE.Matrix4().makeBasis(dir1N, dir2N, dir1N.clone().cross(dir2N));
}, [dir1, dir2]);
const r = fixed ? 0.65 : scale * 0.65;
const arc = React.useMemo(() => {
const segments = 32;
const points = [];
for (let j = 0; j <= segments; j++) {
const angle = j * (Math.PI / 2) / segments;
points.push(new THREE.Vector3(Math.cos(angle) * r, Math.sin(angle) * r, 0));
}
return points;
}, [r]);
return /*#__PURE__*/React.createElement("group", {
ref: objRef,
onPointerDown: onPointerDown,
onPointerMove: onPointerMove,
onPointerUp: onPointerUp,
onPointerOut: onPointerOut,
matrix: matrixL,
matrixAutoUpdate: false
}, annotations && /*#__PURE__*/React.createElement(Html, {
position: [r, r, 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(Line, {
points: arc,
lineWidth: lineWidth * 4,
visible: false,
userData: userData
}), /*#__PURE__*/React.createElement(Line, {
transparent: true,
raycast: () => null,
depthTest: depthTest,
points: arc,
lineWidth: lineWidth,
side: THREE.DoubleSide,
color: isHovered ? hoveredColor : axisColors[axis],
opacity: opacity,
polygonOffset: true,
polygonOffsetFactor: -10,
renderOrder: renderOrder,
fog: false
}));
};
export { AxisRotator };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("three"),r=require("@react-three/fiber"),n=require("../../core/Line.cjs.js"),o=require("../Html.cjs.js"),a=require("./context.cjs.js");function i(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}require("@babel/runtime/helpers/extends"),require("three-stdlib"),require("react-dom/client");var s=i(e),c=i(t);const l=new c.Ray,u=new c.Vector3,d=new c.Matrix4;exports.PlaneSlider=({dir1:e,dir2:t,axis:i})=>{const{translation:p,translationLimits:m,annotations:x,annotationsClass:b,depthTest:g,scale:f,lineWidth:h,fixed:M,axisColors:y,hoveredColor:C,opacity:P,renderOrder:v,onDragStart:w,onDrag:O,onDragEnd:j,userData:k}=s.useContext(a.context),F=r.useThree((e=>e.controls)),z=s.useRef(null),E=s.useRef(null),V=s.useRef(null),q=s.useRef(0),D=s.useRef(0),[R,T]=s.useState(!1),S=s.useCallback((e=>{x&&(z.current.innerText=`${p.current[(i+1)%3].toFixed(2)}, ${p.current[(i+2)%3].toFixed(2)}`,z.current.style.display="block"),e.stopPropagation();const t=e.point.clone(),r=(new c.Vector3).setFromMatrixPosition(E.current.matrixWorld),n=(new c.Vector3).setFromMatrixColumn(E.current.matrixWorld,0).normalize(),o=(new c.Vector3).setFromMatrixColumn(E.current.matrixWorld,1).normalize(),a=(new c.Vector3).setFromMatrixColumn(E.current.matrixWorld,2).normalize(),s=(new c.Plane).setFromNormalAndCoplanarPoint(a,r);V.current={clickPoint:t,e1:n,e2:o,plane:s},q.current=p.current[(i+1)%3],D.current=p.current[(i+2)%3],w({component:"Slider",axis:i,origin:r,directions:[n,o,a]}),F&&(F.enabled=!1),e.target.setPointerCapture(e.pointerId)}),[x,F,w,i]),W=s.useCallback((e=>{if(e.stopPropagation(),R||T(!0),V.current){const{clickPoint:t,e1:r,e2:n,plane:o}=V.current,[a,s]=(null==m?void 0:m[(i+1)%3])||[void 0,void 0],[c,b]=(null==m?void 0:m[(i+2)%3])||[void 0,void 0];l.copy(e.ray),l.intersectPlane(o,u),l.direction.negate(),l.intersectPlane(o,u),u.sub(t);let[g,f]=((e,t,r)=>{const n=Math.abs(e.x)>=Math.abs(e.y)&&Math.abs(e.x)>=Math.abs(e.z)?0:Math.abs(e.y)>=Math.abs(e.x)&&Math.abs(e.y)>=Math.abs(e.z)?1:2,o=[0,1,2].sort(((e,r)=>Math.abs(t.getComponent(r))-Math.abs(t.getComponent(e)))),a=n===o[0]?o[1]:o[0],i=e.getComponent(n),s=e.getComponent(a),c=t.getComponent(n),l=t.getComponent(a),u=r.getComponent(n),d=(r.getComponent(a)-u*(s/i))/(l-c*(s/i));return[(u-d*c)/i,d]})(r,n,u);void 0!==a&&(g=Math.max(g,a-q.current)),void 0!==s&&(g=Math.min(g,s-q.current)),void 0!==c&&(f=Math.max(f,c-D.current)),void 0!==b&&(f=Math.min(f,b-D.current)),p.current[(i+1)%3]=q.current+g,p.current[(i+2)%3]=D.current+f,x&&(z.current.innerText=`${p.current[(i+1)%3].toFixed(2)}, ${p.current[(i+2)%3].toFixed(2)}`),d.makeTranslation(g*r.x+f*n.x,g*r.y+f*n.y,g*r.z+f*n.z),O(d)}}),[x,O,R,p,m,i]),$=s.useCallback((e=>{x&&(z.current.style.display="none"),e.stopPropagation(),V.current=null,j(),F&&(F.enabled=!0),e.target.releasePointerCapture(e.pointerId)}),[x,F,j]),_=s.useCallback((e=>{e.stopPropagation(),T(!1)}),[]),L=s.useMemo((()=>{const r=e.clone().normalize(),n=t.clone().normalize();return(new c.Matrix4).makeBasis(r,n,r.clone().cross(n))}),[e,t]),A=M?1/7:f/7,B=M?.225:.225*f,H=R?C:y[i],I=s.useMemo((()=>[new c.Vector3(0,0,0),new c.Vector3(0,B,0),new c.Vector3(B,B,0),new c.Vector3(B,0,0),new c.Vector3(0,0,0)]),[B]);return s.createElement("group",{ref:E,matrix:L,matrixAutoUpdate:!1},x&&s.createElement(o.Html,{position:[0,0,0]},s.createElement("div",{style:{display:"none",background:"#151520",color:"white",padding:"6px 8px",borderRadius:7,whiteSpace:"nowrap"},className:b,ref:z})),s.createElement("group",{position:[1.7*A,1.7*A,0]},s.createElement("mesh",{visible:!0,onPointerDown:S,onPointerMove:W,onPointerUp:$,onPointerOut:_,scale:B,userData:k,renderOrder:v},s.createElement("planeGeometry",null),s.createElement("meshBasicMaterial",{transparent:!0,depthTest:g,color:H,polygonOffset:!0,polygonOffsetFactor:-10,side:c.DoubleSide,fog:!1})),s.createElement(n.Line,{position:[-B/2,-B/2,0],transparent:!0,depthTest:g,points:I,lineWidth:h,color:H,opacity:P,polygonOffset:!0,polygonOffsetFactor:-10,userData:k,fog:!1,renderOrder:v})))};
+7
View File
@@ -0,0 +1,7 @@
import * as React from 'react';
import * as THREE from 'three';
export declare const PlaneSlider: React.FC<{
dir1: THREE.Vector3;
dir2: THREE.Vector3;
axis: 0 | 1 | 2;
}>;
+202
View File
@@ -0,0 +1,202 @@
import * as React from 'react';
import * as THREE from 'three';
import { useThree } from '@react-three/fiber';
import { Line } from '../../core/Line.js';
import { Html } from '../Html.js';
import { context } from './context.js';
const decomposeIntoBasis = (e1, e2, offset) => {
const i1 = Math.abs(e1.x) >= Math.abs(e1.y) && Math.abs(e1.x) >= Math.abs(e1.z) ? 0 : Math.abs(e1.y) >= Math.abs(e1.x) && Math.abs(e1.y) >= Math.abs(e1.z) ? 1 : 2;
const e2DegrowthOrder = [0, 1, 2].sort((a, b) => Math.abs(e2.getComponent(b)) - Math.abs(e2.getComponent(a)));
const i2 = i1 === e2DegrowthOrder[0] ? e2DegrowthOrder[1] : e2DegrowthOrder[0];
const a1 = e1.getComponent(i1);
const a2 = e1.getComponent(i2);
const b1 = e2.getComponent(i1);
const b2 = e2.getComponent(i2);
const c1 = offset.getComponent(i1);
const c2 = offset.getComponent(i2);
const y = (c2 - c1 * (a2 / a1)) / (b2 - b1 * (a2 / a1));
const x = (c1 - y * b1) / a1;
return [x, y];
};
const ray = /* @__PURE__ */new THREE.Ray();
const intersection = /* @__PURE__ */new THREE.Vector3();
const offsetMatrix = /* @__PURE__ */new THREE.Matrix4();
const PlaneSlider = ({
dir1,
dir2,
axis
}) => {
const {
translation,
translationLimits,
annotations,
annotationsClass,
depthTest,
scale,
lineWidth,
fixed,
axisColors,
hoveredColor,
opacity,
renderOrder,
onDragStart,
onDrag,
onDragEnd,
userData
} = React.useContext(context);
const camControls = useThree(state => state.controls);
const divRef = React.useRef(null);
const objRef = React.useRef(null);
const clickInfo = React.useRef(null);
const offsetX0 = React.useRef(0);
const offsetY0 = React.useRef(0);
const [isHovered, setIsHovered] = React.useState(false);
const onPointerDown = React.useCallback(e => {
if (annotations) {
divRef.current.innerText = `${translation.current[(axis + 1) % 3].toFixed(2)}, ${translation.current[(axis + 2) % 3].toFixed(2)}`;
divRef.current.style.display = 'block';
}
e.stopPropagation();
const clickPoint = e.point.clone();
const origin = new THREE.Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
const e1 = new THREE.Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 0).normalize();
const e2 = new THREE.Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 1).normalize();
const normal = new THREE.Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 2).normalize();
const plane = new THREE.Plane().setFromNormalAndCoplanarPoint(normal, origin);
clickInfo.current = {
clickPoint,
e1,
e2,
plane
};
offsetX0.current = translation.current[(axis + 1) % 3];
offsetY0.current = translation.current[(axis + 2) % 3];
onDragStart({
component: 'Slider',
axis,
origin,
directions: [e1, e2, normal]
});
camControls && (camControls.enabled = false);
// @ts-ignore
e.target.setPointerCapture(e.pointerId);
}, [annotations, camControls, onDragStart, axis]);
const onPointerMove = React.useCallback(e => {
e.stopPropagation();
if (!isHovered) setIsHovered(true);
if (clickInfo.current) {
const {
clickPoint,
e1,
e2,
plane
} = clickInfo.current;
const [minX, maxX] = (translationLimits == null ? void 0 : translationLimits[(axis + 1) % 3]) || [undefined, undefined];
const [minY, maxY] = (translationLimits == null ? void 0 : translationLimits[(axis + 2) % 3]) || [undefined, undefined];
ray.copy(e.ray);
ray.intersectPlane(plane, intersection);
ray.direction.negate();
ray.intersectPlane(plane, intersection);
intersection.sub(clickPoint);
let [offsetX, offsetY] = decomposeIntoBasis(e1, e2, intersection);
/* let offsetY = (intersection.y - (intersection.x * e1.y) / e1.x) / (e2.y - (e2.x * e1.y) / e1.x)
let offsetX = (intersection.x - offsetY * e2.x) / e1.x */
if (minX !== undefined) {
offsetX = Math.max(offsetX, minX - offsetX0.current);
}
if (maxX !== undefined) {
offsetX = Math.min(offsetX, maxX - offsetX0.current);
}
if (minY !== undefined) {
offsetY = Math.max(offsetY, minY - offsetY0.current);
}
if (maxY !== undefined) {
offsetY = Math.min(offsetY, maxY - offsetY0.current);
}
translation.current[(axis + 1) % 3] = offsetX0.current + offsetX;
translation.current[(axis + 2) % 3] = offsetY0.current + offsetY;
if (annotations) {
divRef.current.innerText = `${translation.current[(axis + 1) % 3].toFixed(2)}, ${translation.current[(axis + 2) % 3].toFixed(2)}`;
}
offsetMatrix.makeTranslation(offsetX * e1.x + offsetY * e2.x, offsetX * e1.y + offsetY * e2.y, offsetX * e1.z + offsetY * e2.z);
onDrag(offsetMatrix);
}
}, [annotations, onDrag, isHovered, translation, translationLimits, axis]);
const onPointerUp = React.useCallback(e => {
if (annotations) {
divRef.current.style.display = 'none';
}
e.stopPropagation();
clickInfo.current = null;
onDragEnd();
camControls && (camControls.enabled = true);
// @ts-ignore
e.target.releasePointerCapture(e.pointerId);
}, [annotations, camControls, onDragEnd]);
const onPointerOut = React.useCallback(e => {
e.stopPropagation();
setIsHovered(false);
}, []);
const matrixL = React.useMemo(() => {
const dir1N = dir1.clone().normalize();
const dir2N = dir2.clone().normalize();
return new THREE.Matrix4().makeBasis(dir1N, dir2N, dir1N.clone().cross(dir2N));
}, [dir1, dir2]);
const pos1 = fixed ? 1 / 7 : scale / 7;
const length = fixed ? 0.225 : scale * 0.225;
const color = isHovered ? hoveredColor : axisColors[axis];
const points = React.useMemo(() => [new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, length, 0), new THREE.Vector3(length, length, 0), new THREE.Vector3(length, 0, 0), new THREE.Vector3(0, 0, 0)], [length]);
return /*#__PURE__*/React.createElement("group", {
ref: objRef,
matrix: matrixL,
matrixAutoUpdate: false
}, annotations && /*#__PURE__*/React.createElement(Html, {
position: [0, 0, 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("group", {
position: [pos1 * 1.7, pos1 * 1.7, 0]
}, /*#__PURE__*/React.createElement("mesh", {
visible: true,
onPointerDown: onPointerDown,
onPointerMove: onPointerMove,
onPointerUp: onPointerUp,
onPointerOut: onPointerOut,
scale: length,
userData: userData,
renderOrder: renderOrder
}, /*#__PURE__*/React.createElement("planeGeometry", null), /*#__PURE__*/React.createElement("meshBasicMaterial", {
transparent: true,
depthTest: depthTest,
color: color,
polygonOffset: true,
polygonOffsetFactor: -10,
side: THREE.DoubleSide,
fog: false
})), /*#__PURE__*/React.createElement(Line, {
position: [-length / 2, -length / 2, 0],
transparent: true,
depthTest: depthTest,
points: points,
lineWidth: lineWidth,
color: color,
opacity: opacity,
polygonOffset: true,
polygonOffsetFactor: -10,
userData: userData,
fog: false,
renderOrder: renderOrder
})));
};
export { PlaneSlider };
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("three"),r=require("@react-three/fiber"),n=require("../Html.cjs.js"),o=require("./context.cjs.js"),a=require("../../core/calculateScaleFactor.cjs.js");function i(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}require("@babel/runtime/helpers/extends"),require("react-dom/client");var c=i(e),l=i(t);const s=new l.Vector3,u=new l.Vector3,p=(e,t,r,n)=>{const o=t.dot(t),a=t.dot(e)-t.dot(r),i=t.dot(n);if(0===i)return-a/o;s.copy(n).multiplyScalar(o/i).sub(t),u.copy(n).multiplyScalar(a/i).add(r).sub(e);return-s.dot(u)/s.dot(s)},d=new l.Vector3(0,1,0),m=new l.Vector3,f=new l.Matrix4;exports.ScalingSphere=({direction:e,axis:t})=>{const{scaleLimits:i,annotations:u,annotationsClass:x,depthTest:y,scale:g,lineWidth:h,fixed:b,axisColors:P,hoveredColor:M,opacity:w,renderOrder:v,onDragStart:O,onDrag:j,onDragEnd:k,userData:C}=c.useContext(o.context),S=r.useThree((e=>e.size)),E=r.useThree((e=>e.controls)),R=c.useRef(null),q=c.useRef(null),F=c.useRef(null),D=c.useRef(1),L=c.useRef(1),T=c.useRef(null),[V,z]=c.useState(!1),G=b?1.2:1.2*g,W=c.useCallback((r=>{u&&(R.current.innerText=`${L.current.toFixed(2)}`,R.current.style.display="block"),r.stopPropagation();const n=(new l.Matrix4).extractRotation(q.current.matrixWorld),o=r.point.clone(),i=(new l.Vector3).setFromMatrixPosition(q.current.matrixWorld),c=e.clone().applyMatrix4(n).normalize(),p=q.current.matrixWorld.clone(),d=p.clone().invert(),m=b?1/a.calculateScaleFactor(q.current.getWorldPosition(s),g,r.camera,S):1;T.current={clickPoint:o,dir:c,mPLG:p,mPLGInv:d,offsetMultiplier:m},O({component:"Sphere",axis:t,origin:i,directions:[c]}),E&&(E.enabled=!1),r.target.setPointerCapture(r.pointerId)}),[u,E,e,O,t,b,g,S]),I=c.useCallback((e=>{if(e.stopPropagation(),V||z(!0),T.current){const{clickPoint:r,dir:n,mPLG:o,mPLGInv:a,offsetMultiplier:c}=T.current,[l,s]=(null==i?void 0:i[t])||[1e-5,void 0],d=p(r,n,e.ray.origin,e.ray.direction)*c,x=b?d:d/g;let y=Math.pow(2,.2*x);e.shiftKey&&(y=Math.round(10*y)/10),y=Math.max(y,l/D.current),void 0!==s&&(y=Math.min(y,s/D.current)),L.current=D.current*y,F.current.position.set(0,G+d,0),u&&(R.current.innerText=`${L.current.toFixed(2)}`),m.set(1,1,1),m.setComponent(t,y),f.makeScale(m.x,m.y,m.z).premultiply(o).multiply(a),j(f)}}),[u,G,j,V,i,t]),_=c.useCallback((e=>{u&&(R.current.style.display="none"),e.stopPropagation(),D.current=L.current,T.current=null,F.current.position.set(0,G,0),k(),E&&(E.enabled=!0),e.target.releasePointerCapture(e.pointerId)}),[u,E,k,G]),U=c.useCallback((e=>{e.stopPropagation(),z(!1)}),[]),{radius:H,matrixL:Q}=c.useMemo((()=>{const t=b?h/g*1.8:g/22.5,r=(new l.Quaternion).setFromUnitVectors(d,e.clone().normalize());return{radius:t,matrixL:(new l.Matrix4).makeRotationFromQuaternion(r)}}),[e,g,h,b]),$=V?M:P[t];return c.createElement("group",{ref:q},c.createElement("group",{matrix:Q,matrixAutoUpdate:!1,onPointerDown:W,onPointerMove:I,onPointerUp:_,onPointerOut:U},u&&c.createElement(n.Html,{position:[0,G/2,0]},c.createElement("div",{style:{display:"none",background:"#151520",color:"white",padding:"6px 8px",borderRadius:7,whiteSpace:"nowrap"},className:x,ref:R})),c.createElement("mesh",{ref:F,position:[0,G,0],renderOrder:v,userData:C},c.createElement("sphereGeometry",{args:[H,12,12]}),c.createElement("meshBasicMaterial",{transparent:!0,depthTest:y,color:$,opacity:w,polygonOffset:!0,polygonOffsetFactor:-10}))))},exports.calculateOffset=p;
+7
View File
@@ -0,0 +1,7 @@
import * as React from 'react';
import * as THREE from 'three';
export declare const calculateOffset: (clickPoint: THREE.Vector3, normal: THREE.Vector3, rayStart: THREE.Vector3, rayDir: THREE.Vector3) => number;
export declare const ScalingSphere: React.FC<{
direction: THREE.Vector3;
axis: 0 | 1 | 2;
}>;
+192
View 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 };
+1
View File
@@ -0,0 +1 @@
"use strict";function e(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}Object.defineProperty(exports,"__esModule",{value:!0});const t=e(require("react")).createContext(null);exports.context=t;
+33
View File
@@ -0,0 +1,33 @@
import * as THREE from 'three';
import * as React from 'react';
export type OnDragStartProps = {
component: 'Arrow' | 'Slider' | 'Rotator' | 'Sphere';
axis: 0 | 1 | 2;
origin: THREE.Vector3;
directions: THREE.Vector3[];
};
export type PivotContext = {
onDragStart: (props: OnDragStartProps) => void;
onDrag: (mdW: THREE.Matrix4) => void;
onDragEnd: () => void;
translation: {
current: [number, number, number];
};
translationLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
rotationLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
scaleLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
axisColors: [string | number, string | number, string | number];
hoveredColor: string | number;
opacity: number;
scale: number;
lineWidth: number;
fixed: boolean;
depthTest: boolean;
renderOrder: number;
userData?: {
[key: string]: any;
};
annotations?: boolean;
annotationsClass?: string;
};
export declare const context: React.Context<PivotContext>;
+5
View File
@@ -0,0 +1,5 @@
import * as React from 'react';
const context = /* @__PURE__ */React.createContext(null);
export { context };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("@react-three/fiber"),t=require("react"),i=require("three"),a=require("./AxisArrow.cjs.js"),n=require("./AxisRotator.cjs.js"),o=require("./PlaneSlider.cjs.js"),c=require("./ScalingSphere.cjs.js"),l=require("./context.cjs.js"),s=require("../../core/calculateScaleFactor.cjs.js");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function d(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var i=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,i.get?i:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}require("../../core/Line.cjs.js"),require("three-stdlib"),require("../Html.cjs.js"),require("react-dom/client");var m=u(e),x=d(t),p=d(i);const f=new p.Matrix4,y=new p.Matrix4,w=new p.Matrix4,g=new p.Matrix4,b=new p.Matrix4,E=new p.Matrix4,j=new p.Matrix4,S=new p.Matrix4,h=new p.Matrix4,v=new p.Box3,M=new p.Box3,A=new p.Vector3,q=new p.Vector3,R=new p.Vector3,V=new p.Vector3,P=new p.Vector3,W=new p.Vector3(1,0,0),D=new p.Vector3(0,1,0),O=new p.Vector3(0,0,1),C=x.forwardRef((({enabled:e=!0,matrix:t,onDragStart:i,onDrag:u,onDragEnd:d,autoTransform:C=!0,anchor:L,disableAxes:B=!1,disableSliders:F=!1,disableRotations:z=!1,disableScaling:T=!1,activeAxes:_=[!0,!0,!0],offset:k=[0,0,0],rotation:H=[0,0,0],scale:I=1,lineWidth:U=4,fixed:G=!1,translationLimits:J,rotationLimits:K,scaleLimits:N,depthTest:Q=!0,renderOrder:X=500,axisColors:Y=["#ff2060","#20df80","#2080ff"],hoveredColor:Z="#ffff40",annotations:$=!1,annotationsClass:ee,opacity:re=1,visible:te=!0,userData:ie,children:ae,...ne},oe)=>{const ce=r.useThree((e=>e.invalidate)),le=x.useRef(null),se=x.useRef(null),ue=x.useRef(null),de=x.useRef(null),me=x.useRef([0,0,0]),xe=x.useRef(new p.Vector3(1,1,1)),pe=x.useRef(new p.Vector3(1,1,1));x.useLayoutEffect((()=>{L&&(de.current.updateWorldMatrix(!0,!0),g.copy(de.current.matrixWorld).invert(),v.makeEmpty(),de.current.traverse((e=>{e.geometry&&(e.geometry.boundingBox||e.geometry.computeBoundingBox(),E.copy(e.matrixWorld).premultiply(g),M.copy(e.geometry.boundingBox),M.applyMatrix4(E),v.union(M))})),A.copy(v.max).add(v.min).multiplyScalar(.5),q.copy(v.max).sub(v.min).multiplyScalar(.5),R.copy(q).multiply(new p.Vector3(...L)).add(A),V.set(...k).add(R),ue.current.position.copy(V),ce())}));const fe=x.useMemo((()=>({onDragStart:e=>{f.copy(se.current.matrix),y.copy(se.current.matrixWorld),i&&i(e),ce()},onDrag:e=>{w.copy(le.current.matrixWorld),g.copy(w).invert(),b.copy(y).premultiply(e),E.copy(b).premultiply(g),j.copy(f).invert(),S.copy(E).multiply(j),C&&se.current.matrix.copy(E),u&&u(E,S,b,e),ce()},onDragEnd:()=>{d&&d(),ce()},translation:me,translationLimits:J,rotationLimits:K,axisColors:Y,hoveredColor:Z,opacity:re,scale:I,lineWidth:U,fixed:G,depthTest:Q,renderOrder:X,userData:ie,annotations:$,annotationsClass:ee})),[i,u,d,me,J,K,N,Q,I,U,G,...Y,Z,re,ie,C,$,ee]),ye=new p.Vector3;return r.useFrame((e=>{if(G){const r=s.calculateScaleFactor(ue.current.getWorldPosition(ye),I,e.camera,e.size);xe.current.setScalar(r)}t&&t instanceof p.Matrix4&&(se.current.matrix=t),se.current.updateWorldMatrix(!0,!0),h.makeRotationFromEuler(ue.current.rotation).setPosition(ue.current.position).premultiply(se.current.matrixWorld),pe.current.setFromMatrixScale(h),P.copy(xe.current).divide(pe.current),(Math.abs(ue.current.scale.x-P.x)>1e-4||Math.abs(ue.current.scale.y-P.y)>1e-4||Math.abs(ue.current.scale.z-P.z)>1e-4)&&(ue.current.scale.copy(P),e.invalidate())})),x.useImperativeHandle(oe,(()=>se.current),[]),x.createElement(l.context.Provider,{value:fe},x.createElement("group",{ref:le},x.createElement("group",m.default({ref:se,matrix:t,matrixAutoUpdate:!1},ne),x.createElement("group",{visible:te,ref:ue,position:k,rotation:H},e&&x.createElement(x.Fragment,null,!B&&_[0]&&x.createElement(a.AxisArrow,{axis:0,direction:W}),!B&&_[1]&&x.createElement(a.AxisArrow,{axis:1,direction:D}),!B&&_[2]&&x.createElement(a.AxisArrow,{axis:2,direction:O}),!F&&_[0]&&_[1]&&x.createElement(o.PlaneSlider,{axis:2,dir1:W,dir2:D}),!F&&_[0]&&_[2]&&x.createElement(o.PlaneSlider,{axis:1,dir1:O,dir2:W}),!F&&_[2]&&_[1]&&x.createElement(o.PlaneSlider,{axis:0,dir1:D,dir2:O}),!z&&_[0]&&_[1]&&x.createElement(n.AxisRotator,{axis:2,dir1:W,dir2:D}),!z&&_[0]&&_[2]&&x.createElement(n.AxisRotator,{axis:1,dir1:O,dir2:W}),!z&&_[2]&&_[1]&&x.createElement(n.AxisRotator,{axis:0,dir1:D,dir2:O}),!T&&_[0]&&x.createElement(c.ScalingSphere,{axis:0,direction:W}),!T&&_[1]&&x.createElement(c.ScalingSphere,{axis:1,direction:D}),!T&&_[2]&&x.createElement(c.ScalingSphere,{axis:2,direction:O}))),x.createElement("group",{ref:de},ae))))}));exports.PivotControls=C;
+39
View File
@@ -0,0 +1,39 @@
import * as React from 'react';
import * as THREE from 'three';
import { ForwardRefComponent } from '../../helpers/ts-utils';
import { OnDragStartProps } from './context';
export type PivotControlsProps = {
enabled?: boolean;
scale?: number;
lineWidth?: number;
fixed?: boolean;
offset?: [number, number, number];
rotation?: [number, number, number];
matrix?: THREE.Matrix4;
anchor?: [number, number, number];
autoTransform?: boolean;
activeAxes?: [boolean, boolean, boolean];
disableAxes?: boolean;
disableSliders?: boolean;
disableRotations?: boolean;
disableScaling?: boolean;
translationLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
rotationLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
scaleLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
axisColors?: [string | number, string | number, string | number];
hoveredColor?: string | number;
annotations?: boolean;
annotationsClass?: string;
onDragStart?: (props: OnDragStartProps) => void;
onDrag?: (l: THREE.Matrix4, deltaL: THREE.Matrix4, w: THREE.Matrix4, deltaW: THREE.Matrix4) => void;
onDragEnd?: () => void;
depthTest?: boolean;
renderOrder?: number;
opacity?: number;
visible?: boolean;
userData?: {
[key: string]: any;
};
children?: React.ReactNode;
};
export declare const PivotControls: ForwardRefComponent<PivotControlsProps, THREE.Group>;
+213
View File
@@ -0,0 +1,213 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import { useThree, useFrame } from '@react-three/fiber';
import * as React from 'react';
import * as THREE from 'three';
import { AxisArrow } from './AxisArrow.js';
import { AxisRotator } from './AxisRotator.js';
import { PlaneSlider } from './PlaneSlider.js';
import { ScalingSphere } from './ScalingSphere.js';
import { context } from './context.js';
import { calculateScaleFactor } from '../../core/calculateScaleFactor.js';
const mL0 = /* @__PURE__ */new THREE.Matrix4();
const mW0 = /* @__PURE__ */new THREE.Matrix4();
const mP = /* @__PURE__ */new THREE.Matrix4();
const mPInv = /* @__PURE__ */new THREE.Matrix4();
const mW = /* @__PURE__ */new THREE.Matrix4();
const mL = /* @__PURE__ */new THREE.Matrix4();
const mL0Inv = /* @__PURE__ */new THREE.Matrix4();
const mdL = /* @__PURE__ */new THREE.Matrix4();
const mG = /* @__PURE__ */new THREE.Matrix4();
const bb = /* @__PURE__ */new THREE.Box3();
const bbObj = /* @__PURE__ */new THREE.Box3();
const vCenter = /* @__PURE__ */new THREE.Vector3();
const vSize = /* @__PURE__ */new THREE.Vector3();
const vAnchorOffset = /* @__PURE__ */new THREE.Vector3();
const vPosition = /* @__PURE__ */new THREE.Vector3();
const vScale = /* @__PURE__ */new THREE.Vector3();
const xDir = /* @__PURE__ */new THREE.Vector3(1, 0, 0);
const yDir = /* @__PURE__ */new THREE.Vector3(0, 1, 0);
const zDir = /* @__PURE__ */new THREE.Vector3(0, 0, 1);
const PivotControls = /* @__PURE__ */React.forwardRef(({
enabled = true,
matrix,
onDragStart,
onDrag,
onDragEnd,
autoTransform = true,
anchor,
disableAxes = false,
disableSliders = false,
disableRotations = false,
disableScaling = false,
activeAxes = [true, true, true],
offset = [0, 0, 0],
rotation = [0, 0, 0],
scale = 1,
lineWidth = 4,
fixed = false,
translationLimits,
rotationLimits,
scaleLimits,
depthTest = true,
renderOrder = 500,
axisColors = ['#ff2060', '#20df80', '#2080ff'],
hoveredColor = '#ffff40',
annotations = false,
annotationsClass,
opacity = 1,
visible = true,
userData,
children,
...props
}, fRef) => {
const invalidate = useThree(state => state.invalidate);
const parentRef = React.useRef(null);
const ref = React.useRef(null);
const gizmoRef = React.useRef(null);
const childrenRef = React.useRef(null);
const translation = React.useRef([0, 0, 0]);
const cameraScale = React.useRef(new THREE.Vector3(1, 1, 1));
const gizmoScale = React.useRef(new THREE.Vector3(1, 1, 1));
React.useLayoutEffect(() => {
if (!anchor) return;
childrenRef.current.updateWorldMatrix(true, true);
mPInv.copy(childrenRef.current.matrixWorld).invert();
bb.makeEmpty();
childrenRef.current.traverse(obj => {
if (!obj.geometry) return;
if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
mL.copy(obj.matrixWorld).premultiply(mPInv);
bbObj.copy(obj.geometry.boundingBox);
bbObj.applyMatrix4(mL);
bb.union(bbObj);
});
vCenter.copy(bb.max).add(bb.min).multiplyScalar(0.5);
vSize.copy(bb.max).sub(bb.min).multiplyScalar(0.5);
vAnchorOffset.copy(vSize).multiply(new THREE.Vector3(...anchor)).add(vCenter);
vPosition.set(...offset).add(vAnchorOffset);
gizmoRef.current.position.copy(vPosition);
invalidate();
});
const config = React.useMemo(() => ({
onDragStart: props => {
mL0.copy(ref.current.matrix);
mW0.copy(ref.current.matrixWorld);
onDragStart && onDragStart(props);
invalidate();
},
onDrag: mdW => {
mP.copy(parentRef.current.matrixWorld);
mPInv.copy(mP).invert();
// After applying the delta
mW.copy(mW0).premultiply(mdW);
mL.copy(mW).premultiply(mPInv);
mL0Inv.copy(mL0).invert();
mdL.copy(mL).multiply(mL0Inv);
if (autoTransform) {
ref.current.matrix.copy(mL);
}
onDrag && onDrag(mL, mdL, mW, mdW);
invalidate();
},
onDragEnd: () => {
if (onDragEnd) onDragEnd();
invalidate();
},
translation,
translationLimits,
rotationLimits,
axisColors,
hoveredColor,
opacity,
scale,
lineWidth,
fixed,
depthTest,
renderOrder,
userData,
annotations,
annotationsClass
}), [onDragStart, onDrag, onDragEnd, translation, translationLimits, rotationLimits, scaleLimits, depthTest, scale, lineWidth, fixed, ...axisColors, hoveredColor, opacity, userData, autoTransform, annotations, annotationsClass]);
const vec = new THREE.Vector3();
useFrame(state => {
if (fixed) {
const sf = calculateScaleFactor(gizmoRef.current.getWorldPosition(vec), scale, state.camera, state.size);
cameraScale.current.setScalar(sf);
}
if (matrix && matrix instanceof THREE.Matrix4) {
ref.current.matrix = matrix;
}
// Update gizmo scale in accordance with matrix changes
// Without this, there might be noticable turbulences if scaling happens fast enough
ref.current.updateWorldMatrix(true, true);
mG.makeRotationFromEuler(gizmoRef.current.rotation).setPosition(gizmoRef.current.position).premultiply(ref.current.matrixWorld);
gizmoScale.current.setFromMatrixScale(mG);
vScale.copy(cameraScale.current).divide(gizmoScale.current);
if (Math.abs(gizmoRef.current.scale.x - vScale.x) > 1e-4 || Math.abs(gizmoRef.current.scale.y - vScale.y) > 1e-4 || Math.abs(gizmoRef.current.scale.z - vScale.z) > 1e-4) {
gizmoRef.current.scale.copy(vScale);
state.invalidate();
}
});
React.useImperativeHandle(fRef, () => ref.current, []);
return /*#__PURE__*/React.createElement(context.Provider, {
value: config
}, /*#__PURE__*/React.createElement("group", {
ref: parentRef
}, /*#__PURE__*/React.createElement("group", _extends({
ref: ref,
matrix: matrix,
matrixAutoUpdate: false
}, props), /*#__PURE__*/React.createElement("group", {
visible: visible,
ref: gizmoRef,
position: offset,
rotation: rotation
}, enabled && /*#__PURE__*/React.createElement(React.Fragment, null, !disableAxes && activeAxes[0] && /*#__PURE__*/React.createElement(AxisArrow, {
axis: 0,
direction: xDir
}), !disableAxes && activeAxes[1] && /*#__PURE__*/React.createElement(AxisArrow, {
axis: 1,
direction: yDir
}), !disableAxes && activeAxes[2] && /*#__PURE__*/React.createElement(AxisArrow, {
axis: 2,
direction: zDir
}), !disableSliders && activeAxes[0] && activeAxes[1] && /*#__PURE__*/React.createElement(PlaneSlider, {
axis: 2,
dir1: xDir,
dir2: yDir
}), !disableSliders && activeAxes[0] && activeAxes[2] && /*#__PURE__*/React.createElement(PlaneSlider, {
axis: 1,
dir1: zDir,
dir2: xDir
}), !disableSliders && activeAxes[2] && activeAxes[1] && /*#__PURE__*/React.createElement(PlaneSlider, {
axis: 0,
dir1: yDir,
dir2: zDir
}), !disableRotations && activeAxes[0] && activeAxes[1] && /*#__PURE__*/React.createElement(AxisRotator, {
axis: 2,
dir1: xDir,
dir2: yDir
}), !disableRotations && activeAxes[0] && activeAxes[2] && /*#__PURE__*/React.createElement(AxisRotator, {
axis: 1,
dir1: zDir,
dir2: xDir
}), !disableRotations && activeAxes[2] && activeAxes[1] && /*#__PURE__*/React.createElement(AxisRotator, {
axis: 0,
dir1: yDir,
dir2: zDir
}), !disableScaling && activeAxes[0] && /*#__PURE__*/React.createElement(ScalingSphere, {
axis: 0,
direction: xDir
}), !disableScaling && activeAxes[1] && /*#__PURE__*/React.createElement(ScalingSphere, {
axis: 1,
direction: yDir
}), !disableScaling && activeAxes[2] && /*#__PURE__*/React.createElement(ScalingSphere, {
axis: 2,
direction: zDir
}))), /*#__PURE__*/React.createElement("group", {
ref: childrenRef
}, children))));
});
export { PivotControls };