public static void PopupMultiple ( Rect position, MultipleCallback callback, IEnumerable <DropdownOption <T> > options, IEnumerable <T> selectedOptions, bool hasMultipleDifferentValues ) { string label; selectedOptions = SanitizeMultipleOptions(options, selectedOptions); if (hasMultipleDifferentValues) { label = "\u2014"; // Em Dash } else { var selectedOptionsCount = selectedOptions.Count(); var optionsCount = options.Count(); if (selectedOptionsCount == 0) { label = "Nothing"; } else if (selectedOptionsCount == 1) { label = options.First(o => EqualityComparer <T> .Default.Equals(o.value, selectedOptions.First())).label; } else if (selectedOptionsCount == optionsCount) { label = "Everything"; } else { label = "(Mixed)"; } } if (GUI.Button(position, label, EditorStyles.popup)) { DropdownMultiple ( new Vector2(position.xMin, position.yMax), callback, options, selectedOptions, hasMultipleDifferentValues ); } }
/// <summary> /// Displays a multiple-options dropdown. /// </summary> public static void DropdownMultiple ( Vector2 position, MultipleCallback callback, IEnumerable <DropdownOption <T> > options, HashSet <T> selectedOptions, bool showNothingEverything = true ) { var hasMultipleDifferentValues = EditorGUI.showMixedValue; ICollection <DropdownOption <T> > optionsCache = null; bool hasOptions; if (options != null) { optionsCache = options.CacheToCollection(); hasOptions = optionsCache.Count > 0; } else { hasOptions = false; } var selectedOptionsCopy = selectedOptions.ToHashSet(); // Remove options outside range selectedOptionsCopy.RemoveWhere(so => !optionsCache.Any(o => Equal(o.value, so))); GenericMenu menu = new GenericMenu(); // The callback when a normal option has been selected GenericMenu.MenuFunction2 switchCallback = (o) => { var switchOption = (T)o; if (selectedOptionsCopy.Contains(switchOption)) { selectedOptionsCopy.Remove(switchOption); } else { selectedOptionsCopy.Add(switchOption); } callback(selectedOptionsCopy); // Force copy }; // The callback when the special "Nothing" option has been selected GenericMenu.MenuFunction nothingCallback = () => { callback(new HashSet <T>()); }; // The callback when the special "Everything" option has been selected GenericMenu.MenuFunction everythingCallback = () => { callback(optionsCache.Select((o) => o.value).ToHashSet()); }; // Add the special "Nothing" / "Everything" options if (showNothingEverything) { menu.AddItem ( new GUIContent("Nothing"), !hasMultipleDifferentValues && selectedOptionsCopy.Count == 0, nothingCallback ); if (hasOptions) { menu.AddItem ( new GUIContent("Everything"), !hasMultipleDifferentValues && selectedOptionsCopy.Count == optionsCache.Count && Enumerable.SequenceEqual(selectedOptionsCopy.OrderBy(t => t), optionsCache.Select(o => o.value).OrderBy(t => t)), everythingCallback ); } } // Add a separator (not in Unity default, but pretty) if (showNothingEverything && hasOptions) { menu.AddSeparator(string.Empty); } // Add the normal options if (hasOptions) { foreach (var option in optionsCache) { menu.AddItem ( new GUIContent(option.label), !hasMultipleDifferentValues && (selectedOptionsCopy.Any(selectedOption => Equal(selectedOption, option.value))), switchCallback, option.value ); } } // Show the dropdown menu.DropDown(new Rect(position, Vector2.zero)); }
public static void DropdownMultiple ( Vector2 position, MultipleCallback callback, IEnumerable <DropdownOption <T> > options, IEnumerable <T> selectedOptions, bool hasMultipleDifferentValues ) { selectedOptions = SanitizeMultipleOptions(options, selectedOptions); bool hasOptions = options != null && options.Any(); GenericMenu menu = new GenericMenu(); GenericMenu.MenuFunction2 switchCallback = (o) => { GUI.changed = true; var switchOption = (T)o; var newSelectedOptions = selectedOptions.ToList(); if (newSelectedOptions.Contains(switchOption)) { newSelectedOptions.Remove(switchOption); } else { newSelectedOptions.Add(switchOption); } callback(newSelectedOptions); }; GenericMenu.MenuFunction nothingCallback = () => { GUI.changed = true; callback(Enumerable.Empty <T>()); }; GenericMenu.MenuFunction everythingCallback = () => { GUI.changed = true; callback(options.Select((o) => o.value)); }; menu.AddItem(new GUIContent("Nothing"), !hasMultipleDifferentValues && !selectedOptions.Any(), nothingCallback); menu.AddItem(new GUIContent("Everything"), !hasMultipleDifferentValues && selectedOptions.Count() == options.Count() && Enumerable.SequenceEqual(selectedOptions.OrderBy(t => t), options.Select(o => o.value).OrderBy(t => t)), everythingCallback); if (hasOptions) { menu.AddSeparator(""); // Not in Unity default, but pretty foreach (var option in options) { bool on = !hasMultipleDifferentValues && (selectedOptions.Any(selectedOption => EqualityComparer <T> .Default.Equals(selectedOption, option.value))); menu.AddItem(new GUIContent(option.label), on, switchCallback, option.value); } } menu.DropDown(new Rect(position, Vector2.zero)); }