using UnityEngine; using UnityEditor; namespace Unity.Burst.Editor { internal static class LabeledPopup { // Because the function given to dropdown menu needs takes its parameter // in the form of an object, we need someway to wrap the integer into one. private struct IntegerWrapper { public int Value { get; } public IntegerWrapper(int v) { Value = v; } } /// /// Enables having several popup menus functioning independently at the same time. /// private class PopperCallBack { public static PopperCallBack Instance = null; /// /// Name of the event send when an index have been chosen. /// private const string IndexChangeEventName = "PopperChangingIndex"; private readonly int _controlID; private int _selectedIdx; private readonly GUIView _view; public PopperCallBack(int controlID) { _controlID = controlID; _selectedIdx = -1; _view = GUIView.current; } /// /// Tries to get selection chosen by dropdown menu . /// /// ID of popup menu. /// Current selected index. /// /// Either the selected target, or the /// if none were chosen yet. /// internal static int GetSelectionValue(int controlId, int selectedIdx) { var selected = selectedIdx; // A command event with message IndexChangeEvent will be sent whenever a choice on // the dropdown menu has been made. So if this is not the case return whatever index was given var evt = Event.current; if (evt.type != EventType.ExecuteCommand || evt.commandName != IndexChangeEventName) return selected; // If this is the popup opened right now: Set the selection idx appropriately if (Instance != null && controlId == Instance._controlID) { selected = Instance._selectedIdx; Instance = null; } return selected; } /// /// Sets selection on the opened dropdown, and sends an event /// to the view the popup is within. /// /// Index selected. internal void SetSelection(object index) { _selectedIdx = ((IntegerWrapper)index).Value; _view.SendEvent(EditorGUIUtility.CommandEvent(IndexChangeEventName)); } } /// /// Name used for getting a controlID for popup menus. /// private const string LabelControlName = "LabeledPopup"; /// /// Create a immediate automatically positioned popup menu. /// /// Current active selection index. /// Name to display as the button. /// Display name for the dropdown menu. /// The possibly new active selection index. public static int Popup(int index, GUIContent display, string[] options) { // GetControlRect so space is reserved for the button, and we get a // position to place the drop down context menu at. var pos = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.popup); var controlID = GUIUtility.GetControlID(LabelControlName.GetHashCode(), FocusType.Keyboard, pos); var selected = PopperCallBack.GetSelectionValue(controlID, index); if (GUI.Button(pos, display, EditorStyles.popup)) { PopperCallBack.Instance = new PopperCallBack(controlID); var menu = new GenericMenu(); for (var i = 0; i < options.Length; i++) { var size = options[i]; menu.AddItem(EditorGUIUtility.TrTextContent(size), i == index, PopperCallBack.Instance.SetSelection, new IntegerWrapper(i)); } menu.Popup(pos, index); } return selected; } } }