264 lines
10 KiB
C#
264 lines
10 KiB
C#
#if UNITY_EDITOR
|
|
using System;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEditor.IMGUI.Controls;
|
|
|
|
namespace UnityEngine.InputSystem.Editor
|
|
{
|
|
internal class AdvancedDropdownGUI
|
|
{
|
|
private static class Styles
|
|
{
|
|
#if UNITY_2023_2_OR_NEWER || UNITY_2021_3_28 || UNITY_2022_3_1
|
|
public static readonly GUIStyle toolbarSearchField = "ToolbarSearchTextField";
|
|
#else
|
|
public static readonly GUIStyle toolbarSearchField = "ToolbarSearchTextField";
|
|
#endif
|
|
public static readonly GUIStyle itemStyle = new GUIStyle("PR Label")
|
|
.WithAlignment(TextAnchor.MiddleLeft)
|
|
.WithPadding(new RectOffset())
|
|
.WithMargin(new RectOffset())
|
|
.WithFixedHeight(17);
|
|
public static readonly GUIStyle richTextItemStyle = new GUIStyle("PR Label")
|
|
.WithAlignment(TextAnchor.MiddleLeft)
|
|
.WithPadding(new RectOffset())
|
|
.WithMargin(new RectOffset())
|
|
.WithFixedHeight(17)
|
|
.WithRichText();
|
|
public static readonly GUIStyle header = new GUIStyle("In BigTitle")
|
|
.WithFont(EditorStyles.boldLabel.font)
|
|
.WithMargin(new RectOffset())
|
|
.WithBorder(new RectOffset(0, 0, 3, 3))
|
|
.WithPadding(new RectOffset(6, 6, 6, 6))
|
|
.WithContentOffset(Vector2.zero);
|
|
public static readonly GUIStyle headerArrow = new GUIStyle()
|
|
.WithAlignment(TextAnchor.MiddleCenter)
|
|
.WithFontSize(20)
|
|
.WithNormalTextColor(Color.gray);
|
|
public static readonly GUIStyle checkMark = new GUIStyle("PR Label")
|
|
.WithAlignment(TextAnchor.MiddleCenter)
|
|
.WithPadding(new RectOffset())
|
|
.WithMargin(new RectOffset())
|
|
.WithFixedHeight(17);
|
|
public static readonly GUIContent arrowRightContent = new GUIContent("▸");
|
|
public static readonly GUIContent arrowLeftContent = new GUIContent("◂");
|
|
}
|
|
|
|
//This should ideally match line height
|
|
private static readonly Vector2 s_IconSize = new Vector2(13, 13);
|
|
|
|
internal Rect m_SearchRect;
|
|
internal Rect m_HeaderRect;
|
|
private bool m_FocusSet;
|
|
|
|
internal virtual float searchHeight => m_SearchRect.height;
|
|
|
|
internal virtual float headerHeight => m_HeaderRect.height;
|
|
|
|
internal virtual GUIStyle lineStyle => Styles.itemStyle;
|
|
internal virtual GUIStyle richTextLineStyle => Styles.richTextItemStyle;
|
|
internal GUIStyle headerStyle => Styles.header;
|
|
|
|
internal virtual Vector2 iconSize => s_IconSize;
|
|
|
|
internal AdvancedDropdownState state { get; set; }
|
|
|
|
private readonly SearchField m_SearchField = new SearchField();
|
|
|
|
public void Init()
|
|
{
|
|
m_FocusSet = false;
|
|
}
|
|
|
|
private const float k_IndentPerLevel = 20f;
|
|
|
|
internal virtual void BeginDraw(EditorWindow window)
|
|
{
|
|
}
|
|
|
|
internal virtual void EndDraw(EditorWindow window)
|
|
{
|
|
}
|
|
|
|
internal virtual void DrawItem(AdvancedDropdownItem item, string name, Texture2D icon, bool enabled,
|
|
bool drawArrow, bool selected, bool hasSearch, bool richText = false)
|
|
{
|
|
var content = new GUIContent(name, icon);
|
|
var imgTemp = content.image;
|
|
//we need to pretend we have an icon to calculate proper width in case
|
|
if (content.image == null)
|
|
content.image = Texture2D.whiteTexture;
|
|
var style = richText ? richTextLineStyle : lineStyle;
|
|
var rect = GUILayoutUtility.GetRect(content, style, GUILayout.ExpandWidth(true));
|
|
content.image = imgTemp;
|
|
|
|
if (Event.current.type != EventType.Repaint)
|
|
return;
|
|
|
|
style.Draw(rect, GUIContent.none, false, false, selected, selected);
|
|
if (!hasSearch)
|
|
{
|
|
rect.x += item.indent * k_IndentPerLevel;
|
|
rect.width -= item.indent * k_IndentPerLevel;
|
|
}
|
|
|
|
var imageTemp = content.image;
|
|
if (content.image == null)
|
|
{
|
|
style.Draw(rect, GUIContent.none, false, false, selected, selected);
|
|
rect.x += iconSize.x + 1;
|
|
rect.width -= iconSize.x + 1;
|
|
}
|
|
rect.x += EditorGUIUtility.standardVerticalSpacing;
|
|
rect.width -= EditorGUIUtility.standardVerticalSpacing;
|
|
EditorGUI.BeginDisabledGroup(!enabled);
|
|
style.Draw(rect, content, false, false, selected, selected);
|
|
content.image = imageTemp;
|
|
if (drawArrow)
|
|
{
|
|
var size = style.lineHeight;
|
|
var arrowRect = new Rect(rect.x + rect.width - size, rect.y, size, size);
|
|
style.Draw(arrowRect, Styles.arrowRightContent, false, false, false, false);
|
|
}
|
|
EditorGUI.EndDisabledGroup();
|
|
}
|
|
|
|
internal virtual void DrawHeader(AdvancedDropdownItem group, Action backButtonPressed, bool hasParent)
|
|
{
|
|
var content = new GUIContent(group.name, group.icon);
|
|
m_HeaderRect = GUILayoutUtility.GetRect(content, Styles.header, GUILayout.ExpandWidth(true));
|
|
|
|
if (Event.current.type == EventType.Repaint)
|
|
Styles.header.Draw(m_HeaderRect, content, false, false, false, false);
|
|
|
|
// Back button
|
|
if (hasParent)
|
|
{
|
|
var arrowWidth = 13;
|
|
var arrowRect = new Rect(m_HeaderRect.x, m_HeaderRect.y, arrowWidth, m_HeaderRect.height);
|
|
if (Event.current.type == EventType.Repaint)
|
|
Styles.headerArrow.Draw(arrowRect, Styles.arrowLeftContent, false, false, false, false);
|
|
if (Event.current.type == EventType.MouseDown && m_HeaderRect.Contains(Event.current.mousePosition))
|
|
{
|
|
backButtonPressed();
|
|
Event.current.Use();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal virtual void DrawFooter(AdvancedDropdownItem selectedItem)
|
|
{
|
|
}
|
|
|
|
internal void DrawSearchField(bool isSearchFieldDisabled, string searchString, Action<string> searchChanged)
|
|
{
|
|
if (!isSearchFieldDisabled && !m_FocusSet)
|
|
{
|
|
m_FocusSet = true;
|
|
m_SearchField.SetFocus();
|
|
}
|
|
|
|
using (new EditorGUI.DisabledScope(isSearchFieldDisabled))
|
|
{
|
|
var newSearch = DrawSearchFieldControl(searchString);
|
|
|
|
if (newSearch != searchString)
|
|
{
|
|
searchChanged(newSearch);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal virtual string DrawSearchFieldControl(string searchString)
|
|
{
|
|
var paddingX = 8f;
|
|
var paddingY = 2f;
|
|
var rect = GUILayoutUtility.GetRect(0, 0, Styles.toolbarSearchField);
|
|
//rect.x += paddingX;
|
|
rect.y += paddingY + 1; // Add one for the border
|
|
rect.height += Styles.toolbarSearchField.fixedHeight + paddingY * 3;
|
|
rect.width -= paddingX;// * 2;
|
|
m_SearchRect = rect;
|
|
searchString = m_SearchField.OnToolbarGUI(m_SearchRect, searchString);
|
|
return searchString;
|
|
}
|
|
|
|
internal Rect GetAnimRect(Rect position, float anim)
|
|
{
|
|
// Calculate rect for animated area
|
|
var rect = new Rect(position);
|
|
rect.x = position.x + position.width * anim;
|
|
rect.y += searchHeight;
|
|
rect.height -= searchHeight;
|
|
return rect;
|
|
}
|
|
|
|
internal Vector2 CalculateContentSize(AdvancedDropdownDataSource dataSource)
|
|
{
|
|
var maxWidth = 0f;
|
|
var maxHeight = 0f;
|
|
var includeArrow = false;
|
|
var arrowWidth = 0f;
|
|
|
|
foreach (var child in dataSource.mainTree.children)
|
|
{
|
|
var content = new GUIContent(child.name, child.icon);
|
|
var a = lineStyle.CalcSize(content);
|
|
a.x += iconSize.x + 1;
|
|
|
|
if (maxWidth < a.x)
|
|
{
|
|
maxWidth = a.x + 1;
|
|
includeArrow |= child.children.Any();
|
|
}
|
|
if (child.IsSeparator())
|
|
{
|
|
maxHeight += GUIHelpers.Styles.lineSeparator.CalcHeight(content, maxWidth) + GUIHelpers.Styles.lineSeparator.margin.vertical;
|
|
}
|
|
else
|
|
{
|
|
maxHeight += lineStyle.CalcHeight(content, maxWidth);
|
|
}
|
|
if (arrowWidth == 0)
|
|
{
|
|
lineStyle.CalcMinMaxWidth(Styles.arrowRightContent, out arrowWidth, out arrowWidth);
|
|
}
|
|
}
|
|
if (includeArrow)
|
|
{
|
|
maxWidth += arrowWidth;
|
|
}
|
|
return new Vector2(maxWidth, maxHeight);
|
|
}
|
|
|
|
internal float GetSelectionHeight(AdvancedDropdownDataSource dataSource, Rect buttonRect)
|
|
{
|
|
if (state.GetSelectedIndex(dataSource.mainTree) == -1)
|
|
return 0;
|
|
var height = 0f;
|
|
for (var i = 0; i < dataSource.mainTree.children.Count(); i++)
|
|
{
|
|
var child = dataSource.mainTree.children.ElementAt(i);
|
|
var content = new GUIContent(child.name, child.icon);
|
|
if (state.GetSelectedIndex(dataSource.mainTree) == i)
|
|
{
|
|
var diff = (lineStyle.CalcHeight(content, 0) - buttonRect.height) / 2f;
|
|
return height + diff;
|
|
}
|
|
if (child.IsSeparator())
|
|
{
|
|
height += GUIHelpers.Styles.lineSeparator.CalcHeight(content, 0) + GUIHelpers.Styles.lineSeparator.margin.vertical;
|
|
}
|
|
else
|
|
{
|
|
height += lineStyle.CalcHeight(content, 0);
|
|
}
|
|
}
|
|
return height;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // UNITY_EDITOR
|