A game about forced loneliness, made by TACStudios
at master 123 lines 4.7 kB view raw
1using UnityEngine; 2using UnityEditor; 3 4namespace Unity.Burst.Editor 5{ 6 internal static class LabeledPopup 7 { 8 // Because the function given to dropdown menu needs takes its parameter 9 // in the form of an object, we need someway to wrap the integer into one. 10 private struct IntegerWrapper 11 { 12 public int Value { get; } 13 14 public IntegerWrapper(int v) 15 { 16 Value = v; 17 } 18 } 19 20 /// <summary> 21 /// Enables having several popup menus functioning independently at the same time. 22 /// </summary> 23 private class PopperCallBack 24 { 25 public static PopperCallBack Instance = null; 26 27 /// <summary> 28 /// Name of the event send when an index have been chosen. 29 /// </summary> 30 private const string IndexChangeEventName = "PopperChangingIndex"; 31 32 private readonly int _controlID; 33 private int _selectedIdx; 34 private readonly GUIView _view; 35 36 public PopperCallBack(int controlID) 37 { 38 _controlID = controlID; 39 _selectedIdx = -1; 40 _view = GUIView.current; 41 } 42 43 /// <summary> 44 /// Tries to get selection chosen by dropdown menu <see cref="controlID"/>. 45 /// </summary> 46 /// <param name="controlId">ID of popup menu.</param> 47 /// <param name="selectedIdx">Current selected index.</param> 48 /// <returns> 49 /// Either the selected target, or the <see cref="selectedIdx"/> 50 /// if none were chosen yet. 51 /// </returns> 52 internal static int GetSelectionValue(int controlId, int selectedIdx) 53 { 54 var selected = selectedIdx; 55 56 // A command event with message IndexChangeEvent will be sent whenever a choice on 57 // the dropdown menu has been made. So if this is not the case return whatever index was given 58 var evt = Event.current; 59 if (evt.type != EventType.ExecuteCommand || evt.commandName != IndexChangeEventName) return selected; 60 61 // If this is the popup opened right now: Set the selection idx appropriately 62 if (Instance != null && controlId == Instance._controlID) 63 { 64 selected = Instance._selectedIdx; 65 Instance = null; 66 } 67 68 return selected; 69 } 70 71 /// <summary> 72 /// Sets selection on the opened dropdown, and sends an event 73 /// to the view the popup is within. 74 /// </summary> 75 /// <param name="index">Index selected.</param> 76 internal void SetSelection(object index) 77 { 78 _selectedIdx = ((IntegerWrapper)index).Value; 79 _view.SendEvent(EditorGUIUtility.CommandEvent(IndexChangeEventName)); 80 } 81 } 82 83 /// <summary> 84 /// Name used for getting a controlID for popup menus. 85 /// </summary> 86 private const string LabelControlName = "LabeledPopup"; 87 88 /// <summary> 89 /// Create a immediate automatically positioned popup menu. 90 /// </summary> 91 /// <param name="index">Current active selection index.</param> 92 /// <param name="display">Name to display as the button.</param> 93 /// <param name="options">Display name for the dropdown menu.</param> 94 /// <returns>The possibly new active selection index.</returns> 95 public static int Popup(int index, GUIContent display, string[] options) 96 { 97 // GetControlRect so space is reserved for the button, and we get a 98 // position to place the drop down context menu at. 99 var pos = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight, 100 EditorStyles.popup); 101 102 var controlID = GUIUtility.GetControlID(LabelControlName.GetHashCode(), FocusType.Keyboard, pos); 103 104 var selected = PopperCallBack.GetSelectionValue(controlID, index); 105 106 if (GUI.Button(pos, display, EditorStyles.popup)) 107 { 108 PopperCallBack.Instance = new PopperCallBack(controlID); 109 110 var menu = new GenericMenu(); 111 for (var i = 0; i < options.Length; i++) 112 { 113 var size = options[i]; 114 115 menu.AddItem(EditorGUIUtility.TrTextContent(size), i == index, PopperCallBack.Instance.SetSelection, new IntegerWrapper(i)); 116 } 117 menu.Popup(pos, index); 118 } 119 120 return selected; 121 } 122 } 123}