A game about forced loneliness, made by TACStudios
1#if UNITY_EDITOR
2using System;
3using System.Linq;
4using UnityEditor;
5using UnityEditor.IMGUI.Controls;
6
7namespace UnityEngine.InputSystem.Editor
8{
9 internal class AdvancedDropdownGUI
10 {
11 private static class Styles
12 {
13 public static readonly GUIStyle toolbarSearchField = EditorStyles.toolbarSearchField;
14 public static readonly GUIStyle itemStyle = new GUIStyle("PR Label")
15 .WithAlignment(TextAnchor.MiddleLeft)
16 .WithPadding(new RectOffset())
17 .WithMargin(new RectOffset())
18 .WithFixedHeight(17);
19 public static readonly GUIStyle richTextItemStyle = new GUIStyle("PR Label")
20 .WithAlignment(TextAnchor.MiddleLeft)
21 .WithPadding(new RectOffset())
22 .WithMargin(new RectOffset())
23 .WithFixedHeight(17)
24 .WithRichText();
25 public static readonly GUIStyle header = new GUIStyle("In BigTitle")
26 .WithFont(EditorStyles.boldLabel.font)
27 .WithMargin(new RectOffset())
28 .WithBorder(new RectOffset(0, 0, 3, 3))
29 .WithPadding(new RectOffset(6, 6, 6, 6))
30 .WithContentOffset(Vector2.zero);
31 public static readonly GUIStyle headerArrow = new GUIStyle()
32 .WithAlignment(TextAnchor.MiddleCenter)
33 .WithFontSize(20)
34 .WithNormalTextColor(Color.gray);
35 public static readonly GUIStyle checkMark = new GUIStyle("PR Label")
36 .WithAlignment(TextAnchor.MiddleCenter)
37 .WithPadding(new RectOffset())
38 .WithMargin(new RectOffset())
39 .WithFixedHeight(17);
40 public static readonly GUIContent arrowRightContent = new GUIContent("▸");
41 public static readonly GUIContent arrowLeftContent = new GUIContent("◂");
42 }
43
44 //This should ideally match line height
45 private static readonly Vector2 s_IconSize = new Vector2(13, 13);
46
47 internal Rect m_SearchRect;
48 internal Rect m_HeaderRect;
49 private bool m_FocusSet;
50
51 internal virtual float searchHeight => m_SearchRect.height;
52
53 internal virtual float headerHeight => m_HeaderRect.height;
54
55 internal virtual GUIStyle lineStyle => Styles.itemStyle;
56 internal virtual GUIStyle richTextLineStyle => Styles.richTextItemStyle;
57 internal GUIStyle headerStyle => Styles.header;
58
59 internal virtual Vector2 iconSize => s_IconSize;
60
61 internal AdvancedDropdownState state { get; set; }
62
63 private readonly SearchField m_SearchField = new SearchField();
64
65 public void Init()
66 {
67 m_FocusSet = false;
68 }
69
70 private const float k_IndentPerLevel = 20f;
71
72 internal virtual void BeginDraw(EditorWindow window)
73 {
74 }
75
76 internal virtual void EndDraw(EditorWindow window)
77 {
78 }
79
80 internal virtual void DrawItem(AdvancedDropdownItem item, string name, Texture2D icon, bool enabled,
81 bool drawArrow, bool selected, bool hasSearch, bool richText = false)
82 {
83 var content = new GUIContent(name, icon);
84 var imgTemp = content.image;
85 //we need to pretend we have an icon to calculate proper width in case
86 if (content.image == null)
87 content.image = Texture2D.whiteTexture;
88 var style = richText ? richTextLineStyle : lineStyle;
89 var rect = GUILayoutUtility.GetRect(content, style, GUILayout.ExpandWidth(true));
90 content.image = imgTemp;
91
92 if (Event.current.type != EventType.Repaint)
93 return;
94
95 style.Draw(rect, GUIContent.none, false, false, selected, selected);
96 if (!hasSearch)
97 {
98 rect.x += item.indent * k_IndentPerLevel;
99 rect.width -= item.indent * k_IndentPerLevel;
100 }
101
102 var imageTemp = content.image;
103 if (content.image == null)
104 {
105 style.Draw(rect, GUIContent.none, false, false, selected, selected);
106 rect.x += iconSize.x + 1;
107 rect.width -= iconSize.x + 1;
108 }
109 rect.x += EditorGUIUtility.standardVerticalSpacing;
110 rect.width -= EditorGUIUtility.standardVerticalSpacing;
111 EditorGUI.BeginDisabledGroup(!enabled);
112 style.Draw(rect, content, false, false, selected, selected);
113 content.image = imageTemp;
114 if (drawArrow)
115 {
116 var size = style.lineHeight;
117 var arrowRect = new Rect(rect.x + rect.width - size, rect.y, size, size);
118 style.Draw(arrowRect, Styles.arrowRightContent, false, false, false, false);
119 }
120 EditorGUI.EndDisabledGroup();
121 }
122
123 internal virtual void DrawHeader(AdvancedDropdownItem group, Action backButtonPressed, bool hasParent)
124 {
125 var content = new GUIContent(group.name, group.icon);
126 m_HeaderRect = GUILayoutUtility.GetRect(content, Styles.header, GUILayout.ExpandWidth(true));
127
128 if (Event.current.type == EventType.Repaint)
129 Styles.header.Draw(m_HeaderRect, content, false, false, false, false);
130
131 // Back button
132 if (hasParent)
133 {
134 var arrowWidth = 13;
135 var arrowRect = new Rect(m_HeaderRect.x, m_HeaderRect.y, arrowWidth, m_HeaderRect.height);
136 if (Event.current.type == EventType.Repaint)
137 Styles.headerArrow.Draw(arrowRect, Styles.arrowLeftContent, false, false, false, false);
138 if (Event.current.type == EventType.MouseDown && m_HeaderRect.Contains(Event.current.mousePosition))
139 {
140 backButtonPressed();
141 Event.current.Use();
142 }
143 }
144 }
145
146 internal virtual void DrawFooter(AdvancedDropdownItem selectedItem)
147 {
148 }
149
150 internal void DrawSearchField(bool isSearchFieldDisabled, string searchString, Action<string> searchChanged)
151 {
152 if (!isSearchFieldDisabled && !m_FocusSet)
153 {
154 m_FocusSet = true;
155 m_SearchField.SetFocus();
156 }
157
158 using (new EditorGUI.DisabledScope(isSearchFieldDisabled))
159 {
160 var newSearch = DrawSearchFieldControl(searchString);
161
162 if (newSearch != searchString)
163 {
164 searchChanged(newSearch);
165 }
166 }
167 }
168
169 internal virtual string DrawSearchFieldControl(string searchString)
170 {
171 var paddingX = 8f;
172 var paddingY = 2f;
173 var rect = GUILayoutUtility.GetRect(0, 0, Styles.toolbarSearchField);
174 //rect.x += paddingX;
175 rect.y += paddingY + 1; // Add one for the border
176 rect.height += Styles.toolbarSearchField.fixedHeight + paddingY * 3;
177 rect.width -= paddingX;// * 2;
178 m_SearchRect = rect;
179 searchString = m_SearchField.OnToolbarGUI(m_SearchRect, searchString);
180 return searchString;
181 }
182
183 internal Rect GetAnimRect(Rect position, float anim)
184 {
185 // Calculate rect for animated area
186 var rect = new Rect(position);
187 rect.x = position.x + position.width * anim;
188 rect.y += searchHeight;
189 rect.height -= searchHeight;
190 return rect;
191 }
192
193 internal Vector2 CalculateContentSize(AdvancedDropdownDataSource dataSource)
194 {
195 var maxWidth = 0f;
196 var maxHeight = 0f;
197 var includeArrow = false;
198 var arrowWidth = 0f;
199
200 foreach (var child in dataSource.mainTree.children)
201 {
202 var content = new GUIContent(child.name, child.icon);
203 var a = lineStyle.CalcSize(content);
204 a.x += iconSize.x + 1;
205
206 if (maxWidth < a.x)
207 {
208 maxWidth = a.x + 1;
209 includeArrow |= child.children.Any();
210 }
211 if (child.IsSeparator())
212 {
213 maxHeight += GUIHelpers.Styles.lineSeparator.CalcHeight(content, maxWidth) + GUIHelpers.Styles.lineSeparator.margin.vertical;
214 }
215 else
216 {
217 maxHeight += lineStyle.CalcHeight(content, maxWidth);
218 }
219 if (arrowWidth == 0)
220 {
221 lineStyle.CalcMinMaxWidth(Styles.arrowRightContent, out arrowWidth, out arrowWidth);
222 }
223 }
224 if (includeArrow)
225 {
226 maxWidth += arrowWidth;
227 }
228 return new Vector2(maxWidth, maxHeight);
229 }
230
231 internal float GetSelectionHeight(AdvancedDropdownDataSource dataSource, Rect buttonRect)
232 {
233 if (state.GetSelectedIndex(dataSource.mainTree) == -1)
234 return 0;
235 var height = 0f;
236 for (var i = 0; i < dataSource.mainTree.children.Count(); i++)
237 {
238 var child = dataSource.mainTree.children.ElementAt(i);
239 var content = new GUIContent(child.name, child.icon);
240 if (state.GetSelectedIndex(dataSource.mainTree) == i)
241 {
242 var diff = (lineStyle.CalcHeight(content, 0) - buttonRect.height) / 2f;
243 return height + diff;
244 }
245 if (child.IsSeparator())
246 {
247 height += GUIHelpers.Styles.lineSeparator.CalcHeight(content, 0) + GUIHelpers.Styles.lineSeparator.margin.vertical;
248 }
249 else
250 {
251 height += lineStyle.CalcHeight(content, 0);
252 }
253 }
254 return height;
255 }
256 }
257}
258
259#endif // UNITY_EDITOR