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.

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