diff --git a/BSIPA-ModList/BSIPA-ModList.csproj b/BSIPA-ModList/BSIPA-ModList.csproj index c5185fea..c0c14007 100644 --- a/BSIPA-ModList/BSIPA-ModList.csproj +++ b/BSIPA-ModList/BSIPA-ModList.csproj @@ -47,6 +47,9 @@ + + ..\Refs\UnityEngine.dll + ..\Refs\UnityEngine.CoreModule.dll False @@ -63,6 +66,7 @@ + diff --git a/BSIPA-ModList/Plugin.cs b/BSIPA-ModList/Plugin.cs index 5de5c496..bd99ff60 100644 --- a/BSIPA-ModList/Plugin.cs +++ b/BSIPA-ModList/Plugin.cs @@ -31,13 +31,8 @@ namespace BSIPA_ModList { } - private MainFlowCoordinator mainFlow; - private ModListFlowCoordinator menuFlow; - private MenuButton button; - public void OnApplicationStart() { - Logger.log.Debug("Creating Menu"); } public void OnFixedUpdate() @@ -48,16 +43,11 @@ namespace BSIPA_ModList { if (scene.name == "MenuCore") { - if (mainFlow == null) - mainFlow = Resources.FindObjectsOfTypeAll().First(); - if (menuFlow == null) - menuFlow = new GameObject("BSIPA Mod List Flow Coordinator").AddComponent(); - if (button == null) - button = MenuButtonUI.AddButton("Mod List", "Look at installed mods, and control updating", () => - { - Logger.log.Debug("Presenting own flow controller"); - menuFlow.PresentOn(mainFlow); - }); + if (ButtonUI.Instance == null) + { + Logger.log.Debug("Creating Menu"); + new GameObject("BSIPA Mod List Object").AddComponent().Init(); + } } } diff --git a/BSIPA-ModList/UI/ButtonUI.cs b/BSIPA-ModList/UI/ButtonUI.cs new file mode 100644 index 00000000..e44803ce --- /dev/null +++ b/BSIPA-ModList/UI/ButtonUI.cs @@ -0,0 +1,91 @@ +using CustomUI.BeatSaber; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using UnityEngine.SceneManagement; +using UnityEngine.UI; + +namespace BSIPA_ModList.UI +{ + internal class ButtonUI : MonoBehaviour + { + private const string ControllerPanel = "MainMenuViewController/SmallButtons"; + private const string CopyButton = "CreditsButton"; + + internal static ButtonUI Instance; + + public void Awake() + { + DontDestroyOnLoad(gameObject); + SceneManager.activeSceneChanged += this.SceneManager_activeSceneChanged; + } + + private void SceneManager_activeSceneChanged(Scene from, Scene to) + { + if (to.name == "EmptyTransition") + { + if (Instance != null) + { + Instance.StopAllCoroutines(); + Destroy(Instance.gameObject); + menuFlow = null; + } + Instance = null; + } + } + + public void Init() + { + Instance = this; + + Logger.log.Debug("UI Awake"); + StartCoroutine(AddModListButton()); + } + + private static MainFlowCoordinator mainFlow; + private static ModListFlowCoordinator menuFlow; + + private static readonly WaitUntil _bottomPanelExists = new WaitUntil(() => GameObject.Find(ControllerPanel) != null); + private static RectTransform panel; + + private static HoverHint hintText; + private static Button button; + + private static IEnumerator AddModListButton() + { + Logger.log.Debug("AddModListButton"); + + yield return _bottomPanelExists; + + Logger.log.Debug("Adding button to main menu"); + + lock (Instance) + { + if (mainFlow == null) + mainFlow = Resources.FindObjectsOfTypeAll().First(); + if (menuFlow == null) + menuFlow = new GameObject("BSIPA Mod List Flow Controller").AddComponent(); + if (panel == null) + panel = GameObject.Find(ControllerPanel).transform as RectTransform; + + if (button == null) + { + button = BeatSaberUI.CreateUIButton(panel, CopyButton, () => + { + Logger.log.Debug("Presenting own flow controller"); + menuFlow.PresentOn(mainFlow); + }, "Mod List"); + panel.Find(CopyButton).SetAsLastSibling(); + + hintText = BeatSaberUI.AddHintText(button.transform as RectTransform, "View and control updates for installed mods"); + } + + yield break; + } + } + } +} diff --git a/BSIPA-ModList/UI/ModListFlowCoordinator.cs b/BSIPA-ModList/UI/ModListFlowCoordinator.cs index f339bdfd..ab09b76d 100644 --- a/BSIPA-ModList/UI/ModListFlowCoordinator.cs +++ b/BSIPA-ModList/UI/ModListFlowCoordinator.cs @@ -25,7 +25,7 @@ namespace BSIPA_ModList.UI navigationController.didFinishEvent += backButton_DidFinish; modList = BeatSaberUI.CreateViewController(); - modList.Init(navigationController, PluginManager.AllPlugins, PluginLoader.ignoredPlugins, PluginManager.Plugins); + modList.Init(this, PluginManager.AllPlugins, PluginLoader.ignoredPlugins, PluginManager.Plugins); PushViewControllerToNavigationController(navigationController, modList); } @@ -49,10 +49,54 @@ namespace BSIPA_ModList.UI presentFlow(main, this, finished, immediate, replaceTop); } + public bool HasSelected { get; private set; } = false; + + public void SetSelected(VRUIViewController selected, Action callback = null, bool immediate = false) + { + if (immediate) + { + if (HasSelected) + PopViewController(immediate: true); + PushViewController(selected, callback, true); + } + else + { + if (HasSelected) + PopViewController(() => PushViewController(selected, callback, immediate), immediate); + else + PushViewController(selected, callback, immediate); + } + } + + public void ClearSelected(Action callback = null, bool immediate = false) + { + if (HasSelected) PopViewController(callback, immediate); + } + + public void PushViewController(VRUIViewController controller, Action callback = null, bool immediate = false) + { + PushViewControllerToNavigationController(navigationController, controller, callback, immediate); + } + + public void PopViewController(Action callback = null, bool immediate = false) + { + PopViewControllerFromNavigationController(navigationController, callback, immediate); + } + + private delegate void DismissFlowDel(FlowCoordinator self, FlowCoordinator newF, Action finished, bool immediate); + private static DismissFlowDel dismissFlow; + private void backButton_DidFinish() { + if (dismissFlow == null) + { + var ty = typeof(FlowCoordinator); + var m = ty.GetMethod("DismissFlowCoordinator", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + dismissFlow = (DismissFlowDel)Delegate.CreateDelegate(typeof(DismissFlowDel), m); + } + MainFlowCoordinator mainFlow = Resources.FindObjectsOfTypeAll().First(); - mainFlow.InvokeMethod("DismissFlowCoordinator", this, null, false); + dismissFlow(mainFlow, this, null, false); } } } diff --git a/BSIPA-ModList/UI/ViewControllers/ModInfoViewController.cs b/BSIPA-ModList/UI/ViewControllers/ModInfoViewController.cs index 60cde929..2479627c 100644 --- a/BSIPA-ModList/UI/ViewControllers/ModInfoViewController.cs +++ b/BSIPA-ModList/UI/ViewControllers/ModInfoViewController.cs @@ -4,11 +4,28 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using UnityEngine; +using VRUI; namespace BSIPA_ModList.UI { - internal class ModInfoViewController : CustomViewController + internal class ModInfoViewController : VRUIViewController { + private Sprite Icon; + private string Name; + private string Version; + private string Author; + private string Description; + private bool CanUpdate; + public void Init(Sprite icon, string name, string version, string author, string description, bool canUpdate) + { + Icon = icon; + Name = name; + Version = version; + Author = author; + Description = description; + CanUpdate = canUpdate; + } } } diff --git a/BSIPA-ModList/UI/ViewControllers/ModListController.cs b/BSIPA-ModList/UI/ViewControllers/ModListController.cs index f80a887a..801851bf 100644 --- a/BSIPA-ModList/UI/ViewControllers/ModListController.cs +++ b/BSIPA-ModList/UI/ViewControllers/ModListController.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using CustomUI.BeatSaber; using CustomUI.Utilities; @@ -7,6 +8,7 @@ using IPA.Loader; using IPA.Old; using UnityEngine; using VRUI; +using IPA.Loader.Features; namespace BSIPA_ModList.UI { @@ -31,11 +33,13 @@ namespace BSIPA_ModList.UI } internal PluginLoader.PluginInfo Plugin; + private ModListController list; - public BSIPAModCell(PluginLoader.PluginInfo plugin) + public BSIPAModCell(ModListController list, PluginLoader.PluginInfo plugin) : base($"{plugin.Metadata.Name} v{plugin.Metadata.Version}", plugin.Metadata.Manifest.Author, null) { Plugin = plugin; + this.list = list; if (plugin.Metadata.Manifest.IconPath != null) icon = UIUtilities.LoadSpriteRaw(UIUtilities.GetResource(plugin.Metadata.Assembly, plugin.Metadata.Manifest.IconPath)); @@ -45,20 +49,33 @@ namespace BSIPA_ModList.UI Logger.log.Debug($"BSIPAModCell {plugin.Metadata.Name} {plugin.Metadata.Version}"); } + private ModInfoViewController infoView; + public void OnSelect(ModListController cntrl) { Logger.log.Debug($"Selected BSIPAModCell {Plugin.Metadata.Name} {Plugin.Metadata.Version}"); + + if (infoView == null) + { + infoView = BeatSaberUI.CreateViewController(); + infoView.Init(icon, Plugin.Metadata.Name, Plugin.Metadata.Version.ToString(), Plugin.Metadata.Manifest.Author, + Plugin.Metadata.Manifest.Description, Plugin.Metadata.Features.FirstOrDefault(f => f is NoUpdateFeature) == null); + } + + list.flow.SetSelected(infoView); } } private class BSIPAIgnoredModCell : CustomCellInfo, IClickableCell { internal PluginLoader.PluginMetadata Plugin; + private ModListController list; - public BSIPAIgnoredModCell(PluginLoader.PluginMetadata plugin) + public BSIPAIgnoredModCell(ModListController list, PluginLoader.PluginMetadata plugin) : base($"{plugin.Name} v{plugin.Version}", $"{plugin.Manifest.Author} - Not loaded", BSIPAModCell.DefaultIcon) { Plugin = plugin; + this.list = list; Logger.log.Debug($"BSIPAIgnoredModCell {plugin.Name} {plugin.Version}"); } @@ -66,6 +83,7 @@ namespace BSIPA_ModList.UI public void OnSelect(ModListController cntrl) { Logger.log.Debug($"Selected BSIPAIgnoredModCell {Plugin.Name} {Plugin.Version}"); + } } @@ -84,11 +102,13 @@ namespace BSIPA_ModList.UI } internal IPlugin Plugin; + private ModListController list; - public IPAModCell(IPlugin plugin) + public IPAModCell(ModListController list, IPlugin plugin) : base($"{plugin.Name} {plugin.Version}", "Legacy", DefaultIcon) { Plugin = plugin; + this.list = list; Logger.log.Debug($"IPAModCell {plugin.Name} {plugin.Version}"); } @@ -100,10 +120,10 @@ namespace BSIPA_ModList.UI } #pragma warning restore - private BackButtonNavigationController navigation; + private ModListFlowCoordinator flow; #pragma warning disable CS0618 - public void Init(BackButtonNavigationController navigation, IEnumerable bsipaPlugins, IEnumerable ignoredPlugins, IEnumerable ipaPlugins) + public void Init(ModListFlowCoordinator flow, IEnumerable bsipaPlugins, IEnumerable ignoredPlugins, IEnumerable ipaPlugins) { Logger.log.Debug("List Controller Init"); @@ -111,16 +131,16 @@ namespace BSIPA_ModList.UI DidSelectRowEvent = DidSelectRow; includePageButtons = true; - this.navigation = navigation; + this.flow = flow; reuseIdentifier = "BSIPAModListTableCell"; foreach (var plugin in bsipaPlugins) - Data.Add(new BSIPAModCell(plugin)); + Data.Add(new BSIPAModCell(this, plugin)); foreach (var plugin in ignoredPlugins) - Data.Add(new BSIPAIgnoredModCell(plugin)); + Data.Add(new BSIPAIgnoredModCell(this, plugin)); foreach (var plugin in ipaPlugins) - Data.Add(new IPAModCell(plugin)); + Data.Add(new IPAModCell(this, plugin)); } #pragma warning restore diff --git a/Refs/BeatSaberCustomUI.dll b/Refs/BeatSaberCustomUI.dll index 8f810ea4..297e4173 100644 Binary files a/Refs/BeatSaberCustomUI.dll and b/Refs/BeatSaberCustomUI.dll differ diff --git a/Refs/UnityEngine.dll b/Refs/UnityEngine.dll new file mode 100644 index 00000000..605ef4d4 Binary files /dev/null and b/Refs/UnityEngine.dll differ diff --git a/Refs/UnityEngine.xml b/Refs/UnityEngine.xml new file mode 100644 index 00000000..a4658120 --- /dev/null +++ b/Refs/UnityEngine.xml @@ -0,0 +1,8 @@ + + + + + UnityEngine + + + diff --git a/Refs/refs.txt b/Refs/refs.txt index 3818beda..9554dac9 100644 --- a/Refs/refs.txt +++ b/Refs/refs.txt @@ -3,6 +3,8 @@ ""Managed/ """Assembly-CSharp.dll """UnityEngine. +""""dll +""""xml """"UnityWebRequestModule. """""dll """""xml