@@ -13,34 +13,169 @@ namespace UnityEditor
1313 class AnimationWindowClipPopup
1414 {
1515 [ SerializeField ] public AnimationWindowState state ;
16- [ SerializeField ] private int selectedIndex ;
1716
18- public void OnGUI ( )
17+ static int s_ClipPopupHash = "s_ClipPopupHash" . GetHashCode ( ) ;
18+
19+ internal sealed class ClipPopupCallbackInfo
1920 {
20- if ( state . selection . canChangeAnimationClip )
21+ // The global shared popup state
22+ public static ClipPopupCallbackInfo instance = null ;
23+
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 )
2138 {
22- string [ ] menuContent = GetClipMenuContent ( ) ;
23- EditorGUI . BeginChangeCheck ( ) ;
24- // TODO: Make this more robust
25- selectedIndex = EditorGUILayout . Popup ( ClipToIndex ( state . activeAnimationClip ) , menuContent , EditorStyles . toolbarPopup ) ;
26- 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 )
47+ {
48+ if ( instance == null )
49+ {
50+ Debug . LogError ( "Popup menu has no instance" ) ;
51+ return clip ;
52+ }
53+ if ( instance . m_ControlID == controlID )
54+ {
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 )
2778 {
28- if ( menuContent [ selectedIndex ] == AnimationWindowStyles . createNewClip . text )
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
29109 {
30110 AnimationClip newClip = AnimationWindowUtility . CreateNewClip ( state . selection . rootGameObject . name ) ;
31111 if ( newClip )
32112 {
33113 AnimationWindowUtility . AddClipToAnimationPlayerComponent ( state . activeAnimationPlayer , newClip ) ;
34- state . activeAnimationClip = newClip ;
114+ ClipPopupCallbackInfo . SetSelectedClip ( newClip ) ;
35115 }
116+ }
36117
37- // Layout has changed, bail out now.
38- EditorGUIUtility . ExitGUI ( ) ;
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 )
136+ {
137+ style . font = EditorStyles . miniBoldFont ;
39138 }
40- else
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 ) )
41149 {
42- state . activeAnimationClip = IndexToClip ( selectedIndex ) ;
150+ DisplayClipMenu ( position , controlID , clip ) ;
151+ GUIUtility . keyboardControl = controlID ;
152+ evt . Use ( ) ;
43153 }
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+ if ( state . selection . canChangeAnimationClip )
170+ {
171+ EditorGUI . BeginChangeCheck ( ) ;
172+ var newClip = DoClipPopup ( state . activeAnimationClip , EditorStyles . toolbarPopup ) ;
173+ if ( EditorGUI . EndChangeCheck ( ) )
174+ {
175+ state . activeAnimationClip = newClip ;
176+
177+ // Layout has changed, bail out now.
178+ EditorGUIUtility . ExitGUI ( ) ;
44179 }
45180 }
46181 else if ( state . activeAnimationClip != null )
@@ -50,18 +185,25 @@ public void OnGUI()
50185 }
51186 }
52187
53- private string [ ] GetClipMenuContent ( )
188+ private GUIContent [ ] GetClipMenuContent ( AnimationClip [ ] clips )
54189 {
55- List < string > content = new List < string > ( ) ;
56- content . AddRange ( GetClipNames ( ) ) ;
190+ int size = clips . Length ;
191+ if ( state . selection . canCreateClips )
192+ size += 2 ;
193+
194+ GUIContent [ ] content = new GUIContent [ size ] ;
195+ for ( int i = 0 ; i < clips . Length ; i ++ )
196+ {
197+ content [ i ] = new GUIContent ( CurveUtility . GetClipName ( clips [ i ] ) ) ;
198+ }
57199
58- if ( state . selection . rootGameObject != null )
200+ if ( state . selection . canCreateClips )
59201 {
60- content . Add ( "" ) ;
61- content . Add ( AnimationWindowStyles . createNewClip . text ) ;
202+ content [ content . Length - 2 ] = GUIContent . none ;
203+ content [ content . Length - 1 ] = AnimationWindowStyles . createNewClip ;
62204 }
63205
64- return content . ToArray ( ) ;
206+ return content ;
65207 }
66208
67209 private AnimationClip [ ] GetOrderedClipList ( )
@@ -75,44 +217,14 @@ private AnimationClip[] GetOrderedClipList()
75217 return clips ;
76218 }
77219
78- private string [ ] GetClipNames ( )
79- {
80- AnimationClip [ ] clips = GetOrderedClipList ( ) ;
81- string [ ] clipNames = new string [ clips . Length ] ;
82-
83- for ( int i = 0 ; i < clips . Length ; i ++ )
84- clipNames [ i ] = CurveUtility . GetClipName ( clips [ i ] ) ;
85-
86- return clipNames ;
87- }
88-
89- // TODO: Make this more robust
90- private AnimationClip IndexToClip ( int index )
220+ private int ClipToIndex ( AnimationClip [ ] clips , AnimationClip clip )
91221 {
92- if ( state . activeRootGameObject != null )
222+ for ( int index = 0 ; index < clips . Length ; ++ index )
93223 {
94- AnimationClip [ ] clips = GetOrderedClipList ( ) ;
95- if ( index >= 0 && index < clips . Length )
96- return clips [ index ] ;
224+ if ( clips [ index ] == clip )
225+ return index ;
97226 }
98227
99- return null ;
100- }
101-
102- // TODO: Make this more robust
103- private int ClipToIndex ( AnimationClip clip )
104- {
105- if ( state . activeRootGameObject != null )
106- {
107- int index = 0 ;
108- AnimationClip [ ] clips = GetOrderedClipList ( ) ;
109- foreach ( AnimationClip other in clips )
110- {
111- if ( clip == other )
112- return index ;
113- index ++ ;
114- }
115- }
116228 return 0 ;
117229 }
118230 }
0 commit comments