YIUIDemoWindow.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. //------------------------------------------------------------
  2. // Author: 亦亦
  3. // Mail: 379338943@qq.com
  4. // Data: 2023年2月12日
  5. //------------------------------------------------------------
  6. using System;
  7. using System.IO;
  8. using System.Reflection;
  9. using System.Text;
  10. using System.Text.RegularExpressions;
  11. using Sirenix.OdinInspector;
  12. using Sirenix.OdinInspector.Editor;
  13. using TMPro;
  14. using UnityEditor;
  15. using UnityEditor.SceneManagement;
  16. using UnityEngine;
  17. using YooAsset.Editor;
  18. namespace YIUIFramework.Editor
  19. {
  20. public class YIUIDemoWindow : OdinEditorWindow
  21. {
  22. [Button("YIUI运行指南", 30, Icon = SdfIconType.Link45deg, IconAlignment = IconAlignment.LeftOfText)]
  23. [PropertyOrder(-99999)]
  24. public void OpenDocument()
  25. {
  26. Application.OpenURL("https://lib9kmxvq7k.feishu.cn/wiki/H7SmwXozNiliN3kahZFcqQxqnub");
  27. }
  28. [MenuItem("ET/YIUI Demo")]
  29. private static void OpenWindow()
  30. {
  31. var window = GetWindow<YIUIDemoWindow>("YIUIDemo");
  32. window.Show();
  33. }
  34. //[MenuItem("Tools/关闭 YIUI Demo")]
  35. //错误时使用的 面板出现了错误 会导致如何都打不开 就需要先关闭
  36. private static void CloseWindow()
  37. {
  38. GetWindow<YIUIDemoWindow>().Close();
  39. }
  40. //关闭后刷新资源
  41. public static void CloseWindowRefresh()
  42. {
  43. CloseWindow();
  44. AssetDatabase.SaveAssets();
  45. EditorApplication.ExecuteMenuItem("ET/Loader/ReGenerateProjectAssemblyReference");
  46. EditorApplication.ExecuteMenuItem("Assets/Refresh");
  47. }
  48. private const string YIUIPackageName = "yiuistatesync";
  49. private const string ETPackageName = "statesync";
  50. private const string ETLoaderPackageName = "loader";
  51. private const string UIProjectResPath = "Assets/GameRes/YIUI";
  52. public enum EDemoType
  53. {
  54. YIUI,
  55. ET
  56. }
  57. [Title("模式")]
  58. [HideLabel]
  59. [EnumToggleButtons]
  60. public EDemoType DemoType;
  61. private bool OpenYIUI => DemoType == EDemoType.YIUI;
  62. [BoxGroup(" ")]
  63. [Button("切换Demo", 50), GUIColor(0.4f, 0.8f, 1)]
  64. private void Switch()
  65. {
  66. var tips = "";
  67. if (SyncYooAssetSetting() && CopyET() && ChangeFile() && SwitchToScene())
  68. {
  69. tips = $"成功切换Demo >> {(OpenYIUI ? "YIUI" : "ET")} \n记得编译ET.sln工程!!!";
  70. }
  71. else
  72. {
  73. tips = $"切换Demo 失败 请检查";
  74. }
  75. EditorUtility.DisplayDialog("提示", tips, "确认");
  76. CloseWindowRefresh();
  77. ScriptsReferencesHelper.Run();
  78. }
  79. [HorizontalGroup("DemoChange")]
  80. [Button("同步YooAsset设置", 30)]
  81. private void DemoSyncYooAssetSetting()
  82. {
  83. if (SyncYooAssetSetting())
  84. {
  85. EditorUtility.DisplayDialog("提示", "同步YooAsset设置 成功", "确认");
  86. CloseWindowRefresh();
  87. }
  88. }
  89. private bool SyncYooAssetSetting()
  90. {
  91. var yooSetting = AssetBundleCollectorSettingData.Setting;
  92. if (yooSetting == null)
  93. {
  94. Debug.LogError($"没有找到yoo设置");
  95. return false;
  96. }
  97. var yiuiSetting = SettingLoader.LoadSettingData<YIUIYooAssetSetting>();
  98. if (yiuiSetting == null)
  99. {
  100. Debug.LogError($"没有找到YIUIYooAssetSetting");
  101. return false;
  102. }
  103. var yiuiDefaultPackage = yiuiSetting.GetPackage("DefaultPackage");
  104. if (yiuiDefaultPackage == null)
  105. {
  106. Debug.LogError($"yiuiSetting 没有找到默认包 DefaultPackage");
  107. return false;
  108. }
  109. var defaultPackage = yooSetting.GetPackage("DefaultPackage");
  110. if (defaultPackage == null)
  111. {
  112. Debug.LogError($"yooSetting 没有找到默认包 DefaultPackage");
  113. return false;
  114. }
  115. yooSetting.UniqueBundleName = true;
  116. defaultPackage.EnableAddressable = true; //YIUI Demo必须开启可寻址
  117. var yiuiGroupName = "YIUI";
  118. AssetBundleCollectorGroup yiuiGroup = default;
  119. foreach (var group in defaultPackage.Groups)
  120. {
  121. if (group.GroupName == yiuiGroupName)
  122. {
  123. yiuiGroup = group;
  124. break;
  125. }
  126. }
  127. if (yiuiGroup != null)
  128. defaultPackage.Groups.Remove(yiuiGroup);
  129. defaultPackage.Groups.AddRange(yiuiDefaultPackage.Groups);
  130. CreateUIProjectRes();
  131. EditorUtility.SetDirty(yooSetting);
  132. return true;
  133. }
  134. [HorizontalGroup("DemoChange")]
  135. [Button("场景切换", 30)]
  136. private void DemoSwitchToScene()
  137. {
  138. if (SwitchToScene())
  139. {
  140. EditorUtility.DisplayDialog("提示", "场景切换 成功", "确认");
  141. CloseWindowRefresh();
  142. }
  143. }
  144. private bool SwitchToScene()
  145. {
  146. var scenePath = $"Packages/cn.etetet.{(OpenYIUI ? YIUIPackageName : ETLoaderPackageName)}/Scenes/Init.unity";
  147. var path = $"{Application.dataPath}/../{scenePath}";
  148. if (!File.Exists(path))
  149. {
  150. Debug.LogError($"路径不存在场景: {path} ");
  151. return false;
  152. }
  153. EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single);
  154. return true;
  155. }
  156. [HorizontalGroup("DemoChange")]
  157. [Button("覆盖Init场景", 30)]
  158. private void DemoChangeCoverScene()
  159. {
  160. CallBackOk("覆盖ET.Loader 的Init场景 覆盖后就无法来回切换了请注意!!!", () =>
  161. {
  162. if (DemoCoverScene())
  163. {
  164. EditorUtility.DisplayDialog("提示", "覆盖Init场景 成功", "确认");
  165. CloseWindowRefresh();
  166. }
  167. });
  168. }
  169. private bool DemoCoverScene()
  170. {
  171. var sceneYIUIPath = $"Packages/cn.etetet.{YIUIPackageName}/Scenes/Init.unity";
  172. var sceneETPath = $"Packages/cn.etetet.{ETLoaderPackageName}/Scenes/Init.unity";
  173. try
  174. {
  175. if (!File.Exists(sceneYIUIPath))
  176. {
  177. EditorUtility.DisplayDialog("提示", $"Init场景 源文件不存在。{sceneYIUIPath}", "确认");
  178. return false;
  179. }
  180. File.Copy(sceneYIUIPath, sceneETPath, true);
  181. }
  182. catch (Exception ex)
  183. {
  184. Debug.LogError($"复制 Init场景 过程中失败 注意请关闭IDE编辑器使用 {ex}");
  185. }
  186. return true;
  187. }
  188. [HorizontalGroup("DemoChange")]
  189. [Button("拷贝ET工程", 30)]
  190. private void DemoCopyET()
  191. {
  192. if (CopyET())
  193. {
  194. EditorUtility.DisplayDialog("提示", "拷贝ET工程 成功", "确认");
  195. CloseWindowRefresh();
  196. }
  197. }
  198. private bool CopyET()
  199. {
  200. var et = "ET.sln";
  201. var packageName = OpenYIUI ? YIUIPackageName : ETPackageName;
  202. var sourceFilePath = $"{Application.dataPath}/../Packages/cn.etetet.{packageName}/{et}";
  203. var destinationFilePath = $"{Application.dataPath}/../{et}";
  204. try
  205. {
  206. if (!File.Exists(sourceFilePath))
  207. {
  208. EditorUtility.DisplayDialog("提示", $"{et} 源文件不存在。{sourceFilePath}", "确认");
  209. return false;
  210. }
  211. File.Copy(sourceFilePath, destinationFilePath, true);
  212. }
  213. catch (Exception ex)
  214. {
  215. Debug.LogError($"复制ET.sln过程中失败 注意请关闭IDE编辑器使用 {ex}");
  216. //return false;
  217. }
  218. return true;
  219. }
  220. [HorizontalGroup("DemoChange")]
  221. [Button("注释文件", 30)]
  222. private void DemoChangeFile()
  223. {
  224. if (ChangeFile())
  225. {
  226. EditorUtility.DisplayDialog("提示", "注释文件 成功", "确认");
  227. CloseWindowRefresh();
  228. }
  229. }
  230. private bool ChangeFile()
  231. {
  232. if (!ReplaceEventSystem())
  233. {
  234. return false;
  235. }
  236. if (!ReplaceUIComponentSystem())
  237. {
  238. return false;
  239. }
  240. var sourceFilePath = $"{Application.dataPath}/../Packages/cn.etetet.{YIUIPackageName}/Scripts/HotfixView/Client";
  241. var csFilesInA = Directory.GetFiles(sourceFilePath, "*.cs", SearchOption.AllDirectories);
  242. foreach (var fileInA in csFilesInA)
  243. {
  244. var fileInB = fileInA.Replace("yiuistatesync", "statesync");
  245. if (!ChangeFile(fileInA, OpenYIUI))
  246. {
  247. return false;
  248. }
  249. if (!ChangeFile(fileInB, !OpenYIUI))
  250. {
  251. return false;
  252. }
  253. }
  254. return true;
  255. }
  256. private static bool ChangeFile(string path, bool open)
  257. {
  258. if (File.Exists(path))
  259. {
  260. var fileName = Path.GetFileName(path);
  261. var fileContent = File.ReadAllText(path);
  262. bool startsWithSlashStar = fileContent.StartsWith("/*");
  263. bool endsWithStarSlash = fileContent.EndsWith("*/");
  264. string modifiedContent;
  265. if (open)
  266. {
  267. modifiedContent = fileContent;
  268. if (startsWithSlashStar)
  269. {
  270. modifiedContent = modifiedContent.Substring(2);
  271. }
  272. int endLength = endsWithStarSlash ? 2 : 0;
  273. if (endLength > 0 && modifiedContent.Length > endLength)
  274. {
  275. modifiedContent = modifiedContent.Substring(0, modifiedContent.Length - endLength);
  276. }
  277. }
  278. else
  279. {
  280. if (!startsWithSlashStar)
  281. {
  282. modifiedContent = "/*" + fileContent;
  283. }
  284. else
  285. {
  286. modifiedContent = fileContent;
  287. }
  288. if (!endsWithStarSlash)
  289. {
  290. modifiedContent += "*/";
  291. }
  292. }
  293. try
  294. {
  295. File.WriteAllText(path, modifiedContent);
  296. //Debug.Log($"文件 {fileName} 已修改。 {(open ? "打开" : "关闭")}");
  297. }
  298. catch (Exception e)
  299. {
  300. Debug.LogError($"文件 {fileName} 写入失败 {e}。");
  301. return false;
  302. }
  303. }
  304. return true;
  305. }
  306. private static bool ReplaceUIComponentSystem()
  307. {
  308. string filePath = $"{Application.dataPath}/../Packages/cn.etetet.ui/Scripts/HotfixView/Client/UIComponentSystem.cs";
  309. return ReplaceFile(filePath, "self.UIGlobalComponent =", "//self.UIGlobalComponent =");
  310. }
  311. private static bool ReplaceEventSystem()
  312. {
  313. string filePath = $"{Application.dataPath}/../Packages/cn.etetet.core/Scripts/Core/Share/World/EventSystem/EventSystem.cs";
  314. return ReplaceFile(filePath, "public class EventSystem", "public partial class EventSystem");
  315. }
  316. private static bool ReplaceFile(string filePath, string oldText, string newText, string checkString = "")
  317. {
  318. if (!File.Exists(filePath))
  319. {
  320. Debug.Log($"文件不存在:{filePath}");
  321. return true;
  322. }
  323. try
  324. {
  325. string content = File.ReadAllText(filePath);
  326. if (!content.Contains(string.IsNullOrEmpty(checkString) ? oldText : checkString))
  327. {
  328. return true;
  329. }
  330. if (content.Contains(newText))
  331. {
  332. return true;
  333. }
  334. content = Regex.Replace(content, oldText, newText);
  335. File.WriteAllText(filePath, content, Encoding.UTF8);
  336. return true;
  337. }
  338. catch (Exception ex)
  339. {
  340. Debug.LogError($"替换失败:{filePath} {ex.Message}");
  341. }
  342. return false;
  343. }
  344. [BoxGroup(" ")]
  345. [Button("设置TMP中文字体", 40)]
  346. private void SetTMP()
  347. {
  348. var tmpSettings = Resources.Load<TMP_Settings>("TMP Settings");
  349. if (tmpSettings == null)
  350. {
  351. Debug.LogError($"没有找到TMP设置 请手动设置字体");
  352. return;
  353. }
  354. TMP_FontAsset newDefaultFontAsset = Resources.Load<TMP_FontAsset>("Fonts/SourceHanSansSC-VF SDF");
  355. if (newDefaultFontAsset == null)
  356. {
  357. Debug.LogError($"没有找到新的默认字体 请检查");
  358. return;
  359. }
  360. Type settingsType = typeof(TMP_Settings);
  361. FieldInfo defaultFontAssetField = settingsType.GetField("m_defaultFontAsset", BindingFlags.NonPublic | BindingFlags.Instance);
  362. if (defaultFontAssetField != null && newDefaultFontAsset != null)
  363. {
  364. defaultFontAssetField.SetValue(tmpSettings, newDefaultFontAsset);
  365. }
  366. EditorUtility.DisplayDialog("提示", "设置TMP字体完毕", "确认");
  367. CloseWindowRefresh();
  368. }
  369. [BoxGroup(" ")]
  370. [Button("打开YooAsset设置", 40)]
  371. private void SetYooAssetSetting()
  372. {
  373. Type type = typeof(AssetBundleCollectorSettingData);
  374. FieldInfo fieldInfo = type.GetField("_setting", BindingFlags.NonPublic | BindingFlags.Static);
  375. if (fieldInfo != null)
  376. {
  377. //根据Demo类型可以打开不同的YooAsset设置
  378. if (OpenYIUI)
  379. {
  380. var tempSetting = ScriptableObject.CreateInstance<AssetBundleCollectorSetting>();
  381. var yiuiSetting = SettingLoader.LoadSettingData<YIUIYooAssetSetting>();
  382. if (yiuiSetting == null)
  383. {
  384. Debug.LogError($"没有找到YIUIYooAssetSetting");
  385. return;
  386. }
  387. EditorUtility.SetDirty(yiuiSetting);
  388. tempSetting.Packages = yiuiSetting.Packages;
  389. fieldInfo.SetValue(null, tempSetting);
  390. }
  391. else
  392. {
  393. fieldInfo.SetValue(null, null);
  394. }
  395. CloseWindowRefresh();
  396. EditorApplication.ExecuteMenuItem("YooAsset/AssetBundle Collector");
  397. }
  398. else
  399. {
  400. Debug.LogError($"没有找到AssetBundleCollectorSettingData._setting");
  401. }
  402. }
  403. private void CreateUIProjectRes()
  404. {
  405. var path = $"{Application.dataPath}/../{UIProjectResPath}";
  406. if (!Directory.Exists(path))
  407. {
  408. Directory.CreateDirectory(path);
  409. }
  410. }
  411. public static void CallBackOk(string content, Action okCallBack, Action cancelCallBack = null)
  412. {
  413. #if UNITY_EDITOR
  414. var result = EditorUtility.DisplayDialog("提示", content, "确认");
  415. if (result) //确定
  416. {
  417. try
  418. {
  419. okCallBack?.Invoke();
  420. }
  421. catch (Exception e)
  422. {
  423. Debug.LogError(e);
  424. throw;
  425. }
  426. }
  427. else
  428. {
  429. try
  430. {
  431. cancelCallBack?.Invoke();
  432. }
  433. catch (Exception e)
  434. {
  435. Debug.LogError(e);
  436. throw;
  437. }
  438. }
  439. #endif
  440. }
  441. }
  442. }