完成イメージ
アニメーションクリップをパスで検索したいケースがあったので作成しました。
要素を ドラッグ&ドロップして Inspector などの ObjectField にアタッチすることも可能です。
ソースコード
using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; public class AnimationClipSearch : EditorWindow { [System.Serializable] public class AssetData<T> where T : Object { [SerializeField] private int m_Id; [SerializeField] private string m_Path; [SerializeField] private T m_Asset; [SerializeField] private Texture2D m_Icon; public int Id => m_Id; public string Path => m_Path; public T Asset => m_Asset; public Texture2D Icon => m_Icon; public AssetData(int id, string path, T asset) { m_Id = id; m_Path = path; m_Asset = asset; m_Icon = (Texture2D)EditorGUIUtility.ObjectContent(m_Asset, m_Asset.GetType()).image; } } [MenuItem("EditorWindow/AnimationClipSearch")] private static void Init() { var window = GetWindow(typeof(AnimationClipSearch)); window.titleContent = new GUIContent("AnimationClipSearch"); window.Show(); window.minSize = new Vector2(330, 400); } [SerializeField] private List<AssetData<AnimationClip>> m_AssetDataList; [SerializeField] private TreeViewState m_TreeViewState; private AssetPathListView<AnimationClip> m_AssetPathListView; private SearchField m_SearchField; private void OnGUI() { using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar)) { if (m_AssetDataList == null || GUILayout.Button("Reload", EditorStyles.toolbarButton, GUILayout.Width(80))) { m_AssetDataList = AssetDatabase.FindAssets("t:AnimationClip", new[] { "Assets/" }) .Select(guid => AssetDatabase.GUIDToAssetPath(guid)) .Select((path, index) => new AssetData<AnimationClip>(index, path, AssetDatabase.LoadAssetAtPath<AnimationClip>(path))) .ToList(); m_TreeViewState = null; m_AssetPathListView = null; } if (m_TreeViewState == null) { m_TreeViewState = new TreeViewState(); } if (m_AssetPathListView == null) { m_AssetPathListView = new AssetPathListView<AnimationClip>(m_TreeViewState); m_AssetPathListView.Setup(m_AssetDataList); m_SearchField = new SearchField(); m_SearchField.downOrUpArrowKeyPressed += m_AssetPathListView.SetFocusAndEnsureSelectedItem; } GUILayout.Space(100); GUILayout.FlexibleSpace(); m_AssetPathListView.searchString = m_SearchField.OnToolbarGUI(m_AssetPathListView.searchString); } var rect = EditorGUILayout.GetControlRect(false, GUILayout.ExpandHeight(true)); m_AssetPathListView.OnGUI(rect); } public class AssetPathListView<T> : TreeView where T : Object { private List<AssetData<T>> m_AssetDataList; public AssetPathListView(TreeViewState treeViewState) : base(treeViewState) { showAlternatingRowBackgrounds = true; } public void Setup(List<AssetData<T>> baseElements) { m_AssetDataList = baseElements; Reload(); } protected override TreeViewItem BuildRoot() { var root = new TreeViewItem { id = -1, depth = -1, displayName = "Root" }; foreach (var assetData in m_AssetDataList) { var item = new TreeViewItem { id = assetData.Id, displayName = assetData.Path, icon = assetData.Icon }; root.AddChild(item); } SetupDepthsFromParentsAndChildren(root); return root; } protected override bool CanStartDrag(CanStartDragArgs args) { return true; } protected override void SetupDragAndDrop(SetupDragAndDropArgs args) { DragAndDrop.PrepareStartDrag(); var selectedItems = args.draggedItemIDs; var objects = m_AssetDataList .Where(assetData => selectedItems.Contains(assetData.Id)) .Select(assetData => assetData.Asset) .ToArray(); DragAndDrop.objectReferences = objects; DragAndDrop.StartDrag("AnimationClipSearch Drag"); } } }