1- import { Color , Xfo , NumberParameter , GeomItem , Material , Torus , ZeaPointerEvent } from '@zeainc/zea-engine'
2-
3- import BaseAxialRotationHandle from './BaseAxialRotationHandle'
4- import './Shaders/HandleShader'
1+ import {
2+ MathFunctions ,
3+ Vec3 ,
4+ Xfo ,
5+ XfoParameter ,
6+ ZeaPointerEvent ,
7+ ZeaMouseEvent ,
8+ ZeaTouchEvent ,
9+ NumberParameter ,
10+ GeomItem ,
11+ Material ,
12+ Color ,
13+ Torus ,
14+ } from '@zeainc/zea-engine'
15+ import Handle from './Handle'
16+ import ParameterValueChange from '../UndoRedo/Changes/ParameterValueChange'
17+ import UndoRedoManager from '../UndoRedo/UndoRedoManager'
18+ import SelectionXfoChange from '../UndoRedo/Changes/SelectionXfoChange'
19+ import SelectionGroup from '../SelectionGroup'
20+ import { Change } from '../UndoRedo/Change'
521
622/**
7- * Class representing an axial rotation scene widget. It has a `Torus` shape and is used to rotate objects around the specified axes.
8- * You can do it by specifying the localXfo orientation:
9- *
10- * ```javascript
11- * const xfo = new Xfo()
12- * // This is rotation over `Y` axis
13- * xfo.ori.setFromAxisAndAngle(new Vec3(0, 1, 0), Math.PI * 0.5)
14- * axialRotationHandle.localXfoParam.value = xfo
15- * ```
16- * **Parameters**
17- * * **Radius(`NumberParameter`):** Specifies the radius of the handler.
23+ * Class representing an axial rotation scene widget.
1824 *
19- * @extends BaseAxialRotationHandle
25+ * @extends Handle
2026 */
21- class AxialRotationHandle extends BaseAxialRotationHandle {
27+ class AxialRotationHandle extends Handle {
28+ param : XfoParameter
2229 radiusParam : NumberParameter
30+ private baseXfo : Xfo
31+ private handleXfo : Xfo
32+ private handleToTargetXfo : Xfo
33+ private vec0 : Vec3
34+ private change : Change
2335 private handleMat : Material
24- handle : GeomItem
36+ private handle : GeomItem
37+
38+ selectionGroup : SelectionGroup
39+
2540 /**
2641 * Create an axial rotation scene widget.
2742 *
2843 * @param name - The name value.
29- * @param radius - The radius value.
30- * @param thickness - The thickness value.
31- * @param color - The color value.
3244 */
33- constructor ( name : string , radius : number , thickness : number , color = new Color ( 1 , 1 , 0 ) ) {
45+ constructor (
46+ name : string ,
47+ radius : number ,
48+ thickness : number ,
49+ radians : number = Math . PI * 0.5 ,
50+ color = new Color ( 1 , 1 , 0 )
51+ ) {
3452 super ( name )
3553
3654 this . radiusParam = new NumberParameter ( 'Radius' , radius )
@@ -43,7 +61,7 @@ class AxialRotationHandle extends BaseAxialRotationHandle {
4361 this . handleMat . getParameter ( 'Overlay' ) . value = 0.9
4462
4563 // const handleGeom = new Cylinder(radius, thickness * 2, 64, 2, false);
46- const handleGeom = new Torus ( thickness , radius , 64 , Math . PI * 0.5 )
64+ const handleGeom = new Torus ( thickness , radius , 64 , radians )
4765 this . handle = new GeomItem ( 'handle' , handleGeom , this . handleMat )
4866
4967 this . radiusParam . on ( 'valueChanged' , ( ) => {
@@ -60,55 +78,122 @@ class AxialRotationHandle extends BaseAxialRotationHandle {
6078 }
6179
6280 /**
63- * Applies a special shinning shader to the handle to illustrate interaction with it .
81+ * highlight the handle to indicate it is under the mouse .
6482 */
6583 highlight ( ) : void {
6684 super . highlight ( )
6785 this . handleMat . getParameter ( 'BaseColor' ) . value = this . highlightColorParam . getValue ( )
6886 }
6987
7088 /**
71- * Removes the shining shader from the handle.
89+ * Removes the highlight from the handle once the mouse moves away .
7290 */
7391 unhighlight ( ) : void {
7492 super . unhighlight ( )
7593 this . handleMat . getParameter ( 'BaseColor' ) . value = this . colorParam . getValue ( )
7694 }
7795
7896 /**
79- * Returns handle's global Xfo
97+ * Sets selectionGroup so this handle can modify the items.
8098 *
81- * @return { Xfo } - The Xfo value
99+ * @param selectionGroup - The SelectionGroup.
82100 */
83- getBaseXfo ( ) : Xfo {
84- return this . globalXfoParam . value
101+ setSelectionGroup ( selectionGroup : SelectionGroup ) : void {
102+ this . selectionGroup = selectionGroup
85103 }
86104
87105 /**
88- * Handles the initially drag interaction of the handle.
106+ * Sets the target parameter for this manipulator.
107+ * This parameter will be modified by interactions on the manipulator.
108+ *
109+ * @param param - The parameter that will be modified during manipulation
110+ */
111+ setTargetParam ( param : XfoParameter ) : void {
112+ this . param = param
113+ }
114+
115+ /**
116+ * Returns target's global xfo parameter.
117+ *
118+ * @return {Parameter } - returns parameter
119+ */
120+ getTargetParam ( ) : XfoParameter {
121+ return this . param ? this . param : this . globalXfoParam
122+ }
123+
124+ /**
125+ * Handles the initially drag of the handle.
89126 *
90127 * @param event - The event param.
91128 */
92129 onDragStart ( event : ZeaPointerEvent ) : void {
93- super . onDragStart ( event )
130+ this . highlight ( )
131+
132+ this . baseXfo = this . globalXfoParam . value . clone ( )
133+
134+ this . vec0 = this . grabPos . subtract ( this . baseXfo . tr )
135+ this . vec0 . normalizeInPlace ( )
136+
137+ // this.offsetXfo = this.localXfoParam.value.inverse()
138+ if ( this . selectionGroup ) {
139+ const items = this . selectionGroup . getItems ( )
140+ this . change = new SelectionXfoChange ( Array . from ( items ) , this . baseXfo )
141+ UndoRedoManager . getInstance ( ) . addChange ( this . change )
142+ } else {
143+ const invBaseXfo = this . baseXfo . inverse ( )
144+ const param = this . getTargetParam ( ) as XfoParameter
145+ this . handleToTargetXfo = invBaseXfo . multiply ( param . value )
146+ this . change = new ParameterValueChange ( param )
147+ UndoRedoManager . getInstance ( ) . addChange ( this . change )
148+ }
94149 }
95150
96151 /**
97- * Handles drag interaction of the handle.
152+ * Handles drag action of the handle.
98153 *
99154 * @param event - The event param.
100155 */
101- onDrag ( event : ZeaPointerEvent ) {
102- super . onDrag ( event )
156+ onDrag ( event : ZeaPointerEvent ) : void {
157+ const vec1 = this . holdPos . subtract ( this . baseXfo . tr )
158+ vec1 . normalizeInPlace ( )
159+ let angle = this . vec0 . angleTo ( vec1 )
160+ if ( this . vec0 . cross ( vec1 ) . dot ( this . baseXfo . ori . getZaxis ( ) ) < 0 ) angle = - angle
161+
162+ if ( ( event instanceof ZeaMouseEvent || event instanceof ZeaTouchEvent ) && event . shiftKey ) {
163+ // modulate the angle to X degree increments.
164+ const increment = MathFunctions . degToRad ( 22.5 )
165+ angle = Math . floor ( angle / increment ) * increment
166+ }
167+
168+ const deltaXfo = new Xfo ( )
169+ deltaXfo . ori . setFromAxisAndAngle ( this . baseXfo . ori . getZaxis ( ) , angle )
170+
171+ if ( this . selectionGroup ) {
172+ const selectionXfoChange = < SelectionXfoChange > this . change
173+ selectionXfoChange . setDeltaXfo ( deltaXfo )
174+ } else {
175+ // Add the values in global space.
176+ const newBase = this . baseXfo . clone ( )
177+ newBase . ori = deltaXfo . ori . multiply ( newBase . ori )
178+ const value = newBase . multiply ( this . handleToTargetXfo )
179+
180+ this . change . update ( {
181+ value,
182+ } )
183+ }
103184 }
104185
105186 /**
106- * Handles the end of dragging interaction with the handle.
187+ * Handles the end of dragging the handle.
107188 *
108189 * @param event - The event param.
109190 */
110191 onDragEnd ( event : ZeaPointerEvent ) : void {
111- super . onDragEnd ( event )
192+ if ( this . selectionGroup ) {
193+ const selectionXfoChange = < SelectionXfoChange > this . change
194+ selectionXfoChange . setDone ( )
195+ }
196+ this . change = null
112197 }
113198}
114199
0 commit comments