В редакторе Unity порой требуются самые разные контролы. Многие из них уже есть в наборе стандартного класса EditorGUILayout, однако есть и те, которые там найти не получится, но тем не менее - они актуальны и нужны для редакторов.
Сегодня я хотел бы предоставить вам элемент Popup-multibutton - кнопка с подменю. В отличии от стандартного Popup данная кнопка имеет свой заголовок и немного отличается по внешнему виду.
Данный элемент легко модифицировать в кнопку другого стиля, либо кнопку с изображением.
Так же данный пример хорошо иллюстрирует основные принципы создания элементов управления для OnGUI.
public static int Popup(string title, string[] values, params GUILayoutOption[] settings) { var style = Styles.MiniPullDown; return Popup(new GUIContent(title), values.Select(x => new GUIContent(x)), style, settings); } public static int Popup(string title, string[] values, GUIStyle style, params GUILayoutOption[] settings) { return Popup(new GUIContent(title),values.Select(x => new GUIContent(x)), style, settings); } public static int Popup(string title, GUIContent[] values, params GUILayoutOption[] settings) { var style = Styles.MiniPullDown; return Popup(new GUIContent(title),values.Select(x => new GUIContent(x)), style, settings); } public static int Popup(string title, GUIContent[] values, GUIStyle style, params GUILayoutOption[] settings) { return Popup(new GUIContent(title),values.Select(x => new GUIContent(x)), style, settings); } public static int Popup(GUIContent title, string[] values, params GUILayoutOption[] settings) { var style = Styles.MiniPullDown; return Popup(title, values.Select(x => new GUIContent(x)), style, settings); } public static int Popup(GUIContent title, string[] values, GUIStyle style, params GUILayoutOption[] settings) { return Popup(title, values.Select(x => new GUIContent(x)), style, settings); } public static int Popup(GUIContent title, GUIContent[] values, params GUILayoutOption[] settings) { var style = Styles.MiniPullDown; return Popup(title, values.Select(x => new GUIContent(x)), style, settings); } public static int Popup(GUIContent title, GUIContent[] values, GUIStyle style, params GUILayoutOption[] settings) { int selectedId = -1; Rect position = EditorGUI.IndentedRect(EditorGUILayout.GetControlRect(false, 16f, style, settings)); var id = GUIUtility.GetControlID("Popup".GetHashCode(), FocusType.Native, position); GUI.Box(position, title, style); if (Event.current.type == EventType.mouseDown) { if (position.Contains(Event.current.mousePosition)) { PopupCallbackInfo.instance = new PopupCallbackInfo { controlId = id }; EditorUtility.DisplayCustomMenu(position, values, -1, PopupCallbackInfo.instance.SetValueDelegate, null); Event.current.Use(); } } if (PopupCallbackInfo.instance != null && PopupCallbackInfo.instance.change && PopupCallbackInfo.instance.controlId == id) { selectedId = PopupCallbackInfo.instance.selectedIndex; PopupCallbackInfo.instance = null; } return selectedId; } private sealed class PopupCallbackInfo { public int controlId; public static PopupCallbackInfo instance; public int selectedIndex; public bool change = false; internal void SetValueDelegate(object userData, string[] options, int selected) { selectedIndex = selected; change = true; } }
Пример использования:
var index = GUILayoutEx.Popup("Paste...", new[] {"As {0}", "As {params}"});
У меня в проекте все контролы такого рода хранятся в классе GUILayoutEx - название класса у вас может быть другим.
Сама кнопка будет называться "Paste...". Нажимаемые пункты - "As {0}" и "As {params}".
В index будет попадать число, индекс которого равен индексу нажатой кнопки (отсчет начинается с 0). Если мы ничего не нажали, то в index попадет значение -1.
В результате будет вот такой элемент:
CollectableItemData.cs
[CreateMenuItem(fileName = "newItem", menuName = "Data/Items/Collectable", order = 51]