├── KKTools ├── KKTools Guide.pdf └── Editor │ ├── AssetBundle │ ├── AssetBundleOther.cs │ ├── AssetBundleBuild.cs │ ├── AssetBundleWatch.cs │ └── AssetBundleAnalyzer.cs │ ├── Static │ ├── ShowIconInHierarchy.cs │ ├── ShowSortingOrder.cs │ └── TransformInspectorResetEditor.cs │ ├── Window │ └── SceneWatcher.cs │ ├── KKToolsManager.cs │ ├── UtilityEditor.cs │ ├── Create │ └── MakeFolders.cs │ ├── Prefab │ └── PrefabTool.cs │ ├── UGUI │ └── UGUITool.cs │ └── Finder │ └── GameObjectFinder.cs ├── .gitignore ├── README.md └── LICENCE /KKTools/KKTools Guide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k79k06k02k/KKTools/HEAD/KKTools/KKTools Guide.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # =============== # 2 | # Unity generated # 3 | # =============== # 4 | Temp/ 5 | Library/ 6 | 7 | # ===================================== # 8 | # Visual Studio / MonoDevelop generated # 9 | # ===================================== # 10 | ExportedObj/ 11 | obj/ 12 | *.svd 13 | *.userprefs 14 | *.csproj 15 | *.pidb 16 | *.suo 17 | *.sln 18 | *.user 19 | *.unityproj 20 | *.booproj 21 | 22 | # ============ # 23 | # OS generated # 24 | # ============ # 25 | .DS_Store 26 | .DS_Store? 27 | ._* 28 | .Spotlight-V100 29 | .Trashes 30 | ehthumbs.db 31 | Thumbs.db 32 | 33 | *.meta 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KKTools 2 | [Guide](https://github.com/k79k06k02k/KKTools/blob/master/KKTools/KKTools%20Guide.pdf)

