Last active
May 30, 2018 02:40
-
-
Save tsubaki/713af9c003a16ea71aaa to your computer and use it in GitHub Desktop.
シーン内のコード群から特定のコードを見つける
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// | |
/// ReferenceExplorer | |
/// | |
/// Copyright (c) 2014 Tatsuhiko Yamamura | |
/// Released under the MIT license | |
// / http://opensource.org/licenses/mit-license.php | |
/// | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Text.RegularExpressions; | |
using UnityEditor; | |
using UnityEngine; | |
using Object = UnityEngine.Object; | |
namespace ReferenceExplorer | |
{ | |
/// <summary> | |
/// シーン全体の情報を格納する | |
/// </summary> | |
public class SceneData | |
{ | |
/// <summary> | |
/// Initializes the <see cref="ReferenceExplorer.SceneData"/> class. | |
/// </summary> | |
static SceneData() | |
{ | |
EditorApplication.update += ()=>{ | |
frameCount ++; | |
}; | |
IsSelected = false; | |
IsRegex = false; | |
} | |
/// <summary> | |
/// 検索範囲を選択中のオブジェクトに限定する | |
/// </summary> | |
public static bool IsSelected{ get; set;} | |
/// <summary> | |
/// 検索に正規表現を使用する | |
/// </summary> | |
public static bool IsRegex{get; set;} | |
/// <summary> | |
/// 検索に使用する全てのMonobehaviour | |
/// </summary> | |
static List<MonoBehaviour> allMonobehaviourList = new List<MonoBehaviour> (); | |
/// <summary> | |
/// シーン内の全オブジェクト | |
/// </summary> | |
static List<GameObject> allGameObjectList = new List<GameObject>(); | |
/// <summary> | |
/// エディタのフレームカウント | |
/// </summary> | |
public static long frameCount { get; private set;} | |
/// <summary> | |
/// 更新フレーム。frameCountと一致しなければ更新しない等の用途 | |
/// </summary> | |
static long monobehaviourLastUpdateFrame = 0, gameobjectLastUpdateFrame = 0; | |
/// <summary> | |
/// シーンにある全てのGameObject。isSelectedにチェックがある場合は選択中のオブジェクトを取得する | |
/// </summary> | |
/// <value>GameObject一覧</value> | |
public static List<GameObject> SelectedObjects { | |
get { | |
if (IsSelected) { | |
return new List<GameObject>(Selection.gameObjects); | |
} else { | |
return AllObjects; | |
} | |
} | |
} | |
/// <summary> | |
/// シーン内の全コンポーネントを取得する。isSelectedにチェックがある場合は選択中のオブジェクトのコンポーネントを取得する | |
/// </summary> | |
/// <value>Monobehaviour一覧</value> | |
public static List<MonoBehaviour> SelectedMonobehaviours | |
{ | |
get{ | |
var monobehaviourList = new List<MonoBehaviour> (); | |
if (IsSelected) { | |
foreach (var obj in Selection.gameObjects) { | |
monobehaviourList.AddRange ( AllComponents.FindAll (item => item.gameObject == obj)); | |
} | |
return monobehaviourList; | |
} else { | |
return AllComponents; | |
} | |
} | |
} | |
/// <summary> | |
/// Gets all objects. | |
/// </summary> | |
/// <value>All objects.</value> | |
public static List<GameObject> AllObjects | |
{ | |
get{ | |
if (frameCount != gameobjectLastUpdateFrame) { | |
UpdateAllObjectList (); | |
gameobjectLastUpdateFrame = frameCount; | |
} | |
return new List<GameObject>(allGameObjectList); | |
} | |
} | |
/// <summary> | |
/// Gets all component. | |
/// </summary> | |
/// <value>All component.</value> | |
public static List<MonoBehaviour> AllComponents | |
{ | |
get{ | |
if (monobehaviourLastUpdateFrame != frameCount) { | |
UpdateAllMonobehaviourList (); | |
monobehaviourLastUpdateFrame = frameCount; | |
} | |
return new List<MonoBehaviour> (allMonobehaviourList); | |
} | |
} | |
/// <summary> | |
///Component一覧を更新する | |
/// </summary> | |
static void UpdateAllMonobehaviourList () | |
{ | |
allMonobehaviourList.Clear (); | |
allMonobehaviourList.AddRange (GetComponentsInList<MonoBehaviour> (AllObjects)); | |
} | |
/// <summary> | |
/// GameObject一覧(deactive含む)を更新する | |
/// </summary> | |
static void UpdateAllObjectList() | |
{ | |
allGameObjectList.Clear (); | |
foreach (GameObject obj in (GameObject[])Resources.FindObjectsOfTypeAll (typeof(GameObject))) { | |
if (obj.hideFlags == HideFlags.NotEditable || obj.hideFlags == HideFlags.HideAndDontSave) | |
continue; | |
if (Application.isEditor) { | |
string sAssetPath = AssetDatabase.GetAssetPath (obj.transform.root.gameObject); | |
if (!string.IsNullOrEmpty (sAssetPath)) | |
continue; | |
} | |
allGameObjectList.Add (obj); | |
} | |
} | |
public static IEnumerable<T> GetComponentsInList<T> (IEnumerable<GameObject> gameObjects ) where T : Component | |
{ | |
var componentList = new List<T> (); | |
foreach (var obj in gameObjects) { | |
var component = obj.GetComponent<T> (); | |
if (component != null) { | |
componentList.Add (component); | |
} | |
} | |
return componentList; | |
} | |
/// <summary> | |
/// searchの内容がInputに含まれることを確認する。isRegexにチェックを入れると正規表現で検索する | |
/// </summary> | |
/// <param name="input">インプット</param> | |
/// <param name="search">検索キーワード</param> | |
public static bool Match(string input, string search) | |
{ | |
if (string.IsNullOrEmpty (input)) | |
return false; | |
if (IsRegex) { | |
var match = Regex.Match (input, search); | |
return match.Success; | |
} else { | |
var result = input.IndexOf (search); | |
return (result != 0 && result != -1); | |
} | |
} | |
/// <summary> | |
/// ユニークなMonobehaviourを継承したコンポーネント一覧を取得する | |
/// </summary> | |
/// <returns>検索するオブジェクト一覧</returns> | |
/// <param name="objects">Monobehaviour一覧</param> | |
public static List<MonoBehaviour> GetUniqueMonobehaviour (IEnumerable<GameObject> objects) | |
{ | |
var uniqueMonobehaviourList = new List<MonoBehaviour> (); | |
foreach (var obj in objects) { | |
foreach (var monobehaviour in obj.GetComponents<MonoBehaviour>()) { | |
if (!uniqueMonobehaviourList.Exists (item => item.GetType () == monobehaviour.GetType ())) { | |
uniqueMonobehaviourList.Add (monobehaviour); | |
} | |
} | |
} | |
return uniqueMonobehaviourList; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// | |
/// ReferenceExplorer | |
/// | |
/// Copyright (c) 2014 Tatsuhiko Yamamura | |
/// Released under the MIT license | |
// / http://opensource.org/licenses/mit-license.php | |
/// | |
#pragma warning disable 0618 | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Text.RegularExpressions; | |
using UnityEditor; | |
using UnityEngine; | |
using Object = UnityEngine.Object; | |
namespace ReferenceExplorer | |
{ | |
/// <summary> | |
/// シーン内のクラス群を特定キーワードで検索するエディタウィンドウ | |
/// </summary> | |
public class SearchCodeInSceneWindow : EditorWindow | |
{ | |
/// <summary> | |
/// 検索する文字列 | |
/// </summary> | |
protected string searchText = string.Empty; | |
/// <summary> | |
/// 検索キーワードにヒットしたMonobehaviour一覧 | |
/// </summary> | |
List<CodeObject> ExistCodeObjectList = new List<CodeObject> (); | |
/// <summary> | |
/// 選択中のMonobehaviour | |
/// </summary> | |
int current = 0; | |
/// <summary> | |
/// ウィンドウを開く | |
/// </summary> | |
[MenuItem ("Window/ReferenceExplorer/SearchCode")] | |
static void Open () | |
{ | |
SearchCodeInSceneWindow.GetWindow<SearchCodeInSceneWindow> ("code search"); | |
} | |
/// <summary> | |
/// ContainCodeObjectを更新する | |
/// </summary> | |
void UpdateContainCodeObjectList () | |
{ | |
ExistCodeObjectList.Clear (); | |
var uniqueMonobehaviour = SceneData.GetUniqueMonobehaviour (SceneData.SelectedObjects); | |
foreach (var monobehaviour in uniqueMonobehaviour) { | |
var monoscript = MonoScript.FromMonoBehaviour (monobehaviour); | |
bool isMatch = false; | |
List<string> lines = new List<string> (); | |
foreach (var line in monoscript.text.Split( new string[]{ Environment.NewLine }, StringSplitOptions.None )) { | |
if (!SceneData.Match (line, searchText)) | |
continue; | |
lines.Add (line); | |
isMatch = true; | |
} | |
if (isMatch) { | |
ExistCodeObjectList.Add (new CodeObject () { | |
componentType = monobehaviour.GetType (), | |
monoscript = monoscript, | |
lines = lines.ToArray(), | |
}); | |
} | |
} | |
} | |
#region GUI | |
/// <summary> | |
/// スクロールビューの座標 | |
/// </summary> | |
Vector2 componentScroll, textScroll; | |
/// <summary> | |
/// サーチバーの表示を行う。OnGUIで使用する想定 | |
/// </summary> | |
void SearchBar () | |
{ | |
EditorGUILayout.BeginHorizontal (); | |
EditorGUI.BeginChangeCheck (); | |
SceneData.IsSelected = GUILayout.Toggle (SceneData.IsSelected, "Selection", EditorStyles.toolbarButton , GUILayout.Width (60)); | |
SceneData.IsRegex = GUILayout.Toggle (SceneData.IsRegex, "Regex", EditorStyles.toolbarButton , GUILayout.Width (40)); | |
searchText = GUILayout.TextField (searchText, GUILayout.Width( Screen.width - 110)); | |
if (EditorGUI.EndChangeCheck ()) { | |
UpdateContainCodeObjectList (); | |
} | |
EditorGUILayout.EndHorizontal (); | |
} | |
/// <summary> | |
/// コンポーネントの一覧を表示する。OnGUIで使用する想定 | |
/// </summary> | |
void ContentView () | |
{ | |
var containCodeObjects = ExistCodeObjectList.ToArray (); | |
componentScroll = EditorGUILayout.BeginScrollView (componentScroll); | |
for (int i = 0; i < containCodeObjects.Length; i++) { | |
var containCodeObject = containCodeObjects[i]; | |
EditorGUILayout.BeginHorizontal (); | |
EditorGUI.BeginChangeCheck (); | |
EditorGUILayout.Toggle (i == current, EditorStyles.radioButton, GUILayout.Width(14) ); | |
if (EditorGUI.EndChangeCheck ()) { | |
current = i; | |
} | |
EditorGUILayout.ObjectField (containCodeObject.monoscript, typeof(MonoScript)); | |
EditorGUILayout.EndHorizontal (); | |
if (i == current) { | |
GUILayout.Space (4); | |
var components = SceneData.SelectedMonobehaviours.FindAll (item => item.GetType () == containCodeObject.componentType); | |
EditorGUI.indentLevel = 2; | |
foreach (var obj in components) { | |
EditorGUILayout.ObjectField (obj.gameObject, typeof(GameObject)); | |
} | |
GUILayout.Space (4); | |
EditorGUI.indentLevel = 0; | |
} | |
} | |
EditorGUILayout.EndScrollView (); | |
} | |
/// <summary> | |
/// 選択中のコンポーネントの検索結果を表示する。OnGUIで使用する想定 | |
/// </summary> | |
void CodeLineView() | |
{ | |
if (ExistCodeObjectList.Count <= current) | |
return; | |
var currentContainCodeObject = ExistCodeObjectList [current]; | |
var textHeight = (currentContainCodeObject.lines.Length + 1) * 18; | |
var windowHeight = Mathf.Min (100, textHeight); | |
GUILayout.BeginArea( new Rect(0, Screen.height - 120, Screen.width, 100)); | |
textScroll = EditorGUILayout.BeginScrollView (textScroll); | |
EditorGUILayout.BeginVertical ("box", GUILayout.Height(windowHeight)); | |
foreach (var line in currentContainCodeObject.lines) { | |
EditorGUILayout.BeginHorizontal ("box"); | |
EditorGUILayout.LabelField (line); | |
EditorGUILayout.EndHorizontal (); | |
} | |
EditorGUILayout.EndVertical (); | |
EditorGUILayout.EndScrollView (); | |
GUILayout.EndArea (); | |
} | |
#endregion | |
#region EditorWindowCallback | |
/// <summary> | |
/// Unity Callback OnGUI | |
/// </summary> | |
void OnGUI () | |
{ | |
SearchBar (); | |
ContentView (); | |
CodeLineView (); | |
} | |
/// <summary> | |
/// Unity Callback OnGUI | |
/// </summary> | |
void OnSelectionChange () | |
{ | |
if (!SceneData.IsSelected) | |
return; | |
UpdateContainCodeObjectList (); | |
Repaint (); | |
} | |
#endregion | |
/// <summary> | |
/// 検索して見つかったコンポーネントを格納する | |
/// </summary> | |
class CodeObject | |
{ | |
/// <summary> Monobehaviourのタイプ </summary> | |
public Type componentType; | |
/// <summary> Monobehaviourのコード </summary> | |
public MonoScript monoscript; | |
/// <summary> 一致したライン </summary> | |
public string[] lines; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
機能
シーン内のコードを検索し、合致するコード及びアタッチされているオブジェクトを一覧表示します。
使用方法
Window > ReferenceExplorer > SearchCodeで開きます。
SelectionがONの時は、選択中のオブジェクト群から検索します。
RegexがONの時は、検索キーワードに正規表現を使用します。