using BSIPA_ModList.UI.ViewControllers;
|
|
using CustomUI.BeatSaber;
|
|
using CustomUI.MenuButton;
|
|
using IPA.Loader;
|
|
using IPA.Updating.BeatMods;
|
|
using IPA.Utilities;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using VRUI;
|
|
|
|
namespace BSIPA_ModList.UI
|
|
{
|
|
internal class ModInfoViewController : VRUIViewController
|
|
{
|
|
internal Sprite Icon;
|
|
internal string Name;
|
|
internal string Version;
|
|
internal string Author;
|
|
internal string Description;
|
|
internal PluginLoader.PluginMetadata UpdateInfo;
|
|
|
|
private static RectTransform rowTransformOriginal;
|
|
|
|
private ModInfoView view;
|
|
private RectTransform rowTransform;
|
|
private Button linkHomeButton;
|
|
private Button linkSourceButton;
|
|
private Button linkDonateButton;
|
|
|
|
private ModListFlowCoordinator flowController;
|
|
private bool showEnableDisable = false;
|
|
|
|
private TextMeshProUGUI restartMessage;
|
|
private Button enableDisableButton;
|
|
private new bool enabled = false;
|
|
|
|
public void Init(Sprite icon, string name, string version, string author, string description, PluginLoader.PluginMetadata updateInfo, PluginManifest.LinksObject links = null, bool showEnDis = false, ModListFlowCoordinator mlfc = null)
|
|
{
|
|
showEnableDisable = showEnDis;
|
|
Plugin.OnConfigChaned -= OptHideButton;
|
|
|
|
Icon = icon;
|
|
Name = name;
|
|
Version = version;
|
|
Author = author;
|
|
Description = description;
|
|
UpdateInfo = updateInfo;
|
|
|
|
enabled = !PluginManager.IsDisabled(updateInfo);
|
|
|
|
flowController = mlfc;
|
|
|
|
if (rowTransformOriginal == null)
|
|
rowTransformOriginal = MenuButtonUI.Instance.GetPrivateField<RectTransform>("menuButtonsOriginal");
|
|
|
|
// i also have no clue why this is necessary
|
|
rectTransform.anchorMin = new Vector2(0f, 0f);
|
|
rectTransform.anchorMax = new Vector2(0.5f, 1f);
|
|
|
|
var go = new GameObject("Info View", typeof(RectTransform));
|
|
go.SetActive(false);
|
|
go.AddComponent<RectMask2D>();
|
|
view = go.AddComponent<ModInfoView>();
|
|
var rt = view.transform as RectTransform;
|
|
rt.SetParent(transform);
|
|
rt.anchorMin = new Vector2(0f, 0f);
|
|
rt.anchorMax = new Vector2(1f, 1f);
|
|
rt.anchoredPosition = new Vector2(0f, 0);
|
|
view.Init(this);
|
|
go.SetActive(true);
|
|
|
|
if (showEnDis)
|
|
{
|
|
restartMessage = BeatSaberUI.CreateText(rectTransform, "A restart is required to apply", new Vector2(11f, 33.5f));
|
|
restartMessage.fontSize = 4f;
|
|
restartMessage.gameObject.SetActive(false);
|
|
|
|
enableDisableButton = BeatSaberUI.CreateUIButton(rectTransform, "CreditsButton", new Vector2(33, 32), new Vector2(25, 10), ToggleEnable);
|
|
enableDisableButton.GetComponentInChildren<StartMiddleEndButtonBackgroundController>().SetMiddleSprite();
|
|
UpdateButtonText();
|
|
|
|
Plugin.OnConfigChaned += OptHideButton;
|
|
OptHideButton(Plugin.config.Value);
|
|
}
|
|
|
|
SetupLinks(links);
|
|
}
|
|
|
|
~ModInfoViewController()
|
|
{
|
|
Plugin.OnConfigChaned -= OptHideButton;
|
|
}
|
|
|
|
private void OptHideButton(SelfConfig cfg)
|
|
{
|
|
enableDisableButton?.gameObject.SetActive(cfg.ShowEnableDisable);
|
|
}
|
|
|
|
private Action setAction = () => { };
|
|
private void ToggleEnable()
|
|
{
|
|
var info = enabled ? PluginManager.InfoFromMetadata(UpdateInfo) : null;
|
|
bool needsRestart;
|
|
if (enabled)
|
|
needsRestart = PluginManager.DisablePlugin(info);
|
|
else
|
|
needsRestart = PluginManager.EnablePlugin(UpdateInfo);
|
|
|
|
UpdateButtonText(!enabled, needsRestart);
|
|
if (!needsRestart)
|
|
flowController.exitActions.Add(setAction);
|
|
}
|
|
|
|
private void UpdateButtonText(bool? _enabled = null, bool _needsRestart = false)
|
|
{
|
|
enabled = _enabled ?? enabled;
|
|
if (enabled)
|
|
enableDisableButton.SetButtonText("Disable");
|
|
else
|
|
enableDisableButton.SetButtonText("Enable");
|
|
restartMessage.gameObject.SetActive(_needsRestart);
|
|
}
|
|
|
|
public void Reload(string name, string version, string author, string description)
|
|
{
|
|
Name = name;
|
|
Version = version;
|
|
Author = author;
|
|
Description = description;
|
|
view.Refresh();
|
|
}
|
|
|
|
private void SetupLinks(PluginManifest.LinksObject links = null, Uri moreInfoLink = null)
|
|
{
|
|
bool addedLink = false;
|
|
if (links != null || moreInfoLink != null)
|
|
{
|
|
Logger.log.Debug($"Adding links");
|
|
|
|
rowTransform = Instantiate(rowTransformOriginal, rectTransform);
|
|
rowTransform.anchorMin = new Vector2(0f, 0f);
|
|
rowTransform.anchorMax = new Vector2(1f, .15f);
|
|
rowTransform.anchoredPosition = new Vector2(-3.5f, 4f);
|
|
rowTransform.sizeDelta = Vector2.zero;
|
|
Destroy(rowTransform.GetComponent<StartMiddleEndButtonsGroup>());
|
|
|
|
foreach (Transform child in rowTransform)
|
|
{
|
|
child.name = string.Empty;
|
|
Destroy(child.gameObject);
|
|
}
|
|
|
|
if (links?.ProjectHome != null)
|
|
{
|
|
linkHomeButton = BeatSaberUI.CreateUIButton(rowTransform, "CreditsButton", buttonText: "Home", anchoredPosition: Vector2.zero, sizeDelta: new Vector2(20, 10),
|
|
onClick: () => Process.Start(links.ProjectHome.ToString()));
|
|
addedLink = true;
|
|
}
|
|
if (links?.ProjectSource != null)
|
|
{
|
|
linkSourceButton = BeatSaberUI.CreateUIButton(rowTransform, "CreditsButton", buttonText: "Source", anchoredPosition: Vector2.zero, sizeDelta: new Vector2(20, 10),
|
|
onClick: () => Process.Start(links.ProjectSource.ToString()));
|
|
addedLink = true;
|
|
}
|
|
if (links?.Donate != null)
|
|
{
|
|
linkDonateButton = BeatSaberUI.CreateUIButton(rowTransform, "CreditsButton", buttonText: "Donate", anchoredPosition: Vector2.zero, sizeDelta: new Vector2(20, 10),
|
|
onClick: () => Process.Start(links.Donate.ToString()));
|
|
addedLink = true;
|
|
}
|
|
if (moreInfoLink != null)
|
|
{
|
|
linkDonateButton = BeatSaberUI.CreateUIButton(rowTransform, "CreditsButton", buttonText: "More Info", anchoredPosition: Vector2.zero, sizeDelta: new Vector2(20, 10),
|
|
onClick: () => Process.Start(moreInfoLink.ToString()));
|
|
addedLink = true;
|
|
}
|
|
|
|
foreach (var cmp in rowTransform.GetComponentsInChildren<StartMiddleEndButtonBackgroundController>())
|
|
cmp.SetMiddleSprite();
|
|
}
|
|
if (UpdateInfo != null && !addedLink)
|
|
StartCoroutine(GetMoreInfoLink());
|
|
}
|
|
|
|
private IEnumerator GetMoreInfoLink()
|
|
{
|
|
Logger.log.Debug($"Getting more info link");
|
|
Ref<ApiEndpoint.Mod> mod = new Ref<ApiEndpoint.Mod>(null);
|
|
if (UpdateInfo.Id == null) yield break;
|
|
yield return Updater.GetModInfo(UpdateInfo.Id, UpdateInfo.Version.ToString(), mod);
|
|
try { mod.Verify(); }
|
|
catch (Exception e)
|
|
{
|
|
Logger.log.Warn($"Error getting more info link for mod {UpdateInfo.Id}");
|
|
Logger.log.Warn(e);
|
|
yield break;
|
|
}
|
|
SetupLinks(null, mod.Value.Link);
|
|
}
|
|
|
|
#if DEBUG
|
|
public void Update()
|
|
{
|
|
#if ADJUST_INFO_BUTTON_UI_LINKS
|
|
RectTransform rt = rowTransform;
|
|
|
|
if (rt == null) return;
|
|
|
|
var cpos = rt.anchoredPosition;
|
|
if (Input.GetKey(KeyCode.LeftArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x - .1f, cpos.y);
|
|
}
|
|
else if (Input.GetKey(KeyCode.RightArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x + .1f, cpos.y);
|
|
}
|
|
else if (Input.GetKey(KeyCode.UpArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x, cpos.y + .1f);
|
|
}
|
|
else if (Input.GetKey(KeyCode.DownArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x, cpos.y - .1f);
|
|
}
|
|
else
|
|
return;
|
|
|
|
Logger.log.Debug($"Position now at {rt.anchoredPosition}");
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
internal class ModInfoView : MonoBehaviour
|
|
{
|
|
private MarkdownView mdv;
|
|
private TextMeshProUGUI titleText;
|
|
private TextMeshProUGUI authorText;
|
|
private Image icon;
|
|
private ModInfoViewController controller;
|
|
|
|
private const string TitleFormat = "{0} <size=60%>{1}";
|
|
public void Init(ModInfoViewController controller)
|
|
{
|
|
this.controller = controller;
|
|
|
|
var rectTransform = transform as RectTransform;
|
|
rectTransform.sizeDelta = new Vector2(60f, 10f);
|
|
|
|
titleText = BeatSaberUI.CreateText(rectTransform, string.Format(TitleFormat, controller.Name, controller.Version), new Vector2(11f, 27.5f));
|
|
titleText.fontSize = 6f;
|
|
authorText = BeatSaberUI.CreateText(rectTransform, controller.Author, new Vector2(11f, 22f));
|
|
authorText.fontSize = 4.5f;
|
|
|
|
var mdvgo = new GameObject("MarkDown Desc");
|
|
mdvgo.SetActive(false);
|
|
mdv = mdvgo.AddComponent<MarkdownView>();
|
|
mdv.rectTransform.SetParent(rectTransform);
|
|
mdv.rectTransform.anchorMin = new Vector2(.5f, .5f);
|
|
mdv.rectTransform.anchorMax = new Vector2(.5f, .5f);
|
|
mdv.rectTransform.anchoredPosition = new Vector2(-4f, -3.6f);
|
|
mdv.rectTransform.sizeDelta = new Vector2(65f, 40f);
|
|
mdvgo.SetActive(true);
|
|
mdv.Markdown = controller.Description;
|
|
|
|
icon = new GameObject("Mod Info View Icon", typeof(RectTransform)).AddComponent<Image>();
|
|
icon.gameObject.SetActive(false);
|
|
icon.rectTransform.SetParent(rectTransform, false);
|
|
icon.rectTransform.anchorMin = new Vector2(0.5f, 0.44f);
|
|
icon.rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
|
|
icon.rectTransform.sizeDelta = new Vector2(60f, 10f);
|
|
icon.rectTransform.anchoredPosition = new Vector2(-27.8f, 27.3f);
|
|
icon.sprite = controller.Icon;
|
|
icon.preserveAspect = true;
|
|
icon.useSpriteMesh = true;
|
|
icon.material = CustomUI.Utilities.UIUtilities.NoGlowMaterial;
|
|
icon.gameObject.SetActive(true);
|
|
}
|
|
|
|
public void Refresh()
|
|
{
|
|
titleText.text = string.Format(TitleFormat, controller.Name, controller.Version);
|
|
authorText.text = controller.Author;
|
|
mdv.Markdown = controller.Description;
|
|
icon.sprite = controller.Icon;
|
|
}
|
|
|
|
#if DEBUG
|
|
#if ADJUST_INFO_TEXT_UI_KEYS
|
|
private int currentItem = 0;
|
|
#endif
|
|
public void Update()
|
|
{
|
|
#if ADJUST_INFO_TEXT_UI_KEYS
|
|
RectTransform rt;
|
|
switch (currentItem)
|
|
{
|
|
default:
|
|
currentItem = 0;
|
|
goto case 0; // idk why this is needed tbh
|
|
case 0:
|
|
rt = titleText.rectTransform;
|
|
break;
|
|
case 1:
|
|
rt = authorText.rectTransform;
|
|
break;
|
|
case 2:
|
|
rt = descText.rectTransform;
|
|
break;
|
|
|
|
}
|
|
|
|
if (Input.GetKeyDown(KeyCode.N))
|
|
currentItem++;
|
|
|
|
var cpos = rt.anchoredPosition;
|
|
if (Input.GetKey(KeyCode.LeftArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x - .1f, cpos.y);
|
|
}
|
|
else if (Input.GetKey(KeyCode.RightArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x + .1f, cpos.y);
|
|
}
|
|
else if (Input.GetKey(KeyCode.UpArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x, cpos.y + .1f);
|
|
}
|
|
else if (Input.GetKey(KeyCode.DownArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x, cpos.y - .1f);
|
|
}
|
|
else
|
|
return;
|
|
|
|
Logger.log.Debug($"Position now at {rt.anchoredPosition}");
|
|
#endif
|
|
#if ADJUST_INFO_ICON_UI_KEYS
|
|
var rt = icon.rectTransform;
|
|
if (Input.GetKey(KeyCode.Z))
|
|
{ // adjust anchormin
|
|
var cpos = rt.anchorMin;
|
|
if (Input.GetKey(KeyCode.LeftArrow))
|
|
{
|
|
rt.anchorMin = new Vector2(cpos.x - .001f, cpos.y);
|
|
}
|
|
else if (Input.GetKey(KeyCode.RightArrow))
|
|
{
|
|
rt.anchorMin = new Vector2(cpos.x + .001f, cpos.y);
|
|
}
|
|
else if (Input.GetKey(KeyCode.UpArrow))
|
|
{
|
|
rt.anchorMin = new Vector2(cpos.x, cpos.y + .001f);
|
|
}
|
|
else if (Input.GetKey(KeyCode.DownArrow))
|
|
{
|
|
rt.anchorMin = new Vector2(cpos.x, cpos.y - .001f);
|
|
}
|
|
else
|
|
return;
|
|
|
|
Logger.log.Debug($"Anchor min now at {rt.anchorMin}");
|
|
}
|
|
else if(Input.GetKey(KeyCode.X))
|
|
{ // adjust anchorMax
|
|
var cpos = rt.anchorMax;
|
|
if (Input.GetKey(KeyCode.LeftArrow))
|
|
{
|
|
rt.anchorMax = new Vector2(cpos.x - .001f, cpos.y);
|
|
}
|
|
else if (Input.GetKey(KeyCode.RightArrow))
|
|
{
|
|
rt.anchorMax = new Vector2(cpos.x + .001f, cpos.y);
|
|
}
|
|
else if (Input.GetKey(KeyCode.UpArrow))
|
|
{
|
|
rt.anchorMax = new Vector2(cpos.x, cpos.y + .001f);
|
|
}
|
|
else if (Input.GetKey(KeyCode.DownArrow))
|
|
{
|
|
rt.anchorMax = new Vector2(cpos.x, cpos.y - .001f);
|
|
}
|
|
else
|
|
return;
|
|
|
|
Logger.log.Debug($"Anchor max now at {rt.anchorMax}");
|
|
}
|
|
else
|
|
{
|
|
var cpos = rt.anchoredPosition;
|
|
if (Input.GetKey(KeyCode.LeftArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x - .1f, cpos.y);
|
|
}
|
|
else if (Input.GetKey(KeyCode.RightArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x + .1f, cpos.y);
|
|
}
|
|
else if (Input.GetKey(KeyCode.UpArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x, cpos.y + .1f);
|
|
}
|
|
else if (Input.GetKey(KeyCode.DownArrow))
|
|
{
|
|
rt.anchoredPosition = new Vector2(cpos.x, cpos.y - .1f);
|
|
}
|
|
else
|
|
return;
|
|
|
|
Logger.log.Debug($"Position now at {rt.anchoredPosition}");
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
}
|