├── .gitignore ├── Assets ├── CustomEnumPopup.meta └── CustomEnumPopup │ ├── Editor.meta │ ├── Editor │ ├── CustomEnumPopupDrawer.cs │ ├── CustomEnumPopupDrawer.cs.meta │ ├── CustomEnumPopupWindow.cs │ └── CustomEnumPopupWindow.cs.meta │ ├── Script.meta │ └── Script │ ├── CustomEnumPopup.cs │ └── CustomEnumPopup.cs.meta ├── LICENSE ├── README.md ├── UntiyEnumPopupDemo_Personal.png └── UntiyEnumPopupDemo_Professional.png /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | /ProjectSettings 8 | 9 | # Visual Studio 2015 cache directory 10 | /.vs/ 11 | 12 | # Autogenerated VS/MD/Consulo solution and project files 13 | ExportedObj/ 14 | .consulo/ 15 | *.csproj 16 | *.unityproj 17 | *.sln 18 | *.suo 19 | *.tmp 20 | *.user 21 | *.userprefs 22 | *.pidb 23 | *.booproj 24 | *.svd 25 | *.pdb 26 | 27 | # Unity3D generated meta files 28 | *.pidb.meta 29 | 30 | # Unity3D Generated File On Crash Reports 31 | sysinfo.txt 32 | 33 | # Builds 34 | *.apk 35 | *.unitypackage 36 | -------------------------------------------------------------------------------- /Assets/CustomEnumPopup.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ab13e8e6b247d9e41ad56f90fd8939dc 3 | folderAsset: yes 4 | timeCreated: 1508650876 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/CustomEnumPopup/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d6938476b438e5c45ab148a7784108f5 3 | folderAsset: yes 4 | timeCreated: 1508640697 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/CustomEnumPopup/Editor/CustomEnumPopupDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | [CustomPropertyDrawer(typeof(CustomEnumPopup))] 6 | public class CustomEnumPopupDrawer : PropertyDrawer 7 | { 8 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 9 | { 10 | CustomEnumPopup p = attribute as CustomEnumPopup; 11 | if (!string.IsNullOrEmpty(p.Name)) 12 | { 13 | label.text = p.Name; 14 | } 15 | string[] names = System.Enum.GetNames(fieldInfo.FieldType); 16 | List namesList = new List(); 17 | foreach (var m_name in names) 18 | { 19 | namesList.Add(m_name); 20 | } 21 | namesList.Sort((n1, n2) => { return ((int)System.Enum.Parse(fieldInfo.FieldType, n1)).CompareTo((int)System.Enum.Parse(fieldInfo.FieldType, n2)); }); 22 | names = namesList.ToArray(); 23 | EditorGUI.BeginProperty(position, label, property); 24 | Rect prefixPosition = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); 25 | string name; 26 | if (property.enumValueIndex >= names.Length || property.enumValueIndex < 0) 27 | { 28 | name = "-"; 29 | } 30 | else 31 | { 32 | name = names[property.enumValueIndex]; 33 | } 34 | GUIStyle buttonStyle = new GUIStyle(EditorStyles.popup); 35 | buttonStyle.padding.top = 2; 36 | buttonStyle.padding.bottom = 2; 37 | float baseHeight = GUI.skin.textField.CalcSize(new GUIContent()).y; 38 | Rect popRect = new Rect(prefixPosition.x, position.y, position.x + position.width - prefixPosition.x, baseHeight); 39 | if (GUI.Button(popRect, name, buttonStyle)) 40 | { 41 | CustomEnumPopupWindow window = CustomEnumPopupWindow.CreateInstance(); 42 | var windowRect = prefixPosition; 43 | window.Init(property, fieldInfo.FieldType, p.Type); 44 | windowRect.position = GUIUtility.GUIToScreenPoint(windowRect.position); 45 | windowRect.height = popRect.height + 1; 46 | window.ShowAsDropDown(windowRect, new Vector2(windowRect.width, 400)); 47 | } 48 | EditorGUI.EndProperty(); 49 | } 50 | } -------------------------------------------------------------------------------- /Assets/CustomEnumPopup/Editor/CustomEnumPopupDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ac7f4426dd7726d498017c524253f646 3 | timeCreated: 1494403402 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/CustomEnumPopup/Editor/CustomEnumPopupWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | using UnityEditor; 6 | 7 | public class CustomEnumPopupWindow : EditorWindow 8 | { 9 | public enum CustomEnumPopType 10 | { 11 | Alphabet = 0, 12 | Enum = 1, 13 | } 14 | 15 | Vector2 position; 16 | 17 | SerializedProperty sp; 18 | 19 | List enumNames = new List(); 20 | 21 | System.Type enumType; 22 | 23 | GUIStyle textStyle; 24 | 25 | GUIStyle selectedBackgroundStyle; 26 | 27 | GUIStyle normalBackgroundStyle; 28 | 29 | bool isInitedStype = false; 30 | 31 | bool isSelected = false; 32 | 33 | GUIStyle searchToobar; 34 | 35 | string searchText = string.Empty; 36 | 37 | CustomEnumPopType type; 38 | 39 | bool isShowValue = false; 40 | 41 | SingleEnumName selectSingle = null; 42 | 43 | public void Init(SerializedProperty sp, System.Type enumType, int type) 44 | { 45 | enumNames.Clear(); 46 | this.sp = sp; 47 | this.enumType = enumType; 48 | this.type = (CustomEnumPopType)type; 49 | isShowValue = false; 50 | string[] names = System.Enum.GetNames(enumType); 51 | List namesList = new List(); 52 | foreach (var m_name in names) 53 | { 54 | namesList.Add(m_name); 55 | } 56 | namesList.Sort((n1, n2) => { return ((int)System.Enum.Parse(enumType, n1)).CompareTo((int)System.Enum.Parse(enumType, n2)); }); 57 | names = namesList.ToArray(); 58 | selectSingle = null; 59 | for (int i = 0; i < names.Length; i++) 60 | { 61 | string name = names[i]; 62 | SingleEnumName single = new SingleEnumName(); 63 | single.name = name; 64 | single.index = i; 65 | single.value = (int)System.Enum.Parse(enumType, name); 66 | if (i == sp.enumValueIndex) 67 | { 68 | single.isSelect = true; 69 | selectSingle = single; 70 | } 71 | else 72 | { 73 | single.isSelect = false; 74 | } 75 | enumNames.Add(single); 76 | } 77 | if (this.type == CustomEnumPopType.Alphabet) 78 | { 79 | enumNames.Sort((e1, e2) => { return e1.name.CompareTo(e2.name); }); 80 | } 81 | else 82 | { 83 | enumNames.Sort((e1, e2) => { return e1.value.CompareTo(e2.value); }); 84 | } 85 | 86 | int realIndex; 87 | if (null == selectSingle) 88 | { 89 | realIndex = 0; 90 | } 91 | else 92 | { 93 | realIndex = enumNames.IndexOf(selectSingle); 94 | } 95 | position.y = 16 * realIndex; 96 | 97 | isSelected = false; 98 | var t = typeof(EditorStyles); 99 | var property = t.GetProperty("toolbarSearchField", BindingFlags.NonPublic | BindingFlags.Static); 100 | searchToobar = property.GetValue(null, null) as GUIStyle; 101 | 102 | searchText = string.Empty; 103 | } 104 | 105 | void OnGUI() 106 | { 107 | InitTextStyle(); 108 | 109 | GUILayout.BeginHorizontal(EditorStyles.toolbar); 110 | GUI.backgroundColor = new Color(1f, 1f, 1f, 0.5f); 111 | GUI.SetNextControlName("Search"); 112 | searchText = EditorGUILayout.TextField("", searchText, searchToobar, GUILayout.MinWidth(95)); 113 | EditorGUI.FocusTextInControl("Search"); 114 | if (this.type == CustomEnumPopType.Alphabet) 115 | { 116 | if (GUILayout.Button("E", EditorStyles.toolbarButton, GUILayout.Width(16))) 117 | { 118 | enumNames.Sort((e1, e2) => { return e1.value.CompareTo(e2.value); }); 119 | 120 | int realIndex; 121 | if (null == selectSingle) 122 | { 123 | realIndex = 0; 124 | } 125 | else 126 | { 127 | realIndex = enumNames.IndexOf(selectSingle); 128 | } 129 | position.y = 16 * realIndex; 130 | 131 | this.type = CustomEnumPopType.Enum; 132 | } 133 | } 134 | else if (this.type == CustomEnumPopType.Enum) 135 | { 136 | if (GUILayout.Button("A", EditorStyles.toolbarButton, GUILayout.Width(16))) 137 | { 138 | enumNames.Sort((e1, e2) => { return e1.name.CompareTo(e2.name); }); 139 | 140 | int realIndex; 141 | if (null == selectSingle) 142 | { 143 | realIndex = 0; 144 | } 145 | else 146 | { 147 | realIndex = enumNames.IndexOf(selectSingle); 148 | } 149 | position.y = 16 * realIndex; 150 | 151 | this.type = CustomEnumPopType.Alphabet; 152 | } 153 | } 154 | isShowValue = GUILayout.Toggle(isShowValue, "V", EditorStyles.toolbarButton, GUILayout.Width(16)); 155 | GUILayout.EndHorizontal(); 156 | GUI.backgroundColor = Color.white; 157 | 158 | position = EditorGUILayout.BeginScrollView(position); 159 | 160 | for (int i = 0; i < enumNames.Count; i++) 161 | { 162 | SingleEnumName single = enumNames[i]; 163 | if (!string.IsNullOrEmpty(searchText) && !single.name.ToLower().Contains(searchText)) 164 | { 165 | continue; 166 | } 167 | Rect rect; 168 | if (single.isSelect) 169 | { 170 | rect = EditorGUILayout.BeginHorizontal(selectedBackgroundStyle); 171 | } 172 | else 173 | { 174 | rect = EditorGUILayout.BeginHorizontal(normalBackgroundStyle); 175 | } 176 | GUILayout.Label(single.name, textStyle); 177 | GUILayout.FlexibleSpace(); 178 | if (isShowValue) 179 | { 180 | GUILayout.Label(single.value.ToString(), textStyle); 181 | } 182 | 183 | if (rect.Contains(Event.current.mousePosition) && Event.current.type == EventType.mouseDown) 184 | { 185 | sp.enumValueIndex = single.index; 186 | sp.serializedObject.ApplyModifiedProperties(); 187 | isSelected = true; 188 | } 189 | 190 | EditorGUILayout.EndHorizontal(); 191 | } 192 | 193 | EditorGUILayout.EndScrollView(); 194 | 195 | if (isSelected) 196 | { 197 | isSelected = false; 198 | Close(); 199 | } 200 | } 201 | 202 | void InitTextStyle() 203 | { 204 | if (!isInitedStype) 205 | { 206 | textStyle = new GUIStyle(EditorStyles.label); 207 | textStyle.fixedHeight = 16; 208 | textStyle.alignment = TextAnchor.MiddleLeft; 209 | 210 | Texture2D selectedBg = new Texture2D(32, 32, TextureFormat.RGB24, false); 211 | Texture2D hightLightBg = new Texture2D(32, 32, TextureFormat.RGB24, false); 212 | if (EditorGUIUtility.isProSkin) 213 | { 214 | selectedBg.LoadImage(System.Convert.FromBase64String(s_SelectedBg_Pro)); 215 | hightLightBg.LoadImage(System.Convert.FromBase64String(s_HightLightBg_Pro)); 216 | } 217 | else 218 | { 219 | selectedBg.LoadImage(System.Convert.FromBase64String(s_SelectedBg_Light)); 220 | hightLightBg.LoadImage(System.Convert.FromBase64String(s_HightLightBg_Light)); 221 | } 222 | selectedBackgroundStyle = new GUIStyle(); 223 | selectedBackgroundStyle.normal.background = selectedBg; 224 | normalBackgroundStyle = new GUIStyle(); 225 | normalBackgroundStyle.hover.background = hightLightBg; 226 | 227 | isInitedStype = true; 228 | } 229 | } 230 | 231 | void Update() 232 | { 233 | Repaint(); 234 | } 235 | 236 | const string s_SelectedBg_Pro = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAQklEQVRIDe3SsQkAAAgDQXWN7L+nOMFXdm8dIhzpJPV581l+3T5AYYkkQgEMuCKJUAADrkgiFMCAK5IIBTDgipBoAWXpAJEoZnl3AAAAAElFTkSuQmCC"; 237 | 238 | const string s_HightLightBg_Pro = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAQklEQVRIDe3SsQkAAAgDQXXD7L+MOMFXdm8dIhzpJPV581l+3T5AYYkkQgEMuCKJUAADrkgiFMCAK5IIBTDgipBoARFdATMHrayuAAAAAElFTkSuQmCC"; 239 | 240 | const string s_SelectedBg_Light = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAQUlEQVRIDe3SsQkAAAgDQXV/yMriBF/ZvXWIcKST1OfNZ/l1+wCFJZIIBTDgiiRCAQy4IolQAAOuSCIUwIArQqIF36EB7diYDg8AAAAASUVORK5CYII="; 241 | 242 | const string s_HightLightBg_Light = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAQklEQVRIDe3SsQkAAAgDQXX/ETOMOMFXdm8dIhzpJPV581l+3T5AYYkkQgEMuCKJUAADrkgiFMCAK5IIBTDgipBoAc9YAtQLJ3kPAAAAAElFTkSuQmCC"; 243 | } 244 | public class SingleEnumName 245 | { 246 | public string name; 247 | 248 | public int index; 249 | 250 | public int value; 251 | 252 | public bool isSelect; 253 | } -------------------------------------------------------------------------------- /Assets/CustomEnumPopup/Editor/CustomEnumPopupWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d173002e2a2b03449b41f0508fd6964 3 | timeCreated: 1508640022 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/CustomEnumPopup/Script.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ba56b7f6f81a22143a064914f7713853 3 | folderAsset: yes 4 | timeCreated: 1508640690 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/CustomEnumPopup/Script/CustomEnumPopup.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class CustomEnumPopup : PropertyAttribute 5 | { 6 | public string Name { get; private set; } 7 | 8 | public int Type { get; private set; } 9 | 10 | /// 11 | /// Draw Custom Enum Popup 12 | /// 13 | public CustomEnumPopup() 14 | { 15 | Type = 0; 16 | } 17 | 18 | /// 19 | /// Draw Custom Enum Popup 20 | /// 21 | /// Sort Type 0:Alphabet, 1:Enum 22 | public CustomEnumPopup(int type) 23 | { 24 | this.Type = type; 25 | } 26 | 27 | /// 28 | /// Draw Custom Enum Popup 29 | /// 30 | /// Property Name 31 | public CustomEnumPopup(string name) 32 | { 33 | this.Name = name; 34 | Type = 0; 35 | } 36 | 37 | /// 38 | /// Draw Custom Enum Popup 39 | /// 40 | /// Property Name 41 | /// Sort Type 0:Alphabet, 1:Enum 42 | public CustomEnumPopup(string name, int type) 43 | { 44 | this.Name = name; 45 | this.Type = type; 46 | } 47 | } -------------------------------------------------------------------------------- /Assets/CustomEnumPopup/Script/CustomEnumPopup.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b9111f7ec0009874c8267fa2f7a9026d 3 | timeCreated: 1494403246 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 leechking1987 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UnityEnumPopup 2 | A unity editor extension display custom enum popup 3 | 4 | Support display sorted/default enum names 5 | 6 | Support search enum by name 7 | 8 | Support display enum corresponding values 9 | 10 | Support both Personal/Professional skins 11 | 12 | ![image](/UntiyEnumPopupDemo_Personal.png) 13 | ![image](/UntiyEnumPopupDemo_Professional.png) 14 | 15 | # Useage 16 | ```C# 17 | [CustomEnumPopup] 18 | public YourEnum m_enum; 19 | 20 | [CustomEnumPopup(sortType)] 21 | public YourEnum m_enum; 22 | 23 | [CustomEnumPopup("YourEnumName")] 24 | public YourEnum m_enum; 25 | 26 | [CustomEnumPopup("YourEnumName", sortType)] 27 | public YourEnum m_enum; 28 | ``` 29 | 30 | sortType: 0->Alphabet, 1->Default 31 | 32 | "YourEnumName": property name displaied in inspector 33 | 34 | # Notes 35 | If you have a custom editor script and try to do something like this: 36 | ```C# 37 | int index = yourSerializedProperty.enumValueIndex 38 | EditorGUILayout.PropertyField(yourSerializedProperty); 39 | if(index != yourSerializedProperty.enumValueIndex) 40 | { 41 | //Do Some Thing 42 | } 43 | ``` 44 | this script will never work because the original UnityEnumPopup will block the OnGUI main thread but ours' will not 45 | 46 | you can just make a bit change to the script to make it work again like this: 47 | ```C# 48 | private int index; 49 | 50 | void OnEnable() 51 | { 52 | index = yourSerializedProperty.enumValueIndex 53 | } 54 | 55 | EditorGUILayout.PropertyField(yourSerializedProperty); 56 | if(index != yourSerializedProperty.enumValueIndex) 57 | { 58 | //Do Some Thing 59 | index = yourSerializedProperty.enumValueIndex 60 | } 61 | ``` -------------------------------------------------------------------------------- /UntiyEnumPopupDemo_Personal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leechking1987/UnityEnumPopup/04fb6937c490fe5d7607ee8f64caf01b6527782b/UntiyEnumPopupDemo_Personal.png -------------------------------------------------------------------------------- /UntiyEnumPopupDemo_Professional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leechking1987/UnityEnumPopup/04fb6937c490fe5d7607ee8f64caf01b6527782b/UntiyEnumPopupDemo_Professional.png --------------------------------------------------------------------------------