Last active
July 16, 2020 20:44
-
-
Save MPozek/259e654d50c94dea3ebaaf4492a1efcc to your computer and use it in GitHub Desktop.
Quick access window is a unity editor window with support for storing links to assets you often use for... well quick access
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Collections.Generic; | |
| using System.Linq; | |
| using UnityEditor; | |
| using UnityEngine; | |
| using Object = UnityEngine.Object; | |
| public class QuickAccessWindow : EditorWindow | |
| { | |
| [System.Serializable] | |
| public class Category | |
| { | |
| public string Name; | |
| public string Filter; | |
| public bool IsCustom = false; | |
| public List<string> CustomGuidList = new List<string>(); | |
| } | |
| [System.Serializable] | |
| public class State | |
| { | |
| public int SelectedCategory; | |
| public List<Category> Filters = new List<Category>() | |
| { | |
| new Category() | |
| { | |
| Name = "Scenes", | |
| Filter = "t:scene" | |
| } | |
| }; | |
| } | |
| [MenuItem("Assets/Quick access")] | |
| public static void AddToCategory() | |
| { | |
| PickCustomCategoryPopup.CreateAndShow(); | |
| } | |
| [MenuItem("Assets/Quick access", true)] | |
| public static bool ValidateAddToCategory() | |
| { | |
| return Selection.activeObject; | |
| } | |
| [MenuItem("Utility/Quick access")] | |
| public static void Open() | |
| { | |
| var window = (QuickAccessWindow)EditorWindow.GetWindow(typeof(QuickAccessWindow)); | |
| window.titleContent = new GUIContent("Quick Access"); | |
| window.Show(); | |
| } | |
| [MenuItem("Utility/Quick access clear prefs")] | |
| public static void ClearPrefs() | |
| { | |
| EditorPrefs.DeleteKey(EDITOR_PREFS_KEY); | |
| } | |
| private const string EDITOR_PREFS_KEY = "QuickAccessWindow_State"; | |
| private State _windowState; | |
| private List<List<string>> _refreshedAssets; | |
| private Vector2 _scrollPosition; | |
| private bool _isNewCategoryCustom; | |
| private bool _newFilterFoldout; | |
| private string _newCategoryName; | |
| private string _newCategoryFilter; | |
| private void Load() | |
| { | |
| var serializedState = EditorPrefs.GetString(EDITOR_PREFS_KEY, null); | |
| if (string.IsNullOrEmpty(serializedState)) | |
| { | |
| _windowState = new State(); | |
| } | |
| else | |
| { | |
| _windowState = JsonUtility.FromJson<State>(serializedState); | |
| } | |
| } | |
| private void Save() | |
| { | |
| var serializedState = JsonUtility.ToJson(_windowState); | |
| EditorPrefs.SetString(EDITOR_PREFS_KEY, serializedState); | |
| } | |
| private void AddToCustomCategory(Object[] objects, int categoryIndex) | |
| { | |
| var guidList = _windowState.Filters[categoryIndex].CustomGuidList; | |
| for (int i = 0; i < objects.Length; i++) | |
| { | |
| var obj = objects[i]; | |
| var assetPath = AssetDatabase.GetAssetPath(obj); | |
| if (string.IsNullOrEmpty(assetPath) == false) | |
| { | |
| var guid = AssetDatabase.AssetPathToGUID(assetPath); | |
| if (guidList.Contains(guid) == false) | |
| guidList.Add(guid); | |
| } | |
| } | |
| RefreshFilter(categoryIndex); | |
| Repaint(); | |
| } | |
| private void OnEnable() | |
| { | |
| _refreshedAssets = new List<List<string>>(); | |
| Load(); | |
| Refresh(); | |
| } | |
| private void OnDisable() | |
| { | |
| Save(); | |
| } | |
| private void OnGUI() | |
| { | |
| _windowState.SelectedCategory = Mathf.Clamp(_windowState.SelectedCategory, 0, _windowState.Filters.Count - 1); | |
| HandleDragAndDrop(); | |
| DrawNewCategoryFoldout(); | |
| if (_windowState.Filters.Count > 0) | |
| { | |
| EditorGUILayout.Space(); | |
| EditorGUILayout.BeginHorizontal(); | |
| for (int i = 0; i < _windowState.Filters.Count; i++) | |
| { | |
| if (i % 3 == 0) | |
| { | |
| EditorGUILayout.EndHorizontal(); | |
| EditorGUILayout.BeginHorizontal(); | |
| } | |
| GUI.enabled = i != _windowState.SelectedCategory; | |
| if (GUILayout.Button(_windowState.Filters[i].Name)) | |
| { | |
| _windowState.SelectedCategory = i; | |
| RefreshFilter(i); | |
| } | |
| GUI.enabled = true; | |
| } | |
| EditorGUILayout.EndHorizontal(); | |
| if (GUILayout.Button("Remove selected category")) | |
| { | |
| _windowState.Filters.RemoveAt(_windowState.SelectedCategory); | |
| Refresh(); | |
| return; | |
| } | |
| if (GUILayout.Button("Refresh")) | |
| { | |
| RefreshFilter(_windowState.SelectedCategory); | |
| } | |
| EditorGUILayout.Space(); | |
| DrawSelectedCategoryList(); | |
| } | |
| } | |
| private void HandleDragAndDrop() | |
| { | |
| var category = _windowState.Filters[_windowState.SelectedCategory]; | |
| DragAndDrop.AcceptDrag(); | |
| if (category.IsCustom) | |
| { | |
| var ev = Event.current; | |
| if (ev.type == EventType.DragUpdated) | |
| { | |
| DragAndDrop.visualMode = DragAndDropVisualMode.Copy; | |
| } | |
| if (ev.type == EventType.DragPerform) | |
| { | |
| ev.Use(); | |
| AddToCustomCategory(DragAndDrop.objectReferences, _windowState.SelectedCategory); | |
| } | |
| } | |
| } | |
| private void DrawNewCategoryFoldout() | |
| { | |
| _newFilterFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(_newFilterFoldout, "New Category"); | |
| if (_newFilterFoldout) | |
| { | |
| _newCategoryName = EditorGUILayout.TextField("Name", _newCategoryName); | |
| _isNewCategoryCustom = EditorGUILayout.Toggle("Custom category", _isNewCategoryCustom); | |
| if (!_isNewCategoryCustom) | |
| _newCategoryFilter = EditorGUILayout.TextField("Filter", _newCategoryFilter); | |
| if (GUILayout.Button("+", GUILayout.Width(40f))) | |
| { | |
| if ((_isNewCategoryCustom || !string.IsNullOrEmpty(_newCategoryFilter)) && !string.IsNullOrEmpty(_newCategoryName)) | |
| { | |
| _windowState.Filters.Add(new Category | |
| { | |
| Name = _newCategoryName, | |
| IsCustom = _isNewCategoryCustom, | |
| Filter = _newCategoryFilter | |
| }); | |
| Refresh(); | |
| } | |
| } | |
| } | |
| EditorGUILayout.EndFoldoutHeaderGroup(); | |
| } | |
| private void DrawSelectedCategoryList() | |
| { | |
| var cat = _windowState.Filters[_windowState.SelectedCategory]; | |
| var l = _refreshedAssets[_windowState.SelectedCategory]; | |
| var maxWidthLabel = position.width * 0.65f; | |
| _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, EditorStyles.helpBox); | |
| EditorGUILayout.BeginVertical(); | |
| for (int i = 0; i < l.Count; i++) | |
| { | |
| EditorGUILayout.BeginHorizontal(); | |
| var assetName = System.IO.Path.GetFileNameWithoutExtension(l[i]); | |
| var loadedAsset = AssetDatabase.LoadAssetAtPath<Object>(l[i]); | |
| bool selectPressed = GUILayout.Button( | |
| new GUIContent(assetName, AssetPreview.GetMiniThumbnail(loadedAsset)), | |
| EditorStyles.label, | |
| GUILayout.Height(20f), | |
| GUILayout.MaxWidth(maxWidthLabel) | |
| ); | |
| if (selectPressed) | |
| { | |
| SelectAsset(l[i]); | |
| } | |
| if (GUILayout.Button("Open", GUILayout.MaxWidth(position.width - maxWidthLabel))) | |
| { | |
| OpenAsset(l[i]); | |
| } | |
| if (cat.IsCustom && GUILayout.Button("X")) | |
| { | |
| cat.CustomGuidList.RemoveAt(i); | |
| l.RemoveAt(i); | |
| i--; | |
| } | |
| EditorGUILayout.EndHorizontal(); | |
| } | |
| EditorGUILayout.EndVertical(); | |
| EditorGUILayout.EndScrollView(); | |
| } | |
| private void OpenAsset(string path) | |
| { | |
| var loadedAsset = AssetDatabase.LoadAssetAtPath<Object>(path); | |
| AssetDatabase.OpenAsset(loadedAsset); | |
| } | |
| private void SelectAsset(string path) | |
| { | |
| var asset = AssetDatabase.LoadAssetAtPath<Object>(path); | |
| Selection.activeObject = asset; | |
| ProjectWindowUtil.ShowCreatedAsset(asset); | |
| } | |
| private void Refresh() | |
| { | |
| if (_refreshedAssets.Count > _windowState.Filters.Count) | |
| { | |
| _refreshedAssets.RemoveRange(_windowState.Filters.Count, _refreshedAssets.Count - _windowState.Filters.Count); | |
| } | |
| else if (_refreshedAssets.Count < _windowState.Filters.Count) | |
| { | |
| for (int i = _refreshedAssets.Count; i < _windowState.Filters.Count; i++) | |
| { | |
| _refreshedAssets.Add(new List<string>()); | |
| } | |
| } | |
| for (int i = 0; i < _refreshedAssets.Count; i++) | |
| { | |
| _refreshedAssets[i].Clear(); | |
| } | |
| for (int i = 0; i < _windowState.Filters.Count; i++) | |
| { | |
| RefreshFilter(i); | |
| } | |
| } | |
| private void RefreshFilter(int i) | |
| { | |
| var category = _windowState.Filters[i]; | |
| var pathList = _refreshedAssets[i]; | |
| pathList.Clear(); | |
| IList<string> guids; | |
| if (category.IsCustom) | |
| { | |
| guids = category.CustomGuidList; | |
| } | |
| else | |
| { | |
| guids = AssetDatabase.FindAssets(category.Filter); | |
| } | |
| foreach (var guid in guids) | |
| { | |
| var assetPath = AssetDatabase.GUIDToAssetPath(guid); | |
| pathList.Add(assetPath); | |
| } | |
| } | |
| public class PickCustomCategoryPopup : EditorWindow | |
| { | |
| public static void CreateAndShow() | |
| { | |
| PickCustomCategoryPopup window = ScriptableObject.CreateInstance<PickCustomCategoryPopup>(); | |
| window._qaWindow = (QuickAccessWindow) EditorWindow.GetWindow(typeof(QuickAccessWindow)); | |
| int toggleCount = window._qaWindow._windowState.Filters.Select(c => c.IsCustom).Count(); | |
| window.position = new Rect(Screen.width / 2, Screen.height / 2, 250, toggleCount * EditorGUIUtility.singleLineHeight); | |
| window.titleContent = new GUIContent("Choose custom category"); | |
| window.ShowModalUtility(); | |
| } | |
| private QuickAccessWindow _qaWindow; | |
| private int _selectedFilterIndex; | |
| private void OnGUI() | |
| { | |
| EditorGUILayout.LabelField("Choose a custom category"); | |
| for (int i = 0; i < _qaWindow._windowState.Filters.Count; i++) | |
| { | |
| var f = _qaWindow._windowState.Filters[i]; | |
| if (f.IsCustom) | |
| { | |
| bool didSelect = EditorGUILayout.Toggle(f.Name, i == _selectedFilterIndex); | |
| if (didSelect) | |
| { | |
| _selectedFilterIndex = i; | |
| } | |
| } | |
| } | |
| GUILayout.Space(70); | |
| GUI.enabled = _qaWindow._windowState.Filters[_selectedFilterIndex].IsCustom; | |
| if (GUILayout.Button("Add")) | |
| { | |
| AddSelection(); | |
| this.Close(); | |
| } | |
| GUI.enabled = true; | |
| if (GUILayout.Button("Cancel")) | |
| { | |
| this.Close(); | |
| } | |
| } | |
| private void AddSelection() | |
| { | |
| _qaWindow.AddToCustomCategory(Selection.objects, _selectedFilterIndex); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment