chore: initial commit
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// A maintenance class that removes all empty directories from a project via a menu item
|
||||
/// </summary>
|
||||
public class MMCleanEmptyFolders : MonoBehaviour
|
||||
{
|
||||
static string _consoleLog = "";
|
||||
static List<DirectoryInfo> _listOfEmptyDirectories = new List<DirectoryInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// Parses the project for empty directories and removes them, as well as their associated meta file
|
||||
/// </summary>
|
||||
[MenuItem("Tools/More Mountains/Cleanup empty folders", false, 504)]
|
||||
protected static void CleanupMissingScripts()
|
||||
{
|
||||
_listOfEmptyDirectories.Clear();
|
||||
var assetsDir = Application.dataPath + Path.DirectorySeparatorChar;
|
||||
GetEmptyDirectories(new DirectoryInfo(assetsDir), _listOfEmptyDirectories);
|
||||
|
||||
if (0 < _listOfEmptyDirectories.Count)
|
||||
{
|
||||
_consoleLog = "[MMCleanEmptyFolders] Removed "+ _listOfEmptyDirectories.Count + " empty directories:\n";
|
||||
foreach (var d in _listOfEmptyDirectories)
|
||||
{
|
||||
_consoleLog += "· "+ d.FullName.Replace(assetsDir, "") + "\n";
|
||||
FileUtil.DeleteFileOrDirectory(d.FullName);
|
||||
FileUtil.DeleteFileOrDirectory(d.FullName+".meta");
|
||||
}
|
||||
|
||||
MMDebug.DebugLogInfo(_consoleLog);
|
||||
_consoleLog = "";
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a directory is empty and updates a list of empty directories
|
||||
/// </summary>
|
||||
/// <param name="directory"></param>
|
||||
/// <param name="listOfEmptyDirectories"></param>
|
||||
/// <returns></returns>
|
||||
static bool GetEmptyDirectories(DirectoryInfo directory, List<DirectoryInfo> listOfEmptyDirectories)
|
||||
{
|
||||
bool directoryIsEmpty = true;
|
||||
directoryIsEmpty = (directory.GetDirectories().Count(x => !GetEmptyDirectories(x, listOfEmptyDirectories)) == 0) && (directory.GetFiles("*.*").All(x => x.Extension == ".meta"));
|
||||
|
||||
if (directoryIsEmpty)
|
||||
{
|
||||
listOfEmptyDirectories.Add(directory);
|
||||
}
|
||||
|
||||
return directoryIsEmpty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eef8a54b228d3d148b605064c04e66a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// This class lets you clean all missing scripts on a selection of gameobjects
|
||||
/// </summary>
|
||||
public class MMCleanupMissingScripts : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Processes the cleaning of gameobjects for all missing scripts on them
|
||||
/// </summary>
|
||||
[MenuItem("Tools/More Mountains/Cleanup missing scripts on selected GameObjects", false, 504)]
|
||||
protected static void CleanupMissingScripts()
|
||||
{
|
||||
Object[] collectedDeepHierarchy = EditorUtility.CollectDeepHierarchy(Selection.gameObjects);
|
||||
int removedComponentsCounter = 0;
|
||||
int gameobjectsAffectedCounter = 0;
|
||||
foreach (Object targetObject in collectedDeepHierarchy)
|
||||
{
|
||||
if (targetObject is GameObject gameObject)
|
||||
{
|
||||
int amountOfMissingScripts = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(gameObject);
|
||||
if (amountOfMissingScripts > 0)
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(gameObject, "Removing missing scripts");
|
||||
GameObjectUtility.RemoveMonoBehavioursWithMissingScript(gameObject);
|
||||
removedComponentsCounter += amountOfMissingScripts;
|
||||
gameobjectsAffectedCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
MMDebug.DebugLogInfo("[MMCleanupMissingScripts] Removed " + removedComponentsCounter + " missing scripts from " + gameobjectsAffectedCounter + " GameObjects");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05ed97bf9ce684b47ab50ba3bf13134e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,72 @@
|
||||
// Original FindMissingScriptsRecursively script by SimTex and Clement
|
||||
// http://wiki.unity3d.com/index.php?title=FindMissingScripts
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
public class MMFindMissingScriptsRecursively : EditorWindow
|
||||
{
|
||||
static int go_count = 0, components_count = 0, missing_count = 0;
|
||||
|
||||
[MenuItem("Tools/More Mountains/Find missing scripts recursively", false, 505)]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
EditorWindow.GetWindow(typeof(MMFindMissingScriptsRecursively));
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public void OnGUI()
|
||||
{
|
||||
if (GUILayout.Button("Find Missing Scripts in selected GameObjects"))
|
||||
{
|
||||
FindInSelected();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private static void FindInSelected()
|
||||
{
|
||||
GameObject[] go = Selection.gameObjects;
|
||||
go_count = 0;
|
||||
components_count = 0;
|
||||
missing_count = 0;
|
||||
foreach (GameObject g in go)
|
||||
{
|
||||
FindInGO(g);
|
||||
}
|
||||
Debug.Log(string.Format("Searched {0} GameObjects, {1} components, found {2} missing", go_count, components_count, missing_count));
|
||||
}
|
||||
|
||||
private static void FindInGO(GameObject g)
|
||||
{
|
||||
go_count++;
|
||||
Component[] components = g.GetComponents<Component>();
|
||||
for (int i = 0; i < components.Length; i++)
|
||||
{
|
||||
components_count++;
|
||||
if (components[i] == null)
|
||||
{
|
||||
missing_count++;
|
||||
string s = g.name;
|
||||
Transform t = g.transform;
|
||||
while (t.parent != null)
|
||||
{
|
||||
s = t.parent.name +"/"+s;
|
||||
t = t.parent;
|
||||
}
|
||||
Debug.Log (s + " has an empty script attached in position: " + i, g);
|
||||
}
|
||||
}
|
||||
// Now recurse through each child GO (if there are any):
|
||||
foreach (Transform childT in g.transform)
|
||||
{
|
||||
FindInGO(childT.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c87833dd08a8c842823386dde78cb2a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,283 @@
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
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<string> _resultsList;
|
||||
|
||||
static GUIStyle _padded;
|
||||
static GUIStyle _horizontalPadded;
|
||||
static int _horizontalPadding = 20;
|
||||
static int _verticalPadding = 20;
|
||||
static RectOffset _padding;
|
||||
static RectOffset _horizontalPaddingOnly;
|
||||
|
||||
/// <summary>
|
||||
/// Menu bound method
|
||||
/// </summary>
|
||||
[MenuItem("Tools/More Mountains/Prefab Finder", false, 504)]
|
||||
public static void MenuAction()
|
||||
{
|
||||
OpenWindow();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens and resizes the window
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes padding variables and GUI styles
|
||||
/// </summary>
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws tab buttons
|
||||
/// </summary>
|
||||
protected virtual void DrawTabs()
|
||||
{
|
||||
GUI.skin.box.padding = _padding;
|
||||
GUILayout.BeginHorizontal("box");
|
||||
GUILayout.Space(10);
|
||||
_selectedTab = GUILayout.Toolbar(_selectedTab, _tabs);
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detects changes in tabs selection
|
||||
/// </summary>
|
||||
protected virtual void HandleTabsChange()
|
||||
{
|
||||
if (_lastSelectedTab != _selectedTab)
|
||||
{
|
||||
_lastSelectedTab = _selectedTab;
|
||||
_resultsList = new List<string>();
|
||||
_searchedMonoBehaviourName = _searchedMonoBehaviour == null ? "" : _searchedMonoBehaviour.name;
|
||||
_lastSearchedMonoBehaviour = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the content of the selected tab
|
||||
/// </summary>
|
||||
protected virtual void DrawSelectedTab()
|
||||
{
|
||||
switch (_selectedTab)
|
||||
{
|
||||
case 0:
|
||||
DrawSearchMissing();
|
||||
break;
|
||||
case 1:
|
||||
DrawSearchByMonoBehaviour();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the search by mono form
|
||||
/// </summary>
|
||||
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<string>();
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the search missing form
|
||||
/// </summary>
|
||||
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<string>();
|
||||
foreach (string prefab in allPrefabs)
|
||||
{
|
||||
UnityEngine.Object asset = AssetDatabase.LoadMainAssetAtPath(prefab);
|
||||
GameObject assetGameObject;
|
||||
try
|
||||
{
|
||||
assetGameObject = (GameObject)asset;
|
||||
Component[] components = assetGameObject.GetComponentsInChildren<Component>(true);
|
||||
foreach (Component component in components)
|
||||
{
|
||||
if (component == null)
|
||||
{
|
||||
_resultsList.Add(prefab);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
MMDebug.DebugLogInfo("An error occured with prefab " + prefab);
|
||||
}
|
||||
}
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the result list
|
||||
/// </summary>
|
||||
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
|
||||
/// <summary>
|
||||
/// On GUI we draw our window's contents
|
||||
/// </summary>
|
||||
protected virtual void OnGUI()
|
||||
{
|
||||
InitializePaddingAndStyles();
|
||||
DrawTabs();
|
||||
HandleTabsChange();
|
||||
DrawSelectedTab();
|
||||
DrawResultsList();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets all prefabs and sorts them alphabetically
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string[] GetAllPrefabsInProject()
|
||||
{
|
||||
string[] assetPaths = AssetDatabase.GetAllAssetPaths();
|
||||
List<string> results = new List<string>();
|
||||
foreach (string assetPath in assetPaths)
|
||||
{
|
||||
if (assetPath.Contains(".prefab"))
|
||||
{
|
||||
results.Add(assetPath);
|
||||
}
|
||||
}
|
||||
results.Sort();
|
||||
return results.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6f3cc53c6ac3754bbf1b45956f64a21
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// A class used to add a menu item and a shortcut to group objects together under a parent game object
|
||||
/// </summary>
|
||||
public class MMGroupSelection
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a parent object and puts all selected transforms under it
|
||||
/// </summary>
|
||||
[MenuItem("Tools/More Mountains/Group Selection %g")]
|
||||
public static void GroupSelection()
|
||||
{
|
||||
if (!Selection.activeTransform)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject groupObject = new GameObject();
|
||||
groupObject.name = "Group";
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(groupObject, "Group Selection");
|
||||
|
||||
groupObject.transform.SetParent(Selection.activeTransform.parent, false);
|
||||
|
||||
foreach (Transform selectedTransform in Selection.transforms)
|
||||
{
|
||||
Undo.SetTransformParent(selectedTransform, groupObject.transform, "Group Selection");
|
||||
}
|
||||
Selection.activeGameObject = groupObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a908ed7f06f3bf34e8ff030a385f46f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple class that lets you lock the current inspector by pressing ctrl (or cmd) + L
|
||||
/// Pressing the same shortcut again unlocks the
|
||||
/// </summary>
|
||||
public class MMLockInspector : MonoBehaviour
|
||||
{
|
||||
[MenuItem("Tools/More Mountains/Lock Inspector %l")]
|
||||
static public void LockInspector()
|
||||
{
|
||||
Type inspectorType = typeof(Editor).Assembly.GetType("UnityEditor.InspectorWindow");
|
||||
EditorWindow inspectorWindow = EditorWindow.GetWindow(inspectorType);
|
||||
|
||||
PropertyInfo isLockedPropertyInfo = inspectorType.GetProperty("isLocked", BindingFlags.Public | BindingFlags.Instance);
|
||||
bool state = (bool)isLockedPropertyInfo.GetGetMethod().Invoke(inspectorWindow, new object[] { });
|
||||
|
||||
isLockedPropertyInfo.GetSetMethod().Invoke(inspectorWindow, new object[] { !state });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c0e71f738b287843b432d007a0626bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user