123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- using UnityEngine;
- using System.Collections.Generic;
- using System.Reflection;
- #if UNITY_EDITOR
- using UnityEditor;
- using System.Linq;
- #endif
- /// <summary>
- /// ラベル名からアセットを検索し、アタッチします
- /// </summary>
- public class LabelSearchAttribute : PropertyAttribute
- {
- /// <summary>
- /// <para> falseで検索が完了していなくても、とりあえずインスペクターを表示するようになる</para>
- /// <para>trueだと検索が終わるまでインスペクターが表示されない</para>
- /// </summary>
- public bool init = false;
- /// <summary>
- /// <para>インスペクターが表示された初回のみ検索が行われる</para>
- /// <para>falseだと検索が行われず描画されない</para>
- /// </summary>
- public bool search = true;
- /// <summary>
- /// <para>検索するラベル名</para>
- /// </summary>
- public string labelName;
- /// <summary>
- /// <para>インスペクターにラベル名を表示するかどうか</para>
- /// <para>trueで表示する</para>
- /// </summary>
- public bool canPrintLabelName = false;
- /// <summary>
- /// <para>配列の時に使用する</para>
- /// <para>インスペクターを表示した時、最初から配列のフィールドを描画したい場合trueにする</para>
- /// </summary>
- public bool foldout = false;
- /// <summary>
- /// <para>検索順が降順か昇順か</para>
- /// </summary>
- public Direction direction = Direction.ASC;
- /// <summary>
- /// <para>取得する最大数</para>
- /// <para>負や0を指定しても2147483647になる
- /// </summary>
- public int limit = 2147483647;
- /// <summary>
- /// <para>検索の高速化のためTypeをキャッシュしておく</para>
- /// </summary>
- public static Dictionary<string, System.Type> assetTypes = new Dictionary<string, System.Type>();
- public LabelSearchAttribute(string labelName)
- {
- this.labelName = labelName;
- }
- public LabelSearchAttribute(string labelName, int limit)
- {
- if (Mathf.Sign(limit) == 1)
- {
- this.limit = limit;
- }
- this.labelName = labelName;
- }
- public LabelSearchAttribute(string labelName, Direction direction)
- {
- this.labelName = labelName;
- this.direction = direction;
- }
- public LabelSearchAttribute(string labelName, int limit, Direction direction)
- {
- this.labelName = labelName;
- if (Mathf.Sign(limit) == 1)
- {
- this.limit = limit;
- }
- this.direction = direction;
- }
- public enum Direction
- {
- ASC,
- DESC
- }
- }
- #if UNITY_EDITOR
- /// <summary>
- /// Label drawer.
- /// </summary>
- [CustomPropertyDrawer(typeof(LabelSearchAttribute))]
- public class LabelSearchDrawer : PropertyDrawer
- {
- /// <summary>
- /// GUIの高さ
- /// </summary>
- private const int CONTENT_HEIGHT = 16;
- public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
- {
- if (labelSearchAttribute.init == false)
- {
- labelSearchAttribute.init = true;
- return;
- }
- //デバッグ時使用 ( 検索時間 )
- //double start = EditorApplication.timeSinceStartup;
- if (labelSearchAttribute.canPrintLabelName)
- {
- label.text += string.Format(" ( Label = {0} )", labelSearchAttribute.labelName);
- }
- if (property.isArray)
- {
- EditorGUI.indentLevel = 0;
- labelSearchAttribute.foldout = EditorGUI.Foldout(position, labelSearchAttribute.foldout, label);
- if (labelSearchAttribute.search)
- {
- DrawArrayProperty(position, property, label);
- //デバッグ時使用 ( 検索時間 )
- //Debug.Log (((float)EditorApplication.timeSinceStartup - start) + "ms");
- }
- else
- {
- DrawCachedArrayProperty(position, property, label);
- }
- }
- else
- {
- if (labelSearchAttribute.search)
- {
- DrawSingleProperty(position, property, label);
- ////デバッグ時使用 ( 検索時間 )
- //Debug.Log (((float)EditorApplication.timeSinceStartup - start) + "ms");
- }
- else
- {
- DrawCachedSingleProperty(position, property, label);
- }
- }
- labelSearchAttribute.search = false;
- }
- public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
- {
- float height = 0;
- if (property.isArray && labelSearchAttribute.foldout)
- {
- height = (property.arraySize + 1) * CONTENT_HEIGHT;
- }
- return base.GetPropertyHeight(property, label) + height;
- }
- LabelSearchAttribute labelSearchAttribute
- {
- get { return (LabelSearchAttribute) attribute; }
- }
- /// <summary>
- /// <para>キャッシュされたプロパティを使用して描画する</para>
- /// </summary>
- /// <param name='position'>
- /// Position.
- /// </param>
- /// <param name='property'>
- /// Property.
- /// </param>
- /// <param name='label'>
- /// Label.
- /// </param>
- void DrawCachedSingleProperty(Rect position, SerializedProperty property, GUIContent label)
- {
- property.objectReferenceValue = EditorGUI.ObjectField(position, label, property.objectReferenceValue,
- GetType(property), false);
- }
- /// <summary>
- /// <para>キャッシュされた配列を使用して描画する</para>
- /// <para>負荷削減のため一定間隔で検索を行うようにした</para>
- /// </summary>
- /// <param name='position'>
- /// Position.
- /// </param>
- /// <param name='property'>
- /// Property.
- /// </param>
- /// <param name='label'>
- /// Label.
- /// </param>
- void DrawCachedArrayProperty(Rect position, SerializedProperty property, GUIContent label)
- {
- if (labelSearchAttribute.foldout)
- {
- position.y += CONTENT_HEIGHT;
- EditorGUI.indentLevel = 2;
- System.Type type = GetType(property.GetArrayElementAtIndex(0));
- EditorGUI.LabelField(position, "Size", property.arraySize.ToString());
- for (int i = 0; i < property.arraySize; i++)
- {
- position.y += CONTENT_HEIGHT;
- position.height = CONTENT_HEIGHT;
- GUIContent content =
- EditorGUIUtility.ObjectContent(property.GetArrayElementAtIndex(i).objectReferenceValue, type);
- content.image = AssetPreview.GetMiniTypeThumbnail(type);
- // 要素1つ1つにフォーカスが当たらないためObjectFieldである必要はないのでLabelFieldで描画
- // PingObjectの機能使いたいけど...
- // EditorGUI.ObjectField (position, new GUIContent (ObjectNames.NicifyVariableName ("Element" + i)), property.GetArrayElementAtIndex (i).objectReferenceValue, type, false);
- EditorGUI.LabelField(position, new GUIContent(ObjectNames.NicifyVariableName("Element" + i)), content);
- }
- }
- }
- /// <summary>
- /// <para>アセットを検索して描画する</para>
- /// </summary>
- /// <param name='position'>
- /// Position.
- /// </param>
- /// <param name='property'>
- /// Property.
- /// </param>
- /// <param name='label'>
- /// Label.
- /// </param>
- void DrawSingleProperty(Rect position, SerializedProperty property, GUIContent label)
- {
- System.Type type = GetType(property);
- property.objectReferenceValue = null;
- foreach (string path in GetAllAssetPath())
- {
- System.Type assetType = null;
- Object asset = null;
- if (LabelSearchAttribute.assetTypes.TryGetValue(path, out assetType) == false)
- {
- asset = AssetDatabase.LoadMainAssetAtPath(path);
- if (asset == null)
- {
- continue;
- }
- assetType = asset.GetType();
- LabelSearchAttribute.assetTypes.Add(path, assetType);
- }
- if (type != assetType)
- {
- continue;
- }
- if (asset == null)
- {
- asset = AssetDatabase.LoadMainAssetAtPath(path);
- if (asset == null)
- {
- continue;
- }
- }
- if (
- string.IsNullOrEmpty(
- AssetDatabase.GetLabels(asset).FirstOrDefault(l => l.Equals(labelSearchAttribute.labelName))) ==
- false)
- {
- property.objectReferenceValue = asset;
- break;
- }
- }
- property.objectReferenceValue = EditorGUI.ObjectField(position, label, property.objectReferenceValue, type,
- false);
- }
- /// <summary>
- /// <para>該当するアセットを複数検索して描画する</para>
- /// </summary>
- /// <param name='position'>
- /// Position.
- /// </param>
- /// <param name='property'>
- /// Property.
- /// </param>
- /// <param name='label'>
- /// Label.
- /// </param>
- void DrawArrayProperty(Rect position, SerializedProperty property, GUIContent label)
- {
- int size = 0;
- EditorGUI.indentLevel = 2;
- if (labelSearchAttribute.foldout)
- {
- position.y += CONTENT_HEIGHT;
- EditorGUI.LabelField(position, "Size", property.arraySize.ToString());
- }
- property.arraySize = 0;
- property.InsertArrayElementAtIndex(0);
- System.Type type = GetType(property.GetArrayElementAtIndex(0));
- foreach (string path in GetAllAssetPath())
- {
- System.Type assetType = null;
- Object asset = null;
- if (LabelSearchAttribute.assetTypes.TryGetValue(path, out assetType) == false)
- {
- asset = AssetDatabase.LoadMainAssetAtPath(path);
- assetType = asset.GetType();
- LabelSearchAttribute.assetTypes.Add(path, assetType);
- }
- if (type != assetType)
- {
- continue;
- }
- if (asset == null)
- {
- asset = AssetDatabase.LoadMainAssetAtPath(path);
- }
- if (
- string.IsNullOrEmpty(
- AssetDatabase.GetLabels(asset).FirstOrDefault(l => l.Equals(labelSearchAttribute.labelName))) ==
- false)
- {
- property.arraySize = ++size;
- property.GetArrayElementAtIndex(size - 1).objectReferenceValue = asset;
- if (labelSearchAttribute.foldout)
- {
- position.y += CONTENT_HEIGHT;
- position.height = CONTENT_HEIGHT;
- GUIContent content =
- EditorGUIUtility.ObjectContent(property.GetArrayElementAtIndex(size - 1).objectReferenceValue,
- type);
- content.image = AssetPreview.GetMiniTypeThumbnail(type);
- // 要素1つ1つにフォーカスが当たらないためObjectFieldである必要はないのでLabelFieldで描画
- // PingObjectの機能使いたいけど...
- // EditorGUI.ObjectField (position, new GUIContent (ObjectNames.NicifyVariableName ("Element" + i)), property.GetArrayElementAtIndex (i).objectReferenceValue, type, false);
- EditorGUI.LabelField(position,
- new GUIContent(ObjectNames.NicifyVariableName("Element" + (size - 1))), content);
- }
- }
- if (labelSearchAttribute.limit <= property.arraySize)
- {
- break;
- }
- }
- }
- /// <summary>
- /// 全てのアセットのパスを取得
- /// </summary>
- /// <returns>
- /// The all asset path.
- /// </returns>
- string[] GetAllAssetPath()
- {
- string[] allAssetPath = AssetDatabase.GetAllAssetPaths();
- System.Array.Sort(allAssetPath);
- if (labelSearchAttribute.direction.Equals(LabelSearchAttribute.Direction.DESC))
- {
- System.Array.Reverse(allAssetPath);
- }
- return allAssetPath;
- }
- /// <summary>
- /// プロパティからTypeを取得
- /// </summary>
- /// <returns>
- /// The type.
- /// </returns>
- /// <param name='property'>
- /// Property.
- /// </param>
- System.Type GetType(SerializedProperty property)
- {
- return
- Assembly.Load("UnityEngine.dll")
- .GetType("UnityEngine." + property.type.Replace("PPtr<$", "").Replace(">", ""));
- }
- }
- #endif
|