けいごのなんとか

Unityユーザーとしてのブログ。ギリギリ路線走ってます。

様々なEditorWindow② - SearchableWIndow

様々なEditorWindow①の続きです

SearchableWIndow

このWindowは機能的にはEditorWindowと同じですが、アセットの検索機能を(privateなmethodとして)持ったWindowです。現段階ではReflectionを使わない限り使い道はありません。 どうしても使ってみたい、という方は

「SearchFilter」

「SearchableEditorWindow.CreateSearchFilter」

「SearchableEditorWindow.m_SearchMode」

「HierarchyProperty」

「HierarchyProperty.SetSearchFilter」

「FilteredHierarchy」

「FilteredHierarchy.SearchAllAssets」

「FilteredHierarchy.m_Results」

を逆コンパイルして調べてみると幸せになれるかも。

f:id:anchan828:20130214013449p:plain

こんな感じでUnityの検索機能を自由に使うことができる

俺が実際にプロジェクトでSearchableWindowを使ってる所のソースコード

そのままじゃ動かないので参考程度に。

using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Collections;
using System.Reflection;
using System;
using System.Collections.Generic;

namespace CommandPallet.Plugins
{
    public class SearchAssets : PluginBase
    {
        static Type type = typeof(SearchableEditorWindow);
        static List<FilterResult> results = new List<FilterResult> ();
        static Dictionary<int,AssetData> assets = new Dictionary<int,AssetData> ();
        private string text;
        
        public override void PalletOnGUI ()
        {   
            //SearchFieldGUIを呼び出すだけでSearchFieldが使えたりもする
            //typeof(SearchableEditorWindow).GetMethod ("SearchFieldGUI", (BindingFlags.Instance | BindingFlags.NonPublic)).Invoke (window, new object[0]);
            text = EditorGUILayout.TextField (text);
            object hierarchyProperty = CreateInstance ("UnityEditor.HierarchyProperty", new object{HierarchyType.Assets});
            object filteredHierarchy = CreateInstance ("UnityEditor.FilteredHierarchy", new object{HierarchyType.Assets});     
        
            GetMethod (hierarchyProperty, "SetSearchFilter", new Type{ typeof(SearchFilter)}).Invoke (hierarchyProperty, new object{CreateFilter ()});
            GetMethod (filteredHierarchy, "SearchAllAssets", new Type{hierarchyProperty.GetType ()}).Invoke (filteredHierarchy, new object{hierarchyProperty});
        
            results.Clear ();
        
            foreach (object o in GetNonPublicField<object> ("m_Results", filteredHierarchy)) {
                
                results.Add (new FilterResult {
                    instanceID=GetPublicField<int> ("instanceID", o),
                    name=GetPublicField<string> ("name", o),
                    hasChildren= GetPublicField<bool> ("hasChildren", o),
                    colorCode=GetPublicField<int> ("colorCode", o),
                    isMainRepresentation= GetPublicField<bool> ("isMainRepresentation", o),
                    hasFullPreviewImage=GetPublicField<bool> ("hasFullPreviewImage", o),
                    isFolder= GetPublicField<bool> ("isFolder", o),
                    type=GetPublicField<HierarchyType> ("type", o),
                    guid=GetPublicField<string> ("guid", o),
                    icon=GetPublicField<Texture> ("icon", o)});
            }
        
            results.ForEach (result => {
                AssetData asset = null;
                if (assets.ContainsKey (result.instanceID)) {
                    asset = assets [result.instanceID];
                } else {
                    asset = new AssetData{
                        instanceID=result.instanceID,
                        assetName=result.name,
                        assetPath=AssetDatabase.GetAssetPath (result.instanceID),
                        assetIcon=AssetDatabase.GetCachedIcon (AssetDatabase.GetAssetPath (result.instanceID))};
                }
                Draw (asset);
            
            });
        }
    
        private void Draw (AssetData asset)
        {
            GUILayout.BeginHorizontal ();
            GUILayout.Label (asset.assetIcon);
            GUILayout.BeginVertical ();
            GUILayout.Label (asset.assetName);
            GUILayout.Label (asset.assetPath);
            GUILayout.EndVertical ();
            GUILayout.EndHorizontal ();
            EditorGUI.BeginDisabledGroup (false);
            GUILayout.Label ("-----------------------");
            EditorGUI.EndDisabledGroup ();
        }
    
        private MethodInfo GetMethod (object instance, string methodName, Type types)
        {
            return    instance.GetType ().GetMethod (methodName, (BindingFlags.Instance | BindingFlags.NonPublic), null, types, null);
        }
    
        private object CreateInstance (string typeName, object parameters)
        {
            return Assembly.Load ("UnityEditor.dll").CreateInstance (typeName, false, BindingFlags.Default | BindingFlags.CreateInstance, null, parameters, null, null);
        }
    
        private SearchFilter CreateFilter ()
        {
            return (SearchFilter)type.GetMethod ("CreateFilter", (BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance), null, new Type{typeof(string),typeof(SearchableEditorWindow.SearchMode)}, null).Invoke (palletWindow, new object[]{text,GetNonPublicField<SearchableEditorWindow.SearchMode> ("m_SearchMode", palletWindow)});
        }

        private T GetPublicField<T> (string fieldName, object obj)
        {
            FieldInfo finfo = obj.GetType ().GetField (fieldName, (BindingFlags.Public | BindingFlags.Instance));
            return finfo != null ? (T)finfo.GetValue (obj) : default(T);
        }

        private T GetNonPublicField<T> (string fieldName, object obj)
        {
            return (T)obj.GetType ().GetField (fieldName, (BindingFlags.NonPublic | BindingFlags.Instance)).GetValue (obj);
        }
    }
}