@@ -13,38 +13,173 @@ namespace UnityEditor
13
13
class AnimationWindowClipPopup
14
14
{
15
15
[ SerializeField ] public AnimationWindowState state ;
16
- [ SerializeField ] private int selectedIndex ;
17
16
18
- public void OnGUI ( )
17
+ static int s_ClipPopupHash = "s_ClipPopupHash" . GetHashCode ( ) ;
18
+
19
+ internal sealed class ClipPopupCallbackInfo
19
20
{
20
- AnimationWindowSelectionItem selectedItem = state . selectedItem ;
21
- if ( selectedItem == null )
22
- return ;
21
+ // The global shared popup state
22
+ public static ClipPopupCallbackInfo instance = null ;
23
23
24
- if ( selectedItem . canChangeAnimationClip )
24
+ // Name of the command event sent from the popup menu to OnGUI when user has changed selection
25
+ private const string kPopupMenuChangedMessage = "ClipPopupMenuChanged" ;
26
+
27
+ // The control ID of the popup menu that is currently displayed.
28
+ // Used to pass selection changes back again...
29
+ private readonly int m_ControlID = 0 ;
30
+
31
+ // Which item was selected
32
+ private AnimationClip m_SelectedClip = null ;
33
+
34
+ // Which view should we send it to.
35
+ private readonly GUIView m_SourceView ;
36
+
37
+ public ClipPopupCallbackInfo ( int controlID )
25
38
{
26
- string [ ] menuContent = GetClipMenuContent ( ) ;
27
- EditorGUI . BeginChangeCheck ( ) ;
28
- // TODO: Make this more robust
29
- selectedIndex = EditorGUILayout . Popup ( ClipToIndex ( state . activeAnimationClip ) , menuContent , EditorStyles . toolbarPopup ) ;
30
- if ( EditorGUI . EndChangeCheck ( ) )
39
+ m_ControlID = controlID ;
40
+ m_SourceView = GUIView . current ;
41
+ }
42
+
43
+ public static AnimationClip GetSelectedClipForControl ( int controlID , AnimationClip clip )
44
+ {
45
+ Event evt = Event . current ;
46
+ if ( evt . type == EventType . ExecuteCommand && evt . commandName == kPopupMenuChangedMessage )
31
47
{
32
- if ( menuContent [ selectedIndex ] == AnimationWindowStyles . createNewClip . text )
48
+ if ( instance == null )
49
+ {
50
+ Debug . LogError ( "Popup menu has no instance" ) ;
51
+ return clip ;
52
+ }
53
+ if ( instance . m_ControlID == controlID )
33
54
{
34
- AnimationClip newClip = AnimationWindowUtility . CreateNewClip ( selectedItem . rootGameObject . name ) ;
55
+ clip = instance . m_SelectedClip ;
56
+ instance = null ;
57
+ GUI . changed = true ;
58
+ evt . Use ( ) ;
59
+ }
60
+ }
61
+ return clip ;
62
+ }
63
+
64
+ public static void SetSelectedClip ( AnimationClip clip )
65
+ {
66
+ if ( instance == null )
67
+ {
68
+ Debug . LogError ( "Popup menu has no instance" ) ;
69
+ return ;
70
+ }
71
+
72
+ instance . m_SelectedClip = clip ;
73
+ }
74
+
75
+ public static void SendEvent ( )
76
+ {
77
+ if ( instance == null )
78
+ {
79
+ Debug . LogError ( "Popup menu has no instance" ) ;
80
+ return ;
81
+ }
82
+
83
+ instance . m_SourceView . SendEvent ( EditorGUIUtility . CommandEvent ( kPopupMenuChangedMessage ) ) ;
84
+ }
85
+ }
86
+
87
+
88
+ private void DisplayClipMenu ( Rect position , int controlID , AnimationClip clip )
89
+ {
90
+ AnimationClip [ ] clips = GetOrderedClipList ( ) ;
91
+ GUIContent [ ] menuContent = GetClipMenuContent ( clips ) ;
92
+ int selected = ClipToIndex ( clips , clip ) ;
93
+
94
+ // Center popup menu around button widget
95
+ if ( Application . platform == RuntimePlatform . OSXEditor )
96
+ {
97
+ position . y = position . y - selected * 16 - 19 ;
98
+ }
99
+
100
+ ClipPopupCallbackInfo . instance = new ClipPopupCallbackInfo ( controlID ) ;
101
+
102
+ EditorUtility . DisplayCustomMenu ( position , menuContent , selected , ( userData , options , index ) =>
103
+ {
104
+ if ( index < clips . Length )
105
+ {
106
+ ClipPopupCallbackInfo . SetSelectedClip ( clips [ index ] ) ;
107
+ }
108
+ else
109
+ {
110
+ AnimationClip newClip = AnimationWindowUtility . CreateNewClip ( state . activeRootGameObject . name ) ;
35
111
if ( newClip )
36
112
{
37
113
AnimationWindowUtility . AddClipToAnimationPlayerComponent ( state . activeAnimationPlayer , newClip ) ;
38
- state . selection . UpdateClip ( state . selectedItem , newClip ) ;
39
-
40
- // Layout has changed, bail out now.
41
- EditorGUIUtility . ExitGUI ( ) ;
114
+ ClipPopupCallbackInfo . SetSelectedClip ( newClip ) ;
42
115
}
43
116
}
44
- else
117
+
118
+ ClipPopupCallbackInfo . SendEvent ( ) ;
119
+ } , null ) ;
120
+ }
121
+
122
+ // (case 1029160) Modified version of EditorGUI.DoPopup to fit large data list query.
123
+ private AnimationClip DoClipPopup ( AnimationClip clip , GUIStyle style )
124
+ {
125
+ Rect position = EditorGUILayout . GetControlRect ( false , EditorGUI . kSingleLineHeight , style ) ;
126
+ int controlID = GUIUtility . GetControlID ( s_ClipPopupHash , FocusType . Keyboard , position ) ;
127
+
128
+ clip = ClipPopupCallbackInfo . GetSelectedClipForControl ( controlID , clip ) ;
129
+
130
+ Event evt = Event . current ;
131
+ switch ( evt . type )
132
+ {
133
+ case EventType . Repaint :
134
+ Font originalFont = style . font ;
135
+ if ( originalFont && EditorGUIUtility . GetBoldDefaultFont ( ) && originalFont == EditorStyles . miniFont )
45
136
{
46
- state . selection . UpdateClip ( state . selectedItem , IndexToClip ( selectedIndex ) ) ;
137
+ style . font = EditorStyles . miniBoldFont ;
47
138
}
139
+
140
+ GUIContent buttonContent = EditorGUIUtility . TempContent ( CurveUtility . GetClipName ( clip ) ) ;
141
+ buttonContent . tooltip = AssetDatabase . GetAssetPath ( clip ) ;
142
+
143
+ style . Draw ( position , buttonContent , controlID , false ) ;
144
+
145
+ style . font = originalFont ;
146
+ break ;
147
+ case EventType . MouseDown :
148
+ if ( evt . button == 0 && position . Contains ( evt . mousePosition ) )
149
+ {
150
+ DisplayClipMenu ( position , controlID , clip ) ;
151
+ GUIUtility . keyboardControl = controlID ;
152
+ evt . Use ( ) ;
153
+ }
154
+ break ;
155
+ case EventType . KeyDown :
156
+ if ( evt . MainActionKeyForControl ( controlID ) )
157
+ {
158
+ DisplayClipMenu ( position , controlID , clip ) ;
159
+ evt . Use ( ) ;
160
+ }
161
+ break ;
162
+ }
163
+
164
+ return clip ;
165
+ }
166
+
167
+ public void OnGUI ( )
168
+ {
169
+ AnimationWindowSelectionItem selectedItem = state . selectedItem ;
170
+ if ( selectedItem == null )
171
+ return ;
172
+
173
+ if ( selectedItem . canChangeAnimationClip )
174
+ {
175
+ EditorGUI . BeginChangeCheck ( ) ;
176
+ var newClip = DoClipPopup ( state . activeAnimationClip , EditorStyles . toolbarPopup ) ;
177
+ if ( EditorGUI . EndChangeCheck ( ) )
178
+ {
179
+ state . selection . UpdateClip ( state . selectedItem , newClip ) ;
180
+
181
+ // Layout has changed, bail out now.
182
+ EditorGUIUtility . ExitGUI ( ) ;
48
183
}
49
184
}
50
185
else if ( state . activeAnimationClip != null )
@@ -54,19 +189,27 @@ public void OnGUI()
54
189
}
55
190
}
56
191
57
- private string [ ] GetClipMenuContent ( )
192
+ private GUIContent [ ] GetClipMenuContent ( AnimationClip [ ] clips )
58
193
{
59
- List < string > content = new List < string > ( ) ;
60
- content . AddRange ( GetClipNames ( ) ) ;
61
-
62
194
var selectedItem = state . selectedItem ;
63
- if ( selectedItem . rootGameObject != null && selectedItem . animationIsEditable )
195
+
196
+ int size = clips . Length ;
197
+ if ( selectedItem . canCreateClips )
198
+ size += 2 ;
199
+
200
+ GUIContent [ ] content = new GUIContent [ size ] ;
201
+ for ( int i = 0 ; i < clips . Length ; i ++ )
64
202
{
65
- content . Add ( "" ) ;
66
- content . Add ( AnimationWindowStyles . createNewClip . text ) ;
203
+ content [ i ] = new GUIContent ( CurveUtility . GetClipName ( clips [ i ] ) ) ;
67
204
}
68
205
69
- return content . ToArray ( ) ;
206
+ if ( selectedItem . canCreateClips )
207
+ {
208
+ content [ content . Length - 2 ] = GUIContent . none ;
209
+ content [ content . Length - 1 ] = AnimationWindowStyles . createNewClip ;
210
+ }
211
+
212
+ return content ;
70
213
}
71
214
72
215
private AnimationClip [ ] GetOrderedClipList ( )
@@ -80,44 +223,14 @@ private AnimationClip[] GetOrderedClipList()
80
223
return clips ;
81
224
}
82
225
83
- private string [ ] GetClipNames ( )
226
+ private int ClipToIndex ( AnimationClip [ ] clips , AnimationClip clip )
84
227
{
85
- AnimationClip [ ] clips = GetOrderedClipList ( ) ;
86
- string [ ] clipNames = new string [ clips . Length ] ;
87
-
88
- for ( int i = 0 ; i < clips . Length ; i ++ )
89
- clipNames [ i ] = CurveUtility . GetClipName ( clips [ i ] ) ;
90
-
91
- return clipNames ;
92
- }
93
-
94
- // TODO: Make this more robust
95
- private AnimationClip IndexToClip ( int index )
96
- {
97
- if ( state . activeRootGameObject != null )
228
+ for ( int index = 0 ; index < clips . Length ; ++ index )
98
229
{
99
- AnimationClip [ ] clips = GetOrderedClipList ( ) ;
100
- if ( index >= 0 && index < clips . Length )
101
- return clips [ index ] ;
230
+ if ( clips [ index ] == clip )
231
+ return index ;
102
232
}
103
233
104
- return null ;
105
- }
106
-
107
- // TODO: Make this more robust
108
- private int ClipToIndex ( AnimationClip clip )
109
- {
110
- if ( state . activeRootGameObject != null )
111
- {
112
- int index = 0 ;
113
- AnimationClip [ ] clips = GetOrderedClipList ( ) ;
114
- foreach ( AnimationClip other in clips )
115
- {
116
- if ( clip == other )
117
- return index ;
118
- index ++ ;
119
- }
120
- }
121
234
return 0 ;
122
235
}
123
236
}
0 commit comments