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.

351 lines
13 KiB

  1. using BSIPA_ModList.UI.ViewControllers;
  2. using CustomUI.BeatSaber;
  3. using CustomUI.MenuButton;
  4. using IPA.Loader;
  5. using IPA.Updating.BeatMods;
  6. using IPA.Utilities;
  7. using System;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. using System.Diagnostics;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using TMPro;
  15. using UnityEngine;
  16. using UnityEngine.UI;
  17. using VRUI;
  18. namespace BSIPA_ModList.UI
  19. {
  20. internal class ModInfoViewController : VRUIViewController
  21. {
  22. internal Sprite Icon;
  23. internal string Name;
  24. internal string Version;
  25. internal string Author;
  26. internal string Description;
  27. internal PluginLoader.PluginMetadata UpdateInfo;
  28. private static RectTransform rowTransformOriginal;
  29. private ModInfoView view;
  30. private RectTransform rowTransform;
  31. private Button linkHomeButton;
  32. private Button linkSourceButton;
  33. private Button linkDonateButton;
  34. public void Init(Sprite icon, string name, string version, string author, string description, PluginLoader.PluginMetadata updateInfo, PluginManifest.LinksObject links = null)
  35. {
  36. Icon = icon;
  37. Name = name;
  38. Version = version;
  39. Author = author;
  40. Description = description;
  41. UpdateInfo = updateInfo;
  42. if (rowTransformOriginal == null)
  43. rowTransformOriginal = MenuButtonUI.Instance.GetPrivateField<RectTransform>("menuButtonsOriginal");
  44. // i also have no clue why this is necessary
  45. rectTransform.anchorMin = new Vector2(0f, 0f);
  46. rectTransform.anchorMax = new Vector2(0.5f, 1f);
  47. var go = new GameObject("Info View", typeof(RectTransform));
  48. go.SetActive(false);
  49. go.AddComponent<RectMask2D>();
  50. view = go.AddComponent<ModInfoView>();
  51. var rt = view.transform as RectTransform;
  52. rt.SetParent(transform);
  53. rt.anchorMin = new Vector2(0f, 0f);
  54. rt.anchorMax = new Vector2(1f, 1f);
  55. rt.anchoredPosition = new Vector2(0f, 0);
  56. view.Init(this);
  57. go.SetActive(true);
  58. SetupLinks(links);
  59. }
  60. private void SetupLinks(PluginManifest.LinksObject links = null, Uri moreInfoLink = null)
  61. {
  62. bool addedLink = false;
  63. if (links != null || moreInfoLink != null)
  64. {
  65. Logger.log.Debug($"Adding links");
  66. rowTransform = Instantiate(rowTransformOriginal, rectTransform);
  67. rowTransform.anchorMin = new Vector2(0f, 0f);
  68. rowTransform.anchorMax = new Vector2(1f, .15f);
  69. rowTransform.anchoredPosition = new Vector2(-3.5f, 4f);
  70. rowTransform.sizeDelta = Vector2.zero;
  71. Destroy(rowTransform.GetComponent<StartMiddleEndButtonsGroup>());
  72. foreach (Transform child in rowTransform)
  73. {
  74. child.name = string.Empty;
  75. Destroy(child.gameObject);
  76. }
  77. if (links?.ProjectHome != null)
  78. {
  79. linkHomeButton = BeatSaberUI.CreateUIButton(rowTransform, "QuitButton", buttonText: "Home", anchoredPosition: Vector2.zero, sizeDelta: new Vector2(20, 10),
  80. onClick: () => Process.Start(links.ProjectHome.ToString()));
  81. linkHomeButton.GetComponentInChildren<HorizontalLayoutGroup>().padding = new RectOffset(6, 6, 0, 0);
  82. addedLink = true;
  83. }
  84. if (links?.ProjectSource != null)
  85. {
  86. linkSourceButton = BeatSaberUI.CreateUIButton(rowTransform, "QuitButton", buttonText: "Source", anchoredPosition: Vector2.zero, sizeDelta: new Vector2(20, 10),
  87. onClick: () => Process.Start(links.ProjectSource.ToString()));
  88. linkSourceButton.GetComponentInChildren<HorizontalLayoutGroup>().padding = new RectOffset(6, 6, 0, 0);
  89. addedLink = true;
  90. }
  91. if (links?.Donate != null)
  92. {
  93. linkDonateButton = BeatSaberUI.CreateUIButton(rowTransform, "QuitButton", buttonText: "Donate", anchoredPosition: Vector2.zero, sizeDelta: new Vector2(20, 10),
  94. onClick: () => Process.Start(links.Donate.ToString()));
  95. linkDonateButton.GetComponentInChildren<HorizontalLayoutGroup>().padding = new RectOffset(6, 6, 0, 0);
  96. addedLink = true;
  97. }
  98. if (moreInfoLink != null)
  99. {
  100. linkDonateButton = BeatSaberUI.CreateUIButton(rowTransform, "QuitButton", buttonText: "More Info", anchoredPosition: Vector2.zero, sizeDelta: new Vector2(20, 10),
  101. onClick: () => Process.Start(moreInfoLink.ToString()));
  102. linkDonateButton.GetComponentInChildren<HorizontalLayoutGroup>().padding = new RectOffset(6, 6, 0, 0);
  103. addedLink = true;
  104. }
  105. foreach (var cmp in rowTransform.GetComponentsInChildren<StartMiddleEndButtonBackgroundController>())
  106. cmp.SetMiddleSprite();
  107. }
  108. if (UpdateInfo != null && !addedLink)
  109. StartCoroutine(GetMoreInfoLink());
  110. }
  111. private IEnumerator GetMoreInfoLink()
  112. {
  113. Logger.log.Debug($"Getting more info link");
  114. Ref<ApiEndpoint.Mod> mod = new Ref<ApiEndpoint.Mod>(null);
  115. if (UpdateInfo.Id == null) yield break;
  116. yield return Updater.GetModInfo(UpdateInfo.Id, UpdateInfo.Version.ToString(), mod);
  117. try { mod.Verify(); }
  118. catch (Exception e)
  119. {
  120. Logger.log.Warn($"Error getting more info link for mod {UpdateInfo.Id}");
  121. Logger.log.Warn(e);
  122. yield break;
  123. }
  124. SetupLinks(null, mod.Value.Link);
  125. }
  126. #if DEBUG
  127. public void Update()
  128. {
  129. #if ADJUST_INFO_BUTTON_UI_LINKS
  130. RectTransform rt = rowTransform;
  131. if (rt == null) return;
  132. var cpos = rt.anchoredPosition;
  133. if (Input.GetKey(KeyCode.LeftArrow))
  134. {
  135. rt.anchoredPosition = new Vector2(cpos.x - .1f, cpos.y);
  136. }
  137. else if (Input.GetKey(KeyCode.RightArrow))
  138. {
  139. rt.anchoredPosition = new Vector2(cpos.x + .1f, cpos.y);
  140. }
  141. else if (Input.GetKey(KeyCode.UpArrow))
  142. {
  143. rt.anchoredPosition = new Vector2(cpos.x, cpos.y + .1f);
  144. }
  145. else if (Input.GetKey(KeyCode.DownArrow))
  146. {
  147. rt.anchoredPosition = new Vector2(cpos.x, cpos.y - .1f);
  148. }
  149. else
  150. return;
  151. Logger.log.Debug($"Position now at {rt.anchoredPosition}");
  152. #endif
  153. }
  154. #endif
  155. }
  156. internal class ModInfoView : MonoBehaviour
  157. {
  158. private TextMeshProUGUI titleText;
  159. private TextMeshProUGUI authorText;
  160. private TextMeshProUGUI descText;
  161. private Image icon;
  162. public void Init(ModInfoViewController controller)
  163. {
  164. var rectTransform = transform as RectTransform;
  165. rectTransform.sizeDelta = new Vector2(60f, 10f);
  166. titleText = BeatSaberUI.CreateText(rectTransform, $"{controller.Name} <size=60%>{controller.Version}", new Vector2(11f, 27.5f));
  167. titleText.fontSize = 6f;
  168. authorText = BeatSaberUI.CreateText(rectTransform, controller.Author, new Vector2(11f, 22f));
  169. authorText.fontSize = 4.5f;
  170. /*
  171. descText = BeatSaberUI.CreateText(rectTransform, controller.Description, new Vector2(-4.5f, 12f));
  172. descText.fontSize = 3.5f;
  173. descText.enableWordWrapping = true;
  174. descText.overflowMode = TextOverflowModes.ScrollRect;*/
  175. var mdvgo = new GameObject("MarkDown Desc");
  176. mdvgo.SetActive(false);
  177. var mdv = mdvgo.AddComponent<MarkdownView>();
  178. mdv.rectTransform.SetParent(rectTransform);
  179. mdv.rectTransform.anchorMin = new Vector2(.5f, .5f);
  180. mdv.rectTransform.anchorMax = new Vector2(.5f, .5f);
  181. mdv.rectTransform.anchoredPosition = new Vector2(-4f, -3.6f);
  182. mdv.rectTransform.sizeDelta = new Vector2(65f, 40f);
  183. mdvgo.SetActive(true);
  184. mdv.Markdown = controller.Description;
  185. icon = new GameObject("Mod Info View Icon", typeof(RectTransform)).AddComponent<Image>();
  186. icon.gameObject.SetActive(false);
  187. icon.rectTransform.SetParent(rectTransform, false);
  188. icon.rectTransform.anchorMin = new Vector2(0.5f, 0.44f);
  189. icon.rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
  190. icon.rectTransform.sizeDelta = new Vector2(60f, 10f);
  191. icon.rectTransform.anchoredPosition = new Vector2(-27.8f, 27.3f);
  192. icon.sprite = controller.Icon;
  193. icon.preserveAspect = true;
  194. icon.useSpriteMesh = true;
  195. icon.material = CustomUI.Utilities.UIUtilities.NoGlowMaterial;
  196. icon.gameObject.SetActive(true);
  197. }
  198. #if DEBUG
  199. #if ADJUST_INFO_TEXT_UI_KEYS
  200. private int currentItem = 0;
  201. #endif
  202. public void Update()
  203. {
  204. #if ADJUST_INFO_TEXT_UI_KEYS
  205. RectTransform rt;
  206. switch (currentItem)
  207. {
  208. default:
  209. currentItem = 0;
  210. goto case 0; // idk why this is needed tbh
  211. case 0:
  212. rt = titleText.rectTransform;
  213. break;
  214. case 1:
  215. rt = authorText.rectTransform;
  216. break;
  217. case 2:
  218. rt = descText.rectTransform;
  219. break;
  220. }
  221. if (Input.GetKeyDown(KeyCode.N))
  222. currentItem++;
  223. var cpos = rt.anchoredPosition;
  224. if (Input.GetKey(KeyCode.LeftArrow))
  225. {
  226. rt.anchoredPosition = new Vector2(cpos.x - .1f, cpos.y);
  227. }
  228. else if (Input.GetKey(KeyCode.RightArrow))
  229. {
  230. rt.anchoredPosition = new Vector2(cpos.x + .1f, cpos.y);
  231. }
  232. else if (Input.GetKey(KeyCode.UpArrow))
  233. {
  234. rt.anchoredPosition = new Vector2(cpos.x, cpos.y + .1f);
  235. }
  236. else if (Input.GetKey(KeyCode.DownArrow))
  237. {
  238. rt.anchoredPosition = new Vector2(cpos.x, cpos.y - .1f);
  239. }
  240. else
  241. return;
  242. Logger.log.Debug($"Position now at {rt.anchoredPosition}");
  243. #endif
  244. #if ADJUST_INFO_ICON_UI_KEYS
  245. var rt = icon.rectTransform;
  246. if (Input.GetKey(KeyCode.Z))
  247. { // adjust anchormin
  248. var cpos = rt.anchorMin;
  249. if (Input.GetKey(KeyCode.LeftArrow))
  250. {
  251. rt.anchorMin = new Vector2(cpos.x - .001f, cpos.y);
  252. }
  253. else if (Input.GetKey(KeyCode.RightArrow))
  254. {
  255. rt.anchorMin = new Vector2(cpos.x + .001f, cpos.y);
  256. }
  257. else if (Input.GetKey(KeyCode.UpArrow))
  258. {
  259. rt.anchorMin = new Vector2(cpos.x, cpos.y + .001f);
  260. }
  261. else if (Input.GetKey(KeyCode.DownArrow))
  262. {
  263. rt.anchorMin = new Vector2(cpos.x, cpos.y - .001f);
  264. }
  265. else
  266. return;
  267. Logger.log.Debug($"Anchor min now at {rt.anchorMin}");
  268. }
  269. else if(Input.GetKey(KeyCode.X))
  270. { // adjust anchorMax
  271. var cpos = rt.anchorMax;
  272. if (Input.GetKey(KeyCode.LeftArrow))
  273. {
  274. rt.anchorMax = new Vector2(cpos.x - .001f, cpos.y);
  275. }
  276. else if (Input.GetKey(KeyCode.RightArrow))
  277. {
  278. rt.anchorMax = new Vector2(cpos.x + .001f, cpos.y);
  279. }
  280. else if (Input.GetKey(KeyCode.UpArrow))
  281. {
  282. rt.anchorMax = new Vector2(cpos.x, cpos.y + .001f);
  283. }
  284. else if (Input.GetKey(KeyCode.DownArrow))
  285. {
  286. rt.anchorMax = new Vector2(cpos.x, cpos.y - .001f);
  287. }
  288. else
  289. return;
  290. Logger.log.Debug($"Anchor max now at {rt.anchorMax}");
  291. }
  292. else
  293. {
  294. var cpos = rt.anchoredPosition;
  295. if (Input.GetKey(KeyCode.LeftArrow))
  296. {
  297. rt.anchoredPosition = new Vector2(cpos.x - .1f, cpos.y);
  298. }
  299. else if (Input.GetKey(KeyCode.RightArrow))
  300. {
  301. rt.anchoredPosition = new Vector2(cpos.x + .1f, cpos.y);
  302. }
  303. else if (Input.GetKey(KeyCode.UpArrow))
  304. {
  305. rt.anchoredPosition = new Vector2(cpos.x, cpos.y + .1f);
  306. }
  307. else if (Input.GetKey(KeyCode.DownArrow))
  308. {
  309. rt.anchoredPosition = new Vector2(cpos.x, cpos.y - .1f);
  310. }
  311. else
  312. return;
  313. Logger.log.Debug($"Position now at {rt.anchoredPosition}");
  314. }
  315. #endif
  316. }
  317. #endif
  318. }
  319. }