3 | 4 | ## Support & Feedback 5 | Blog:[http://k79k06k02k.com/blog](http://k79k06k02k.com/blog)
6 | Facebook:[https://www.facebook.com/k79k06k02k](https://www.facebook.com/k79k06k02k)
7 | Email:k79k06k02k@gmail.com

8 | 9 | Something code are quote from [AssetBundleAnalyzer](http://forum.unity3d.com/threads/asset-bundle-analyzer.182413/)、[GameObjectFinder](http://wiki.unity3d.com/index.php/FindGameObjects)、[SceneWatcher](http://wiki.unity3d.com/index.php/SceneViewWindow) The license of the that follow theirs. 10 | -------------------------------------------------------------------------------- /KKTools/Editor/AssetBundle/AssetBundleOther.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : AssetBundleOther.cs 4 | **********************************************************/ 5 | using UnityEngine; 6 | using UnityEditor; 7 | using System.Text; 8 | 9 | public class AssetBundleOther : AssetPostprocessor 10 | { 11 | public static void ShowAllAssetBundleNames() 12 | { 13 | StringBuilder sb = new StringBuilder(); 14 | string[] assetBundleNames = AssetDatabase.GetAllAssetBundleNames(); 15 | 16 | foreach (string str in assetBundleNames) 17 | sb.Append(str + "\n"); 18 | 19 | Debug.Log("AssetBundleNames:\n" + sb.ToString()); 20 | } 21 | 22 | void OnPostprocessAssetbundleNameChanged(string path, string previous, string next) 23 | { 24 | Debug.Log("AB: " + path + "\told: " + previous + "\tnew: " + next); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Arkai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /KKTools/Editor/Static/ShowIconInHierarchy.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : ShowIconInHierarchy.cs 4 | **********************************************************/ 5 | using UnityEngine; 6 | using System.Collections; 7 | using System.Reflection; 8 | using UnityEditor; 9 | 10 | public class ShowIconInHierarchy { 11 | 12 | private const int WIDTH = 16; 13 | 14 | private static readonly MethodInfo mGetIconForObject = typeof(EditorGUIUtility) 15 | .GetMethod("GetIconForObject", BindingFlags.NonPublic | BindingFlags.Static); 16 | 17 | [InitializeOnLoadMethod] 18 | private static void Example() 19 | { 20 | EditorApplication.hierarchyWindowItemOnGUI += OnGUI; 21 | } 22 | 23 | private static void OnGUI(int instanceID, Rect selectionRect) 24 | { 25 | var go = EditorUtility.InstanceIDToObject(instanceID) as GameObject; 26 | 27 | if (go == null) 28 | { 29 | return; 30 | } 31 | 32 | var parameters = new object[] { go }; 33 | var icon = mGetIconForObject.Invoke(null, parameters) as Texture; 34 | 35 | if (icon == null) 36 | { 37 | return; 38 | } 39 | 40 | var pos = selectionRect; 41 | pos.x = pos.xMax - WIDTH; 42 | pos.width = WIDTH; 43 | 44 | GUI.DrawTexture(pos, icon, ScaleMode.ScaleToFit, true); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /KKTools/Editor/Window/SceneWatcher.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : SceneWatcher.cs 4 | // Reference: http://wiki.unity3d.com/index.php/SceneViewWindow 5 | **********************************************************/ 6 | 7 | using System.IO; 8 | using UnityEditor; 9 | using UnityEngine; 10 | 11 | public class SceneWatcher : EditorWindow 12 | { 13 | 14 | private Vector2 scrollPos; 15 | 16 | 17 | public static void Init() 18 | { 19 | var window = (SceneWatcher)GetWindow(typeof(SceneWatcher), false, "Scene Watcher"); 20 | window.position = new Rect(window.position.xMin + 100f, window.position.yMin + 100f, 400f, 400f); 21 | } 22 | 23 | 24 | void OnGUI() 25 | { 26 | EditorGUILayout.BeginVertical(); 27 | this.scrollPos = EditorGUILayout.BeginScrollView(this.scrollPos, false, false); 28 | 29 | GUILayout.Label("Scenes In Build", EditorStyles.boldLabel); 30 | for (var i = 0; i < EditorBuildSettings.scenes.Length; i++) 31 | { 32 | var scene = EditorBuildSettings.scenes[i]; 33 | if (scene.enabled) 34 | { 35 | var sceneName = Path.GetFileNameWithoutExtension(scene.path); 36 | var pressed = GUILayout.Button(i + ": " + sceneName, new GUIStyle(GUI.skin.GetStyle("Button")) { alignment = TextAnchor.MiddleLeft }); 37 | if (pressed) 38 | { 39 | if (EditorApplication.SaveCurrentSceneIfUserWantsTo()) 40 | { 41 | EditorApplication.OpenScene(scene.path); 42 | } 43 | } 44 | } 45 | } 46 | 47 | EditorGUILayout.EndScrollView(); 48 | EditorGUILayout.EndVertical(); 49 | } 50 | } -------------------------------------------------------------------------------- /KKTools/Editor/KKToolsManager.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : KKToolsManager.cs 4 | **********************************************************/ 5 | using UnityEditor; 6 | 7 | public class KKToolsManager 8 | { 9 | //======================================================================================= 10 | //AssetBundle 11 | [MenuItem("KKTools/AssetBundle/AssetBundle Analyze")] 12 | static void AssetBundle_Analyze() 13 | { 14 | AssetBundleAnalyzer.ShowWindow(); 15 | } 16 | 17 | [MenuItem("KKTools/AssetBundle/AssetBundle Watch")] 18 | static void AssetBundle_Watch() 19 | { 20 | AssetBundleWatch.ShowWindow(); 21 | } 22 | 23 | [MenuItem("KKTools/AssetBundle/AssetBundle Build")] 24 | static void AssetBundle_Build() 25 | { 26 | AssetBundleBuild.ShowWindow(); 27 | } 28 | 29 | [MenuItem("KKTools/AssetBundle/AssetBundle Build All Platform")] 30 | static void AssetBundle_BuildAllPlatform() 31 | { 32 | AssetBundleBuild.BuildAllPlatform(); 33 | } 34 | 35 | [MenuItem("KKTools/AssetBundle/AssetBundle Show All Name")] 36 | static void AssetBundle_ShowAllNames() 37 | { 38 | AssetBundleOther.ShowAllAssetBundleNames(); 39 | } 40 | 41 | 42 | //======================================================================================= 43 | //Create 44 | [MenuItem("KKTools/Create/Make Project Folders")] 45 | static void Create_MakeFolders() 46 | { 47 | MakeFolders.ShowWindow(); 48 | } 49 | 50 | 51 | //======================================================================================= 52 | //Finder 53 | [MenuItem("KKTools/Finder/Finder")] 54 | static void Finder_GameObjectFinder() 55 | { 56 | GameObjectFinder.ShowWindow(); 57 | } 58 | 59 | 60 | //======================================================================================= 61 | //Prefab 62 | [MenuItem("KKTools/Prefab/Prefab Tool")] 63 | static void Prefab_PrefabTool() 64 | { 65 | PrefabTool.ShowView(); 66 | } 67 | 68 | 69 | //======================================================================================= 70 | //UGUI 71 | [MenuItem("KKTools/UGUI/UGUI Tool")] 72 | static void UGUI_UGUITool() 73 | { 74 | UGUITool.ShowWindow(); 75 | } 76 | 77 | 78 | //======================================================================================= 79 | //Window 80 | [MenuItem("KKTools/Window/Scene Watcher")] 81 | static void Window_SceneWatcher() 82 | { 83 | SceneWatcher.Init(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /KKTools/Editor/UtilityEditor.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : UtilityEditor.cs 4 | **********************************************************/ 5 | using UnityEngine; 6 | using UnityEditor; 7 | 8 | public class UtilityEditor 9 | { 10 | public static bool GetCommonButton(string btnName) 11 | { 12 | GUIStyle BtnStyle = new GUIStyle(GUI.skin.button); 13 | BtnStyle.fontSize = 25; 14 | BtnStyle.fixedHeight = 50; 15 | 16 | return GUILayout.Button(btnName, BtnStyle); 17 | } 18 | 19 | 20 | /// 21 | /// Create Folder(path not include "Assets") 22 | /// EX: GameResources/Prefabs/Sprites/Enemy 23 | /// 24 | public static void CreateFolder(string name) 25 | { 26 | string[] splitName = name.Split('/'); 27 | 28 | string prefixFolderName = ""; 29 | string pathValid = ""; 30 | for (int i = 0; i < splitName.Length; i++) 31 | { 32 | pathValid += "/" + splitName[i]; 33 | 34 | if (AssetDatabase.IsValidFolder("Assets" + pathValid) == false) 35 | AssetDatabase.CreateFolder("Assets" + prefixFolderName, splitName[i]); 36 | 37 | prefixFolderName += "/" + splitName[i]; 38 | } 39 | } 40 | 41 | public static int Tabs(string[] options, int selected) 42 | { 43 | const float DarkGray = 0.6f; 44 | const float LightGray = 0.9f; 45 | const float StartSpace = 10; 46 | 47 | GUILayout.Space(StartSpace); 48 | Color storeColor = GUI.backgroundColor; 49 | Color highlightCol = new Color(LightGray, LightGray, LightGray); 50 | Color bgCol = new Color(DarkGray, DarkGray, DarkGray); 51 | 52 | GUIStyle buttonStyle = new GUIStyle(GUI.skin.button); 53 | buttonStyle.padding.bottom = 8; 54 | 55 | GUILayout.BeginHorizontal(); 56 | { 57 | for (int i = 0; i < options.Length; ++i) 58 | { 59 | GUI.backgroundColor = i == selected ? highlightCol : bgCol; 60 | if (GUILayout.Button(options[i], buttonStyle)) 61 | { 62 | selected = i; 63 | } 64 | } 65 | } 66 | GUILayout.EndHorizontal(); 67 | 68 | GUI.backgroundColor = storeColor; 69 | 70 | var texture = new Texture2D(1, 1); 71 | texture.SetPixel(0, 0, highlightCol); 72 | texture.Apply(); 73 | GUI.DrawTexture(new Rect(0, buttonStyle.lineHeight + buttonStyle.border.top + buttonStyle.margin.top + StartSpace, Screen.width, 4), texture); 74 | 75 | return selected; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /KKTools/Editor/Static/ShowSortingOrder.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : ShowSortingOrder.cs 4 | **********************************************************/ 5 | using UnityEngine; 6 | using UnityEditor; 7 | 8 | public class ShowSortingOrder 9 | { 10 | private const int _LableWidth = 20; 11 | private const int _BtnWidth = 45; 12 | private const string _LablePlus = "+"; 13 | private const string _LableLess = "-"; 14 | 15 | 16 | [InitializeOnLoadMethod] 17 | private static void Init() 18 | { 19 | EditorApplication.hierarchyWindowItemOnGUI += OnGUI; 20 | } 21 | 22 | private static void OnGUI(int instanceID, Rect selectionRect) 23 | { 24 | var go = EditorUtility.InstanceIDToObject(instanceID) as GameObject; 25 | 26 | if (go == null) 27 | { 28 | return; 29 | } 30 | 31 | Component objSpriteRenderer = go.GetComponent(); 32 | Component objCanvas = go.GetComponent(); 33 | Component obj = (objCanvas == null) ? objSpriteRenderer : objCanvas; 34 | 35 | if (obj == null) 36 | return; 37 | 38 | 39 | if (obj.GetType() == typeof(SpriteRenderer)) 40 | { 41 | Show((SpriteRenderer)obj, selectionRect); 42 | } 43 | else if (obj.GetType() == typeof(Canvas)) 44 | { 45 | Show((Canvas)obj, selectionRect); 46 | } 47 | } 48 | 49 | static void Show(SpriteRenderer objSpriteRenderer, Rect selectionRect) 50 | { 51 | var pos = selectionRect; 52 | pos.x = pos.xMax - _LableWidth; 53 | pos.width = _LableWidth; 54 | 55 | if (GUI.Button(pos, _LablePlus)) 56 | { 57 | objSpriteRenderer.sortingOrder++; 58 | } 59 | 60 | pos.x -= _BtnWidth; 61 | pos.width = _BtnWidth; 62 | 63 | 64 | var centeredStyle = GUI.skin.GetStyle("Label"); 65 | centeredStyle.alignment = TextAnchor.UpperCenter; 66 | EditorGUI.LabelField(pos, objSpriteRenderer.sortingOrder.ToString(), centeredStyle); 67 | EditorUtility.SetDirty(objSpriteRenderer); 68 | 69 | pos.x -= _LableWidth; 70 | pos.width = _LableWidth; 71 | 72 | if (GUI.Button(pos, _LableLess)) 73 | { 74 | objSpriteRenderer.sortingOrder--; 75 | } 76 | } 77 | 78 | static void Show(Canvas objCanvas, Rect selectionRect) 79 | { 80 | var pos = selectionRect; 81 | pos.x = pos.xMax - _LableWidth; 82 | pos.width = _LableWidth; 83 | 84 | if (GUI.Button(pos, _LablePlus)) 85 | { 86 | objCanvas.sortingOrder++; 87 | } 88 | 89 | pos.x -= _BtnWidth; 90 | pos.width = _BtnWidth; 91 | 92 | var centeredStyle = GUI.skin.GetStyle("Label"); 93 | centeredStyle.alignment = TextAnchor.UpperCenter; 94 | EditorGUI.LabelField(pos, objCanvas.sortingOrder.ToString(), centeredStyle); 95 | EditorUtility.SetDirty(objCanvas); 96 | 97 | pos.x -= _LableWidth; 98 | pos.width = _LableWidth; 99 | 100 | if (GUI.Button(pos, _LableLess)) 101 | { 102 | objCanvas.sortingOrder--; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /KKTools/Editor/AssetBundle/AssetBundleBuild.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : AssetBundleBuild.cs 4 | **********************************************************/ 5 | using UnityEngine; 6 | using UnityEditor; 7 | 8 | public class AssetBundleBuild : EditorWindow 9 | { 10 | bool[] isTargetToggle; 11 | 12 | static string[] BUILD_TARGET_NAMES = { "Android", "IOS", "PC" }; 13 | 14 | static string folder = "AssetBundles"; 15 | 16 | 17 | public static void ShowWindow() 18 | { 19 | EditorWindow script = EditorWindow.GetWindow(typeof(AssetBundleBuild)); 20 | script.position = new Rect(script.position.xMin + 100f, script.position.yMin + 100f, 600, 120); 21 | script.autoRepaintOnSceneChange = true; 22 | script.Show(); 23 | script.titleContent = new GUIContent("AB Build"); 24 | } 25 | public static void BuildAllPlatform() 26 | { 27 | if (EditorUtility.DisplayDialog("", 28 | "Are you sure?", 29 | "Yes", 30 | "No")) 31 | { 32 | for (int i = 0; i < BUILD_TARGET_NAMES.Length; i++) 33 | { 34 | UtilityEditor.CreateFolder(folder + "/" + BUILD_TARGET_NAMES[i]); 35 | 36 | BuildPipeline.BuildAssetBundles(Application.dataPath + "/" + folder + "/" + BUILD_TARGET_NAMES[i], BuildAssetBundleOptions.CollectDependencies, GetTarget(BUILD_TARGET_NAMES[i])); 37 | 38 | } 39 | } 40 | } 41 | 42 | private void OnEnable() 43 | { 44 | isTargetToggle = new bool[BUILD_TARGET_NAMES.Length]; 45 | 46 | 47 | switch (EditorUserBuildSettings.activeBuildTarget) 48 | { 49 | case BuildTarget.Android: 50 | isTargetToggle[0] = true; 51 | break; 52 | 53 | case BuildTarget.iOS: 54 | isTargetToggle[1] = true; 55 | break; 56 | 57 | case BuildTarget.StandaloneWindows: 58 | isTargetToggle[2] = true; 59 | break; 60 | 61 | default: 62 | isTargetToggle[2] = true; 63 | break; 64 | } 65 | } 66 | 67 | 68 | void OnGUI() 69 | { 70 | EditorGUILayout.LabelField("Choose Build Target", EditorStyles.boldLabel); 71 | EditorGUILayout.BeginHorizontal(); 72 | GUILayout.Space(25.0f); 73 | 74 | for (int i = 0; i < BUILD_TARGET_NAMES.Length; i++) 75 | { 76 | CreateToogle(i, BUILD_TARGET_NAMES[i], isTargetToggle[i]); 77 | } 78 | 79 | EditorGUILayout.EndHorizontal(); 80 | GUILayout.Space(25.0f); 81 | 82 | 83 | if (UtilityEditor.GetCommonButton("Create")) 84 | { 85 | if (EditorUtility.DisplayDialog("", 86 | "Are you sure?", 87 | "Yes", 88 | "No")) 89 | { 90 | for (int i = 0; i < isTargetToggle.Length; i++) 91 | { 92 | if (isTargetToggle[i]) 93 | { 94 | UtilityEditor.CreateFolder(folder + "/" + BUILD_TARGET_NAMES[i]); 95 | 96 | BuildPipeline.BuildAssetBundles(Application.dataPath + "/" + folder + "/" + BUILD_TARGET_NAMES[i], BuildAssetBundleOptions.CollectDependencies, GetTarget(BUILD_TARGET_NAMES[i])); 97 | } 98 | } 99 | 100 | this.Close(); 101 | } 102 | } 103 | } 104 | 105 | void CreateToogle(int index, string name, bool value) 106 | { 107 | isTargetToggle[index] = EditorGUILayout.ToggleLeft(" " + name, value); 108 | } 109 | 110 | static BuildTarget GetTarget(string name) 111 | { 112 | switch (name) 113 | { 114 | case "Android": 115 | return BuildTarget.Android; 116 | 117 | case "iOS": 118 | return BuildTarget.iOS; 119 | 120 | case "PC": 121 | return BuildTarget.StandaloneWindows; 122 | 123 | default: 124 | return BuildTarget.StandaloneWindows; 125 | } 126 | 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /KKTools/Editor/AssetBundle/AssetBundleWatch.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : AssetBundleWatch.cs 4 | **********************************************************/ 5 | using UnityEngine; 6 | using UnityEditor; 7 | 8 | public class AssetBundleWatch : EditorWindow 9 | { 10 | string[] Types = new string[] { "Select One", "Show All" }; 11 | int tabIndex = 0; 12 | 13 | private string[] assetBundleNames; 14 | public int index = 0; 15 | 16 | string _LevelStr = " "; 17 | 18 | Vector2 scrollPos; 19 | GUIStyle BtnStyle; 20 | GUIStyle LableStyle; 21 | GUIStyle BoxStyle; 22 | bool isShowAll = false; 23 | 24 | public static void ShowWindow() 25 | { 26 | EditorWindow script = EditorWindow.GetWindow(typeof(AssetBundleWatch)); 27 | script.position = new Rect(script.position.xMin + 100f, script.position.yMin + 100f, 700, 700); 28 | script.autoRepaintOnSceneChange = true; 29 | script.Show(); 30 | script.titleContent = new GUIContent("AB Watch"); 31 | } 32 | 33 | void OnGUI() 34 | { 35 | BtnStyle = new GUIStyle(GUI.skin.button); 36 | BtnStyle.fontSize = 16; 37 | BtnStyle.alignment = TextAnchor.MiddleLeft; 38 | 39 | LableStyle = new GUIStyle(GUI.skin.label); 40 | LableStyle.fontSize = 16; 41 | LableStyle.alignment = TextAnchor.MiddleLeft; 42 | 43 | BoxStyle = new GUIStyle(GUI.skin.box); 44 | 45 | assetBundleNames = AssetDatabase.GetAllAssetBundleNames(); 46 | 47 | 48 | if (assetBundleNames.Length == 0) 49 | { 50 | EditorGUILayout.HelpBox("No AssetBundle Data", MessageType.Warning); 51 | return; 52 | } 53 | 54 | tabIndex = UtilityEditor.Tabs(Types, tabIndex); 55 | GUILayout.Space(10); 56 | 57 | string[] assetName = null; 58 | 59 | switch (tabIndex) 60 | { 61 | case 0: 62 | EditorGUILayout.LabelField("Select AssetBundle Names", EditorStyles.boldLabel); 63 | 64 | index = EditorGUILayout.Popup(index, assetBundleNames); 65 | GUILayout.Space(10f); 66 | 67 | assetName = AssetDatabase.FindAssets("b:" + assetBundleNames[index]); 68 | 69 | EditorGUILayout.BeginVertical(); 70 | this.scrollPos = EditorGUILayout.BeginScrollView(this.scrollPos, false, false); 71 | EditorGUILayout.Space(); 72 | 73 | 74 | foreach (string item in assetName) 75 | { 76 | string path = AssetDatabase.GUIDToAssetPath(item); 77 | string[] level = path.Split('/'); 78 | 79 | if (GUILayout.Button(GetLevelString(level.Length - 1) + path, BtnStyle)) 80 | EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(path)); 81 | } 82 | 83 | 84 | EditorGUILayout.EndScrollView(); 85 | EditorGUILayout.EndVertical(); 86 | 87 | GUILayout.Space(25.0f); 88 | break; 89 | 90 | 91 | case 1: 92 | EditorGUILayout.LabelField("AssetBundle", EditorStyles.boldLabel); 93 | 94 | EditorGUILayout.BeginVertical(); 95 | this.scrollPos = EditorGUILayout.BeginScrollView(this.scrollPos, false, false); 96 | 97 | int count = 1; 98 | foreach (string name in assetBundleNames) 99 | { 100 | assetName = AssetDatabase.FindAssets("b:" + name); 101 | 102 | EditorGUILayout.BeginVertical(BoxStyle); 103 | GUILayout.Label(count.ToString("000") + ". " + name + ":", LableStyle); 104 | foreach (string item in assetName) 105 | { 106 | string path = AssetDatabase.GUIDToAssetPath(item); 107 | string[] level = path.Split('/'); 108 | 109 | if (GUILayout.Button(GetLevelString(level.Length - 1) + path, BtnStyle)) 110 | EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath(path)); 111 | } 112 | EditorGUILayout.EndVertical(); 113 | 114 | count++; 115 | GUILayout.Space(25.0f); 116 | } 117 | 118 | EditorGUILayout.EndScrollView(); 119 | EditorGUILayout.EndVertical(); 120 | 121 | GUILayout.Space(25.0f); 122 | break; 123 | } 124 | } 125 | 126 | 127 | string GetLevelString(int count) 128 | { 129 | string temp = string.Empty; 130 | 131 | for (int i = 0; i < count; i++) 132 | temp += _LevelStr; 133 | 134 | return temp; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /KKTools/Editor/Create/MakeFolders.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : MakeFolders.cs 4 | // Reference: http://wiki.unity3d.com/index.php/Create_project_directories 5 | **********************************************************/ 6 | using UnityEngine; 7 | using UnityEditor; 8 | using System.Collections.Generic; 9 | 10 | public class MakeFolders : EditorWindow 11 | { 12 | private Vector2 scrollPos; 13 | 14 | private bool isToggleAll = false; 15 | private bool isToggleAllLast = false; 16 | 17 | private bool[] isCreateFolder; 18 | private List folderList = new List(); 19 | 20 | public class Folder 21 | { 22 | public Folder(string name, bool isDefaultCreate = false) 23 | { 24 | this.name = name; 25 | this.isDefaultCreate = isDefaultCreate; 26 | } 27 | 28 | public string name; 29 | public bool isDefaultCreate; 30 | } 31 | 32 | public static void ShowWindow() 33 | { 34 | EditorWindow editorWindow = EditorWindow.GetWindow(typeof(MakeFolders)); 35 | editorWindow.position = new Rect(editorWindow.position.xMin + 100f, editorWindow.position.yMin + 100f, 400f, 400f); 36 | editorWindow.autoRepaintOnSceneChange = true; 37 | editorWindow.Show(); 38 | editorWindow.titleContent = new GUIContent("Make Folders"); 39 | } 40 | 41 | void OnEnable() 42 | { 43 | folderList = new List(); 44 | folderList.Add(new Folder("Scenes", true)); 45 | folderList.Add(new Folder("Scripts", true)); 46 | folderList.Add(new Folder("Plugins", true)); 47 | folderList.Add(new Folder("Resources", true)); 48 | folderList.Add(new Folder("Resources/Materials")); 49 | folderList.Add(new Folder("Resources/Models")); 50 | folderList.Add(new Folder("Resources/Textures")); 51 | folderList.Add(new Folder("Resources/Shaders")); 52 | folderList.Add(new Folder("Resources/Prefabs")); 53 | folderList.Add(new Folder("Resources/Sprites")); 54 | folderList.Add(new Folder("Resources/Physics")); 55 | folderList.Add(new Folder("Resources/Fonts")); 56 | folderList.Add(new Folder("Resources/Music")); 57 | 58 | 59 | isCreateFolder = new bool[folderList.Count]; 60 | 61 | for (int i = 0; i < folderList.Count; i++) 62 | isCreateFolder[i] = folderList[i].isDefaultCreate; 63 | 64 | } 65 | 66 | void OnGUI() 67 | { 68 | EditorGUILayout.LabelField("Choose Folders", EditorStyles.boldLabel); 69 | 70 | EditorGUILayout.BeginVertical(); 71 | this.scrollPos = EditorGUILayout.BeginScrollView(this.scrollPos, false, false); 72 | EditorGUILayout.Space(); 73 | 74 | isToggleAll = EditorGUILayout.ToggleLeft(" Toggle All", isToggleAll); 75 | 76 | if (isToggleAll != isToggleAllLast) 77 | ToggleAll(isToggleAll); 78 | 79 | EditorGUILayout.Space(); 80 | 81 | for (int i = 0; i < folderList.Count; i++) 82 | { 83 | CreateToogle(i, folderList[i]); 84 | } 85 | 86 | EditorGUILayout.EndScrollView(); 87 | EditorGUILayout.EndVertical(); 88 | 89 | EditorGUILayout.Space(); 90 | 91 | if (UtilityEditor.GetCommonButton("Make MakeFolders")) 92 | { 93 | 94 | if (Check() == false) 95 | { 96 | if (EditorUtility.DisplayDialog("Alert", "Please Choose Folder!!", "OK")) 97 | return; 98 | } 99 | 100 | if (EditorUtility.DisplayDialog("", 101 | "Are you sure?", 102 | "Yes", 103 | "No")) 104 | { 105 | for (int i = 0; i < isCreateFolder.Length; i++) 106 | { 107 | if (isCreateFolder[i] == true) 108 | CreateFolders(folderList[i].name); 109 | } 110 | 111 | 112 | this.Close(); 113 | } 114 | } 115 | 116 | EditorGUILayout.Space(); 117 | 118 | } 119 | 120 | void CreateToogle(int index, Folder folder) 121 | { 122 | isCreateFolder[index] = EditorGUILayout.ToggleLeft(" " + folder.name, isCreateFolder[index]); 123 | } 124 | 125 | void CreateFolders(string name) 126 | { 127 | bool isCreate = false; 128 | 129 | string[] splitName = name.Split('/'); 130 | 131 | string prefixFolderName = ""; 132 | string pathValid = ""; 133 | for (int i = 0; i < splitName.Length; i++) 134 | { 135 | pathValid += "/" + splitName[i]; 136 | 137 | if (AssetDatabase.IsValidFolder("Assets" + pathValid) == false) 138 | { 139 | AssetDatabase.CreateFolder("Assets" + prefixFolderName, splitName[i]); 140 | isCreate = true; 141 | } 142 | 143 | prefixFolderName += "/" + splitName[i]; 144 | } 145 | 146 | 147 | if (isCreate) 148 | Debug.Log("Folder [ Assets/" + name + " ] is Create!!"); 149 | else 150 | Debug.LogWarning("Folder [ Assets/" + name + " ] is Exist!!"); 151 | } 152 | 153 | bool Check() 154 | { 155 | for (int i = 0; i < isCreateFolder.Length; i++) 156 | if (isCreateFolder[i] == true) 157 | return true; 158 | 159 | return false; 160 | } 161 | 162 | void ToggleAll(bool isToggle) 163 | { 164 | isToggleAllLast = isToggle; 165 | 166 | for (int i = 0; i < isCreateFolder.Length; i++) 167 | isCreateFolder[i] = isToggle; 168 | } 169 | } -------------------------------------------------------------------------------- /KKTools/Editor/Static/TransformInspectorResetEditor.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : TransformInspectorResetEditor.cs 4 | **********************************************************/ 5 | using UnityEngine; 6 | using UnityEditor; 7 | 8 | [CanEditMultipleObjects] 9 | [CustomEditor(typeof(Transform), true)] 10 | public class TransformInspectorResetEditor : Editor 11 | { 12 | static public TransformInspectorResetEditor instance; 13 | 14 | SerializedProperty mPos; 15 | SerializedProperty mRot; 16 | SerializedProperty mScale; 17 | 18 | void OnEnable () 19 | { 20 | instance = this; 21 | 22 | mPos = serializedObject.FindProperty("m_LocalPosition"); 23 | mRot = serializedObject.FindProperty("m_LocalRotation"); 24 | mScale = serializedObject.FindProperty("m_LocalScale"); 25 | } 26 | 27 | void OnDestroy () { instance = null; } 28 | 29 | 30 | public override void OnInspectorGUI () 31 | { 32 | EditorGUIUtility.labelWidth=15f; 33 | 34 | serializedObject.Update(); 35 | 36 | DrawPosition(); 37 | DrawRotation(); 38 | DrawScale(); 39 | 40 | serializedObject.ApplyModifiedProperties(); 41 | 42 | } 43 | 44 | void DrawPosition () 45 | { 46 | GUILayout.BeginHorizontal(); 47 | bool reset = GUILayout.Button("P", GUILayout.Width(20f)); 48 | EditorGUILayout.PropertyField(mPos.FindPropertyRelative("x")); 49 | EditorGUILayout.PropertyField(mPos.FindPropertyRelative("y")); 50 | EditorGUILayout.PropertyField(mPos.FindPropertyRelative("z")); 51 | GUILayout.EndHorizontal(); 52 | 53 | if (reset) mPos.vector3Value = Vector3.zero; 54 | } 55 | 56 | void DrawScale () 57 | { 58 | GUILayout.BeginHorizontal(); 59 | { 60 | bool reset = GUILayout.Button("S", GUILayout.Width(20f)); 61 | 62 | EditorGUILayout.PropertyField(mScale.FindPropertyRelative("x")); 63 | EditorGUILayout.PropertyField(mScale.FindPropertyRelative("y")); 64 | EditorGUILayout.PropertyField(mScale.FindPropertyRelative("z")); 65 | 66 | if (reset) mScale.vector3Value = Vector3.one; 67 | } 68 | GUILayout.EndHorizontal(); 69 | } 70 | 71 | 72 | enum Axes : int 73 | { 74 | None = 0, 75 | X = 1, 76 | Y = 2, 77 | Z = 4, 78 | All = 7, 79 | } 80 | 81 | Axes CheckDifference (Transform t, Vector3 original) 82 | { 83 | Vector3 next = t.localEulerAngles; 84 | 85 | Axes axes = Axes.None; 86 | 87 | if (Differs(next.x, original.x)) axes |= Axes.X; 88 | if (Differs(next.y, original.y)) axes |= Axes.Y; 89 | if (Differs(next.z, original.z)) axes |= Axes.Z; 90 | 91 | return axes; 92 | } 93 | 94 | Axes CheckDifference (SerializedProperty property) 95 | { 96 | Axes axes = Axes.None; 97 | 98 | if (property.hasMultipleDifferentValues) 99 | { 100 | Vector3 original = property.quaternionValue.eulerAngles; 101 | 102 | foreach (Object obj in serializedObject.targetObjects) 103 | { 104 | axes |= CheckDifference(obj as Transform, original); 105 | if (axes == Axes.All) break; 106 | } 107 | } 108 | return axes; 109 | } 110 | 111 | static bool FloatField (string name, ref float value, bool hidden, bool greyedOut, GUILayoutOption opt) 112 | { 113 | float newValue = value; 114 | GUI.changed = false; 115 | 116 | if (!hidden) 117 | { 118 | if (greyedOut) 119 | { 120 | GUI.color = new Color(0.7f, 0.7f, 0.7f); 121 | newValue = EditorGUILayout.FloatField(name, newValue, opt); 122 | GUI.color = Color.white; 123 | } 124 | else 125 | { 126 | newValue = EditorGUILayout.FloatField(name, newValue, opt); 127 | } 128 | } 129 | else if (greyedOut) 130 | { 131 | GUI.color = new Color(0.7f, 0.7f, 0.7f); 132 | float.TryParse(EditorGUILayout.TextField(name, "--", opt), out newValue); 133 | GUI.color = Color.white; 134 | } 135 | else 136 | { 137 | float.TryParse(EditorGUILayout.TextField(name, "--", opt), out newValue); 138 | } 139 | 140 | if (GUI.changed && Differs(newValue, value)) 141 | { 142 | value = newValue; 143 | return true; 144 | } 145 | return false; 146 | } 147 | 148 | static bool Differs (float a, float b) { return Mathf.Abs(a - b) > 0.0001f; } 149 | 150 | void DrawRotation () 151 | { 152 | GUILayout.BeginHorizontal(); 153 | { 154 | bool reset = GUILayout.Button("R", GUILayout.Width(20f)); 155 | 156 | Vector3 visible = (serializedObject.targetObject as Transform).localEulerAngles; 157 | 158 | visible.x = WrapAngle(visible.x); 159 | visible.y = WrapAngle(visible.y); 160 | visible.z = WrapAngle(visible.z); 161 | 162 | Axes changed = CheckDifference(mRot); 163 | Axes altered = Axes.None; 164 | 165 | GUILayoutOption opt = GUILayout.MinWidth(30f); 166 | 167 | if (FloatField("X", ref visible.x, (changed & Axes.X) != 0, false, opt)) altered |= Axes.X; 168 | if (FloatField("Y", ref visible.y, (changed & Axes.Y) != 0, false, opt)) altered |= Axes.Y; 169 | if (FloatField("Z", ref visible.z, (changed & Axes.Z) != 0, false, opt)) altered |= Axes.Z; 170 | 171 | if (reset) 172 | { 173 | mRot.quaternionValue = Quaternion.identity; 174 | } 175 | else if (altered != Axes.None) 176 | { 177 | RegisterUndo("Change Rotation", serializedObject.targetObjects); 178 | 179 | foreach (Object obj in serializedObject.targetObjects) 180 | { 181 | Transform t = obj as Transform; 182 | Vector3 v = t.localEulerAngles; 183 | 184 | if ((altered & Axes.X) != 0) v.x = visible.x; 185 | if ((altered & Axes.Y) != 0) v.y = visible.y; 186 | if ((altered & Axes.Z) != 0) v.z = visible.z; 187 | 188 | t.localEulerAngles = v; 189 | } 190 | } 191 | } 192 | GUILayout.EndHorizontal(); 193 | } 194 | 195 | float WrapAngle(float angle) 196 | { 197 | while (angle > 180f) angle -= 360f; 198 | while (angle < -180f) angle += 360f; 199 | return angle; 200 | } 201 | 202 | void RegisterUndo(string name, params Object[] objects) 203 | { 204 | if (objects != null && objects.Length > 0) 205 | { 206 | UnityEditor.Undo.RecordObjects(objects, name); 207 | 208 | foreach (Object obj in objects) 209 | { 210 | if (obj == null) continue; 211 | EditorUtility.SetDirty(obj); 212 | } 213 | } 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /KKTools/Editor/Prefab/PrefabTool.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : PrefabTool.cs 4 | **********************************************************/ 5 | using UnityEngine; 6 | using UnityEditor; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | 11 | public class PrefabTool : EditorWindow 12 | { 13 | string path = "Assets/"; 14 | string extension = ".prefab"; 15 | string[] Types = new string[] { "Create", "Apply" }; 16 | int tabIndex = 0; 17 | 18 | Vector2 scrollPos; 19 | GUIStyle BtnStyle; 20 | List selectObj = new List(); 21 | 22 | public static void ShowView() 23 | { 24 | EditorWindow script = GetWindow(typeof(PrefabTool)); 25 | script.position = new Rect(script.position.xMin + 100f, script.position.yMin + 100f, 500, 700); 26 | script.autoRepaintOnSceneChange = true; 27 | script.Show(); 28 | script.titleContent = new GUIContent("Prefab Tool"); 29 | } 30 | 31 | void OnHierarchyChange() 32 | { 33 | Repaint(); 34 | } 35 | void OnSelectionChange() 36 | { 37 | Repaint(); 38 | } 39 | 40 | void OnGUI() 41 | { 42 | tabIndex = UtilityEditor.Tabs(Types, tabIndex); 43 | GUILayout.Space(10); 44 | 45 | BtnStyle = new GUIStyle(GUI.skin.button); 46 | BtnStyle.fontSize = 16; 47 | BtnStyle.alignment = TextAnchor.MiddleLeft; 48 | 49 | selectObj.Clear(); 50 | selectObj = Selection.gameObjects.ToList(); 51 | 52 | for (int i = selectObj.Count - 1; i >= 0; i--) 53 | { 54 | if (GetFiltered(selectObj[i])) 55 | selectObj.Remove(selectObj[i]); 56 | } 57 | 58 | EditorGUILayout.BeginHorizontal(); 59 | EditorGUILayout.LabelField("Choose GameObjects", EditorStyles.boldLabel); 60 | EditorGUILayout.LabelField("Count : " + selectObj.Count, EditorStyles.boldLabel); 61 | EditorGUILayout.EndHorizontal(); 62 | 63 | if (selectObj.Count == 0) 64 | { 65 | EditorGUILayout.HelpBox(GetHelpString(), MessageType.Warning); 66 | return; 67 | } 68 | 69 | selectObj.Sort(delegate (GameObject a, GameObject b) 70 | { 71 | return a.name.CompareTo(b.name); 72 | }); 73 | 74 | EditorGUILayout.BeginVertical(); 75 | scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, false); 76 | EditorGUILayout.Space(); 77 | 78 | 79 | foreach (GameObject obj in selectObj) 80 | { 81 | if (GUILayout.Button(obj.name, BtnStyle)) 82 | EditorGUIUtility.PingObject(obj); 83 | } 84 | 85 | EditorGUILayout.EndScrollView(); 86 | EditorGUILayout.EndVertical(); 87 | 88 | 89 | if (UtilityEditor.GetCommonButton(Types[tabIndex])) 90 | Execute(); 91 | } 92 | 93 | string GetHelpString() 94 | { 95 | StringBuilder sb = new StringBuilder(); 96 | sb.Append("No Source." + "\n\n"); 97 | sb.Append("Please Check Select GameObject:" + "\n"); 98 | 99 | switch (tabIndex) 100 | { 101 | case 0: 102 | sb.Append("1.GameObject Is In Scene" + "\n"); 103 | sb.Append("2.GameObject Is not a Prefab" + "\n"); 104 | sb.Append("3.GameObject Is Active"); 105 | break; 106 | 107 | case 1: 108 | sb.Append("1.GameObject Is In Scene" + "\n"); 109 | sb.Append("2.GameObject Is a Prefab"); 110 | break; 111 | } 112 | 113 | return sb.ToString(); 114 | } 115 | 116 | 117 | bool GetFiltered(GameObject obj) 118 | { 119 | switch (tabIndex) 120 | { 121 | case 0: 122 | return PrefabUtility.GetPrefabType(obj) == PrefabType.PrefabInstance || PrefabUtility.GetPrefabType(obj) == PrefabType.Prefab || obj.activeSelf == false; 123 | 124 | case 1: 125 | return PrefabUtility.GetPrefabType(obj) != PrefabType.PrefabInstance; 126 | 127 | default: 128 | return true; 129 | } 130 | } 131 | 132 | void Execute() 133 | { 134 | switch (tabIndex) 135 | { 136 | case 0: 137 | PrefabCreate(); 138 | break; 139 | 140 | case 1: 141 | PrefabApply(); 142 | break; 143 | } 144 | } 145 | 146 | void PrefabCreate() 147 | { 148 | if (EditorUtility.DisplayDialog("", 149 | "Are you sure?", 150 | "Yes", 151 | "No")) 152 | { 153 | 154 | int count = 1; 155 | foreach (GameObject obj in selectObj) 156 | { 157 | EditorUtility.DisplayProgressBar("Create Prefab", string.Format("({0} / {1}) Path:[{2}];Name:[{3}]", count, selectObj.Count, path, obj.name), count / (float)selectObj.Count); 158 | 159 | Object emptyPrefab = PrefabUtility.CreateEmptyPrefab(path + obj.name + extension); 160 | 161 | if (emptyPrefab != null) 162 | { 163 | GameObject prefab = PrefabUtility.ReplacePrefab(obj, emptyPrefab); 164 | 165 | if (prefab != null) 166 | Debug.Log(string.Format("Create Prefab  Path:[{0}];Name:[{1}] Success!!", path, obj.name + extension)); 167 | } 168 | 169 | AssetDatabase.Refresh(); 170 | count++; 171 | } 172 | 173 | EditorUtility.ClearProgressBar(); 174 | } 175 | } 176 | 177 | void PrefabApply() 178 | { 179 | if (EditorUtility.DisplayDialog("", 180 | "Are you sure?", 181 | "Yes", 182 | "No")) 183 | { 184 | 185 | for (int i = 0; i < selectObj.Count; i++) 186 | { 187 | Object parentObject = PrefabUtility.GetPrefabParent(selectObj[i]); 188 | string prefabPath = AssetDatabase.GetAssetPath(parentObject); 189 | prefabPath = prefabPath.Substring(0, prefabPath.Length - (selectObj[i].name + extension).Length); 190 | 191 | 192 | EditorUtility.DisplayProgressBar("Apply Prefab", string.Format("({0} / {1}) Path:[{2}];Name:[{3}]", i + 1, selectObj.Count, prefabPath, selectObj[i].name), (i + 1) / (float)selectObj.Count); 193 | GameObject prefab = PrefabUtility.ReplacePrefab(selectObj[i], PrefabUtility.GetPrefabParent(selectObj[i]), ReplacePrefabOptions.ConnectToPrefab); 194 | 195 | if (prefab != null) 196 | Debug.Log(string.Format("Apply Prefab  Path:[{0}];Name:[{1}] Success!!", prefabPath, selectObj[i].name + extension)); 197 | } 198 | 199 | EditorUtility.ClearProgressBar(); 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /KKTools/Editor/UGUI/UGUITool.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : UGUITool.cs 4 | **********************************************************/ 5 | using UnityEngine; 6 | using UnityEditor; 7 | using System.Text; 8 | 9 | public class UGUITool : EditorWindow 10 | { 11 | private string[] types = new string[] 12 | { 13 | "Anchors to Corners", 14 | "Corners to Anchors", 15 | "Mirror Horizontally Around Anchors", 16 | "Mirror Horizontally Around Parent Center", 17 | "Mirror Vertically Around Anchors", 18 | "Mirror Vertically Around Parent Center", 19 | }; 20 | 21 | private Vector2 scrollPos; 22 | private GUIStyle BtnStyle; 23 | 24 | public static void ShowWindow() 25 | { 26 | EditorWindow editorWindow = GetWindow(typeof(UGUITool)); 27 | editorWindow.position = new Rect(editorWindow.position.xMin + 100f, editorWindow.position.yMin + 100f, 400f, 190f); 28 | editorWindow.autoRepaintOnSceneChange = true; 29 | editorWindow.Show(); 30 | editorWindow.titleContent = new GUIContent("UGUI Tool"); 31 | } 32 | 33 | 34 | void OnHierarchyChange() 35 | { 36 | Repaint(); 37 | } 38 | void OnSelectionChange() 39 | { 40 | Repaint(); 41 | } 42 | 43 | void OnGUI() 44 | { 45 | if (Selection.activeGameObject == null || Selection.activeGameObject.GetComponent() == null) 46 | { 47 | EditorGUILayout.HelpBox(GetHelpString(), MessageType.Warning); 48 | return; 49 | } 50 | 51 | 52 | BtnStyle = new GUIStyle(GUI.skin.button); 53 | BtnStyle.fontSize = 16; 54 | BtnStyle.alignment = TextAnchor.MiddleCenter; 55 | 56 | EditorGUILayout.LabelField("Features:", EditorStyles.boldLabel); 57 | 58 | EditorGUILayout.BeginVertical(); 59 | scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, false); 60 | 61 | for (int i = 0; i < types.Length; i++) 62 | if (GUILayout.Button(types[i], BtnStyle)) 63 | OnBtnClick(i); 64 | 65 | 66 | EditorGUILayout.EndScrollView(); 67 | EditorGUILayout.EndVertical(); 68 | } 69 | 70 | string GetHelpString() 71 | { 72 | StringBuilder sb = new StringBuilder(); 73 | sb.Append("No Source." + "\n\n"); 74 | sb.Append("Please Check Select GameObject:" + "\n"); 75 | sb.Append("1.GameObject is not Null" + "\n"); 76 | sb.Append("2.GameObject is UI (Have RectTransform Component)"); 77 | 78 | return sb.ToString(); 79 | } 80 | 81 | void OnBtnClick(int index) 82 | { 83 | switch (index) 84 | { 85 | case 0: 86 | AnchorsToCorners(); 87 | break; 88 | 89 | case 1: 90 | CornersToAnchors(); 91 | break; 92 | 93 | case 2: 94 | MirrorHorizontallyAnchors(); 95 | break; 96 | 97 | case 3: 98 | MirrorHorizontallyParent(); 99 | break; 100 | 101 | case 4: 102 | MirrorVerticallyAnchors(); 103 | break; 104 | 105 | case 5: 106 | MirrorVerticallyParent(); 107 | break; 108 | } 109 | } 110 | 111 | 112 | void AnchorsToCorners() 113 | { 114 | foreach (Transform transform in Selection.transforms) 115 | { 116 | RectTransform t = transform as RectTransform; 117 | RectTransform pt = Selection.activeTransform.parent as RectTransform; 118 | 119 | if (t == null || pt == null) return; 120 | 121 | Vector2 newAnchorsMin = new Vector2(t.anchorMin.x + t.offsetMin.x / pt.rect.width, 122 | t.anchorMin.y + t.offsetMin.y / pt.rect.height); 123 | Vector2 newAnchorsMax = new Vector2(t.anchorMax.x + t.offsetMax.x / pt.rect.width, 124 | t.anchorMax.y + t.offsetMax.y / pt.rect.height); 125 | 126 | t.anchorMin = newAnchorsMin; 127 | t.anchorMax = newAnchorsMax; 128 | t.offsetMin = t.offsetMax = new Vector2(0, 0); 129 | } 130 | } 131 | 132 | void CornersToAnchors() 133 | { 134 | foreach (Transform transform in Selection.transforms) 135 | { 136 | RectTransform t = transform as RectTransform; 137 | 138 | if (t == null) return; 139 | 140 | t.offsetMin = t.offsetMax = new Vector2(0, 0); 141 | } 142 | } 143 | 144 | void MirrorHorizontallyAnchors() 145 | { 146 | MirrorHorizontally(false); 147 | } 148 | 149 | void MirrorHorizontallyParent() 150 | { 151 | MirrorHorizontally(true); 152 | } 153 | 154 | void MirrorHorizontally(bool mirrorAnchors) 155 | { 156 | foreach (Transform transform in Selection.transforms) 157 | { 158 | RectTransform t = transform as RectTransform; 159 | RectTransform pt = Selection.activeTransform.parent as RectTransform; 160 | 161 | if (t == null || pt == null) return; 162 | 163 | if (mirrorAnchors) 164 | { 165 | Vector2 oldAnchorMin = t.anchorMin; 166 | t.anchorMin = new Vector2(1 - t.anchorMax.x, t.anchorMin.y); 167 | t.anchorMax = new Vector2(1 - oldAnchorMin.x, t.anchorMax.y); 168 | } 169 | 170 | Vector2 oldOffsetMin = t.offsetMin; 171 | t.offsetMin = new Vector2(-t.offsetMax.x, t.offsetMin.y); 172 | t.offsetMax = new Vector2(-oldOffsetMin.x, t.offsetMax.y); 173 | 174 | t.localScale = new Vector3(-t.localScale.x, t.localScale.y, t.localScale.z); 175 | } 176 | } 177 | 178 | void MirrorVerticallyAnchors() 179 | { 180 | MirrorVertically(false); 181 | } 182 | 183 | void MirrorVerticallyParent() 184 | { 185 | MirrorVertically(true); 186 | } 187 | 188 | void MirrorVertically(bool mirrorAnchors) 189 | { 190 | foreach (Transform transform in Selection.transforms) 191 | { 192 | RectTransform t = transform as RectTransform; 193 | RectTransform pt = Selection.activeTransform.parent as RectTransform; 194 | 195 | if (t == null || pt == null) return; 196 | 197 | if (mirrorAnchors) 198 | { 199 | Vector2 oldAnchorMin = t.anchorMin; 200 | t.anchorMin = new Vector2(t.anchorMin.x, 1 - t.anchorMax.y); 201 | t.anchorMax = new Vector2(t.anchorMax.x, 1 - oldAnchorMin.y); 202 | } 203 | 204 | Vector2 oldOffsetMin = t.offsetMin; 205 | t.offsetMin = new Vector2(t.offsetMin.x, -t.offsetMax.y); 206 | t.offsetMax = new Vector2(t.offsetMax.x, -oldOffsetMin.y); 207 | 208 | t.localScale = new Vector3(t.localScale.x, -t.localScale.y, t.localScale.z); 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /KKTools/Editor/AssetBundle/AssetBundleAnalyzer.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : AssetBundleAnalyzer.cs 4 | // Reference: http://forum.unity3d.com/threads/asset-bundle-analyzer.182413/ 5 | **********************************************************/ 6 | using System.IO; 7 | using UnityEngine; 8 | using UnityEditor; 9 | using System.Collections.Generic; 10 | 11 | public class AssetBundleAnalyzer : EditorWindow 12 | { 13 | private struct StatData 14 | { 15 | public string typeName; 16 | public string objName; 17 | public int size; 18 | } 19 | 20 | private class StatDataComparer : IComparer 21 | { 22 | Dictionary _typeSizeMap; 23 | 24 | public StatDataComparer(Dictionary typeSizeMap) 25 | { 26 | _typeSizeMap = typeSizeMap; 27 | } 28 | 29 | public int Compare(StatData stat1, StatData stat2) 30 | { 31 | int typeSize1 = _typeSizeMap[stat1.typeName]; 32 | int typeSize2 = _typeSizeMap[stat2.typeName]; 33 | 34 | int stringCompare = stat1.typeName.CompareTo(stat2.typeName); 35 | 36 | if (typeSize1 > typeSize2) 37 | { 38 | return -1; 39 | } 40 | else if (typeSize1 < typeSize2) 41 | { 42 | return +1; 43 | } 44 | else if (stringCompare != 0) 45 | { 46 | return stringCompare; 47 | } 48 | else if (stat1.size > stat2.size) 49 | { 50 | return -1; 51 | } 52 | else if (stat1.size < stat2.size) 53 | { 54 | return +1; 55 | } 56 | else 57 | { 58 | return 0; 59 | } 60 | } 61 | } 62 | 63 | private Vector2 scrollPosition = Vector2.zero; 64 | private bool compressed = false; 65 | private BuildTarget buildTarget = EditorUserBuildSettings.activeBuildTarget; 66 | private string outputPath = ""; 67 | private string selectedPath = ""; 68 | private Object analyzedObject = null; 69 | private List statistics = new List(); 70 | private Dictionary typeSizeMap = new Dictionary(); 71 | private Dictionary typeStatusMap = new Dictionary(); 72 | 73 | public static void ShowWindow() 74 | { 75 | EditorWindow script = EditorWindow.GetWindow(typeof(AssetBundleAnalyzer)); 76 | script.autoRepaintOnSceneChange = true; 77 | script.Show(); 78 | script.titleContent = new GUIContent("AB Analyzer"); 79 | } 80 | 81 | void OnGUI() 82 | { 83 | Object currentObject = null; 84 | string assetPath = ""; 85 | 86 | if (Selection.activeObject != null && AssetDatabase.Contains(Selection.activeObject)) 87 | { 88 | assetPath = Path.GetFullPath(AssetDatabase.GetAssetPath(Selection.activeObject)); 89 | if (assetPath.ToLower().Contains(".abbin")) 90 | { 91 | currentObject = Selection.activeObject; 92 | } 93 | } 94 | 95 | GUILayout.Label("Asset bundle to analyze", EditorStyles.boldLabel); 96 | if (currentObject != null) 97 | { 98 | FileInfo file = new FileInfo(assetPath); 99 | 100 | GUILayout.Label(" file: " + assetPath); 101 | GUILayout.Label(" size: " + file.Length / 1024 + " Kb"); 102 | } 103 | else 104 | { 105 | GUILayout.Label(" file: None (select in project)"); 106 | GUILayout.Label(" size: 0 Kb"); 107 | } 108 | 109 | GUILayout.Label("Settings", EditorStyles.boldLabel); 110 | 111 | compressed = EditorGUILayout.Toggle(" Compress", compressed); 112 | buildTarget = (BuildTarget)EditorGUILayout.EnumPopup(" Build Target", buildTarget); 113 | 114 | EditorGUILayout.BeginHorizontal(); 115 | { 116 | selectedPath = EditorGUILayout.TextField(" Output path: ", selectedPath); 117 | if (GUILayout.Button("select", GUILayout.Width(50))) 118 | { 119 | selectedPath = EditorUtility.SaveFolderPanel("Select output directory", "", selectedPath); 120 | } 121 | 122 | outputPath = selectedPath + "/.analyze"; 123 | } 124 | EditorGUILayout.EndHorizontal(); 125 | 126 | EditorGUILayout.Space(); 127 | if (GUILayout.Button("analyze", GUILayout.Width(100)) && currentObject != null) 128 | { 129 | if (outputPath.Length == 0) 130 | { 131 | Debug.LogError("Please select valid output path"); 132 | return; 133 | } 134 | 135 | try 136 | { 137 | if (Directory.Exists(outputPath)) 138 | { 139 | Directory.Delete(outputPath, true); 140 | } 141 | } 142 | finally 143 | { 144 | Directory.CreateDirectory(outputPath); 145 | } 146 | 147 | if (!Directory.Exists(outputPath)) 148 | { 149 | Debug.LogError("Please select valid output path"); 150 | return; 151 | } 152 | 153 | analyzeAssetBundle(currentObject, buildTarget); 154 | } 155 | 156 | if (analyzedObject != currentObject) 157 | { 158 | statistics.Clear(); 159 | analyzedObject = null; 160 | } 161 | 162 | if (analyzedObject != null) 163 | { 164 | scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); 165 | { 166 | string curType = ""; 167 | 168 | foreach (StatData data in statistics) 169 | { 170 | if (curType != data.typeName) 171 | { 172 | EditorGUILayout.BeginHorizontal(); 173 | { 174 | typeStatusMap[data.typeName] = EditorGUILayout.Foldout(typeStatusMap[data.typeName], data.typeName); 175 | 176 | GUI.skin.label.alignment = TextAnchor.MiddleRight; 177 | GUI.skin.label.fontStyle = FontStyle.Bold; 178 | 179 | GUILayout.Label(typeSizeMap[data.typeName] / 1024 + " Kb"); 180 | GUILayout.Space(400); 181 | } 182 | EditorGUILayout.EndHorizontal(); 183 | 184 | curType = data.typeName; 185 | } 186 | 187 | if (typeStatusMap[data.typeName]) 188 | { 189 | EditorGUILayout.BeginHorizontal(); 190 | { 191 | GUI.skin.label.alignment = TextAnchor.MiddleLeft; 192 | GUI.skin.label.fontStyle = FontStyle.Normal; 193 | 194 | GUILayout.Label(" " + data.objName); 195 | 196 | GUI.skin.label.alignment = TextAnchor.MiddleRight; 197 | GUILayout.Label(data.size / 1024 + " Kb"); 198 | 199 | GUILayout.Space(400); 200 | } 201 | EditorGUILayout.EndHorizontal(); 202 | } 203 | } 204 | } 205 | EditorGUILayout.EndScrollView(); 206 | } 207 | } 208 | 209 | private void analyzeAssetBundle(Object obj, BuildTarget buildTarget) 210 | { 211 | typeStatusMap.Clear(); 212 | typeSizeMap.Clear(); 213 | statistics.Clear(); 214 | analyzedObject = obj; 215 | 216 | string assetPath = Path.GetFullPath(AssetDatabase.GetAssetPath(obj)); 217 | WWW www = new WWW("file:///" + assetPath); 218 | Object[] loadedObjects = www.assetBundle.LoadAllAssets(); 219 | 220 | foreach (Object loadedObj in loadedObjects) 221 | { 222 | string directory = outputPath + "/" + loadedObj.GetType().FullName + "/"; 223 | if (!Directory.Exists(directory)) 224 | { 225 | Directory.CreateDirectory(directory); 226 | } 227 | 228 | string bundlePath = directory + loadedObj.name.Replace("/", ".") + "." + loadedObj.GetInstanceID() + ".bytes"; 229 | BuildPipeline.BuildAssetBundle(loadedObj, null, bundlePath, 230 | compressed ? 0 : BuildAssetBundleOptions.UncompressedAssetBundle, 231 | buildTarget); 232 | 233 | if (File.Exists(bundlePath)) 234 | { 235 | StatData stat = new StatData(); 236 | stat.objName = loadedObj.name; 237 | stat.typeName = loadedObj.GetType().FullName; 238 | 239 | FileInfo fileInfo = new FileInfo(bundlePath); 240 | stat.size = (int)fileInfo.Length; 241 | 242 | statistics.Add(stat); 243 | } 244 | } 245 | 246 | www.assetBundle.Unload(true); 247 | www.Dispose(); 248 | 249 | foreach (StatData data in statistics) 250 | { 251 | if (typeSizeMap.ContainsKey(data.typeName)) 252 | { 253 | typeSizeMap[data.typeName] += data.size; 254 | } 255 | else 256 | { 257 | typeSizeMap.Add(data.typeName, data.size); 258 | } 259 | } 260 | 261 | foreach (string typeName in typeSizeMap.Keys) 262 | { 263 | typeStatusMap.Add(typeName, false); 264 | } 265 | 266 | statistics.Sort(new StatDataComparer(typeSizeMap)); 267 | } 268 | } -------------------------------------------------------------------------------- /KKTools/Editor/Finder/GameObjectFinder.cs: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | // Author : K.(k79k06k02k) 3 | // FileName : GameObjectFinder.cs 4 | // Reference: http://wiki.unity3d.com/index.php/FindGameObjects 5 | **********************************************************/ 6 | using UnityEngine; 7 | using UnityEditor; 8 | using System.Linq; 9 | using System.Collections.Generic; 10 | 11 | public class GameObjectFinder : EditorWindow 12 | { 13 | private static string _staticFilterString = ""; 14 | 15 | 16 | public static void ShowWindow() 17 | { 18 | var window = (GameObjectFinder)EditorWindow.GetWindow(typeof(GameObjectFinder), false, "Finder", true); 19 | window.position = new Rect(100, 100, 800, 600); 20 | window.Initialize(); 21 | } 22 | 23 | 24 | public void Initialize() 25 | { 26 | if (_initialized) return; 27 | 28 | _filterString = _staticFilterString; 29 | 30 | EditorApplication.hierarchyWindowChanged += GetSceneGameObjects; 31 | EditorApplication.hierarchyWindowChanged += TryAutoSearch; 32 | EditorApplication.projectWindowChanged += GetProjectGameObjects; 33 | EditorApplication.projectWindowChanged += TryAutoSearch; 34 | 35 | GetComponentTypes(); 36 | GetSceneGameObjects(); 37 | GetProjectGameObjects(); 38 | TryAutoSearch(); 39 | 40 | _initialized = true; 41 | } 42 | 43 | private float _INVERT_WIDTH = 120; 44 | private float _EXTRAS_WIDTH = 135; 45 | private bool _initialized = false; 46 | 47 | private void OnGUI() 48 | { 49 | Initialize(); 50 | 51 | if (Event.current.type == EventType.KeyDown) ProcessKeyEvent(Event.current); 52 | 53 | EditorGUI.BeginChangeCheck(); 54 | 55 | DrawIncludedObjects(); 56 | 57 | DrawFilters(); 58 | 59 | if (EditorGUI.EndChangeCheck()) TryAutoSearch(); 60 | 61 | DrawResults(); 62 | 63 | DrawSettings(); 64 | } 65 | 66 | private void ProcessKeyEvent(Event current) 67 | { 68 | int index = _results.IndexOf(_selectedListing); 69 | switch (current.keyCode) 70 | { 71 | case KeyCode.UpArrow: 72 | index -= 1; 73 | break; 74 | 75 | case KeyCode.DownArrow: 76 | index += 1; 77 | break; 78 | 79 | default: 80 | return; 81 | } 82 | 83 | index = Wrap(index, _results.Count); 84 | _selectedListing = _results[index]; 85 | 86 | Selection.activeGameObject = _selectedListing.GameObject; 87 | EditorGUIUtility.PingObject(_selectedListing.GameObject); 88 | 89 | float listingHeight = EditorStyles.toolbarButton.CalcHeight(new GUIContent(" "), 100); 90 | float listingPosition = index * listingHeight; 91 | 92 | float completeListingHeight = Mathf.Floor(_scrollHeight / listingHeight) * listingHeight; 93 | float heightDifference = _scrollHeight - completeListingHeight; 94 | 95 | if (listingPosition > _resultScrollbarPosition.y + completeListingHeight - heightDifference) _resultScrollbarPosition.y = listingPosition - completeListingHeight - heightDifference + listingHeight; 96 | 97 | if (listingPosition < _resultScrollbarPosition.y) _resultScrollbarPosition.y = listingPosition; 98 | 99 | Repaint(); 100 | } 101 | 102 | private void DrawSearchButton() 103 | { 104 | if (!_autoSearch) 105 | { 106 | var style = EditorStyles.miniButton; 107 | FontStyle oldFontStyle = style.fontStyle; 108 | if (!_autoSearch && _wantSearch) 109 | { 110 | style.fontStyle = FontStyle.Bold; 111 | } 112 | if (GUILayout.Button("Search", style)) UpdateSearch(); 113 | style.fontStyle = oldFontStyle; 114 | } 115 | } 116 | 117 | private bool _foldoutIncludedObjects = true; 118 | private void DrawIncludedObjects() 119 | { 120 | EditorGUILayout.Space(); 121 | 122 | if (GUILayout.Button(new GUIContent("Included GameObjects"), EditorStyles.toolbarButton)) _foldoutIncludedObjects = !_foldoutIncludedObjects; 123 | 124 | if (_foldoutIncludedObjects) 125 | { 126 | EditorGUI.indentLevel++; 127 | DrawIncludePrefabObjects(); 128 | DrawIncludeSceneObjects(); 129 | EditorGUI.indentLevel--; 130 | } 131 | } 132 | 133 | private bool _foldoutSettings = false; 134 | private bool _autoSearch = true; 135 | private bool _wantSearch = false; 136 | private void DrawSettings() 137 | { 138 | GUILayout.FlexibleSpace(); 139 | 140 | if (GUILayout.Button(new GUIContent("Settings"), EditorStyles.toolbarButton)) _foldoutSettings = !_foldoutSettings; 141 | 142 | if (_foldoutSettings) 143 | { 144 | _autoSearch = EditorGUILayout.ToggleLeft(new GUIContent("Auto-Search", "On-the-fly search updating. Use the \"Search\" button to manually update the results."), _autoSearch); 145 | } 146 | } 147 | 148 | private GameObjectListing _selectedListing; 149 | private Vector2 _resultScrollbarPosition; 150 | private bool _foldoutResults = true; 151 | private float _scrollHeight; 152 | private void DrawResults() 153 | { 154 | EditorGUILayout.Space(); 155 | 156 | if (GUILayout.Button(new GUIContent(string.Format("Results ({0})", _results.Count)), EditorStyles.toolbarButton)) _foldoutResults = !_foldoutResults; 157 | 158 | if (_foldoutResults) 159 | { 160 | DrawSearchButton(); 161 | 162 | _resultScrollbarPosition = GUILayout.BeginScrollView(_resultScrollbarPosition); 163 | 164 | EditorGUI.indentLevel++; 165 | 166 | var style = EditorStyles.toolbarButton; 167 | Color oldTextColor = new Color(style.normal.textColor.r, style.normal.textColor.g, style.normal.textColor.b); 168 | TextAnchor oldAlignment = style.alignment; 169 | style.alignment = TextAnchor.MiddleLeft; 170 | foreach (var listing in _results) 171 | { 172 | style.normal.textColor = listing.Color; 173 | if (_selectedListing != null && listing == _selectedListing) style.normal.textColor = Color.white; 174 | if (GUILayout.Button(listing.GameObject.name, style)) 175 | { 176 | _selectedListing = listing; 177 | 178 | GameObject target = Event.current.button == 1 ? listing.GetRootGameObject() : listing.GameObject; 179 | Selection.activeGameObject = target; 180 | EditorGUIUtility.PingObject(target); 181 | } 182 | } 183 | style.normal.textColor = oldTextColor; 184 | style.alignment = oldAlignment; 185 | 186 | EditorGUI.indentLevel--; 187 | 188 | GUILayout.EndScrollView(); 189 | 190 | if (Event.current.type == EventType.Repaint) _scrollHeight = GUILayoutUtility.GetLastRect().height; 191 | } 192 | } 193 | 194 | private bool _foldoutFilters = true; 195 | private void DrawFilters() 196 | { 197 | EditorGUILayout.Space(); 198 | 199 | if (GUILayout.Button(new GUIContent("Filters"), EditorStyles.toolbarButton)) _foldoutFilters = !_foldoutFilters; 200 | 201 | if (_foldoutFilters) 202 | { 203 | EditorGUI.indentLevel++; 204 | 205 | DrawFilterString(); 206 | DrawFilterUnassignedScript(); 207 | DrawFilterLayer(); 208 | DrawFilterTag(); 209 | DrawFilterComponent(); 210 | DrawFilterScript(); 211 | DrawFilterStatic(); 212 | 213 | EditorGUI.indentLevel--; 214 | } 215 | } 216 | 217 | private bool _filterStatic; 218 | private bool _invertStaticFilter; 219 | private StaticEditorFlags _filteredStaticFlag = StaticEditorFlags.LightmapStatic; 220 | private void DrawFilterStatic() 221 | { 222 | EditorGUILayout.BeginHorizontal(); 223 | _filterStatic = EditorGUILayout.ToggleLeft(new GUIContent("Static", "Filter objects by static flag."), _filterStatic); 224 | if (_filterStatic) 225 | { 226 | _filteredStaticFlag = (StaticEditorFlags)EditorGUILayout.EnumPopup(_filteredStaticFlag); 227 | if (GUILayout.Button(_invertStaticFilter ? new GUIContent("Not Set", "Objects without this static flag set.") 228 | : new GUIContent("Is Set", "Objects with this static flag set."), 229 | EditorStyles.miniButton, GUILayout.Width(_INVERT_WIDTH))) 230 | _invertStaticFilter = !_invertStaticFilter; 231 | } 232 | EditorGUILayout.EndHorizontal(); 233 | } 234 | 235 | private bool _filterComponent; 236 | private bool _invertComponentFilter; 237 | private int _filteredComponentIndex = 0; 238 | private void DrawFilterComponent() 239 | { 240 | EditorGUILayout.BeginHorizontal(); 241 | 242 | _filterComponent = EditorGUILayout.ToggleLeft(new GUIContent("Component", "Filter objects by component."), _filterComponent); 243 | if (_filterComponent) 244 | { 245 | _filteredComponentIndex = EditorGUILayout.Popup(_filteredComponentIndex, _componentNames); 246 | if (GUILayout.Button(_invertComponentFilter ? new GUIContent("Missing Component", "Objects without this component.") 247 | : new GUIContent("Has Component", "Objects with this component."), 248 | EditorStyles.miniButton, GUILayout.Width(_INVERT_WIDTH))) 249 | _invertComponentFilter = !_invertComponentFilter; 250 | } 251 | 252 | EditorGUILayout.EndHorizontal(); 253 | 254 | if (!_invertComponentFilter) 255 | { 256 | DrawColliderFilterExtras(); 257 | } 258 | } 259 | 260 | private enum ColliderFilterExtras { All, IsTrigger, IsNotTrigger } 261 | private ColliderFilterExtras _colliderFilterExtra = ColliderFilterExtras.All; 262 | private bool _filterComponentIsCollider; 263 | private void DrawColliderFilterExtras() 264 | { 265 | if (_filterComponent) 266 | { 267 | System.Type type = _componentTypes[_filteredComponentIndex]; 268 | if (type == null) return; 269 | 270 | _filterComponentIsCollider = type == typeof(Collider) || type.IsSubclassOf(typeof(Collider)) || type == typeof(Collider2D) || type.IsSubclassOf(typeof(Collider2D)); 271 | 272 | if (_filterComponentIsCollider) 273 | { 274 | EditorGUILayout.BeginHorizontal(); 275 | EditorGUILayout.Space(); 276 | _colliderFilterExtra = (ColliderFilterExtras)EditorGUILayout.EnumPopup(_colliderFilterExtra, GUILayout.Width(_EXTRAS_WIDTH)); 277 | EditorGUILayout.EndHorizontal(); 278 | } 279 | } 280 | } 281 | 282 | private bool FilterColliderComponent(Component component) 283 | { 284 | if (_filterComponentIsCollider) 285 | { 286 | if (_colliderFilterExtra == ColliderFilterExtras.All) return false; 287 | 288 | if (component is Collider) 289 | { 290 | switch (_colliderFilterExtra) 291 | { 292 | case ColliderFilterExtras.IsTrigger: 293 | return !((Collider)component).isTrigger; 294 | 295 | case ColliderFilterExtras.IsNotTrigger: 296 | return ((Collider)component).isTrigger; 297 | } 298 | } 299 | else if (component is Collider2D) 300 | { 301 | switch (_colliderFilterExtra) 302 | { 303 | case ColliderFilterExtras.IsTrigger: 304 | return !((Collider2D)component).isTrigger; 305 | 306 | case ColliderFilterExtras.IsNotTrigger: 307 | return ((Collider2D)component).isTrigger; 308 | } 309 | } 310 | } 311 | 312 | return true; 313 | } 314 | 315 | private string[] _componentNames; 316 | private System.Type[] _componentTypes; 317 | private void GetComponentTypes() 318 | { 319 | var assembly = System.Reflection.Assembly.GetAssembly(typeof(Component)); 320 | _componentTypes = assembly.GetTypes().Where(t => typeof(Component).IsAssignableFrom(t) && t.IsPublic && t != typeof(Component)).ToArray(); 321 | 322 | _componentNames = new string[_componentTypes.Length]; 323 | for (int i = 0; i < _componentTypes.Length; i++) _componentNames[i] = GetComponentName(_componentTypes[i]); 324 | 325 | for (int i = 0; i < _componentNames.Length; i++) 326 | { 327 | string name = _componentNames[i]; 328 | 329 | bool contained = false; 330 | for (int j = 0; j < _componentNames.Length; j++) 331 | { 332 | if (i == j) continue; 333 | 334 | if (_componentNames[j].Contains(name + "/")) 335 | { 336 | contained = true; 337 | break; 338 | } 339 | } 340 | 341 | if (contained) _componentNames[i] = name + '/' + name.Split('/').Last(); 342 | } 343 | } 344 | 345 | private string GetComponentName(System.Type type) 346 | { 347 | string name = type.Name; 348 | while (type.BaseType != null && type.BaseType != typeof(Component) && type.BaseType != typeof(Behaviour)) 349 | { 350 | name = type.BaseType.Name + "/" + name; 351 | type = type.BaseType; 352 | } 353 | 354 | return name; 355 | } 356 | 357 | private bool _filterScript; 358 | private bool _invertScriptFilter; 359 | private MonoScript _filteredScript = null; 360 | private void DrawFilterScript() 361 | { 362 | EditorGUILayout.BeginHorizontal(); 363 | _filterScript = EditorGUILayout.ToggleLeft(new GUIContent("Script", "Filter objects by script."), _filterScript); 364 | if (_filterScript) 365 | { 366 | _filteredScript = (MonoScript)EditorGUILayout.ObjectField(_filteredScript, typeof(MonoScript), true); 367 | if (_filteredScript != null) 368 | { 369 | var type = _filteredScript.GetClass(); 370 | if (type.IsAbstract) _filteredScript = null; 371 | if (!type.IsSubclassOf(typeof(MonoBehaviour))) _filteredScript = null; 372 | } 373 | 374 | if (GUILayout.Button(_invertScriptFilter ? new GUIContent("Missing Script", "Objects without this script.") 375 | : new GUIContent("Has Script", "Objects with this script."), 376 | EditorStyles.miniButton, GUILayout.Width(_INVERT_WIDTH))) 377 | _invertScriptFilter = !_invertScriptFilter; 378 | } 379 | EditorGUILayout.EndHorizontal(); 380 | } 381 | 382 | private bool _filterTag; 383 | private bool _invertTagFilter; 384 | private string _filteredTag = "Untagged"; 385 | private void DrawFilterTag() 386 | { 387 | EditorGUILayout.BeginHorizontal(); 388 | _filterTag = EditorGUILayout.ToggleLeft(new GUIContent("Tag", "Filter objects by tag."), _filterTag); 389 | 390 | if (_filterTag) 391 | { 392 | _filteredTag = EditorGUILayout.TagField(_filteredTag); 393 | if (GUILayout.Button(_invertTagFilter ? new GUIContent("Not Tagged", "Objects without this tag.") 394 | : new GUIContent("Is Tagged", "Objects with this tag."), 395 | EditorStyles.miniButton, GUILayout.Width(_INVERT_WIDTH))) 396 | _invertTagFilter = !_invertTagFilter; 397 | } 398 | EditorGUILayout.EndHorizontal(); 399 | } 400 | 401 | private bool _filterLayer; 402 | private bool _invertLayerFilter; 403 | private LayerMask _filteredLayer; 404 | private void DrawFilterLayer() 405 | { 406 | EditorGUILayout.BeginHorizontal(); 407 | _filterLayer = EditorGUILayout.ToggleLeft(new GUIContent("Layer", "Filter objects by layer."), _filterLayer); 408 | 409 | if (_filterLayer) 410 | { 411 | _filteredLayer = EditorGUILayout.LayerField(_filteredLayer); 412 | if (GUILayout.Button(_invertLayerFilter ? new GUIContent("Not In Layer", "Objects not in this layer.") 413 | : new GUIContent("In Layer", "Objects in this layer."), 414 | EditorStyles.miniButton, GUILayout.Width(_INVERT_WIDTH))) 415 | _invertLayerFilter = !_invertLayerFilter; 416 | } 417 | EditorGUILayout.EndHorizontal(); 418 | } 419 | 420 | private bool _filterUnassignedScript; 421 | private void DrawFilterUnassignedScript() 422 | { 423 | _filterUnassignedScript = EditorGUILayout.ToggleLeft(new GUIContent("Unassigned Script", "Objects with unassigned script components."), _filterUnassignedScript); 424 | } 425 | 426 | private string _filterString = ""; 427 | private bool _caseSensitive = false; 428 | private void DrawFilterString() 429 | { 430 | EditorGUILayout.BeginHorizontal(); 431 | string newFilterString = EditorGUILayout.TextField(_filterString); 432 | if (_filterString != newFilterString) 433 | { 434 | _filterString = newFilterString; 435 | _staticFilterString = _filterString; 436 | } 437 | 438 | if (GUILayout.Button(_caseSensitive ? new GUIContent("Match Case", "Use case sensitive name searching.") 439 | : new GUIContent("Ignore Case", "Use any-case name searching."), 440 | EditorStyles.miniButton, GUILayout.Width(_INVERT_WIDTH))) 441 | _caseSensitive = !_caseSensitive; 442 | EditorGUILayout.EndHorizontal(); 443 | } 444 | 445 | private bool _includeSceneObjects = false; 446 | private void DrawIncludeSceneObjects() 447 | { 448 | _includeSceneObjects = EditorGUILayout.ToggleLeft(new GUIContent("Include Scene", "Include scene gameobjects in the search."), _includeSceneObjects); 449 | } 450 | 451 | private bool _includePrefabObjects = true; 452 | private bool _includePrefabChildren = false; 453 | private void DrawIncludePrefabObjects() 454 | { 455 | EditorGUILayout.BeginHorizontal(); 456 | _includePrefabObjects = EditorGUILayout.ToggleLeft(new GUIContent("Include Prefabs", "Include prefab gameobjects in the search."), _includePrefabObjects); 457 | if (_includePrefabObjects) 458 | { 459 | if (GUILayout.Button(_includePrefabChildren ? new GUIContent("With Children", "Include chilcren in the seasrch.") 460 | : new GUIContent("No Children", "Exclude children in the search."), EditorStyles.miniButton, GUILayout.Width(_INVERT_WIDTH))) 461 | { 462 | _includePrefabChildren = !_includePrefabChildren; 463 | GetProjectGameObjects(); 464 | } 465 | } 466 | EditorGUILayout.EndHorizontal(); 467 | } 468 | 469 | private bool _focused; 470 | private void OnFocus() { _focused = true; } 471 | private void OnLostFocus() { _focused = false; } 472 | 473 | private int _MAX_AUTO_SEARCHABLE = 10000; 474 | private void TryAutoSearch() 475 | { 476 | 477 | if (_autoSearch) 478 | { 479 | int numObjectsToSearch = 0; 480 | if (_includePrefabObjects) numObjectsToSearch += _projectListings.Length; 481 | if (_includeSceneObjects) numObjectsToSearch += _sceneListings.Length; 482 | if (numObjectsToSearch > _MAX_AUTO_SEARCHABLE) 483 | { 484 | _autoSearch = false; 485 | Debug.LogWarning(string.Format("Auto-Searching disabled! Attempted to search {0} (>{1}) objects without express permission from user. Searches of this magnitude must be made manually.", numObjectsToSearch, _MAX_AUTO_SEARCHABLE)); 486 | _wantSearch = true; 487 | return; 488 | } 489 | UpdateSearch(); 490 | } 491 | else 492 | { 493 | _wantSearch = true; 494 | } 495 | } 496 | 497 | private void UpdateSearch() 498 | { 499 | Search(); 500 | _wantSearch = false; 501 | _resultScrollbarPosition = Vector2.zero; 502 | _selectedListing = null; 503 | } 504 | 505 | private List _results = new List(); 506 | private void Search() 507 | { 508 | _results = new List(); 509 | 510 | if (_includePrefabObjects) 511 | { 512 | _results.AddRange(Filter(_projectListings)); 513 | } 514 | 515 | if (_includeSceneObjects) 516 | { 517 | _results.AddRange(Filter(_sceneListings)); 518 | } 519 | 520 | if (!_focused) Repaint(); 521 | } 522 | 523 | private List Filter(GameObjectListing[] gameObjectListings) 524 | { 525 | string filterString = _caseSensitive ? _filterString : _filterString.ToLower(); 526 | string[] filterSubstrings = filterString.Split(new char[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries); 527 | 528 | var filtered = new List(); 529 | if (gameObjectListings == null) return filtered; 530 | foreach (var listing in gameObjectListings) 531 | { 532 | GameObject go = listing.GameObject; 533 | 534 | bool passSubstringFilter = true; 535 | foreach (var substring in filterSubstrings) 536 | { 537 | if (_caseSensitive ? !go.name.Contains(substring) : !go.name.ToLower().Contains(substring)) 538 | { 539 | passSubstringFilter = false; 540 | break; 541 | } 542 | } 543 | if (!passSubstringFilter) continue; 544 | 545 | if (_filterUnassignedScript) 546 | { 547 | bool passMissingScriptFilter = false; 548 | var components = go.GetComponents(); 549 | foreach (var component in components) 550 | { 551 | if (component == null) 552 | { 553 | passMissingScriptFilter = true; 554 | break; 555 | } 556 | } 557 | if (!passMissingScriptFilter) continue; 558 | } 559 | 560 | if (_filterLayer && _invertLayerFilter != (_filteredLayer != go.layer)) continue; 561 | 562 | if (_filterTag && _invertTagFilter != (!go.CompareTag(_filteredTag))) continue; 563 | 564 | if (_filterComponent) 565 | { 566 | System.Type componentType = _componentTypes[_filteredComponentIndex]; 567 | if (componentType != null) 568 | { 569 | var component = go.GetComponent(componentType); 570 | if (_invertComponentFilter && component != null || !_invertComponentFilter && component == null) continue; 571 | 572 | if (!_invertComponentFilter && _filterComponentIsCollider && FilterColliderComponent(component)) continue; 573 | } 574 | } 575 | 576 | if (_filterScript && _filteredScript != null && _invertScriptFilter != (go.GetComponent(_filteredScript.GetClass()) == null)) continue; 577 | 578 | if (_filterStatic && _invertStaticFilter != !GameObjectUtility.AreStaticEditorFlagsSet(go, _filteredStaticFlag)) continue; 579 | 580 | filtered.Add(listing); 581 | } 582 | 583 | return filtered; 584 | } 585 | 586 | private GameObjectListing[] _sceneListings = new GameObjectListing[0]; 587 | private void GetSceneGameObjects() 588 | { 589 | GameObject[] sceneGameObjects = FindObjectsOfType(); 590 | 591 | _sceneListings = new GameObjectListing[sceneGameObjects.Length]; 592 | for (int i = 0; i < sceneGameObjects.Length; i++) _sceneListings[i] = new GameObjectListing(sceneGameObjects[i]); 593 | } 594 | 595 | private GameObjectListing[] _projectListings = new GameObjectListing[0]; 596 | private void GetProjectGameObjects() 597 | { 598 | string[] files = System.IO.Directory.GetFiles(Application.dataPath, "*.prefab", System.IO.SearchOption.AllDirectories); 599 | int dataPathLength = Application.dataPath.Length - "Assets".Length; 600 | 601 | List prefabs = new List(); 602 | foreach (string fullPath in files) 603 | { 604 | string path = fullPath.Remove(0, dataPathLength); 605 | GameObject go = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject; 606 | if (go != null) 607 | { 608 | prefabs.Add(new GameObjectListing(go)); 609 | 610 | if (_includePrefabChildren) prefabs.AddRange(GetChildGameObjects(go.transform)); 611 | } 612 | } 613 | 614 | _projectListings = prefabs.ToArray(); 615 | } 616 | 617 | private List GetChildGameObjects(Transform parent) 618 | { 619 | var children = new List(); 620 | 621 | int childCount = parent.childCount; 622 | for (int i = 0; i < childCount; i++) 623 | { 624 | Transform child = parent.GetChild(i); 625 | children.Add(new GameObjectListing(child.gameObject, parent.gameObject)); 626 | children.AddRange(GetChildGameObjects(child)); 627 | } 628 | 629 | return children; 630 | } 631 | 632 | private int Wrap(int number, int max) 633 | { 634 | return ((number % max) + max) % max; 635 | } 636 | 637 | private class GameObjectListing 638 | { 639 | public static Color PrefabColor = new Color(77f / 255, 128f / 255, 217f / 255); 640 | public static Color PrefabChildColor = new Color(126f / 255, 158f / 255, 215f / 255); 641 | public static Color DefaultColor = new Color(180f / 255, 180f / 255, 180f / 255); 642 | 643 | public Color Color 644 | { 645 | get 646 | { 647 | if (_prefabType == PrefabType.Prefab || _prefabType == PrefabType.PrefabInstance) 648 | { 649 | return _isChild ? GameObjectListing.PrefabChildColor : GameObjectListing.PrefabColor; 650 | } 651 | else 652 | { 653 | return GameObjectListing.DefaultColor; 654 | } 655 | } 656 | } 657 | 658 | public readonly GameObject GameObject; 659 | public readonly GameObject Parent; 660 | private PrefabType _prefabType; 661 | private bool _isChild; 662 | public GameObjectListing(GameObject gameObject, GameObject parent = null) 663 | { 664 | GameObject = gameObject; 665 | Parent = parent; 666 | _prefabType = PrefabUtility.GetPrefabType(gameObject); 667 | _isChild = parent != null || PrefabUtility.FindRootGameObjectWithSameParentPrefab(gameObject) != gameObject; 668 | } 669 | 670 | public GameObject GetRootGameObject() 671 | { 672 | return GameObject.transform.root.gameObject; 673 | } 674 | } 675 | } --------------------------------------------------------------------------------