private void DrawSearch() { EditorGUI.BeginChangeCheck(); using (new GUILayout.HorizontalScope()) { GUI.SetNextControlName(CONTROL_NAME_SEARCH); m_SearchText = GUILayout.TextField(m_SearchText, "ToolbarSeachTextField"); if (GUILayout.Button("", string.IsNullOrEmpty(m_SearchText) ? "ToolbarSeachCancelButtonEmpty" : "ToolbarSeachCancelButton")) { m_SearchText = ""; } } if (!EditorGUI.EndChangeCheck()) { return; } // If searching for nothing, the Root Item will be the Current Item if (string.IsNullOrEmpty(m_SearchText)) { m_CurrentItem = m_RootItem; m_CurrentSelected = -1; } // Else we're searching and the Current Item is the Search Item else { m_CurrentItem = m_SearchItem; m_CurrentSelected = 0; } // Save the Search Text (Unity does this for Add Component so we'll do the same) EditorPrefs.SetString(target.GetType().ToString() + CONTROL_NAME_SEARCH, m_SearchText); }
private bool CanShow(ScriptableObjectCreatorItem item) { if (m_CurrentItem == m_SearchItem) { if ((item.m_Script != null && item.m_Name.ToLower().Contains(m_SearchText.ToLower())) || item == m_CreateItem) { return(true); } } else if (item.m_Parent == m_CurrentItem || item == m_CreateItem) { return(true); } return(false); }
private void DrawDropdown() { DrawSearch(); bool headerFocused = m_CurrentItem.DrawAsHeader(); if (headerFocused) { m_CurrentSelected = -1; } using (GUILayout.ScrollViewScope scope = new GUILayout.ScrollViewScope(m_Scroll)) { if (m_CurrentItem == m_CreateItem) { DrawCreate(); } else { for (int i = 0; i < m_Items.Count; i++) { ScriptableObjectCreatorItem item = m_Items[i]; if (!CanShow(item)) { continue; } bool focused = item.DrawItem(m_CurrentSelected == i); if (focused) { m_CurrentSelected = i; } } } m_Scroll = scope.scrollPosition; } }
private void CreateAllItems() { // Get all classes that inherit ScriptableObject from the Unity Assemblies, we will ignore our own classes that inherit from those List <Type> inheritTypes = AppDomain.CurrentDomain.GetAssemblies() .Select(x => { return(x .GetTypes() .Where(t => !string.IsNullOrEmpty(t.Namespace) && t.Namespace.StartsWith("Unity") && t.IsSubclassOf(typeof(ScriptableObject)) && !t.IsSubclassOf(typeof(UnityEditor.Editor)) )); }) .SelectMany(x => x) .ToList(); // Find all scripts in the project, each script found will be associated with a ScriptableObjectCreatorItem List <MonoScript> scripts = AssetDatabase.FindAssets("t:MonoScript") .Select(x => AssetDatabase.LoadAssetAtPath <MonoScript>(AssetDatabase.GUIDToAssetPath(x))) .Where(t => t.GetClass() != null && !t.GetClass().IsAbstract&& t.GetClass().IsSubclassOf(typeof(ScriptableObject)) && !inheritTypes.Any(x => t.GetClass().IsSubclassOf(x)) ) .ToList(); m_Items.Clear(); // Create the Root Item, it will be the first Item selected m_RootItem = new ScriptableObjectCreatorItem { m_Name = "Scriptable Object" }; m_Items.Add(m_RootItem); foreach (MonoScript script in scripts) { ScriptableObjectCreatorItem lastFolder = null; string[] hierarchy = GetFolderHierarchy(script.GetClass()); if (hierarchy == null) { continue; } for (int i = 0; i < hierarchy.Length; i++) { // Check if it already exists, if it does exist just keep going ScriptableObjectCreatorItem folder = m_Items.FirstOrDefault(x => x.m_Name == hierarchy[i]); if (folder == null) { // Use the Namespace info to create Folders folder = new ScriptableObjectCreatorItem { m_Name = hierarchy[i], m_Parent = i == 0 ? m_RootItem : lastFolder }; folder.m_Clicked = () => { m_CurrentItem = folder; }; folder.m_ClickedAsHeader = () => { m_CurrentItem = folder.m_Parent; }; m_Items.Add(folder); } lastFolder = folder; } // Create a Script Item ScriptableObjectCreatorItem item = new ScriptableObjectCreatorItem { m_Name = script.GetClass().Name, m_Script = script, m_Parent = lastFolder ?? m_RootItem }; item.m_Clicked = () => { AddScript(item.m_Script); }; m_Items.Add(item); } // Sort all items by Name m_Items.Sort((a, b) => a.m_Name.CompareTo(b.m_Name)); // Create Item that will allow the user to create their own scripts. It will always be at the bottom of the list. m_CreateItem = new ScriptableObjectCreatorItem { m_Name = "New Script", m_Parent = m_RootItem }; m_CreateItem.m_Clicked = () => { m_CreateItem.m_Parent = m_CurrentItem; m_CurrentItem = m_CreateItem; m_CreateText = string.IsNullOrEmpty(m_SearchText) ? "NewScriptableObject" : m_SearchText; m_SearchText = string.Empty; }; m_CreateItem.m_ClickedAsHeader = () => { m_CurrentItem = m_CurrentItem.m_Parent; }; m_Items.Add(m_CreateItem); // Create Item that will show that the user is currently searching. It doesn't need to be in the items list. m_SearchItem = new ScriptableObjectCreatorItem { m_Name = "Search", m_Parent = m_RootItem, m_ClickedAsHeader = () => { m_SearchText = string.Empty; m_CurrentItem = m_RootItem; EditorGUI.FocusTextInControl(null); } }; if (string.IsNullOrEmpty(m_SearchText)) { m_CurrentItem = m_RootItem; } else { m_CurrentItem = m_SearchItem; m_CurrentSelected = 0; } }