#if UNITY_EDITOR using UnityEngine; using UnityEditor; using System.Collections; using System.Collections.Generic; namespace MoreMountains.Tools { /// /// As static class that lets you look for missing scripts on any prefab in your project, or for prefabs equipped with a certain type of MonoBehaviour /// public class MMFindPrefabsByMono : EditorWindow { protected Vector2 _scrollView; protected string[] _tabs = new string[] { "Find prefabs with missing components", "Find prefabs by MonoBehaviour" }; protected int _selectedTab; protected int _lastSelectedTab = -1; protected MonoScript _searchedMonoBehaviour; protected MonoScript _lastSearchedMonoBehaviour; protected string _searchedMonoBehaviourName = ""; protected List _resultsList; static GUIStyle _padded; static GUIStyle _horizontalPadded; static int _horizontalPadding = 20; static int _verticalPadding = 20; static RectOffset _padding; static RectOffset _horizontalPaddingOnly; /// /// Menu bound method /// [MenuItem("Tools/More Mountains/Prefab Finder", false, 504)] public static void MenuAction() { OpenWindow(); } /// /// Opens and resizes the window /// public static void OpenWindow() { InitializePaddingAndStyles(); MMFindPrefabsByMono window = (MMFindPrefabsByMono)EditorWindow.GetWindow(typeof(MMFindPrefabsByMono)); window.position = new Rect(400, 400, 800, 600); window.titleContent = new GUIContent("MM Prefabs Finder"); window.Show(); } /// /// Initializes padding variables and GUI styles /// static void InitializePaddingAndStyles() { if (_padding == null) { _padding = new RectOffset(_horizontalPadding, _horizontalPadding, _verticalPadding, _verticalPadding); _horizontalPaddingOnly = new RectOffset(_horizontalPadding, _horizontalPadding, 0, 0); _padded = new GUIStyle { name = "padded", padding = _padding }; _horizontalPadded = new GUIStyle { name = "horizontalPadded", padding = _horizontalPaddingOnly }; } } /// /// Draws tab buttons /// protected virtual void DrawTabs() { GUI.skin.box.padding = _padding; GUILayout.BeginHorizontal("box"); GUILayout.Space(10); _selectedTab = GUILayout.Toolbar(_selectedTab, _tabs); GUILayout.EndHorizontal(); } /// /// Detects changes in tabs selection /// protected virtual void HandleTabsChange() { if (_lastSelectedTab != _selectedTab) { _lastSelectedTab = _selectedTab; _resultsList = new List(); _searchedMonoBehaviourName = _searchedMonoBehaviour == null ? "" : _searchedMonoBehaviour.name; _lastSearchedMonoBehaviour = null; } } /// /// Draws the content of the selected tab /// protected virtual void DrawSelectedTab() { switch (_selectedTab) { case 0: DrawSearchMissing(); break; case 1: DrawSearchByMonoBehaviour(); break; } } /// /// Draws the search by mono form /// protected virtual void DrawSearchByMonoBehaviour() { GUILayout.BeginHorizontal("box"); GUILayout.Space(20); GUILayout.BeginVertical(); GUILayout.Label("Select a MonoBehaviour to search for:"); _searchedMonoBehaviour = (MonoScript)EditorGUILayout.ObjectField(_searchedMonoBehaviour, typeof(MonoScript), false); GUILayout.EndVertical(); GUILayout.Space(10); if (_searchedMonoBehaviour != _lastSearchedMonoBehaviour) { string[] allPrefabsInProject = GetAllPrefabsInProject(); _lastSearchedMonoBehaviour = _searchedMonoBehaviour; _searchedMonoBehaviourName = _searchedMonoBehaviour.name; AssetDatabase.SaveAssets(); string searchedMonoBehaviourPath = AssetDatabase.GetAssetPath(_searchedMonoBehaviour); _resultsList = new List(); foreach (string prefab in allPrefabsInProject) { string[] pathName = new string[] { prefab }; string[] monoDependenciesPaths = AssetDatabase.GetDependencies(pathName, false); foreach (string monoDependencyPath in monoDependenciesPaths) { if (monoDependencyPath == searchedMonoBehaviourPath) { _resultsList.Add(prefab); } } } } GUILayout.EndHorizontal(); } /// /// Draws the search missing form /// protected virtual void DrawSearchMissing() { GUILayout.BeginHorizontal("box"); GUILayout.Space(20); if (GUILayout.Button("Search the project for prefabs with missing scripts")) { string[] allPrefabs = GetAllPrefabsInProject(); _resultsList = new List(); foreach (string prefab in allPrefabs) { UnityEngine.Object asset = AssetDatabase.LoadMainAssetAtPath(prefab); GameObject assetGameObject; try { assetGameObject = (GameObject)asset; Component[] components = assetGameObject.GetComponentsInChildren(true); foreach (Component component in components) { if (component == null) { _resultsList.Add(prefab); } } } catch { Debug.Log("An error occured with prefab " + prefab); } } } GUILayout.EndHorizontal(); } /// /// Draws the result list /// protected virtual void DrawResultsList() { GUILayout.BeginHorizontal(_padded); if (_resultsList != null) { if (_resultsList.Count == 0) { switch (_selectedTab) { case 0: GUILayout.Label("No prefabs have missing components.", EditorStyles.boldLabel); break; case 1: if (!string.IsNullOrEmpty(_searchedMonoBehaviourName)) { GUILayout.Label("No prefabs use component " + _searchedMonoBehaviourName, EditorStyles.boldLabel); } break; } GUILayout.EndHorizontal(); // end padded } else { switch (_selectedTab) { case 0: GUILayout.Label("These prefabs have missing components :", EditorStyles.boldLabel); break; case 1: GUILayout.Label("MonoBehaviour " + _searchedMonoBehaviourName + " was found in these prefabs :", EditorStyles.boldLabel); break; } GUILayout.EndHorizontal(); // end padded GUILayout.BeginHorizontal(); GUI.skin.scrollView.padding = _padding; _scrollView = GUILayout.BeginScrollView(_scrollView); foreach (string s in _resultsList) { GUILayout.BeginHorizontal(_horizontalPadded); GUILayout.Label(s, GUILayout.Width(4 * (position.width - 4 * _horizontalPadding) / 5)); GUI.skin.button.alignment = TextAnchor.MiddleCenter; if (GUILayout.Button("Select prefab", GUILayout.Width((position.width - 4 * _horizontalPadding) / 5 - 20))) { Selection.activeObject = AssetDatabase.LoadMainAssetAtPath(s); } GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); GUILayout.EndHorizontal(); } } } #if UNITY_EDITOR /// /// On GUI we draw our window's contents /// protected virtual void OnGUI() { InitializePaddingAndStyles(); DrawTabs(); HandleTabsChange(); DrawSelectedTab(); DrawResultsList(); } #endif /// /// Gets all prefabs and sorts them alphabetically /// /// public static string[] GetAllPrefabsInProject() { string[] assetPaths = AssetDatabase.GetAllAssetPaths(); List results = new List(); foreach (string assetPath in assetPaths) { if (assetPath.Contains(".prefab")) { results.Add(assetPath); } } results.Sort(); return results.ToArray(); } } } #endif