update CCK to 3.10, fixing unity 2021 crash :)
This commit is contained in:
parent
48a978fa2a
commit
d11e0fb3a9
492 changed files with 2165204 additions and 437687 deletions
426
Assets/ABI.CCK/Scripts/Editor/GUIExtensions/EditorGUIExtensions.cs
Executable file
426
Assets/ABI.CCK/Scripts/Editor/GUIExtensions/EditorGUIExtensions.cs
Executable file
|
@ -0,0 +1,426 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using ABI.CCK.Scripts.Editor.Tools;
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ABI.CCK.Scripts.Editor
|
||||
{
|
||||
public static partial class EditorGUIExtensions
|
||||
{
|
||||
private const float DEFAULT_DROPDOWN_BUTTON_WIDTH = 35;
|
||||
private static readonly Dictionary<string, GUIContent> s_iconContentCache = new();
|
||||
private static int s_lastSelectedValue = -1;
|
||||
|
||||
#region Specialized EditorGUI
|
||||
|
||||
public delegate void AppendAdditionalMenuItemsDelegate(GenericMenuBuilder genericMenuBuilder, ReorderableList list);
|
||||
public static void UtilityMenu(Rect rect, ReorderableList list, SerializedProperty property = null, AppendAdditionalMenuItemsDelegate appendAdditionalMenuItems = null)
|
||||
{
|
||||
Rect dropdownButtonRect = new(rect.x + rect.width - 21, rect.y, 20, EditorGUIUtility.singleLineHeight);
|
||||
if (!EditorGUI.DropdownButton(dropdownButtonRect, GUIContent.none, FocusType.Passive))
|
||||
return;
|
||||
|
||||
GenericMenuBuilder genericMenuBuilder = new();
|
||||
ClipboardUtils.AppendToMenu(genericMenuBuilder, list, property); // default for all uses atm
|
||||
if (appendAdditionalMenuItems != null)
|
||||
{
|
||||
genericMenuBuilder.AddSeparator();
|
||||
appendAdditionalMenuItems.Invoke(genericMenuBuilder, list);
|
||||
}
|
||||
genericMenuBuilder.DropDown(dropdownButtonRect);
|
||||
}
|
||||
|
||||
public static string AdvancedDropdownInput(
|
||||
Rect rect,
|
||||
string currentValue,
|
||||
List<string> dropdownItems,
|
||||
string label,
|
||||
string defaultTitle,
|
||||
GUIContent buttonContent = null)
|
||||
{
|
||||
if (buttonContent == null)
|
||||
{
|
||||
buttonContent = dropdownItems.Contains(currentValue)
|
||||
? GetCachedIconContent("d_Search Icon")
|
||||
: GetCachedIconContent("console.erroricon.sml");
|
||||
}
|
||||
|
||||
string title = (dropdownItems.Count == 0 ? defaultTitle : currentValue);
|
||||
return CustomDropdown(rect, label, currentValue, dropdownItems.ToArray(), buttonContent, DEFAULT_DROPDOWN_BUTTON_WIDTH, title);
|
||||
}
|
||||
|
||||
public static string AdvancedDropdownInput(
|
||||
Rect rect,
|
||||
string currentValue,
|
||||
List<string> dropdownItems,
|
||||
string title,
|
||||
GUIContent buttonContent = null)
|
||||
{
|
||||
if (buttonContent == null)
|
||||
{
|
||||
buttonContent = dropdownItems.Contains(currentValue)
|
||||
? GetCachedIconContent("d_Search Icon")
|
||||
: GetCachedIconContent("console.erroricon.sml");
|
||||
}
|
||||
|
||||
return CustomDropdown(rect, currentValue, dropdownItems.ToArray(), buttonContent, DEFAULT_DROPDOWN_BUTTON_WIDTH, title);
|
||||
}
|
||||
|
||||
public static string AdvancedDropdownInput(
|
||||
Rect rect,
|
||||
string currentValue,
|
||||
string[] dropdownItems,
|
||||
string title,
|
||||
GUIContent buttonContent = null)
|
||||
{
|
||||
if (buttonContent == null)
|
||||
{
|
||||
buttonContent = dropdownItems.Contains(currentValue)
|
||||
? GetCachedIconContent("d_Search Icon")
|
||||
: GetCachedIconContent("console.erroricon.sml");
|
||||
}
|
||||
|
||||
return CustomDropdown(rect, currentValue, dropdownItems, buttonContent, DEFAULT_DROPDOWN_BUTTON_WIDTH, title);
|
||||
}
|
||||
|
||||
// bit lazy ig
|
||||
public static void LimitSliderSided(string label, ref Vector2 limits, float hardLimitMin, float hardLimitMax)
|
||||
{
|
||||
var originalLabelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 150;
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField(label, GUILayout.Width(originalLabelWidth - 16));
|
||||
limits.x = EditorGUILayout.FloatField(limits.x, GUILayout.Width(50));
|
||||
GUILayout.Space(-13);
|
||||
EditorGUILayout.MinMaxSlider(ref limits.x, ref limits.y, hardLimitMin, hardLimitMax);
|
||||
GUILayout.Space(-13);
|
||||
limits.y = EditorGUILayout.FloatField(limits.y, GUILayout.Width(50));
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUIUtility.labelWidth = originalLabelWidth;
|
||||
}
|
||||
|
||||
public static void LimitSliderSided(ref Rect rect, float spacing, string label, ref Vector2 limits, float hardLimitMin, float hardLimitMax)
|
||||
{
|
||||
// Save the original label width and adjust it for your custom drawing
|
||||
var originalLabelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 150;
|
||||
|
||||
// Calculate positions and sizes for custom drawing elements within the rect
|
||||
float labelWidth = originalLabelWidth - 16;
|
||||
float fieldWidth = 50;
|
||||
float sliderWidth = rect.width - labelWidth - fieldWidth * 2 - spacing * 4;
|
||||
float currentY = rect.y;
|
||||
|
||||
// Label
|
||||
Rect labelRect = new Rect(rect.x, currentY, labelWidth, EditorGUIUtility.singleLineHeight);
|
||||
GUI.Label(labelRect, label);
|
||||
|
||||
// Field for limits.x
|
||||
Rect fieldXRect = new Rect(labelRect.xMax + spacing, currentY, fieldWidth, EditorGUIUtility.singleLineHeight);
|
||||
limits.x = EditorGUI.FloatField(fieldXRect, limits.x);
|
||||
|
||||
// MinMaxSlider
|
||||
Rect sliderRect = new Rect(fieldXRect.xMax + spacing, currentY, sliderWidth, EditorGUIUtility.singleLineHeight);
|
||||
EditorGUI.MinMaxSlider(sliderRect, ref limits.x, ref limits.y, hardLimitMin, hardLimitMax);
|
||||
|
||||
// Field for limits.y
|
||||
Rect fieldYRect = new Rect(sliderRect.xMax + spacing, currentY, fieldWidth, EditorGUIUtility.singleLineHeight);
|
||||
limits.y = EditorGUI.FloatField(fieldYRect, limits.y);
|
||||
|
||||
// Reset the original label width
|
||||
EditorGUIUtility.labelWidth = originalLabelWidth;
|
||||
|
||||
// Adjust rect.y for the next control, if you're drawing multiple controls in sequence
|
||||
rect.y += spacing;
|
||||
}
|
||||
|
||||
public static void LimitSliderSidedProp(string label, SerializedProperty limitsProp, float hardLimitMin, float hardLimitMax) {
|
||||
Vector2 limits = limitsProp.vector2Value;
|
||||
LimitSliderSided(label, ref limits, hardLimitMin, hardLimitMax);
|
||||
limitsProp.vector2Value = limits;
|
||||
}
|
||||
|
||||
public static void LimitSliderSidedFloats(string label, SerializedProperty floatMin, SerializedProperty floatMax, float hardLimitMin, float hardLimitMax) {
|
||||
Vector2 limits = new(floatMin.floatValue, floatMax.floatValue);
|
||||
LimitSliderSided(label, ref limits, hardLimitMin, hardLimitMax);
|
||||
floatMin.floatValue = limits.x;
|
||||
floatMax.floatValue = limits.y;
|
||||
}
|
||||
|
||||
public static void LimitSliderSidedFloats(ref Rect rect, float spacing, string label, SerializedProperty floatMin, SerializedProperty floatMax, float hardLimitMin, float hardLimitMax) {
|
||||
Vector2 limits = new(floatMin.floatValue, floatMax.floatValue);
|
||||
LimitSliderSided(ref rect, spacing, label, ref limits, hardLimitMin, hardLimitMax);
|
||||
floatMin.floatValue = limits.x;
|
||||
floatMax.floatValue = limits.y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CustomPopup
|
||||
|
||||
public static string CustomPopup(Rect rect, string label, string currentItem, string[] items,
|
||||
string title = null)
|
||||
{
|
||||
// TODO: temp fix
|
||||
int currentIndex = Array.IndexOf(items, currentItem);
|
||||
currentIndex = CustomPopup(rect, label, currentIndex, items, title);
|
||||
return currentIndex >= 0 && currentIndex < items.Length ? items[currentIndex] : CVRCommon.NONE_OR_EMPTY;
|
||||
}
|
||||
|
||||
public static string CustomPopup(Rect rect, string currentItem, string[] items,
|
||||
string title = null)
|
||||
{
|
||||
// TODO: temp fix
|
||||
int currentIndex = Array.IndexOf(items, currentItem);
|
||||
currentIndex = CustomPopup(rect, currentIndex, items, title);
|
||||
return currentIndex >= 0 && currentIndex < items.Length ? items[currentIndex] : CVRCommon.NONE_OR_EMPTY;
|
||||
}
|
||||
|
||||
public static int CustomPopup(Rect rect, string label, int currentItem, string[] items, string title = null)
|
||||
{
|
||||
int controlId = GUIUtility.GetControlID(FocusType.Passive);
|
||||
|
||||
// Use label width to position the dropdown appropriately
|
||||
float labelWidth = EditorGUIUtility.labelWidth;
|
||||
|
||||
Rect labelRect = new Rect(rect.x, rect.y, labelWidth, rect.height);
|
||||
Rect buttonRect = new Rect(rect.x + labelWidth, rect.y, rect.width - labelWidth, rect.height);
|
||||
|
||||
EditorGUI.LabelField(labelRect, label);
|
||||
|
||||
string current = currentItem >= 0 && currentItem < items.Length ? items[currentItem] : CVRCommon.NONE_OR_EMPTY;
|
||||
if (EditorGUI.DropdownButton(buttonRect, new GUIContent(current), FocusType.Passive))
|
||||
{
|
||||
GUIUtility.keyboardControl = controlId;
|
||||
new CustomAdvancedDropdown(new AdvancedDropdownState(), items, title, selected =>
|
||||
{
|
||||
s_lastSelectedValue = selected;
|
||||
}).Show(buttonRect); // We'll show the dropdown right where our buttonRect is
|
||||
}
|
||||
|
||||
if (controlId == GUIUtility.keyboardControl && s_lastSelectedValue != -1)
|
||||
{
|
||||
currentItem = s_lastSelectedValue;
|
||||
s_lastSelectedValue = -1;
|
||||
}
|
||||
|
||||
return currentItem;
|
||||
}
|
||||
|
||||
// CustomPopup but no label
|
||||
public static int CustomPopup(Rect rect, int currentItem, string[] items, string title = null)
|
||||
{
|
||||
int controlId = GUIUtility.GetControlID(FocusType.Passive);
|
||||
|
||||
Rect buttonRect = new Rect(rect.x, rect.y, rect.width, rect.height);
|
||||
|
||||
string current = currentItem >= 0 && currentItem < items.Length ? items[currentItem] : CVRCommon.NONE_OR_EMPTY;
|
||||
if (EditorGUI.DropdownButton(buttonRect, new GUIContent(current), FocusType.Passive))
|
||||
{
|
||||
GUIUtility.keyboardControl = controlId;
|
||||
new CustomAdvancedDropdown(new AdvancedDropdownState(), items, title, selected =>
|
||||
{
|
||||
s_lastSelectedValue = selected;
|
||||
}).Show(buttonRect); // We'll show the dropdown right where our buttonRect is
|
||||
}
|
||||
|
||||
if (controlId == GUIUtility.keyboardControl && s_lastSelectedValue != -1)
|
||||
{
|
||||
currentItem = s_lastSelectedValue;
|
||||
s_lastSelectedValue = -1;
|
||||
}
|
||||
|
||||
return currentItem;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CustomDropdown
|
||||
|
||||
public static string CustomDropdown(
|
||||
Rect rect,
|
||||
string label,
|
||||
string currentItem,
|
||||
string[] items,
|
||||
string title = null)
|
||||
{
|
||||
GUIContent defaultButtonContent = items.Contains(currentItem)
|
||||
? GetCachedIconContent("d_Search Icon")
|
||||
: GetCachedIconContent("console.erroricon.sml");
|
||||
|
||||
return CustomDropdown(rect, label, currentItem, items, defaultButtonContent, DEFAULT_DROPDOWN_BUTTON_WIDTH, title);
|
||||
}
|
||||
|
||||
public static string CustomDropdown(
|
||||
Rect rect,
|
||||
string label,
|
||||
string currentItem,
|
||||
string[] items,
|
||||
GUIContent buttonContent,
|
||||
string title = null)
|
||||
{
|
||||
return CustomDropdown(rect, label, currentItem, items, buttonContent, DEFAULT_DROPDOWN_BUTTON_WIDTH, title);
|
||||
}
|
||||
|
||||
private static string CustomDropdown(
|
||||
Rect rect,
|
||||
string label,
|
||||
string currentItem,
|
||||
string[] items,
|
||||
GUIContent buttonContent,
|
||||
float dropdownButtonWidth,
|
||||
string title)
|
||||
{
|
||||
float labelWidth = 2f + EditorGUIUtility.labelWidth;
|
||||
float indentOffset = 15 * EditorGUI.indentLevel;
|
||||
|
||||
Rect textFieldRect = new Rect(rect.x + labelWidth - indentOffset, rect.y, rect.width - labelWidth + indentOffset - dropdownButtonWidth, rect.height);
|
||||
Rect buttonRect = new Rect(rect.x + rect.width - dropdownButtonWidth, rect.y, dropdownButtonWidth, rect.height);
|
||||
Rect dropdownRect = new Rect(rect.x + labelWidth, rect.y, rect.width - labelWidth, rect.height);
|
||||
|
||||
EditorGUI.LabelField(new Rect(rect.x, rect.y, labelWidth, rect.height), label);
|
||||
currentItem = EditorGUI.TextField(textFieldRect, currentItem);
|
||||
|
||||
return CustomDropdown(currentItem, items, title, buttonRect, dropdownRect, buttonContent);
|
||||
}
|
||||
|
||||
private static string CustomDropdown(
|
||||
Rect rect,
|
||||
string currentItem,
|
||||
string[] items,
|
||||
GUIContent buttonContent,
|
||||
float dropdownButtonWidth,
|
||||
string title)
|
||||
{
|
||||
float indentOffset = 15 * EditorGUI.indentLevel;
|
||||
Rect textFieldRect = new Rect(rect.x - indentOffset, rect.y, rect.width + indentOffset - dropdownButtonWidth, rect.height);
|
||||
Rect buttonRect = new Rect(rect.x + rect.width - dropdownButtonWidth, rect.y, dropdownButtonWidth, rect.height);
|
||||
Rect dropdownRect = new Rect(rect.x, rect.y, rect.width, rect.height);
|
||||
|
||||
currentItem = EditorGUI.TextField(textFieldRect, currentItem);
|
||||
return CustomDropdown(currentItem, items, title, buttonRect, dropdownRect, buttonContent);
|
||||
}
|
||||
|
||||
private static string CustomDropdown(
|
||||
string currentItem,
|
||||
string[] items,
|
||||
string title,
|
||||
Rect buttonRect,
|
||||
Rect dropdownRect,
|
||||
GUIContent buttonContent)
|
||||
{
|
||||
int controlId = GUIUtility.GetControlID(FocusType.Passive);
|
||||
|
||||
if (EditorGUI.DropdownButton(buttonRect, buttonContent, FocusType.Passive))
|
||||
{
|
||||
GUIUtility.keyboardControl = controlId;
|
||||
new CustomAdvancedDropdown(new AdvancedDropdownState(), items, title, selected =>
|
||||
{
|
||||
s_lastSelectedValue = selected;
|
||||
}).Show(dropdownRect);
|
||||
}
|
||||
|
||||
if (controlId == GUIUtility.keyboardControl && s_lastSelectedValue != -1)
|
||||
{
|
||||
currentItem = items[s_lastSelectedValue];
|
||||
s_lastSelectedValue = -1;
|
||||
}
|
||||
|
||||
return currentItem;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
public static GUIContent GetCachedIconContent(string iconName)
|
||||
{
|
||||
if (s_iconContentCache.TryGetValue(iconName, out GUIContent iconContent))
|
||||
return iconContent;
|
||||
|
||||
iconContent = EditorGUIUtility.IconContent(iconName);
|
||||
s_iconContentCache[iconName] = iconContent;
|
||||
return iconContent;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Custom GUI
|
||||
|
||||
private class CustomAdvancedDropdown : AdvancedDropdown
|
||||
{
|
||||
private readonly Action<int> _onItemSelected;
|
||||
private readonly string[] _items;
|
||||
private readonly string _title;
|
||||
|
||||
internal CustomAdvancedDropdown(AdvancedDropdownState state, string[] items, string title, Action<int> onItemSelected) : base(state)
|
||||
{
|
||||
_items = items ?? Array.Empty<string>();
|
||||
_title = title ?? "Items";
|
||||
_onItemSelected = onItemSelected;
|
||||
}
|
||||
|
||||
internal new void Show(Rect rect)
|
||||
{
|
||||
minimumSize = new Vector2(rect.width, 200f);
|
||||
|
||||
// We have to set the maximumSize through reflection, cause unity is cool
|
||||
typeof(AdvancedDropdown).GetProperty("maximumSize", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
?.SetValue(this, new Vector2(rect.width, 400f));
|
||||
|
||||
base.Show(rect);
|
||||
}
|
||||
|
||||
protected override AdvancedDropdownItem BuildRoot()
|
||||
{
|
||||
AdvancedDropdownItem root = new AdvancedDropdownItem(_title);
|
||||
|
||||
for (var itemIdx = 0; itemIdx < _items.Length; itemIdx++)
|
||||
{
|
||||
var item = _items[itemIdx];
|
||||
AdvancedDropdownItem current = root;
|
||||
string[] parts = item.Split('/');
|
||||
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
{
|
||||
string name = parts[i];
|
||||
AdvancedDropdownItem child = current.children.FirstOrDefault(c => c.name == name);
|
||||
|
||||
if (child == null)
|
||||
{
|
||||
child = new AdvancedDropdownItem(name)
|
||||
{
|
||||
id = itemIdx // id is based on itteration order
|
||||
};
|
||||
if (name == item && name == _title)
|
||||
child.icon = GetCachedIconContent("d_FilterSelectedOnly").image as Texture2D;
|
||||
|
||||
current.AddChild(child);
|
||||
}
|
||||
|
||||
current = child;
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
protected override void ItemSelected(AdvancedDropdownItem item)
|
||||
{
|
||||
base.ItemSelected(item);
|
||||
_onItemSelected?.Invoke(item.id);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue