ViewManager.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using AppUI.Manager;
  4. using UnityEngine;
  5. using UnityEngine.UI;
  6. namespace AppUI.Manager.View
  7. {
  8. public enum UIPrefabsFolder
  9. {
  10. Home,
  11. Component,
  12. Infrared,
  13. Manager,
  14. Module,
  15. User,
  16. Util
  17. }
  18. public enum UIViewType
  19. {
  20. HomeView,
  21. UserCenterView,
  22. DeviceView,
  23. DeviceArcheryView,
  24. DeviceGunView,
  25. PositioningView,
  26. InfraredView,
  27. SettingsView,
  28. SocialView,
  29. PersonalView,
  30. ConnectGuidanceView,
  31. InfraredScreenPositioningView,
  32. CalibrationView,
  33. HomeViewTip,
  34. GameResultView,
  35. /**旧页面或者未完成的页面**/
  36. RankingView,
  37. GyrGuidanceView,
  38. MagGuidanceView,
  39. ModeSelectView,
  40. RoleSelectView,
  41. PKMatchView,
  42. RelateValidateView,
  43. RetrievePasswordView,
  44. }
  45. public enum UIPrefabType
  46. {
  47. AuthLoginMask,
  48. SmartBowDeviceHub,
  49. ModuleView,
  50. ModuleGuestView,
  51. ModuleViewHorizontal,
  52. ModuleSideSlip,
  53. RetrievePasswordView
  54. }
  55. public class ViewConfig
  56. {
  57. public string path;
  58. public int groupIndex;
  59. public bool overrideSorting;
  60. }
  61. public class ViewManager
  62. {
  63. private static readonly string currentPrefix = "Wonderfitter/";
  64. private static GameObject currentViewParent;
  65. static Transform GetViewParent(int groupIndex) => ViewMgr.EnsureGroup(groupIndex);
  66. private class ViewCacheInfo
  67. {
  68. public string fullPath;
  69. public GameObject gameObject;
  70. }
  71. private static readonly List<ViewCacheInfo> _ViewCacheInfos = new();
  72. // =========================
  73. // 🔥 配置中心(替代所有 if)
  74. // =========================
  75. private static readonly Dictionary<UIViewType, ViewConfig> ViewConfigs = new()
  76. { {
  77. UIViewType.HomeView,
  78. new ViewConfig
  79. {
  80. path = "Home/HomeView",
  81. }
  82. },{
  83. UIViewType.UserCenterView,
  84. new ViewConfig
  85. {
  86. path = "Home/UserCenterView",
  87. }
  88. },{
  89. UIViewType.DeviceView,
  90. new ViewConfig
  91. {
  92. path = "Home/DeviceView",
  93. groupIndex = 0,
  94. }
  95. },{
  96. UIViewType.PositioningView,
  97. new ViewConfig
  98. {
  99. path = "Infrared/PositioningView",
  100. groupIndex = 0,
  101. }
  102. },{
  103. UIViewType.InfraredView,
  104. new ViewConfig
  105. {
  106. path = "Infrared/InfraredView",
  107. groupIndex = 0,
  108. }
  109. },{
  110. UIViewType.SettingsView,
  111. new ViewConfig
  112. {
  113. path = "Home/SettingsView",
  114. groupIndex = 0,
  115. }
  116. },{
  117. UIViewType.RankingView,
  118. new ViewConfig
  119. {
  120. path = "Home/RankingView",
  121. groupIndex = 0,
  122. }
  123. },
  124. {
  125. UIViewType.DeviceArcheryView,
  126. new ViewConfig
  127. {
  128. path = "Home/DeviceArcheryView"
  129. }
  130. },
  131. {
  132. UIViewType.DeviceGunView,
  133. new ViewConfig
  134. {
  135. path = "Home/DeviceGunView"
  136. }
  137. },
  138. {
  139. UIViewType.GyrGuidanceView,
  140. new ViewConfig
  141. {
  142. path = "NineAxis/GyrGuidanceView"
  143. }
  144. },
  145. {
  146. UIViewType.MagGuidanceView,
  147. new ViewConfig
  148. {
  149. path = "NineAxis/MagGuidanceView"
  150. }
  151. },{
  152. UIViewType.ModeSelectView,
  153. new ViewConfig
  154. {
  155. path = "Home/ModeSelectView"
  156. }
  157. },
  158. {
  159. UIViewType.GameResultView,
  160. new ViewConfig
  161. {
  162. path = "Common/GameResultView",
  163. groupIndex = 0,
  164. overrideSorting = true
  165. }
  166. },
  167. {
  168. UIViewType.RoleSelectView,
  169. new ViewConfig
  170. {
  171. path = "Home/RoleSelectView",
  172. groupIndex = 0,
  173. overrideSorting = true
  174. }
  175. },
  176. {
  177. UIViewType.PKMatchView,
  178. new ViewConfig
  179. {
  180. path = "Home/PKMatchView",
  181. groupIndex = 0,
  182. overrideSorting = true
  183. }
  184. },
  185. {
  186. UIViewType.InfraredScreenPositioningView,
  187. new ViewConfig
  188. {
  189. path = "Infrared/InfraredScreenPositioningView",
  190. groupIndex = 1,
  191. overrideSorting = false
  192. }
  193. }, {
  194. UIViewType.CalibrationView,
  195. new ViewConfig
  196. {
  197. path = "Infrared/CalibrationView",
  198. groupIndex = 1,
  199. overrideSorting = false
  200. }
  201. }, {
  202. UIViewType.RelateValidateView,
  203. new ViewConfig
  204. {
  205. path = "RelateValidateView/RelateValidateView",
  206. }
  207. }, {
  208. UIViewType.RetrievePasswordView,
  209. new ViewConfig
  210. {
  211. path = "User/RetrievePasswordView",
  212. }
  213. }
  214. };
  215. /**
  216. * 定义一些常用的预制体路径配置,如 ModuleView,避免在代码中硬编码字符串路径,同时也方便后续维护和修改。
  217. */
  218. private static readonly Dictionary<UIPrefabType, ViewConfig> UIPrefabConfigs = new()
  219. {
  220. {
  221. UIPrefabType.AuthLoginMask,//用户登陆的mask(BowArrow/Resources 下)
  222. new ViewConfig
  223. {
  224. path = "Textures/GameIcon/Prefabs/Parts/Home/AuthLoginMask/AuthLoginMask"
  225. }
  226. },
  227. {
  228. UIPrefabType.SmartBowDeviceHub,
  229. new ViewConfig
  230. {
  231. path = currentPrefix + "Bluetooth/SmartBowDeviceHub"
  232. }
  233. },
  234. {
  235. UIPrefabType.ModuleView,
  236. new ViewConfig
  237. {
  238. path = currentPrefix + "Module/ModuleView"
  239. }
  240. },{
  241. UIPrefabType.ModuleGuestView,
  242. new ViewConfig
  243. {
  244. path = currentPrefix + "Module/ModuleGuestView"
  245. }
  246. },
  247. {
  248. UIPrefabType.ModuleViewHorizontal,
  249. new ViewConfig
  250. {
  251. path = currentPrefix + "Module/ModuleViewHorizontal"
  252. }
  253. }, {
  254. UIPrefabType.ModuleSideSlip,
  255. new ViewConfig
  256. {
  257. path = currentPrefix + "Module/ModuleSideSlip"
  258. }
  259. } , {
  260. UIPrefabType.RetrievePasswordView,
  261. new ViewConfig
  262. {
  263. path = currentPrefix + "User/RetrievePasswordView",
  264. }
  265. }
  266. };
  267. // =========================
  268. // Show
  269. // =========================
  270. public static GameObject ShowView(UIViewType type)
  271. {
  272. ViewConfig config = ViewConfigs[type];
  273. return InstantiateView(config.path, type);
  274. }
  275. // =========================
  276. // Hide
  277. // =========================
  278. public static void HideView(UIViewType type)
  279. {
  280. _DestroyExistViews(GetFullPath(type));
  281. }
  282. public static void HideView<T>(UIPrefabsFolder folder = UIPrefabsFolder.Home)
  283. {
  284. _DestroyExistViews(ResolveFullPath<T>(folder));
  285. }
  286. public static void RemoveView(GameObject view)
  287. {
  288. if (!view) return;
  289. _ViewCacheInfos.RemoveAll(e =>
  290. {
  291. if (e.gameObject == view)
  292. {
  293. Object.Destroy(e.gameObject);
  294. return true;
  295. }
  296. return false;
  297. });
  298. }
  299. private static string GetFullPath(UIViewType type)
  300. {
  301. if (ViewConfigs.TryGetValue(type, out ViewConfig config))
  302. return currentPrefix + config.path;
  303. return currentPrefix + GetConfig(type).path;
  304. }
  305. static string ResolveFullPath<T>(UIPrefabsFolder folder)
  306. {
  307. string typeName = typeof(T).Name;
  308. if (System.Enum.TryParse(typeName, out UIViewType viewType))
  309. return GetFullPath(viewType);
  310. return currentPrefix + $"{folder}/{typeName}";
  311. }
  312. public static void RemoveView<T>(UIPrefabsFolder folder = UIPrefabsFolder.Home)
  313. {
  314. _RemoveView(ResolveFullPath<T>(folder));
  315. }
  316. // =========================
  317. // Instantiate Core
  318. // =========================
  319. private static GameObject InstantiateView(string path, UIViewType type)
  320. {
  321. _ = ViewMgr.Instance;
  322. ViewConfig config = GetConfig(type);
  323. currentViewParent = GetViewParent(config.groupIndex).gameObject;
  324. string fullPath = currentPrefix + path;
  325. _DestroyExistViews(fullPath);
  326. GameObject prefab = Resources.Load<GameObject>(fullPath);
  327. if (prefab == null)
  328. {
  329. Debug.LogError($"ViewManager: Resources 中未找到预制体 \"{fullPath}\"");
  330. return null;
  331. }
  332. GameObject o = Object.Instantiate(prefab, currentViewParent.transform);
  333. // =========================
  334. // sorting(无 if 判断)
  335. // =========================
  336. if (config.overrideSorting)
  337. {
  338. Canvas canvas = o.GetComponent<Canvas>();
  339. if (canvas != null)
  340. canvas.overrideSorting = true;
  341. }
  342. // =========================
  343. // UI适配
  344. // =========================
  345. RectTransform rectTransform = RemoveCanvasScaler(o.transform);
  346. if (rectTransform != null)
  347. {
  348. if (rectTransform == o.GetComponent<RectTransform>())
  349. {
  350. rectTransform.anchorMin = Vector2.zero;
  351. rectTransform.anchorMax = Vector2.one;
  352. rectTransform.offsetMin = Vector2.zero;
  353. rectTransform.offsetMax = Vector2.zero;
  354. rectTransform.localScale = Vector3.one;
  355. }
  356. else
  357. {
  358. rectTransform.pivot = new Vector2(0.5f, 0.5f);
  359. rectTransform.localScale = Vector3.one;
  360. rectTransform.sizeDelta = ((RectTransform)currentViewParent.transform).rect.size;
  361. rectTransform.anchoredPosition = Vector2.zero;
  362. }
  363. }
  364. _ViewCacheInfos.Add(new ViewCacheInfo
  365. {
  366. fullPath = fullPath,
  367. gameObject = o
  368. });
  369. return o;
  370. }
  371. // =========================
  372. // Config getter
  373. // =========================
  374. private static ViewConfig GetConfig(UIViewType type)
  375. {
  376. if (ViewConfigs.TryGetValue(type, out var config))
  377. return config;
  378. return new ViewConfig
  379. {
  380. path = type.ToString(),
  381. groupIndex = 0,
  382. overrideSorting = false
  383. };
  384. }
  385. public static ViewConfig GetConfig(UIPrefabType type)
  386. {
  387. if (UIPrefabConfigs.TryGetValue(type, out var config))
  388. return config;
  389. return new ViewConfig
  390. {
  391. path = type.ToString(),
  392. groupIndex = 0,
  393. overrideSorting = false
  394. };
  395. }
  396. public static GameObject GetPrefabByType(UIPrefabType type)
  397. {
  398. string path = GetConfig(type).path;
  399. GameObject prefab = Resources.Load<GameObject>(path);
  400. if (prefab == null)
  401. Debug.LogError($"ViewManager: Resources 中未找到预制体 \"{path}\" (UIPrefabType.{type})");
  402. return prefab;
  403. }
  404. // =========================
  405. // Remove CanvasScaler
  406. // =========================
  407. private static RectTransform RemoveCanvasScaler(Transform parent)
  408. {
  409. Canvas canvas = parent.GetComponent<Canvas>();
  410. if (canvas != null)
  411. {
  412. CanvasScaler scaler = parent.GetComponent<CanvasScaler>();
  413. if (scaler != null)
  414. {
  415. Object.Destroy(scaler);
  416. return parent.GetComponent<RectTransform>();
  417. }
  418. }
  419. foreach (Transform child in parent)
  420. {
  421. RectTransform result = RemoveCanvasScaler(child);
  422. if (result != null)
  423. return result;
  424. }
  425. return null;
  426. }
  427. // =========================
  428. // Hide All
  429. // =========================
  430. public static void HideAllView()
  431. {
  432. foreach (var v in _ViewCacheInfos)
  433. {
  434. if (v.gameObject)
  435. Object.Destroy(v.gameObject);
  436. }
  437. _ViewCacheInfos.Clear();
  438. }
  439. // =========================
  440. // Destroy logic
  441. // =========================
  442. private static void _DestroyExistViews(string fullPath)
  443. {
  444. _ViewCacheInfos.FindAll(e => e.fullPath == fullPath).ForEach(e =>
  445. {
  446. if (e.gameObject)
  447. Object.Destroy(e.gameObject);
  448. });
  449. _ViewCacheInfos.RemoveAll(e => e.fullPath == fullPath);
  450. }
  451. private static void _RemoveView(string fullPath)
  452. {
  453. _ViewCacheInfos.RemoveAll(e => e.fullPath == fullPath);
  454. }
  455. }
  456. }