SEditorUtils.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Reflection;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. using UnityEditor;
  9. using Debug = UnityEngine.Debug;
  10. namespace SUnityEditorTools
  11. {
  12. /// <summary>
  13. /// Shell / cmd / 等等常用Editor需要用到的工具集
  14. /// </summary>
  15. public class SEditorUtils
  16. {
  17. /// <summary>
  18. /// 用于非主线程里执行主线程的函数
  19. /// </summary>
  20. internal static Queue<Action> _mainThreadActions = new Queue<Action>();
  21. static SEditorUtils()
  22. {
  23. KUnityEditorEventCatcher.OnEditorUpdateEvent -= OnEditorUpdate;
  24. KUnityEditorEventCatcher.OnEditorUpdateEvent += OnEditorUpdate;
  25. }
  26. /// <summary>
  27. /// 捕获Unity Editor update事件
  28. /// </summary>
  29. private static void OnEditorUpdate()
  30. {
  31. // 主线程委托
  32. while (_mainThreadActions.Count > 0)
  33. {
  34. var action = _mainThreadActions.Dequeue();
  35. if (action != null) action();
  36. }
  37. }
  38. /// <summary>
  39. /// 异步线程回到主线程进行回调
  40. /// </summary>
  41. /// <param name="action"></param>
  42. public static void CallMainThread(Action action)
  43. {
  44. _mainThreadActions.Enqueue(action);
  45. }
  46. /// <summary>
  47. /// 清除Console log
  48. /// </summary>
  49. public static void ClearConsoleLog()
  50. {
  51. Assembly assembly = Assembly.GetAssembly(typeof (ActiveEditorTracker));
  52. Type type = assembly.GetType("UnityEditorInternal.LogEntries");
  53. MethodInfo method = type.GetMethod("Clear");
  54. method.Invoke(new object(), null);
  55. }
  56. /// <summary>
  57. /// 执行批处理命令
  58. /// </summary>
  59. /// <param name="command"></param>
  60. /// <param name="workingDirectory"></param>
  61. public static void ExecuteCommand(string command, string workingDirectory = null)
  62. {
  63. var fProgress = .1f;
  64. EditorUtility.DisplayProgressBar("KEditorUtils.ExecuteCommand", command, fProgress);
  65. try
  66. {
  67. string cmd;
  68. string preArg;
  69. var os = Environment.OSVersion;
  70. Debug.Log(String.Format("[ExecuteCommand]Command on OS: {0}", os.ToString()));
  71. if (os.ToString().Contains("Windows"))
  72. {
  73. cmd = "cmd.exe";
  74. preArg = "/C ";
  75. }
  76. else
  77. {
  78. cmd = "sh";
  79. preArg = "-c ";
  80. }
  81. Debug.Log("[ExecuteCommand]" + command);
  82. var allOutput = new StringBuilder();
  83. using (var process = new Process())
  84. {
  85. if (workingDirectory != null)
  86. process.StartInfo.WorkingDirectory = workingDirectory;
  87. process.StartInfo.FileName = cmd;
  88. process.StartInfo.Arguments = preArg + "\"" + command + "\"";
  89. process.StartInfo.UseShellExecute = false;
  90. process.StartInfo.CreateNoWindow = true;
  91. process.StartInfo.RedirectStandardOutput = true;
  92. process.StartInfo.RedirectStandardError = true;
  93. process.Start();
  94. while (true)
  95. {
  96. var line = process.StandardOutput.ReadLine();
  97. if (line == null)
  98. break;
  99. allOutput.AppendLine(line);
  100. EditorUtility.DisplayProgressBar("[ExecuteCommand] " + command, line, fProgress);
  101. fProgress += .001f;
  102. }
  103. var err = process.StandardError.ReadToEnd();
  104. if (!String.IsNullOrEmpty(err))
  105. {
  106. Debug.LogError(String.Format("[ExecuteCommand] {0}", err));
  107. }
  108. process.WaitForExit();
  109. }
  110. Debug.Log("[ExecuteResult]" + allOutput);
  111. }
  112. finally
  113. {
  114. EditorUtility.ClearProgressBar();
  115. }
  116. }
  117. public delegate void EachDirectoryDelegate(string fileFullPath, string fileRelativePath);
  118. /// <summary>
  119. /// 递归一个目录所有文件,callback
  120. /// </summary>
  121. /// <param name="dirPath"></param>
  122. /// <param name="eachCallback"></param>
  123. public static void EachDirectoryFiles(string dirPath, EachDirectoryDelegate eachCallback)
  124. {
  125. foreach (var filePath in Directory.GetFiles(dirPath, "*", SearchOption.AllDirectories))
  126. {
  127. var fileRelativePath = filePath.Replace(dirPath, "");
  128. if (fileRelativePath.StartsWith("/") || fileRelativePath.StartsWith("\\"))
  129. fileRelativePath = fileRelativePath.Substring(1, fileRelativePath.Length - 1);
  130. var cleanFilePath = filePath.Replace("\\", "/");
  131. fileRelativePath = fileRelativePath.Replace("\\", "/");
  132. eachCallback(cleanFilePath, fileRelativePath);
  133. }
  134. }
  135. /// <summary>
  136. /// 将丑陋的windows路径,替换掉\字符
  137. /// </summary>
  138. /// <param name="path"></param>
  139. /// <returns></returns>
  140. public static string GetCleanPath(string path)
  141. {
  142. return path.Replace("\\", "/");
  143. }
  144. /// <summary>
  145. /// 在指定目录中搜寻字符串并返回匹配}
  146. /// </summary>
  147. /// <param name="sourceFolder"></param>
  148. /// <param name="searchWord"></param>
  149. /// <param name="fileFilter"></param>
  150. /// <returns></returns>
  151. public static Dictionary<string, List<Match>> FindStrMatchesInFolderTexts(string sourceFolder, Regex searchWord,
  152. Func<string, bool> fileFilter = null)
  153. {
  154. var retMatches = new Dictionary<string, List<Match>>();
  155. var allFiles = new List<string>();
  156. AddFileNamesToList(sourceFolder, allFiles);
  157. foreach (string fileName in allFiles)
  158. {
  159. if (fileFilter != null && !fileFilter(fileName))
  160. continue;
  161. retMatches[fileName] = new List<Match>();
  162. string contents = File.ReadAllText(fileName);
  163. var matches = searchWord.Matches(contents);
  164. if (matches.Count > 0)
  165. {
  166. for (int i = 0; i < matches.Count; i++)
  167. {
  168. retMatches[fileName].Add(matches[i]);
  169. }
  170. }
  171. }
  172. return retMatches;
  173. }
  174. private static void AddFileNamesToList(string sourceDir, List<string> allFiles)
  175. {
  176. string[] fileEntries = Directory.GetFiles(sourceDir);
  177. foreach (string fileName in fileEntries)
  178. {
  179. allFiles.Add(fileName);
  180. }
  181. //Recursion
  182. string[] subdirectoryEntries = Directory.GetDirectories(sourceDir);
  183. foreach (string item in subdirectoryEntries)
  184. {
  185. // Avoid "reparse points"
  186. if ((File.GetAttributes(item) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint)
  187. {
  188. AddFileNamesToList(item, allFiles);
  189. }
  190. }
  191. }
  192. /// <summary>
  193. /// 从所有的程序集收集指定类型,public, 包括继承的
  194. /// </summary>
  195. /// <returns></returns>
  196. public static IList<Type> FindAllPublicTypes(Type findType)
  197. {
  198. var list = new List<Type>();
  199. Assembly[] Assemblies = AppDomain.CurrentDomain.GetAssemblies();
  200. for (int n = 0; n < Assemblies.Length; n++)
  201. {
  202. Assembly asm = Assemblies[n];
  203. foreach (var type in asm.GetExportedTypes())
  204. {
  205. if (findType.IsAssignableFrom(type) || findType == type)
  206. {
  207. list.Add(type);
  208. }
  209. }
  210. }
  211. return list;
  212. }
  213. }
  214. }