You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
11 KiB

  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using CustomUI.BeatSaber;
  5. using CustomUI.Utilities;
  6. using HMUI;
  7. using IPA.Loader;
  8. using IPA.Old;
  9. using UnityEngine;
  10. using VRUI;
  11. using IPA.Loader.Features;
  12. using TMPro;
  13. namespace BSIPA_ModList.UI
  14. {
  15. internal class ModListController : CustomListViewController
  16. {
  17. private interface IClickableCell
  18. {
  19. void OnSelect(ModListController cntrl);
  20. }
  21. private class BSIPAModCell : CustomCellInfo, IClickableCell
  22. {
  23. private static Sprite _defaultIcon;
  24. public static Sprite DefaultIcon
  25. {
  26. get
  27. {
  28. if (_defaultIcon == null)
  29. _defaultIcon = UIUtilities.LoadSpriteFromResources("BSIPA_ModList.Icons.mod_bsipa.png");
  30. return _defaultIcon;
  31. }
  32. }
  33. internal PluginLoader.PluginInfo Plugin;
  34. private ModListController list;
  35. public BSIPAModCell(ModListController list, PluginLoader.PluginInfo plugin)
  36. : base($"{plugin.Metadata.Name} <size=60%>v{plugin.Metadata.Version}", plugin.Metadata.Manifest.Author, null)
  37. {
  38. Plugin = plugin;
  39. this.list = list;
  40. if (string.IsNullOrWhiteSpace(subtext))
  41. subtext = "<color=#BFBFBF><i>Unspecified Author</i>";
  42. if (plugin.Metadata.Manifest.IconPath != null)
  43. {
  44. try
  45. {
  46. icon = UIUtilities.LoadSpriteRaw(UIUtilities.GetResource(plugin.Metadata.Assembly, plugin.Metadata.Manifest.IconPath));
  47. }
  48. catch (Exception e)
  49. {
  50. Logger.log.Error($"Error loading icon for {plugin.Metadata.Name}");
  51. Logger.log.Error(e);
  52. }
  53. }
  54. if (icon == null)
  55. icon = DefaultIcon;
  56. Logger.log.Debug($"BSIPAModCell {plugin.Metadata.Name} {plugin.Metadata.Version}");
  57. }
  58. private ModInfoViewController infoView;
  59. public void OnSelect(ModListController cntrl)
  60. {
  61. Logger.log.Debug($"Selected BSIPAModCell {Plugin.Metadata.Name} {Plugin.Metadata.Version}");
  62. if (infoView == null)
  63. {
  64. var desc = Plugin.Metadata.Manifest.Description;
  65. if (string.IsNullOrWhiteSpace(desc))
  66. desc = "<color=#BFBFBF><i>No description</i>";
  67. infoView = BeatSaberUI.CreateViewController<ModInfoViewController>();
  68. infoView.Init(icon, Plugin.Metadata.Name, "v" + Plugin.Metadata.Version.ToString(), subtext,
  69. desc, Plugin.Metadata.Features.FirstOrDefault(f => f is NoUpdateFeature) != null ? Plugin.Metadata : null,
  70. Plugin.Metadata.Manifest.Links);
  71. }
  72. list.flow.SetSelected(infoView, immediate: list.flow.HasSelected);
  73. }
  74. }
  75. private class BSIPAIgnoredModCell : CustomCellInfo, IClickableCell
  76. {
  77. internal PluginLoader.PluginMetadata Plugin;
  78. private ModListController list;
  79. private const string authorFormat = "{0} <color=#BFBFBF>- <i>Not loaded</i>";
  80. private string authorText;
  81. public BSIPAIgnoredModCell(ModListController list, PluginLoader.PluginMetadata plugin)
  82. : base($"<color=#878787>{plugin.Name} <size=60%>v{plugin.Version}", "", BSIPAModCell.DefaultIcon)
  83. {
  84. Plugin = plugin;
  85. this.list = list;
  86. if (string.IsNullOrWhiteSpace(plugin.Manifest.Author))
  87. authorText = "<color=#BFBFBF><i>Unspecified Author</i>";
  88. else
  89. authorText = plugin.Manifest.Author;
  90. subtext = string.Format(authorFormat, authorText);
  91. Logger.log.Debug($"BSIPAIgnoredModCell {plugin.Name} {plugin.Version}");
  92. }
  93. private ModInfoViewController infoView;
  94. public void OnSelect(ModListController cntrl)
  95. {
  96. Logger.log.Debug($"Selected BSIPAIgnoredModCell {Plugin.Name} {Plugin.Version}");
  97. if (infoView == null)
  98. {
  99. var desc = Plugin.Manifest.Description;
  100. if (string.IsNullOrWhiteSpace(desc))
  101. desc = "<color=#BFBFBF><i>No description</i>";
  102. infoView = BeatSaberUI.CreateViewController<ModInfoViewController>();
  103. infoView.Init(icon, Plugin.Name, "v" + Plugin.Version.ToString(), authorText,
  104. desc, Plugin.Features.FirstOrDefault(f => f is NoUpdateFeature) != null ? Plugin : null,
  105. Plugin.Manifest.Links);
  106. }
  107. list.flow.SetSelected(infoView, immediate: list.flow.HasSelected);
  108. }
  109. }
  110. private class LibraryModCell : CustomCellInfo, IClickableCell
  111. {
  112. private static Sprite _defaultIcon;
  113. public static Sprite DefaultIcon
  114. {
  115. get
  116. {
  117. if (_defaultIcon == null)
  118. _defaultIcon = UIUtilities.LoadSpriteFromResources("BSIPA_ModList.Icons.library.png");
  119. return _defaultIcon;
  120. }
  121. }
  122. internal PluginLoader.PluginInfo Plugin;
  123. private ModListController list;
  124. public LibraryModCell(ModListController list, PluginLoader.PluginInfo plugin)
  125. : base($"{plugin.Metadata.Name} <size=60%>v{plugin.Metadata.Version}", plugin.Metadata.Manifest.Author, null)
  126. {
  127. Plugin = plugin;
  128. this.list = list;
  129. if (string.IsNullOrWhiteSpace(subtext))
  130. subtext = "<color=#BFBFBF><i>Unspecified Author</i>";
  131. icon = DefaultIcon;
  132. Logger.log.Debug($"LibraryModCell {plugin.Metadata.Name} {plugin.Metadata.Version}");
  133. }
  134. private ModInfoViewController infoView;
  135. public void OnSelect(ModListController cntrl)
  136. {
  137. Logger.log.Debug($"Selected LibraryModCell {Plugin.Metadata.Name} {Plugin.Metadata.Version}");
  138. if (infoView == null)
  139. {
  140. var desc = Plugin.Metadata.Manifest.Description;
  141. if (string.IsNullOrWhiteSpace(desc))
  142. desc = "<color=#BFBFBF><i>No description</i>";
  143. infoView = BeatSaberUI.CreateViewController<ModInfoViewController>();
  144. infoView.Init(icon, Plugin.Metadata.Name, "v" + Plugin.Metadata.Version.ToString(), subtext,
  145. desc, Plugin.Metadata.Features.FirstOrDefault(f => f is NoUpdateFeature) != null ? Plugin.Metadata : null,
  146. Plugin.Metadata.Manifest.Links);
  147. }
  148. list.flow.SetSelected(infoView, immediate: list.flow.HasSelected);
  149. }
  150. }
  151. #pragma warning disable CS0618
  152. private class IPAModCell : CustomCellInfo, IClickableCell
  153. {
  154. private static Sprite _defaultIcon;
  155. public static Sprite DefaultIcon
  156. {
  157. get
  158. {
  159. if (_defaultIcon == null)
  160. _defaultIcon = UIUtilities.LoadSpriteFromResources("BSIPA_ModList.Icons.mod_ipa.png");
  161. return _defaultIcon;
  162. }
  163. }
  164. internal IPlugin Plugin;
  165. private ModListController list;
  166. public IPAModCell(ModListController list, IPlugin plugin)
  167. : base($"{plugin.Name} <size=60%>{plugin.Version}", "<color=#BFBFBF><i>Legacy</i>", DefaultIcon)
  168. {
  169. Plugin = plugin;
  170. this.list = list;
  171. Logger.log.Debug($"IPAModCell {plugin.Name} {plugin.Version}");
  172. }
  173. private ModInfoViewController infoView;
  174. public void OnSelect(ModListController cntrl)
  175. {
  176. Logger.log.Debug($"Selected IPAModCell {Plugin.Name} {Plugin.Version}");
  177. if (infoView == null)
  178. {
  179. infoView = BeatSaberUI.CreateViewController<ModInfoViewController>();
  180. infoView.Init(icon, Plugin.Name, "v" + Plugin.Version.ToString(), "<color=#BFBFBF><i>Unknown Author</i>",
  181. "<color=#A0A0A0>This mod was written for IPA Reloaded. No metadata is avaliable for this mod. " +
  182. "Please contact the mod author and ask them to port it to BSIPA to provide more information.", null);
  183. }
  184. list.flow.SetSelected(infoView, immediate: list.flow.HasSelected);
  185. }
  186. }
  187. #pragma warning restore
  188. public override TableCell CellForIdx(int idx)
  189. {
  190. var cell = base.CellForIdx(idx) as LevelListTableCell;
  191. var nameText = cell.GetPrivateField<TextMeshProUGUI>("_songNameText");
  192. nameText.overflowMode = TextOverflowModes.Overflow;
  193. return cell;
  194. }
  195. private ModListFlowCoordinator flow;
  196. #pragma warning disable CS0618
  197. public void Init(ModListFlowCoordinator flow, IEnumerable<PluginLoader.PluginInfo> bsipaPlugins, IEnumerable<PluginLoader.PluginMetadata> ignoredPlugins, IEnumerable<IPlugin> ipaPlugins)
  198. {
  199. Logger.log.Debug("List Controller Init");
  200. DidActivateEvent = DidActivate;
  201. DidSelectRowEvent = DidSelectRow;
  202. rectTransform.anchorMin = new Vector2(0f, 0f);
  203. rectTransform.anchorMax = new Vector2(.4f, 1f);
  204. includePageButtons = true;
  205. this.flow = flow;
  206. reuseIdentifier = "BSIPAModListTableCell";
  207. foreach (var plugin in bsipaPlugins.Where(p => !p.Metadata.IsBare))
  208. Data.Add(new BSIPAModCell(this, plugin));
  209. foreach (var plugin in ignoredPlugins)
  210. Data.Add(new BSIPAIgnoredModCell(this, plugin));
  211. foreach (var plugin in bsipaPlugins.Where(p => p.Metadata.IsBare))
  212. Data.Add(new LibraryModCell(this, plugin));
  213. foreach (var plugin in ipaPlugins)
  214. Data.Add(new IPAModCell(this, plugin));
  215. }
  216. #pragma warning restore
  217. private void DidSelectRow(TableView view, int index)
  218. {
  219. Debug.Assert(ReferenceEquals(view.dataSource, this));
  220. (Data[index] as IClickableCell)?.OnSelect(this);
  221. }
  222. private new void DidActivate(bool first, ActivationType type)
  223. {
  224. var rt = _customListTableView.transform as RectTransform;
  225. rt.anchorMin = new Vector2(.1f, 0f);
  226. rt.anchorMax = new Vector2(.9f, 1f);
  227. }
  228. }
  229. }