1+ #if UNITY_2020_1_OR_NEWER
2+ using UnityEditor ;
3+ using UnityEngine ;
4+ using UnityEngine . Events ;
5+ using System . Reflection ;
6+ using UnityEditorInternal ;
7+
8+ namespace Lachee . Utilities . Editor
9+ {
10+ [ CustomPropertyDrawer ( typeof ( UnityEventBase ) , true ) ]
11+ public class UnityEventDrawer : UnityEditorInternal . UnityEventDrawer
12+ {
13+ #region Private Functions i steal from UnityEventDrawerer
14+ private static readonly FieldInfo fi_reoderableList ;
15+ private static readonly FieldInfo fi_dummyEvent ;
16+ private static readonly FieldInfo fi_text ;
17+ private static readonly MethodInfo mi_RestoreState ;
18+ private static readonly MethodInfo mi_GetDummyEvent ;
19+
20+ static UnityEventDrawer ( )
21+ {
22+ var T = typeof ( UnityEditorInternal . UnityEventDrawer ) ;
23+ fi_reoderableList = T . GetField ( "m_ReorderableList" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
24+ fi_dummyEvent = T . GetField ( "m_DummyEvent" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
25+ fi_text = T . GetField ( "m_Text" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
26+ mi_GetDummyEvent = T . GetMethod ( "GetDummyEvent" , BindingFlags . NonPublic | BindingFlags . Static ) ;
27+ mi_RestoreState = T . GetMethod ( "RestoreState" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
28+ }
29+
30+ private static UnityEventBase GetDummyEvent ( SerializedProperty prop )
31+ => ( UnityEventBase ) mi_GetDummyEvent . Invoke ( null , new object [ ] { prop } ) ;
32+
33+ private ReorderableList reorderableList
34+ {
35+ get => ( ReorderableList ) fi_reoderableList . GetValue ( this ) ;
36+ }
37+ private UnityEventBase dummyEvent
38+ {
39+ get => ( UnityEventBase ) fi_dummyEvent . GetValue ( this ) ;
40+ set => fi_dummyEvent . SetValue ( this , value ) ;
41+ }
42+ private string text
43+ {
44+ get => ( string ) fi_text . GetValue ( this ) ;
45+ set => fi_text . SetValue ( this , value ) ;
46+ }
47+ private State RestoreState ( SerializedProperty property )
48+ => ( State ) mi_RestoreState . Invoke ( this , new [ ] { property } ) ;
49+ #endregion
50+
51+ private readonly GUIContent iconToolbarPlus = EditorGUIUtility . TrIconContent ( "Toolbar Plus" , "Add new event listener" ) ;
52+ private readonly GUIStyle headerBackground = "LODSliderBG" ;
53+ private readonly GUIStyle preButton = "RL FooterButton" ;
54+ private readonly Color headerColor = new Color ( 0.85f , 0.85f , 0.85f ) ;
55+
56+ private bool ? _isFolded ;
57+ private bool isFolded
58+ {
59+ get => _isFolded . GetValueOrDefault ( EditorPrefs . GetBool ( $ "com.lachee.utilities.UnityEventsFoldout", true ) ) ;
60+ set
61+ {
62+ _isFolded = value ;
63+ EditorPrefs . SetBool ( $ "com.lachee.utilities.UnityEventsFoldout", value ) ;
64+ }
65+ }
66+
67+ private float CalculateBackgroundHeight ( SerializedProperty property )
68+ {
69+ var list = reorderableList ;
70+ if ( list == null || list . count == 0 || isFolded )
71+ return EditorGUIUtility . singleLineHeight + 2f ;
72+
73+ return base . GetPropertyHeight ( property , GUIContent . none ) ;
74+ }
75+
76+ public override void OnGUI ( Rect position , SerializedProperty property , GUIContent label )
77+ {
78+ RestoreState ( property ) ;
79+
80+ text = label . text ;
81+ dummyEvent = GetDummyEvent ( property ) ;
82+
83+ float lineHeight = EditorGUIUtility . singleLineHeight ;
84+
85+ // Draw the folder
86+ if ( reorderableList . count > 0 )
87+ {
88+ isFolded = ! EditorGUI . Foldout ( new Rect ( position . x , position . y , position . width , lineHeight ) , ! isFolded , GUIContent . none ) ;
89+ }
90+ else
91+ {
92+ _isFolded = true ;
93+ }
94+
95+ // Draw the event box
96+ Rect headerRect = new Rect ( position . x + 2 , position . y , position . width - 2 , CalculateBackgroundHeight ( property ) ) ;
97+ Rect headerLabel = new Rect ( headerRect . x + 6 , headerRect . y + 1 , headerRect . width - 100 , lineHeight ) ;
98+ Rect headerAddButton = new Rect ( headerRect . x + headerRect . width - 25 , headerRect . y + 2 , 24 , headerRect . height + 4 ) ;
99+
100+ // Draw the base GUI if we are unfolded
101+ if ( ! isFolded )
102+ {
103+ base . OnGUI ( headerRect , property , label ) ;
104+ }
105+ else
106+ {
107+ if ( Event . current . type == EventType . Repaint )
108+ {
109+ GUI . backgroundColor = headerColor ;
110+ headerBackground . Draw ( headerRect , GUIContent . none , false , false , false , false ) ;
111+ GUI . backgroundColor = Color . white ;
112+ }
113+
114+ DrawEventHeader ( headerLabel ) ;
115+ if ( GUI . Button ( headerAddButton , iconToolbarPlus , preButton ) )
116+ {
117+ isFolded = false ;
118+ OnAddEvent ( reorderableList ) ;
119+ }
120+ }
121+ }
122+
123+ public override float GetPropertyHeight ( SerializedProperty property , GUIContent label )
124+ {
125+ return CalculateBackgroundHeight ( property ) + 5f ;
126+ }
127+
128+ }
129+ }
130+ #endif
0 commit comments