2
2
// Copyright (c) Unity Technologies. For terms of use, see
3
3
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
4
4
5
- using System ;
5
+ using System . Collections . Generic ;
6
6
using UnityEngine ;
7
7
8
8
namespace UnityEditor . IMGUI . Controls
@@ -14,27 +14,49 @@ public class ArcHandle
14
14
15
15
static readonly float s_DefaultRadiusHandleSize = 0.03f ;
16
16
17
- static float DefaultAngleHandleSizeFunction ( Vector3 position )
17
+ static readonly Dictionary < int , Quaternion > s_MostRecentValidAngleHandleOrientations =
18
+ new Dictionary < int , Quaternion > ( ) ;
19
+
20
+ // only used inside of DefaultAngleHandleDrawFunction to look up and store the most recent valid orientation per handle
21
+ // done so that DefaultAngleHandleDrawFunction can be a static method, which makes angleHandleDrawFunction more usable by sub-classes
22
+ static int s_CurrentlyDrawingAngleHandleHash ;
23
+
24
+ public static void DefaultAngleHandleDrawFunction (
25
+ int controlID , Vector3 position , Quaternion rotation , float size , EventType eventType
26
+ )
18
27
{
19
- return HandleUtility . GetHandleSize ( position ) * s_DefaultAngleHandleSize ;
28
+ Handles . DrawLine ( Vector3 . zero , position ) ;
29
+
30
+ // draw a cylindrical "hammer head" to indicate the direction the handle will move
31
+ Vector3 worldPosition = Handles . matrix . MultiplyPoint3x4 ( position ) ;
32
+ Vector3 normal = worldPosition - Handles . matrix . MultiplyPoint3x4 ( Vector3 . zero ) ;
33
+ Vector3 tangent = Handles . matrix . MultiplyVector ( Quaternion . AngleAxis ( 90f , Vector3 . up ) * position ) ;
34
+ Quaternion mostRecentValidOrientation ;
35
+ if ( ! s_MostRecentValidAngleHandleOrientations . TryGetValue ( s_CurrentlyDrawingAngleHandleHash , out mostRecentValidOrientation ) )
36
+ mostRecentValidOrientation = Quaternion . identity ;
37
+ rotation = Mathf . Approximately ( tangent . sqrMagnitude , 0f ) ?
38
+ mostRecentValidOrientation : Quaternion . LookRotation ( tangent , normal ) ;
39
+ s_MostRecentValidAngleHandleOrientations [ s_CurrentlyDrawingAngleHandleHash ] = rotation ;
40
+ Matrix4x4 matrix =
41
+ Matrix4x4 . TRS ( worldPosition , rotation , ( Vector3 . one + Vector3 . forward * s_DefaultAngleHandleSizeRatio ) ) ;
42
+ using ( new Handles . DrawingScope ( matrix ) )
43
+ Handles . CylinderHandleCap ( controlID , Vector3 . zero , Quaternion . identity , size , eventType ) ;
44
+ s_CurrentlyDrawingAngleHandleHash = 0 ;
20
45
}
21
46
22
- static float DefaultRadiusHandleSizeFunction ( Vector3 position )
47
+ public static float DefaultAngleHandleSizeFunction ( Vector3 position )
23
48
{
24
- return HandleUtility . GetHandleSize ( position ) * s_DefaultRadiusHandleSize ;
49
+ return HandleUtility . GetHandleSize ( position ) * s_DefaultAngleHandleSize ;
25
50
}
26
51
27
- static void DefaultRadiusHandleDrawFunction (
28
- int controlID , Vector3 position , Quaternion rotation , float size , EventType eventType
29
- )
52
+ public static float DefaultRadiusHandleSizeFunction ( Vector3 position )
30
53
{
31
- Handles . DotHandleCap ( controlID , position , rotation , size , eventType ) ;
54
+ return HandleUtility . GetHandleSize ( position ) * s_DefaultRadiusHandleSize ;
32
55
}
33
56
34
57
private bool m_ControlIDsReserved = false ;
35
58
private int m_AngleHandleControlID ;
36
59
private int [ ] m_RadiusHandleControlIDs = new int [ 4 ] ;
37
- private Quaternion m_MostRecentValidAngleHandleOrientation = Quaternion . identity ;
38
60
39
61
public float angle { get ; set ; }
40
62
@@ -60,6 +82,15 @@ public ArcHandle()
60
82
{
61
83
radius = 1f ;
62
84
SetColorWithoutRadiusHandle ( Color . white , 0.1f ) ;
85
+ angleHandleDrawFunction = DefaultAngleHandleDrawFunction ;
86
+ angleHandleSizeFunction = DefaultAngleHandleSizeFunction ;
87
+ radiusHandleDrawFunction = Handles . DotHandleCap ;
88
+ radiusHandleSizeFunction = DefaultRadiusHandleSizeFunction ;
89
+ }
90
+
91
+ ~ ArcHandle ( )
92
+ {
93
+ s_MostRecentValidAngleHandleOrientations . Remove ( GetHashCode ( ) ) ;
63
94
}
64
95
65
96
public void SetColorWithoutRadiusHandle ( Color color , float fillColorAlpha )
@@ -147,15 +178,13 @@ public void DrawHandle()
147
178
Vector3 newPosition ;
148
179
EditorGUI . BeginChangeCheck ( ) ;
149
180
{
150
- float size = radiusHandleSizeFunction == null ?
151
- DefaultRadiusHandleSizeFunction ( radiusHandlePosition ) :
152
- radiusHandleSizeFunction ( radiusHandlePosition ) ;
181
+ var size = radiusHandleSizeFunction == null ? 0f : radiusHandleSizeFunction ( radiusHandlePosition ) ;
153
182
newPosition = Handles . Slider (
154
183
m_RadiusHandleControlIDs [ i ] ,
155
184
radiusHandlePosition ,
156
185
Vector3 . forward ,
157
186
size ,
158
- radiusHandleDrawFunction ?? DefaultRadiusHandleDrawFunction ,
187
+ radiusHandleDrawFunction ,
159
188
SnapSettings . move . z
160
189
) ;
161
190
}
@@ -171,21 +200,20 @@ public void DrawHandle()
171
200
// draw angle handle last so it will always take precedence when overlapping a radius handle
172
201
using ( new Handles . DrawingScope ( Handles . color * angleHandleColor ) )
173
202
{
174
- if ( Handles . color . a > 0f )
203
+ if ( Handles . color . a > 0f && angleHandleDrawFunction != null )
175
204
{
176
205
EditorGUI . BeginChangeCheck ( ) ;
177
206
{
178
- float size = angleHandleSizeFunction == null ?
179
- DefaultAngleHandleSizeFunction ( angleHandlePosition ) :
180
- angleHandleSizeFunction ( angleHandlePosition ) ;
207
+ var size = angleHandleSizeFunction == null ? 0f : angleHandleSizeFunction ( angleHandlePosition ) ;
208
+ s_CurrentlyDrawingAngleHandleHash = GetHashCode ( ) ;
181
209
angleHandlePosition = Handles . Slider2D (
182
210
m_AngleHandleControlID ,
183
211
angleHandlePosition ,
184
212
Vector3 . up ,
185
213
Vector3 . forward ,
186
214
Vector3 . right ,
187
215
size ,
188
- angleHandleDrawFunction ?? DefaultAngleHandleDrawFunction ,
216
+ angleHandleDrawFunction ,
189
217
Vector2 . zero
190
218
) ;
191
219
}
@@ -207,23 +235,5 @@ internal void GetControlIDs()
207
235
m_RadiusHandleControlIDs [ i ] = GUIUtility . GetControlID ( GetHashCode ( ) , FocusType . Passive ) ;
208
236
m_ControlIDsReserved = true ;
209
237
}
210
-
211
- private void DefaultAngleHandleDrawFunction (
212
- int controlID , Vector3 position , Quaternion rotation , float size , EventType eventType
213
- )
214
- {
215
- Handles . DrawLine ( Vector3 . zero , position ) ;
216
-
217
- // draw a cylindrical "hammer head" to indicate the direction the handle will move
218
- Vector3 worldPosition = Handles . matrix . MultiplyPoint3x4 ( position ) ;
219
- Vector3 normal = worldPosition - Handles . matrix . MultiplyPoint3x4 ( Vector3 . zero ) ;
220
- Vector3 tangent = Handles . matrix . MultiplyVector ( Quaternion . AngleAxis ( 90f , Vector3 . up ) * position ) ;
221
- m_MostRecentValidAngleHandleOrientation = rotation = tangent . sqrMagnitude == 0f ?
222
- m_MostRecentValidAngleHandleOrientation : Quaternion . LookRotation ( tangent , normal ) ;
223
- Matrix4x4 matrix =
224
- Matrix4x4 . TRS ( worldPosition , rotation , ( Vector3 . one + Vector3 . forward * s_DefaultAngleHandleSizeRatio ) ) ;
225
- using ( new Handles . DrawingScope ( matrix ) )
226
- Handles . CylinderHandleCap ( controlID , Vector3 . zero , Quaternion . identity , size , eventType ) ;
227
- }
228
238
}
229
239
}
0 commit comments