@react-three/drei 9.99.7 → 9.101.0

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.
@@ -0,0 +1,192 @@
1
+ import * as React from 'react';
2
+ import * as THREE from 'three';
3
+ import { useThree } from '@react-three/fiber';
4
+ import { Html } from '../Html.js';
5
+ import { context } from './context.js';
6
+ import { calculateScaleFactor } from '../../core/calculateScaleFactor.js';
7
+
8
+ const vec1 = /* @__PURE__ */new THREE.Vector3();
9
+ const vec2 = /* @__PURE__ */new THREE.Vector3();
10
+ const calculateOffset = (clickPoint, normal, rayStart, rayDir) => {
11
+ const e1 = normal.dot(normal);
12
+ const e2 = normal.dot(clickPoint) - normal.dot(rayStart);
13
+ const e3 = normal.dot(rayDir);
14
+ if (e3 === 0) {
15
+ return -e2 / e1;
16
+ }
17
+ vec1.copy(rayDir).multiplyScalar(e1 / e3).sub(normal);
18
+ vec2.copy(rayDir).multiplyScalar(e2 / e3).add(rayStart).sub(clickPoint);
19
+ const offset = -vec1.dot(vec2) / vec1.dot(vec1);
20
+ return offset;
21
+ };
22
+ const upV = /* @__PURE__ */new THREE.Vector3(0, 1, 0);
23
+ const scaleV = /* @__PURE__ */new THREE.Vector3();
24
+ const scaleMatrix = /* @__PURE__ */new THREE.Matrix4();
25
+ const ScalingSphere = ({
26
+ direction,
27
+ axis
28
+ }) => {
29
+ const {
30
+ scaleLimits,
31
+ annotations,
32
+ annotationsClass,
33
+ depthTest,
34
+ scale,
35
+ lineWidth,
36
+ fixed,
37
+ axisColors,
38
+ hoveredColor,
39
+ opacity,
40
+ onDragStart,
41
+ onDrag,
42
+ onDragEnd,
43
+ userData
44
+ } = React.useContext(context);
45
+ const size = useThree(state => state.size);
46
+ // @ts-expect-error new in @react-three/fiber@7.0.5
47
+ const camControls = useThree(state => state.controls);
48
+ const divRef = React.useRef(null);
49
+ const objRef = React.useRef(null);
50
+ const meshRef = React.useRef(null);
51
+ const scale0 = React.useRef(1);
52
+ const scaleCur = React.useRef(1);
53
+ const clickInfo = React.useRef(null);
54
+ const [isHovered, setIsHovered] = React.useState(false);
55
+ const position = fixed ? 1.2 : 1.2 * scale;
56
+ const onPointerDown = React.useCallback(e => {
57
+ if (annotations) {
58
+ divRef.current.innerText = `${scaleCur.current.toFixed(2)}`;
59
+ divRef.current.style.display = 'block';
60
+ }
61
+ e.stopPropagation();
62
+ const rotation = new THREE.Matrix4().extractRotation(objRef.current.matrixWorld);
63
+ const clickPoint = e.point.clone();
64
+ const origin = new THREE.Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
65
+ const dir = direction.clone().applyMatrix4(rotation).normalize();
66
+ const mPLG = objRef.current.matrixWorld.clone();
67
+ const mPLGInv = mPLG.clone().invert();
68
+ const offsetMultiplier = fixed ? 1 / calculateScaleFactor(objRef.current.getWorldPosition(vec1), scale, e.camera, size) : 1;
69
+ clickInfo.current = {
70
+ clickPoint,
71
+ dir,
72
+ mPLG,
73
+ mPLGInv,
74
+ offsetMultiplier
75
+ };
76
+ onDragStart({
77
+ component: 'Sphere',
78
+ axis,
79
+ origin,
80
+ directions: [dir]
81
+ });
82
+ camControls && (camControls.enabled = false);
83
+ // @ts-ignore - setPointerCapture is not in the type definition
84
+ e.target.setPointerCapture(e.pointerId);
85
+ }, [annotations, camControls, direction, onDragStart, axis, fixed, scale, size]);
86
+ const onPointerMove = React.useCallback(e => {
87
+ e.stopPropagation();
88
+ if (!isHovered) setIsHovered(true);
89
+ if (clickInfo.current) {
90
+ const {
91
+ clickPoint,
92
+ dir,
93
+ mPLG,
94
+ mPLGInv,
95
+ offsetMultiplier
96
+ } = clickInfo.current;
97
+ 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
98
+
99
+ const offsetW = calculateOffset(clickPoint, dir, e.ray.origin, e.ray.direction);
100
+ const offsetL = offsetW * offsetMultiplier;
101
+ const offsetH = fixed ? offsetL : offsetL / scale;
102
+ let upscale = Math.pow(2, offsetH * 0.2);
103
+
104
+ // @ts-ignore
105
+ if (e.shiftKey) {
106
+ upscale = Math.round(upscale * 10) / 10;
107
+ }
108
+ upscale = Math.max(upscale, min / scale0.current);
109
+ if (max !== undefined) {
110
+ upscale = Math.min(upscale, max / scale0.current);
111
+ }
112
+ scaleCur.current = scale0.current * upscale;
113
+ meshRef.current.position.set(0, position + offsetL, 0);
114
+ if (annotations) {
115
+ divRef.current.innerText = `${scaleCur.current.toFixed(2)}`;
116
+ }
117
+ scaleV.set(1, 1, 1);
118
+ scaleV.setComponent(axis, upscale);
119
+ scaleMatrix.makeScale(scaleV.x, scaleV.y, scaleV.z).premultiply(mPLG).multiply(mPLGInv);
120
+ onDrag(scaleMatrix);
121
+ }
122
+ }, [annotations, position, onDrag, isHovered, scaleLimits, axis]);
123
+ const onPointerUp = React.useCallback(e => {
124
+ if (annotations) {
125
+ divRef.current.style.display = 'none';
126
+ }
127
+ e.stopPropagation();
128
+ scale0.current = scaleCur.current;
129
+ clickInfo.current = null;
130
+ meshRef.current.position.set(0, position, 0);
131
+ onDragEnd();
132
+ camControls && (camControls.enabled = true);
133
+ // @ts-ignore - releasePointerCapture & PointerEvent#pointerId is not in the type definition
134
+ e.target.releasePointerCapture(e.pointerId);
135
+ }, [annotations, camControls, onDragEnd, position]);
136
+ const onPointerOut = React.useCallback(e => {
137
+ e.stopPropagation();
138
+ setIsHovered(false);
139
+ }, []);
140
+ const {
141
+ radius,
142
+ matrixL
143
+ } = React.useMemo(() => {
144
+ const radius = fixed ? lineWidth / scale * 1.8 : scale / 22.5;
145
+ const quaternion = new THREE.Quaternion().setFromUnitVectors(upV, direction.clone().normalize());
146
+ const matrixL = new THREE.Matrix4().makeRotationFromQuaternion(quaternion);
147
+ return {
148
+ radius,
149
+ matrixL
150
+ };
151
+ }, [direction, scale, lineWidth, fixed]);
152
+ const color = isHovered ? hoveredColor : axisColors[axis];
153
+ return /*#__PURE__*/React.createElement("group", {
154
+ ref: objRef
155
+ }, /*#__PURE__*/React.createElement("group", {
156
+ matrix: matrixL,
157
+ matrixAutoUpdate: false,
158
+ onPointerDown: onPointerDown,
159
+ onPointerMove: onPointerMove,
160
+ onPointerUp: onPointerUp,
161
+ onPointerOut: onPointerOut
162
+ }, annotations && /*#__PURE__*/React.createElement(Html, {
163
+ position: [0, position / 2, 0]
164
+ }, /*#__PURE__*/React.createElement("div", {
165
+ style: {
166
+ display: 'none',
167
+ background: '#151520',
168
+ color: 'white',
169
+ padding: '6px 8px',
170
+ borderRadius: 7,
171
+ whiteSpace: 'nowrap'
172
+ },
173
+ className: annotationsClass,
174
+ ref: divRef
175
+ })), /*#__PURE__*/React.createElement("mesh", {
176
+ ref: meshRef,
177
+ position: [0, position, 0],
178
+ renderOrder: 500,
179
+ userData: userData
180
+ }, /*#__PURE__*/React.createElement("sphereGeometry", {
181
+ args: [radius, 12, 12]
182
+ }), /*#__PURE__*/React.createElement("meshBasicMaterial", {
183
+ transparent: true,
184
+ depthTest: depthTest,
185
+ color: color,
186
+ opacity: opacity,
187
+ polygonOffset: true,
188
+ polygonOffsetFactor: -10
189
+ }))));
190
+ };
191
+
192
+ export { ScalingSphere, calculateOffset };
@@ -1,7 +1,7 @@
1
1
  import * as THREE from 'three';
