#154 adds a searchable menu for faster atom creation. (#186)

* #154 adds a searchable menu for faster atom creation. default hotkey is ALT+1

* better name representation

* added missing meta file

* #154 - Minor nitpick fixes

Co-authored-by: Adam Ramberg <adam@mambojambostudios.com>
This commit is contained in:
Oliver Biwer 2020-08-23 12:55:06 +02:00 committed by GitHub
parent 39e6867d28
commit d6688c2b59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 140 additions and 0 deletions

View File

@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace UnityAtoms.Editor
{
public static class AtomsSearchableAssetCreationMenu
{
class StringTree<T>
{
public Dictionary<string, StringTree<T>> SubTrees { get; } = new Dictionary<string, StringTree<T>>();
public T Value { get; private set; }
public void Insert(string path, T value, int idx = 0)
{
Internal_Insert(path.Split('/'), idx, value);
}
private void Internal_Insert(string[] path, int idx, T value)
{
if (idx >= path.Length)
{
Value = value;
return;
}
if (!SubTrees.ContainsKey(path[idx])) SubTrees.Add(path[idx], new StringTree<T>());
SubTrees[path[idx]].Internal_Insert(path, idx + 1, value);
}
}
[MenuItem(itemName: "Assets/Create/Atoms Search &1", isValidateFunction: false, priority: -1)] // Adds to the project window's create menu
public static void AtomsSearchMenu()
{
StringTree<Type> typeTree = new StringTree<Type>();
foreach (var type in TypeCache.GetTypesWithAttribute<CreateAssetMenuAttribute>()
.Where(t => t.Namespace != null && t.Namespace.Contains("Atom")))
{
var name = type.GetCustomAttribute<CreateAssetMenuAttribute>().menuName;
var i = name.LastIndexOf('/');
name = (i == -1) ? name : name.Substring(0, i + 1) + type.Name;
typeTree.Insert(name, type, 1);
}
var projectBrowserType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.ProjectBrowser");
var projectBrowser = EditorWindow.GetWindow(projectBrowserType);
Vector2 xy = new Vector2(projectBrowser.position.x + 10, projectBrowser.position.y + 60);
var dropdown = new SearchTypeDropdown(new AdvancedDropdownState(), typeTree,
(s) =>
{
EditorApplication.ExecuteMenuItem("Assets/Create/" +
s.GetCustomAttribute<CreateAssetMenuAttribute>().menuName);
})
{
MinimumSize = new Vector2(projectBrowser.position.width - 20, projectBrowser.position.height - 80)
};
var rect = new Rect(xy.x, xy.y, projectBrowser.position.width - 20, projectBrowser.position.height);
dropdown.Show(new Rect()); // don't use this to position the
var window = typeof(SearchTypeDropdown).GetField("m_WindowInstance", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(dropdown) as EditorWindow;
window.position = rect;
}
private class SearchTypeDropdown : AdvancedDropdown
{
private readonly StringTree<Type> _list;
private readonly Action<Type> _func;
private readonly List<Type> _lookup = new List<Type>();
public Vector2 MinimumSize
{
get => minimumSize;
set => minimumSize = value;
}
public SearchTypeDropdown(AdvancedDropdownState state, StringTree<Type> list, Action<Type> func) : base(state)
{
_list = list;
_func = func;
}
protected override void ItemSelected(AdvancedDropdownItem item)
{
base.ItemSelected(item);
_func?.Invoke(_lookup[item.id]);
}
private void Render(StringTree<Type> tree, string key, AdvancedDropdownItem parentGroup)
{
if (tree.Value != null)
{
_lookup.Add(tree.Value);
parentGroup.AddChild(new AdvancedDropdownItem(key) { id = _lookup.Count - 1 });
}
else
{
var self = new AdvancedDropdownItem(key);
foreach (var subtree in tree.SubTrees)
{
Render(subtree.Value, subtree.Key, self);
}
parentGroup.AddChild(self);
}
}
protected override AdvancedDropdownItem BuildRoot()
{
var root = new AdvancedDropdownItem("UnityAtoms");
foreach (var subtree in _list.SubTrees)
{
Render(subtree.Value, subtree.Key, root);
}
return root;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7e409436a3e3fb84786643aafeabde5e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: