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;
}
}
}