2
2
  import * as React from 'react';
3
3
  export type OnDragStartProps = {
4
- component: 'Arrow' | 'Slider' | 'Rotator';
4
+ component: 'Arrow' | 'Slider' | 'Rotator' | 'Sphere';
5
5
  axis: 0 | 1 | 2;
6
6
  origin: THREE.Vector3;
7
7
  directions: THREE.Vector3[];
@@ -15,6 +15,7 @@ export type PivotContext = {
15
15
  };
16
16
  translationLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
17
17
  rotationLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
18
+ scaleLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
18
19
  axisColors: [string | number, string | number, string | number];
19
20
  hoveredColor: string | number;
20
21
  opacity: number;
@@ -1 +1 @@
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"),o=require("./AxisRotator.cjs.js"),n=require("./PlaneSlider.cjs.js"),c=require("./context.cjs.js"),l=require("../../core/calculateScaleFactor.cjs.js");function s(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(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 d=s(e),x=u(t),m=u(i);const p=new m.Matrix4,f=new m.Matrix4,y=new m.Matrix4,w=new m.Matrix4,v=new m.Matrix4,g=new m.Matrix4,j=new m.Matrix4,b=new m.Matrix4,E=new m.Box3,A=new m.Box3,h=new m.Vector3,M=new m.Vector3,q=new m.Vector3,S=new m.Vector3,R=new m.Vector3(1,0,0),P=new m.Vector3(0,1,0),D=new m.Vector3(0,0,1),V=x.forwardRef((({matrix:e,onDragStart:t,onDrag:i,onDragEnd:s,autoTransform:u=!0,anchor:V,disableAxes:W=!1,disableSliders:C=!1,disableRotations:L=!1,activeAxes:O=[!0,!0,!0],offset:B=[0,0,0],rotation:T=[0,0,0],scale:_=1,lineWidth:z=4,fixed:F=!1,translationLimits:k,rotationLimits:H,depthTest:I=!0,axisColors:U=["#ff2060","#20df80","#2080ff"],hoveredColor:G="#ffff40",annotations:J=!1,annotationsClass:K,opacity:N=1,visible:Q=!0,userData:X,children:Y,...Z},$)=>{const ee=r.useThree((e=>e.invalidate)),re=x.useRef(null),te=x.useRef(null),ie=x.useRef(null),ae=x.useRef(null),oe=x.useRef([0,0,0]);x.useLayoutEffect((()=>{V&&(ae.current.updateWorldMatrix(!0,!0),w.copy(ae.current.matrixWorld).invert(),E.makeEmpty(),ae.current.traverse((e=>{e.geometry&&(e.geometry.boundingBox||e.geometry.computeBoundingBox(),g.copy(e.matrixWorld).premultiply(w),A.copy(e.geometry.boundingBox),A.applyMatrix4(g),E.union(A))})),h.copy(E.max).add(E.min).multiplyScalar(.5),M.copy(E.max).sub(E.min).multiplyScalar(.5),q.copy(M).multiply(new m.Vector3(...V)).add(h),S.set(...B).add(q),ie.current.position.copy(S),ee())}));const ne=x.useMemo((()=>({onDragStart:e=>{p.copy(te.current.matrix),f.copy(te.current.matrixWorld),t&&t(e),ee()},onDrag:e=>{y.copy(re.current.matrixWorld),w.copy(y).invert(),v.copy(f).premultiply(e),g.copy(v).premultiply(w),j.copy(p).invert(),b.copy(g).multiply(j),u&&te.current.matrix.copy(g),i&&i(g,b,v,e),ee()},onDragEnd:()=>{s&&s(),ee()},translation:oe,translationLimits:k,rotationLimits:H,axisColors:U,hoveredColor:G,opacity:N,scale:_,lineWidth:z,fixed:F,depthTest:I,userData:X,annotations:J,annotationsClass:K})),[t,i,s,oe,k,H,I,_,z,F,...U,G,N,X,u,J,K]),ce=new m.Vector3;return r.useFrame((e=>{if(F){const a=l.calculateScaleFactor(ie.current.getWorldPosition(ce),_,e.camera,e.size);var r,t,i;if(ie.current)(null==(r=ie.current)?void 0:r.scale.x)===a&&(null==(t=ie.current)?void 0:t.scale.y)===a&&(null==(i=ie.current)?void 0:i.scale.z)===a||(ie.current.scale.setScalar(a),e.invalidate())}})),x.useImperativeHandle($,(()=>te.current),[]),x.useLayoutEffect((()=>{e&&e instanceof m.Matrix4&&(te.current.matrix=e)}),[e]),x.createElement(c.context.Provider,{value:ne},x.createElement("group",{ref:re},x.createElement("group",d.default({ref:te,matrix:e,matrixAutoUpdate:!1},Z),x.createElement("group",{visible:Q,ref:ie,position:B,rotation:T},!W&&O[0]&&x.createElement(a.AxisArrow,{axis:0,direction:R}),!W&&O[1]&&x.createElement(a.AxisArrow,{axis:1,direction:P}),!W&&O[2]&&x.createElement(a.AxisArrow,{axis:2,direction:D}),!C&&O[0]&&O[1]&&x.createElement(n.PlaneSlider,{axis:2,dir1:R,dir2:P}),!C&&O[0]&&O[2]&&x.createElement(n.PlaneSlider,{axis:1,dir1:D,dir2:R}),!C&&O[2]&&O[1]&&x.createElement(n.PlaneSlider,{axis:0,dir1:P,dir2:D}),!L&&O[0]&&O[1]&&x.createElement(o.AxisRotator,{axis:2,dir1:R,dir2:P}),!L&&O[0]&&O[2]&&x.createElement(o.AxisRotator,{axis:1,dir1:D,dir2:R}),!L&&O[2]&&O[1]&&x.createElement(o.AxisRotator,{axis:0,dir1:P,dir2:D})),x.createElement("group",{ref:ae},Y))))}));exports.PivotControls=V;
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"),s=require("./context.cjs.js"),l=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 x=u(e),m=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,j=new p.Matrix4,E=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),C=new p.Vector3(0,0,1),L=m.forwardRef((({matrix:e,onDragStart:t,onDrag:i,onDragEnd:u,autoTransform:d=!0,anchor:L,disableAxes:O=!1,disableSliders:B=!1,disableRotations:F=!1,disableScaling:z=!1,activeAxes:T=[!0,!0,!0],offset:_=[0,0,0],rotation:k=[0,0,0],scale:H=1,lineWidth:I=4,fixed:U=!1,translationLimits:G,rotationLimits:J,scaleLimits:K,depthTest:N=!0,axisColors:Q=["#ff2060","#20df80","#2080ff"],hoveredColor:X="#ffff40",annotations:Y=!1,annotationsClass:Z,opacity:$=1,visible:ee=!0,userData:re,children:te,...ie},ae)=>{const ne=r.useThree((e=>e.invalidate)),oe=m.useRef(null),ce=m.useRef(null),se=m.useRef(null),le=m.useRef(null),ue=m.useRef([0,0,0]),de=m.useRef(new p.Vector3(1,1,1)),xe=m.useRef(new p.Vector3(1,1,1));m.useLayoutEffect((()=>{L&&(le.current.updateWorldMatrix(!0,!0),g.copy(le.current.matrixWorld).invert(),v.makeEmpty(),le.current.traverse((e=>{e.geometry&&(e.geometry.boundingBox||e.geometry.computeBoundingBox(),j.copy(e.matrixWorld).premultiply(g),M.copy(e.geometry.boundingBox),M.applyMatrix4(j),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(..._).add(R),se.current.position.copy(V),ne())}));const me=m.useMemo((()=>({onDragStart:e=>{f.copy(ce.current.matrix),y.copy(ce.current.matrixWorld),t&&t(e),ne()},onDrag:e=>{w.copy(oe.current.matrixWorld),g.copy(w).invert(),b.copy(y).premultiply(e),j.copy(b).premultiply(g),E.copy(f).invert(),S.copy(j).multiply(E),d&&ce.current.matrix.copy(j),i&&i(j,S,b,e),ne()},onDragEnd:()=>{u&&u(),ne()},translation:ue,translationLimits:G,rotationLimits:J,axisColors:Q,hoveredColor:X,opacity:$,scale:H,lineWidth:I,fixed:U,depthTest:N,userData:re,annotations:Y,annotationsClass:Z})),[t,i,u,ue,G,J,K,N,H,I,U,...Q,X,$,re,d,Y,Z]),pe=new p.Vector3;return r.useFrame((r=>{if(U){const e=l.calculateScaleFactor(se.current.getWorldPosition(pe),H,r.camera,r.size);de.current.setScalar(e)}e&&e instanceof p.Matrix4&&(ce.current.matrix=e),ce.current.updateWorldMatrix(!0,!0),h.makeRotationFromEuler(se.current.rotation).setPosition(se.current.position).premultiply(ce.current.matrixWorld),xe.current.setFromMatrixScale(h),P.copy(de.current).divide(xe.current),(Math.abs(se.current.scale.x-P.x)>1e-4||Math.abs(se.current.scale.y-P.y)>1e-4||Math.abs(se.current.scale.z-P.z)>1e-4)&&(se.current.scale.copy(P),r.invalidate())})),m.useImperativeHandle(ae,(()=>ce.current),[]),m.createElement(s.context.Provider,{value:me},m.createElement("group",{ref:oe},m.createElement("group",x.default({ref:ce,matrix:e,matrixAutoUpdate:!1},ie),m.createElement("group",{visible:ee,ref:se,position:_,rotation:k},!O&&T[0]&&m.createElement(a.AxisArrow,{axis:0,direction:W}),!O&&T[1]&&m.createElement(a.AxisArrow,{axis:1,direction:D}),!O&&T[2]&&m.createElement(a.AxisArrow,{axis:2,direction:C}),!B&&T[0]&&T[1]&&m.createElement(o.PlaneSlider,{axis:2,dir1:W,dir2:D}),!B&&T[0]&&T[2]&&m.createElement(o.PlaneSlider,{axis:1,dir1:C,dir2:W}),!B&&T[2]&&T[1]&&m.createElement(o.PlaneSlider,{axis:0,dir1:D,dir2:C}),!F&&T[0]&&T[1]&&m.createElement(n.AxisRotator,{axis:2,dir1:W,dir2:D}),!F&&T[0]&&T[2]&&m.createElement(n.AxisRotator,{axis:1,dir1:C,dir2:W}),!F&&T[2]&&T[1]&&m.createElement(n.AxisRotator,{axis:0,dir1:D,dir2:C}),!z&&T[0]&&m.createElement(c.ScalingSphere,{axis:0,direction:W}),!z&&T[1]&&m.createElement(c.ScalingSphere,{axis:1,direction:D}),!z&&T[2]&&m.createElement(c.ScalingSphere,{axis:2,direction:C})),m.createElement("group",{ref:le},te))))}));exports.PivotControls=L;
@@ -15,8 +15,10 @@ type PivotControlsProps = {
15
15
  disableAxes?: boolean;
16
16
  disableSliders?: boolean;
17
17
  disableRotations?: boolean;
18
+ disableScaling?: boolean;
18
19
  translationLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
19
20
  rotationLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
21
+ scaleLimits?: [[number, number] | undefined, [number, number] | undefined, [number, number] | undefined];
20
22
  axisColors?: [string | number, string | number, string | number];
21
23
  hoveredColor?: string | number;
22
24
  annotations?: boolean;
@@ -5,6 +5,7 @@ import * as THREE from 'three';
5
5
  import { AxisArrow } from './AxisArrow.js';
6
6
  import { AxisRotator } from './AxisRotator.js';
7
7
  import { PlaneSlider } from './PlaneSlider.js';
8
+ import { ScalingSphere } from './ScalingSphere.js';
8
9
  import { context } from './context.js';
9
10
  import { calculateScaleFactor } from '../../core/calculateScaleFactor.js';
10
11
 
@@ -16,12 +17,14 @@ const mW = /* @__PURE__ */new THREE.Matrix4();
16
17
  const mL = /* @__PURE__ */new THREE.Matrix4();
17
18
  const mL0Inv = /* @__PURE__ */new THREE.Matrix4();
18
19
  const mdL = /* @__PURE__ */new THREE.Matrix4();
20
+ const mG = /* @__PURE__ */new THREE.Matrix4();
19
21
  const bb = /* @__PURE__ */new THREE.Box3();
20
22
  const bbObj = /* @__PURE__ */new THREE.Box3();
21
23
  const vCenter = /* @__PURE__ */new THREE.Vector3();
22
24
  const vSize = /* @__PURE__ */new THREE.Vector3();
23
25
  const vAnchorOffset = /* @__PURE__ */new THREE.Vector3();
24
26
  const vPosition = /* @__PURE__ */new THREE.Vector3();
27
+ const vScale = /* @__PURE__ */new THREE.Vector3();
25
28
  const xDir = /* @__PURE__ */new THREE.Vector3(1, 0, 0);
26
29
  const yDir = /* @__PURE__ */new THREE.Vector3(0, 1, 0);
27
30
  const zDir = /* @__PURE__ */new THREE.Vector3(0, 0, 1);
@@ -35,6 +38,7 @@ const PivotControls = /* @__PURE__ */React.forwardRef(({
35
38
  disableAxes = false,
36
39
  disableSliders = false,
37
40
  disableRotations = false,
41
+ disableScaling = false,
38
42
  activeAxes = [true, true, true],
39
43
  offset = [0, 0, 0],
40
44
  rotation = [0, 0, 0],
@@ -43,6 +47,7 @@ const PivotControls = /* @__PURE__ */React.forwardRef(({
43
47
  fixed = false,
44
48
  translationLimits,
45
49
  rotationLimits,
50
+ scaleLimits,
46
51
  depthTest = true,
47
52
  axisColors = ['#ff2060', '#20df80', '#2080ff'],
48
53
  hoveredColor = '#ffff40',
@@ -60,6 +65,8 @@ const PivotControls = /* @__PURE__ */React.forwardRef(({
60
65
  const gizmoRef = React.useRef(null);
61
66
  const childrenRef = React.useRef(null);
62
67
  const translation = React.useRef([0, 0, 0]);
68
+ const cameraScale = React.useRef(new THREE.Vector3(1, 1, 1));
69
+ const gizmoScale = React.useRef(new THREE.Vector3(1, 1, 1));
63
70
  React.useLayoutEffect(() => {
64
71
  if (!anchor) return;
65
72
  childrenRef.current.updateWorldMatrix(true, true);
@@ -95,7 +102,9 @@ const PivotControls = /* @__PURE__ */React.forwardRef(({
95
102
  mL.copy(mW).premultiply(mPInv);
96
103
  mL0Inv.copy(mL0).invert();
97
104
  mdL.copy(mL).multiply(mL0Inv);
98
- if (autoTransform) ref.current.matrix.copy(mL);
105
+ if (autoTransform) {
106
+ ref.current.matrix.copy(mL);
107
+ }
99
108
  onDrag && onDrag(mL, mdL, mW, mdW);
100
109
  invalidate();
101
110
  },
@@ -116,26 +125,28 @@ const PivotControls = /* @__PURE__ */React.forwardRef(({
116
125
  userData,
117
126
  annotations,
118
127
  annotationsClass
119
- }), [onDragStart, onDrag, onDragEnd, translation, translationLimits, rotationLimits, depthTest, scale, lineWidth, fixed, ...axisColors, hoveredColor, opacity, userData, autoTransform, annotations, annotationsClass]);
128
+ }), [onDragStart, onDrag, onDragEnd, translation, translationLimits, rotationLimits, scaleLimits, depthTest, scale, lineWidth, fixed, ...axisColors, hoveredColor, opacity, userData, autoTransform, annotations, annotationsClass]);
120
129
  const vec = new THREE.Vector3();
121
130
  useFrame(state => {
122
131
  if (fixed) {
123
132
  const sf = calculateScaleFactor(gizmoRef.current.getWorldPosition(vec), scale, state.camera, state.size);
124
- if (gizmoRef.current) {
125
- var _gizmoRef$current, _gizmoRef$current2, _gizmoRef$current3;
126
- if (((_gizmoRef$current = gizmoRef.current) == null ? void 0 : _gizmoRef$current.scale.x) !== sf || ((_gizmoRef$current2 = gizmoRef.current) == null ? void 0 : _gizmoRef$current2.scale.y) !== sf || ((_gizmoRef$current3 = gizmoRef.current) == null ? void 0 : _gizmoRef$current3.scale.z) !== sf) {
127
- gizmoRef.current.scale.setScalar(sf);
128
- state.invalidate();
129
- }
130
- }
133
+ cameraScale.current.setScalar(sf);
134
+ }
135
+ if (matrix && matrix instanceof THREE.Matrix4) {
136
+ ref.current.matrix = matrix;
137
+ }
138
+ // Update gizmo scale in accordance with matrix changes
139
+ // Without this, there might be noticable turbulences if scaling happens fast enough
140
+ ref.current.updateWorldMatrix(true, true);
141
+ mG.makeRotationFromEuler(gizmoRef.current.rotation).setPosition(gizmoRef.current.position).premultiply(ref.current.matrixWorld);
142
+ gizmoScale.current.setFromMatrixScale(mG);
143
+ vScale.copy(cameraScale.current).divide(gizmoScale.current);
144
+ 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) {
145
+ gizmoRef.current.scale.copy(vScale);
146
+ state.invalidate();
131
147
  }
132
148
  });
133
149
  React.useImperativeHandle(fRef, () => ref.current, []);
134
- React.useLayoutEffect(() => {
135
- // If the matrix is a real matrix4 it means that the user wants to control the gizmo
136
- // In that case it should just be set, as a bare prop update would merely copy it
137
- if (matrix && matrix instanceof THREE.Matrix4) ref.current.matrix = matrix;
138
- }, [matrix]);
139
150
  return /*#__PURE__*/React.createElement(context.Provider, {
140
151
  value: config
141
152
  }, /*#__PURE__*/React.createElement("group", {
@@ -182,6 +193,15 @@ const PivotControls = /* @__PURE__ */React.forwardRef(({
182
193
  axis: 0,
183
194
  dir1: yDir,
184
195
  dir2: zDir
196
+ }), !disableScaling && activeAxes[0] && /*#__PURE__*/React.createElement(ScalingSphere, {
197
+ axis: 0,
198
+ direction: xDir
199
+ }), !disableScaling && activeAxes[1] && /*#__PURE__*/React.createElement(ScalingSphere, {
200
+ axis: 1,
201
+ direction: yDir
202
+ }), !disableScaling && activeAxes[2] && /*#__PURE__*/React.createElement(ScalingSphere, {
203
+ axis: 2,
204
+ direction: zDir
185
205
  })), /*#__PURE__*/React.createElement("group", {
186
206
  ref: childrenRef
187
207
  }, children))));