using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.IO; using System.Text; using UnityEngine; using UnityEditor; using UnityEditor.SceneManagement; namespace YooAsset.Editor { /// /// 编辑器工具类 /// public static class EditorTools { static EditorTools() { InitAssembly(); } #region Assembly #if UNITY_2019_4_OR_NEWER private static void InitAssembly() { } /// /// 获取带继承关系的所有类的类型 /// public static List GetAssignableTypes(System.Type parentType) { TypeCache.TypeCollection collection = TypeCache.GetTypesDerivedFrom(parentType); return collection.ToList(); } /// /// 获取带有指定属性的所有类的类型 /// public static List GetTypesWithAttribute(System.Type attrType) { TypeCache.TypeCollection collection = TypeCache.GetTypesWithAttribute(attrType); return collection.ToList(); } #else private static readonly List _cacheTypes = new List(10000); private static void InitAssembly() { _cacheTypes.Clear(); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { List types = assembly.GetTypes().ToList(); _cacheTypes.AddRange(types); } } /// /// 获取带继承关系的所有类的类型 /// public static List GetAssignableTypes(System.Type parentType) { List result = new List(); for (int i = 0; i < _cacheTypes.Count; i++) { Type type = _cacheTypes[i]; if (parentType.IsAssignableFrom(type)) { if (type.Name == parentType.Name) continue; result.Add(type); } } return result; } /// /// 获取带有指定属性的所有类的类型 /// public static List GetTypesWithAttribute(System.Type attrType) { List result = new List(); for (int i = 0; i < _cacheTypes.Count; i++) { Type type = _cacheTypes[i]; if (type.GetCustomAttribute(attrType) != null) { result.Add(type); } } return result; } #endif /// /// 调用私有的静态方法 /// /// 类的类型 /// 类里要调用的方法名 /// 调用方法传入的参数 public static object InvokeNonPublicStaticMethod(System.Type type, string method, params object[] parameters) { var methodInfo = type.GetMethod(method, BindingFlags.NonPublic | BindingFlags.Static); if (methodInfo == null) { UnityEngine.Debug.LogError($"{type.FullName} not found method : {method}"); return null; } return methodInfo.Invoke(null, parameters); } /// /// 调用公开的静态方法 /// /// 类的类型 /// 类里要调用的方法名 /// 调用方法传入的参数 public static object InvokePublicStaticMethod(System.Type type, string method, params object[] parameters) { var methodInfo = type.GetMethod(method, BindingFlags.Public | BindingFlags.Static); if (methodInfo == null) { UnityEngine.Debug.LogError($"{type.FullName} not found method : {method}"); return null; } return methodInfo.Invoke(null, parameters); } #endregion #region EditorUtility /// /// 搜集资源 /// /// 搜集的资源类型 /// 指定搜索的文件夹列表 /// 返回搜集到的资源路径列表 public static string[] FindAssets(EAssetSearchType searchType, string[] searchInFolders) { // 注意:AssetDatabase.FindAssets()不支持末尾带分隔符的文件夹路径 for (int i = 0; i < searchInFolders.Length; i++) { string folderPath = searchInFolders[i]; searchInFolders[i] = folderPath.TrimEnd('/'); } // 注意:获取指定目录下的所有资源对象(包括子文件夹) string[] guids; if (searchType == EAssetSearchType.All) guids = AssetDatabase.FindAssets(string.Empty, searchInFolders); else guids = AssetDatabase.FindAssets($"t:{searchType}", searchInFolders); // 注意:AssetDatabase.FindAssets()可能会获取到重复的资源 HashSet result = new HashSet(); for (int i = 0; i < guids.Length; i++) { string guid = guids[i]; string assetPath = AssetDatabase.GUIDToAssetPath(guid); if (result.Contains(assetPath) == false) { result.Add(assetPath); } } // 返回结果 return result.ToArray(); } /// /// 搜集资源 /// /// 搜集的资源类型 /// 指定搜索的文件夹 /// 返回搜集到的资源路径列表 public static string[] FindAssets(EAssetSearchType searchType, string searchInFolder) { return FindAssets(searchType, new string[] { searchInFolder }); } /// /// 打开搜索面板 /// /// 标题名称 /// 默认搜索路径 /// 返回选择的文件夹绝对路径,如果无效返回NULL public static string OpenFolderPanel(string title, string defaultPath, string defaultName = "") { string openPath = EditorUtility.OpenFolderPanel(title, defaultPath, defaultName); if (string.IsNullOrEmpty(openPath)) return null; if (openPath.Contains("/Assets") == false) { Debug.LogWarning("Please select unity assets folder."); return null; } return openPath; } /// /// 打开搜索面板 /// /// 标题名称 /// 默认搜索路径 /// 返回选择的文件绝对路径,如果无效返回NULL public static string OpenFilePath(string title, string defaultPath, string extension = "") { string openPath = EditorUtility.OpenFilePanel(title, defaultPath, extension); if (string.IsNullOrEmpty(openPath)) return null; if (openPath.Contains("/Assets") == false) { Debug.LogWarning("Please select unity assets file."); return null; } return openPath; } /// /// 显示进度框 /// public static void DisplayProgressBar(string tips, int progressValue, int totalValue) { EditorUtility.DisplayProgressBar("进度", $"{tips} : {progressValue}/{totalValue}", (float)progressValue / totalValue); } /// /// 隐藏进度框 /// public static void ClearProgressBar() { EditorUtility.ClearProgressBar(); } #endregion #region EditorWindow public static void FocusUnitySceneWindow() { EditorWindow.FocusWindowIfItsOpen(); } public static void CloseUnityGameWindow() { System.Type T = Assembly.Load("UnityEditor").GetType("UnityEditor.GameView"); EditorWindow.GetWindow(T, false, "GameView", true).Close(); } public static void FocusUnityGameWindow() { System.Type T = Assembly.Load("UnityEditor").GetType("UnityEditor.GameView"); EditorWindow.GetWindow(T, false, "GameView", true); } public static void FocueUnityProjectWindow() { System.Type T = Assembly.Load("UnityEditor").GetType("UnityEditor.ProjectBrowser"); EditorWindow.GetWindow(T, false, "Project", true); } public static void FocusUnityHierarchyWindow() { System.Type T = Assembly.Load("UnityEditor").GetType("UnityEditor.SceneHierarchyWindow"); EditorWindow.GetWindow(T, false, "Hierarchy", true); } public static void FocusUnityInspectorWindow() { System.Type T = Assembly.Load("UnityEditor").GetType("UnityEditor.InspectorWindow"); EditorWindow.GetWindow(T, false, "Inspector", true); } public static void FocusUnityConsoleWindow() { System.Type T = Assembly.Load("UnityEditor").GetType("UnityEditor.ConsoleWindow"); EditorWindow.GetWindow(T, false, "Console", true); } #endregion #region EditorConsole private static MethodInfo _clearConsoleMethod; private static MethodInfo ClearConsoleMethod { get { if (_clearConsoleMethod == null) { Assembly assembly = Assembly.GetAssembly(typeof(SceneView)); System.Type logEntries = assembly.GetType("UnityEditor.LogEntries"); _clearConsoleMethod = logEntries.GetMethod("Clear"); } return _clearConsoleMethod; } } /// /// 清空控制台 /// public static void ClearUnityConsole() { ClearConsoleMethod.Invoke(new object(), null); } #endregion #region SceneUtility public static bool HasDirtyScenes() { var sceneCount = EditorSceneManager.sceneCount; for (var i = 0; i < sceneCount; ++i) { var scene = EditorSceneManager.GetSceneAt(i); if (scene.isDirty) return true; } return false; } #endregion #region StringUtility public static string RemoveFirstChar(string str) { if (string.IsNullOrEmpty(str)) return str; return str.Substring(1); } public static string RemoveLastChar(string str) { if (string.IsNullOrEmpty(str)) return str; return str.Substring(0, str.Length - 1); } public static List StringToStringList(string str, char separator) { List result = new List(); if (!String.IsNullOrEmpty(str)) { string[] splits = str.Split(separator); foreach (string split in splits) { string value = split.Trim(); //移除首尾空格 if (!String.IsNullOrEmpty(value)) { result.Add(value); } } } return result; } public static T NameToEnum(string name) { if (Enum.IsDefined(typeof(T), name) == false) { throw new ArgumentException($"Enum {typeof(T)} is not defined name {name}"); } return (T)Enum.Parse(typeof(T), name); } #endregion #region 文件 /// /// 创建文件所在的目录 /// /// 文件路径 public static void CreateFileDirectory(string filePath) { string destDirectory = Path.GetDirectoryName(filePath); CreateDirectory(destDirectory); } /// /// 创建文件夹 /// public static bool CreateDirectory(string directory) { if (Directory.Exists(directory) == false) { Directory.CreateDirectory(directory); return true; } else { return false; } } /// /// 删除文件夹及子目录 /// public static bool DeleteDirectory(string directory) { if (Directory.Exists(directory)) { Directory.Delete(directory, true); return true; } else { return false; } } /// /// 文件重命名 /// public static void FileRename(string filePath, string newName) { string dirPath = Path.GetDirectoryName(filePath); string destPath; if (Path.HasExtension(filePath)) { string extentsion = Path.GetExtension(filePath); destPath = $"{dirPath}/{newName}{extentsion}"; } else { destPath = $"{dirPath}/{newName}"; } FileInfo fileInfo = new FileInfo(filePath); fileInfo.MoveTo(destPath); } /// /// 移动文件 /// public static void MoveFile(string filePath, string destPath) { if (File.Exists(destPath)) File.Delete(destPath); FileInfo fileInfo = new FileInfo(filePath); fileInfo.MoveTo(destPath); } /// /// 拷贝文件夹 /// 注意:包括所有子目录的文件 /// public static void CopyDirectory(string sourcePath, string destPath) { sourcePath = EditorTools.GetRegularPath(sourcePath); // If the destination directory doesn't exist, create it. if (Directory.Exists(destPath) == false) Directory.CreateDirectory(destPath); string[] fileList = Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories); foreach (string file in fileList) { string temp = EditorTools.GetRegularPath(file); string savePath = temp.Replace(sourcePath, destPath); CopyFile(file, savePath, true); } } /// /// 拷贝文件 /// public static void CopyFile(string sourcePath, string destPath, bool overwrite) { if (File.Exists(sourcePath) == false) throw new FileNotFoundException(sourcePath); // 创建目录 CreateFileDirectory(destPath); // 复制文件 File.Copy(sourcePath, destPath, overwrite); } /// /// 清空文件夹 /// /// 要清理的文件夹路径 public static void ClearFolder(string directoryPath) { if (Directory.Exists(directoryPath) == false) return; // 删除文件 string[] allFiles = Directory.GetFiles(directoryPath); for (int i = 0; i < allFiles.Length; i++) { File.Delete(allFiles[i]); } // 删除文件夹 string[] allFolders = Directory.GetDirectories(directoryPath); for (int i = 0; i < allFolders.Length; i++) { Directory.Delete(allFolders[i], true); } } /// /// 获取文件字节大小 /// public static long GetFileSize(string filePath) { FileInfo fileInfo = new FileInfo(filePath); return fileInfo.Length; } /// /// 读取文件的所有文本内容 /// public static string ReadFileAllText(string filePath) { if (File.Exists(filePath) == false) return string.Empty; return File.ReadAllText(filePath, Encoding.UTF8); } /// /// 读取文本的所有文本内容 /// public static string[] ReadFileAllLine(string filePath) { if (File.Exists(filePath) == false) return null; return File.ReadAllLines(filePath, Encoding.UTF8); } /// /// 检测AssetBundle文件是否合法 /// public static bool CheckBundleFileValid(byte[] fileData) { string signature = ReadStringToNull(fileData, 20); if (signature == "UnityFS" || signature == "UnityRaw" || signature == "UnityWeb" || signature == "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA") return true; else return false; } private static string ReadStringToNull(byte[] data, int maxLength) { List bytes = new List(); for (int i = 0; i < data.Length; i++) { if (i >= maxLength) break; byte bt = data[i]; if (bt == 0) break; bytes.Add(bt); } if (bytes.Count == 0) return string.Empty; else return Encoding.UTF8.GetString(bytes.ToArray()); } #endregion #region 路径 /// /// 获取规范的路径 /// public static string GetRegularPath(string path) { return path.Replace('\\', '/').Replace("\\", "/"); //替换为Linux路径格式 } /// /// 移除路径里的后缀名 /// public static string RemoveExtension(string str) { if (string.IsNullOrEmpty(str)) return str; int index = str.LastIndexOf('.'); if (index == -1) return str; else return str.Remove(index); //"assets/config/test.unity3d" --> "assets/config/test" } /// /// 获取项目工程路径 /// public static string GetProjectPath() { string projectPath = Path.GetDirectoryName(Application.dataPath); return GetRegularPath(projectPath); } /// /// 转换文件的绝对路径为Unity资源路径 /// 例如 D:\\YourPorject\\Assets\\Works\\file.txt 替换为 Assets/Works/file.txt /// public static string AbsolutePathToAssetPath(string absolutePath) { string content = GetRegularPath(absolutePath); return Substring(content, "Assets/", true); } /// /// 转换Unity资源路径为文件的绝对路径 /// 例如:Assets/Works/file.txt 替换为 D:\\YourPorject/Assets/Works/file.txt /// public static string AssetPathToAbsolutePath(string assetPath) { string projectPath = GetProjectPath(); return $"{projectPath}/{assetPath}"; } /// /// 递归查找目标文件夹路径 /// /// 搜索的根目录 /// 目标文件夹名称 /// 返回找到的文件夹路径,如果没有找到返回空字符串 public static string FindFolder(string root, string folderName) { DirectoryInfo rootInfo = new DirectoryInfo(root); DirectoryInfo[] infoList = rootInfo.GetDirectories(); for (int i = 0; i < infoList.Length; i++) { string fullPath = infoList[i].FullName; if (infoList[i].Name == folderName) return fullPath; string result = FindFolder(fullPath, folderName); if (string.IsNullOrEmpty(result) == false) return result; } return string.Empty; } /// /// 截取字符串 /// 获取匹配到的后面内容 /// /// 内容 /// 关键字 /// 分割的结果里是否包含关键字 /// 是否使用初始匹配的位置,否则使用末尾匹配的位置 public static string Substring(string content, string key, bool includeKey, bool firstMatch = true) { if (string.IsNullOrEmpty(key)) return content; int startIndex = -1; if (firstMatch) startIndex = content.IndexOf(key); //返回子字符串第一次出现位置 else startIndex = content.LastIndexOf(key); //返回子字符串最后出现的位置 // 如果没有找到匹配的关键字 if (startIndex == -1) return content; if (includeKey) return content.Substring(startIndex); else return content.Substring(startIndex + key.Length); } #endregion } }