├── README.md
├── .gitignore
├── InspectorButton.cs
└── EditorIconViewer.cs
/README.md:
--------------------------------------------------------------------------------
1 | UnityPublic
2 | ===========
3 |
4 | A front-facing repository for various tools and boiler plate scripts.
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | [Ll]ibrary/
2 | [Tt]emp/
3 | [Oo]bj/
4 |
5 | # Autogenerated VS/MD solution and project files
6 | *.csproj
7 | *.unityproj
8 | *.sln
9 |
--------------------------------------------------------------------------------
/InspectorButton.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | #if UNITY_EDITOR
3 | using UnityEditor;
4 | #endif
5 | using System.Reflection;
6 |
7 | ///
8 | /// This attribute can only be applied to fields because its
9 | /// associated PropertyDrawer only operates on fields (either
10 | /// public or tagged with the [SerializeField] attribute) in
11 | /// the target MonoBehaviour.
12 | ///
13 | [System.AttributeUsage(System.AttributeTargets.Field)]
14 | public class InspectorButtonAttribute : PropertyAttribute
15 | {
16 | public static float kDefaultButtonWidth = 80;
17 |
18 | public readonly string MethodName;
19 |
20 | private float _buttonWidth = kDefaultButtonWidth;
21 | public float ButtonWidth
22 | {
23 | get { return _buttonWidth; }
24 | set { _buttonWidth = value; }
25 | }
26 |
27 | public InspectorButtonAttribute(string MethodName)
28 | {
29 | this.MethodName = MethodName;
30 | }
31 | }
32 |
33 | #if UNITY_EDITOR
34 | [CustomPropertyDrawer(typeof(InspectorButtonAttribute))]
35 | public class InspectorButtonPropertyDrawer : PropertyDrawer
36 | {
37 | private MethodInfo _eventMethodInfo = null;
38 |
39 | public override void OnGUI(Rect position, SerializedProperty prop, GUIContent label)
40 | {
41 | InspectorButtonAttribute inspectorButtonAttribute = (InspectorButtonAttribute)attribute;
42 | Rect buttonRect = new Rect(position.x + (position.width - inspectorButtonAttribute.ButtonWidth) * 0.5f, position.y, inspectorButtonAttribute.ButtonWidth, position.height);
43 | if (GUI.Button(buttonRect, label.text))
44 | {
45 | System.Type eventOwnerType = prop.serializedObject.targetObject.GetType();
46 | string eventName = inspectorButtonAttribute.MethodName;
47 |
48 | if (_eventMethodInfo == null)
49 | _eventMethodInfo = eventOwnerType.GetMethod(eventName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
50 |
51 | if (_eventMethodInfo != null)
52 | _eventMethodInfo.Invoke(prop.serializedObject.targetObject, null);
53 | else
54 | Debug.LogWarning(string.Format("InspectorButton: Unable to find method {0} in {1}", eventName, eventOwnerType));
55 | }
56 | }
57 | }
58 | #endif
59 |
--------------------------------------------------------------------------------
/EditorIconViewer.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using UnityEditor;
3 | using System.Collections;
4 | using System.Linq;
5 | using System.Collections.Generic;
6 |
7 | public class EditorIconViewer : EditorWindow
8 | {
9 | public class IconGroup
10 | {
11 | public string name;
12 | public GUIStyle[] iconData;
13 | public float iconWidthThreshold;
14 | public float maxWidth;
15 | }
16 |
17 | // Icons are categorized by their height, into buckets defined by
18 | // the two arrays below. The number of thresholds should always exceed
19 | // the number of group names by one.
20 | public List iconGroups;
21 | public static float[] kIconThresholds = { 0, 9, 25, 35, 100, 99999 };
22 | public static string[] kIconGroupNames = { "Mini", "Small", "Medium", "Large", "X-Large" };
23 |
24 | #region Blacklisted Items
25 | // Names of known style states that have a texture present in the 'background' field but
26 | // whose icons show up as empty images when renderered.
27 | protected static bool kHideBlacklistedIcons = true;
28 | protected static HashSet kIconBlacklist = new HashSet()
29 | {
30 | "PlayerSettingsPlatform",
31 | "PreferencesSection",
32 | "ProfilerPaneLeftBackground",
33 | "flow var 0",
34 | "flow var 0 on",
35 | "flow var 1",
36 | "flow var 1 on",
37 | "flow var 2",
38 | "flow var 2 on",
39 | "flow var 3",
40 | "flow var 3 on",
41 | "flow var 4",
42 | "flow var 4 on",
43 | "flow var 5",
44 | "flow var 5 on",
45 | "flow var 6",
46 | "flow var 6 on",
47 | };
48 | #endregion
49 |
50 | public static float kSidePanelMinWidth = 150;
51 | public static float kSidePanelMaxWidth = 250;
52 | public static float kScrollbarWidth = 15;
53 | public static float kSelectionGridPadding = 10;
54 |
55 | public static string kUsageString =
56 | "All of the icons presented in this collection are easily accessible when writing a custom editor script, for both Inspectors and Editor Windows. " +
57 | "In the OnEnable method of your editor, obtain a copy of the editor's skin with the following:\n\n" +
58 | "GUISkin _editorSkin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector);\n\n" +
59 | "Textures shown in this tool can be retrieved by using their style names, shown at the top of the left-hand panel when you select an icon from the grid. For example:\n\n" +
60 | "GUILayout.Button(_editorSkin.GetStyle(\"MeTransPlayhead\").normal.background);\n\n" +
61 | "Or you can simply use the style itself when rendering a control:\n\n" +
62 | "GUILayout.Button(\"\", _editorSkin.GetStyle(\"MeTransPlayhead\"));\n\n" +
63 | "If additional style states are available (such as Focused, Hover, or Active), they will appear in the panel when selected.";
64 |
65 | protected GUISkin _editorSkin;
66 | protected GUIStyle _selectedIcon;
67 | protected Vector2 _scrollPos;
68 | protected float _drawScale;
69 |
70 | [MenuItem("Tools/Editor Icons")]
71 | static void Init()
72 | {
73 | EditorIconViewer window = (EditorIconViewer)GetWindow(typeof(EditorIconViewer), false, "Editor Icon Viewer");
74 | window.position = new Rect(150, 150, 700, 400);
75 | }
76 |
77 | void OnEnable()
78 | {
79 | _editorSkin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector);
80 | _scrollPos = Vector2.zero;
81 | SetSelectedIcon(null);
82 |
83 | iconGroups = new List();
84 |
85 | for (int i = 0; i < kIconGroupNames.Length; ++i)
86 | {
87 | IconGroup group = new IconGroup();
88 | group.name = kIconGroupNames[i];
89 |
90 | float minHeight = kIconThresholds[i];
91 | float maxHeight = kIconThresholds[i + 1];
92 |
93 | group.iconData = _editorSkin.customStyles
94 | .Where(style =>
95 | {
96 | if (style.normal.background == null)
97 | return false;
98 | if (style.normal.background.height <= minHeight || style.normal.background.height > maxHeight)
99 | return false;
100 | if (kHideBlacklistedIcons && kIconBlacklist.Contains(style.name))
101 | return false;
102 |
103 | return true;
104 | })
105 | .OrderBy(style => style.normal.background.height).ToArray();
106 |
107 | float maxWidth = 0;
108 | foreach (GUIStyle style in group.iconData)
109 | maxWidth = (style.normal.background.width > maxWidth) ? style.normal.background.width : maxWidth;
110 | group.maxWidth = maxWidth;
111 |
112 | iconGroups.Add(group);
113 | }
114 | }
115 |
116 | void OnGUI()
117 | {
118 | float sidePanelWidth = CalculateSidePanelWidth();
119 | GUILayout.BeginArea(new Rect(0, 0, sidePanelWidth, position.height), GUI.skin.box);
120 | DrawIconDisplay(_selectedIcon);
121 | GUILayout.EndArea();
122 |
123 | GUI.BeginGroup(new Rect(sidePanelWidth, 0, position.width - sidePanelWidth, position.height));
124 | _scrollPos = GUILayout.BeginScrollView(_scrollPos, true, true, GUILayout.MaxWidth(position.width - sidePanelWidth));
125 |
126 | for (int i = 0; i < iconGroups.Count; ++i)
127 | {
128 | IconGroup group = iconGroups[i];
129 | EditorGUILayout.LabelField(group.name);
130 | DrawIconSelectionGrid(group.iconData, group.maxWidth);
131 |
132 | GUILayout.Space(15);
133 | }
134 |
135 | GUILayout.EndScrollView();
136 | GUI.EndGroup();
137 | }
138 |
139 | protected float CalculateSidePanelWidth()
140 | {
141 | return Mathf.Clamp(position.width * 0.21f, kSidePanelMinWidth, kSidePanelMaxWidth);
142 | }
143 |
144 | protected void DrawIconDisplay(GUIStyle style)
145 | {
146 | if (style == null)
147 | {
148 | DrawCenteredMessage("No icon selected");
149 | GUILayout.FlexibleSpace();
150 | DrawHelpIcon();
151 | return;
152 | }
153 |
154 | Texture2D iconTexture = style.normal.background;
155 |
156 | EditorGUILayout.BeginVertical();
157 |
158 | EditorGUILayout.BeginHorizontal();
159 | GUILayout.FlexibleSpace();
160 | GUILayout.Label(style.name, EditorStyles.whiteLargeLabel);
161 | GUILayout.FlexibleSpace();
162 | EditorGUILayout.EndHorizontal();
163 |
164 | EditorGUILayout.BeginHorizontal();
165 | GUILayout.FlexibleSpace();
166 | GUILayout.Label("Normal");
167 | GUILayout.FlexibleSpace();
168 | EditorGUILayout.EndHorizontal();
169 |
170 | float iconOffset = 45;
171 | float iconWidth = iconTexture.width * _drawScale;
172 | float iconHeight = iconTexture.height * _drawScale;
173 | float sidePanelWidth = CalculateSidePanelWidth();
174 | GUI.DrawTexture(new Rect((sidePanelWidth - iconWidth) * 0.5f, iconOffset, iconWidth, iconHeight), iconTexture, ScaleMode.StretchToFill);
175 | GUILayout.Space(iconHeight + 10);
176 |
177 | EditorGUILayout.BeginHorizontal();
178 | if (GUILayout.Toggle(_drawScale == 1.0f, "1x", EditorStyles.miniButtonLeft))
179 | {
180 | _drawScale = 1.0f;
181 | }
182 | if (GUILayout.Toggle(_drawScale == 1.5f, "1.5x", EditorStyles.miniButtonMid))
183 | {
184 | _drawScale = 1.5f;
185 | }
186 | if (GUILayout.Toggle(_drawScale == 2.0f, "2x", EditorStyles.miniButtonRight))
187 | {
188 | _drawScale = 2.0f;
189 | }
190 | EditorGUILayout.EndHorizontal();
191 |
192 | GUILayout.Space(10);
193 |
194 | DrawIconStyleState(style.active, "Active");
195 | DrawIconStyleState(style.hover, "Hover");
196 | DrawIconStyleState(style.focused, "Focused");
197 |
198 | GUILayout.Space(10);
199 |
200 | EditorGUILayout.LabelField(string.Format("Width: {0}px", iconTexture.width));
201 | EditorGUILayout.LabelField(string.Format("Height: {0}px", iconTexture.height));
202 |
203 | GUILayout.FlexibleSpace();
204 | DrawHelpIcon();
205 |
206 | EditorGUILayout.EndVertical();
207 | }
208 |
209 | protected void DrawIconStyleState(GUIStyleState state, string label)
210 | {
211 | if (state == null || state.background == null)
212 | return;
213 |
214 | EditorGUILayout.BeginHorizontal();
215 | GUILayout.FlexibleSpace();
216 | GUILayout.Label(label);
217 | GUILayout.FlexibleSpace();
218 | EditorGUILayout.EndHorizontal();
219 |
220 | EditorGUILayout.BeginHorizontal();
221 | GUILayout.FlexibleSpace();
222 | GUILayout.Box(state.background);
223 | GUILayout.FlexibleSpace();
224 | EditorGUILayout.EndHorizontal();
225 | }
226 |
227 | protected void SetSelectedIcon(GUIStyle icon)
228 | {
229 | _selectedIcon = icon;
230 | _drawScale = 1.0f;
231 | }
232 |
233 | protected void DrawIconSelectionGrid(GUIStyle[] icons, float maxIconWidth)
234 | {
235 | float sidePanelWidth = CalculateSidePanelWidth();
236 | int xCount = Mathf.FloorToInt((position.width - sidePanelWidth - kScrollbarWidth) / (maxIconWidth + kSelectionGridPadding));
237 | int selected = GUILayout.SelectionGrid(-1, icons.Select(style => style.normal.background).ToArray(), xCount, GUI.skin.box);
238 |
239 | if (selected > -1)
240 | {
241 | SetSelectedIcon(icons[selected]);
242 | }
243 | }
244 |
245 | protected void DrawCenteredMessage(string msg)
246 | {
247 | EditorGUILayout.BeginHorizontal();
248 | GUILayout.FlexibleSpace();
249 | EditorGUILayout.BeginVertical();
250 | GUILayout.FlexibleSpace();
251 | GUILayout.Label(msg);
252 | GUILayout.FlexibleSpace();
253 | EditorGUILayout.EndVertical();
254 | GUILayout.FlexibleSpace();
255 | EditorGUILayout.EndHorizontal();
256 | }
257 |
258 | protected void DrawHelpIcon()
259 | {
260 | EditorGUILayout.BeginHorizontal();
261 | GUILayout.FlexibleSpace();
262 | if (GUILayout.Button("", _editorSkin.GetStyle("CN EntryInfo")))
263 | {
264 | EditorUtility.DisplayDialog("Editor Icon Viewer", kUsageString, "Ok");
265 | }
266 | EditorGUILayout.EndHorizontal();
267 | }
268 | }
269 |
--------------------------------------------------------------------------------