From 557b82b9526a6a053debb9ec7ab36f6a1cb21347 Mon Sep 17 00:00:00 2001 From: DarkTerraYT Date: Sun, 20 Oct 2024 01:07:40 -0400 Subject: [PATCH 1/4] Add Mod Sources Menu and a few new methods to ModHelperText. --- .../Api/Components/ModHelperText.cs | 17 ++ .../Resources/OpenFolderIcon.png | Bin 0 -> 16599 bytes .../UI/Menus/ModSourcesMenu.cs | 156 ++++++++++++++++++ BloonsTD6 Mod Helper/UI/Menus/ModsMenu.cs | 14 ++ 4 files changed, 187 insertions(+) create mode 100644 BloonsTD6 Mod Helper/Resources/OpenFolderIcon.png create mode 100644 BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs diff --git a/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs b/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs index 16a6b918b..ecd74ce45 100644 --- a/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs +++ b/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs @@ -37,6 +37,23 @@ public void SetText(string text) } } + public void EnableAutoSizing() + { + Text.enableAutoSizing = true; + } + + public void EnableAutoSizing(float fontSizeMax) + { + EnableAutoSizing(); + Text.fontSizeMax = fontSizeMax; + } + + public void EnableAutoSizing(float fontSizeMax, float fontSizeMin) + { + EnableAutoSizing(fontSizeMax); + Text.fontSizeMin = fontSizeMin; + } + /// /// Creates a new ModHelperText /// diff --git a/BloonsTD6 Mod Helper/Resources/OpenFolderIcon.png b/BloonsTD6 Mod Helper/Resources/OpenFolderIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..6d38217a044f32cb8c528db7b1f70d179ce4fe3b GIT binary patch literal 16599 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 Squ{nbq#&m%Tk!Bj!2bag^Ih8j literal 0 HcmV?d00001 diff --git a/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs b/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs new file mode 100644 index 000000000..bc8c1d0d4 --- /dev/null +++ b/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs @@ -0,0 +1,156 @@ +using BTD_Mod_Helper.Api; +using BTD_Mod_Helper.Api.Components; +using BTD_Mod_Helper.Api.Enums; +using BTD_Mod_Helper.Api.Helpers; +using Il2CppAssets.Scripts.Unity.UI_New.Popups; +using Il2CppAssets.Scripts.Unity.UI_New.Settings; +using Il2CppNinjaKiwi.Common; +using Newtonsoft.Json; +using NfdSharp; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEngine; + +namespace BTD_Mod_Helper.UI.Menus +{ + internal class ModSourcesMenu : ModGameMenu + { + internal static bool ModSourcesPresent => Directory.GetFiles(MelonMain.ModSourcesFolder).Length > 0; + + private static ModHelperScrollPanel sourcesScroll; + + private static readonly string ModSources = ModHelper.Localize(nameof(ModSources), "Mod Sources"); + private static readonly string FoundModSources = ModHelper.Localize(nameof(FoundModSources), "Found Mod Sources"); + + private static bool currentlyLoadingSources = false; + + bool CheckSource(string path) + { + foreach (var file in Directory.GetFiles(path)) + { + if (Path.GetExtension(file) == ".sln") + { + return true; + } + } + + return false; + } + + public override bool OnMenuOpened(Il2CppSystem.Object data) + { + GameMenu.gameObject.DestroyAllChildren(); + CommonForegroundHeader.SetText(ModSources); + CommonForegroundHeader.AutoLocalize = true; + + var panel = GameMenu.gameObject.AddModHelperPanel(new("Panel", 0, -150, 3300, 1900), VanillaSprites.MainBGPanelBlue); + + panel.AddText(new("TitleText", 0, 850, 2000, 125), FoundModSources).EnableAutoSizing(150); + + sourcesScroll = panel.AddScrollPanel(new("ScrollPanel", 0, -150, 3000, 1500), RectTransform.Axis.Vertical, VanillaSprites.BlueInsertPanelRound, 100, 100); + + MelonCoroutines.Start(GenerateScrollContent()); + + CreateExtraElements(panel); + + return true; + } + + public IEnumerator GenerateScrollContent(string search = "") + { + if(currentlyLoadingSources) + { + PopupScreen.instance.SafelyQueue(screen => screen.ShowOkPopup("Wait until the mod sources have finished loading!")); + + yield break; + } + + currentlyLoadingSources = true; + + sourcesScroll.ScrollContent.RectTransform.DestroyAllChildren(); + + int i = 0; + + foreach (var folder in Directory.GetDirectories(MelonMain.ModSourcesFolder).OrderBy(path => path)) + { + Sprite icon = null; + string name = ""; + + foreach(var file in Directory.GetFiles(folder)) + { + if(Path.GetFileName(file) == "Icon.png") + { + Texture2D iconTexture = new(2, 2); + iconTexture.LoadFromFile(file); + + icon = Sprite.Create(new Rect(0, 0, iconTexture.width, iconTexture.height), new Vector2(), 10, iconTexture); + } + + if(Path.GetExtension(file) == ".sln" && name == "") + { + name = Path.GetFileNameWithoutExtension(file); + + } + + if (Closing) { currentlyLoadingSources = false; yield break; } + } + + if (Closing) { currentlyLoadingSources = false; yield break; } + + if (name != "" && name.ToLower().Contains(search)) sourcesScroll.AddScrollContent(CreateSourcePanel(name, folder, icon)); + + yield return null; + } + + currentlyLoadingSources = false; + } + + internal void CreateExtraElements(ModHelperPanel panel) + { + string searchText = ""; + + var searchBtn = panel.AddButton(new("SearchBtn", -1500, 700, 175), VanillaSprites.BlueBtn, new Action(() => { if(!string.IsNullOrEmpty(searchText) && !string.IsNullOrWhiteSpace(searchText)) MelonCoroutines.Start(GenerateScrollContent(searchText)); })); + searchBtn.AddImage(new("Image", 125), VanillaSprites.SearchIcon); + + var searchBar = panel.AddInputField(new("SearchBar", -650, 700, 1500, 125), searchText, VanillaSprites.BlueInsertPanel, new Action(input => + { + if(input != null) + { + searchText = input.ToLower(); + } + }), 75, Il2CppTMPro.TMP_InputField.CharacterValidation.Alphanumeric, Il2CppTMPro.TextAlignmentOptions.Left, "", 20); + + var refreshButton = panel.AddButton(new("RefreshBtn", 1400, 750, 250), VanillaSprites.RestartBtn, new Action(() => MelonCoroutines.Start(GenerateScrollContent()))); + } + + private ModHelperPanel CreateSourcePanel(string name, string path, Sprite iconSprite) + { + var panel = ModHelperPanel.Create(new("SourcePanel_" + name, 2500, 600), VanillaSprites.MainBGPanelBlue); + + var nameText = panel.AddText(new("Name", 100, 100, 1500, 200), name.Localize()); + nameText.Text.fontSizeMax = 200; + nameText.Text.enableAutoSizing = true; + + var pathText = panel.AddText(new("Path", 100, -100, 1500, 150), path); + nameText.Text.fontSizeMax = 150; + nameText.Text.enableAutoSizing = true; + + var openFolder = panel.AddButton(new("OpenFolderButton", 1050, 150, 250), VanillaSprites.BlueBtn, new Action(() => ProcessHelper.OpenFolder(path))); + openFolder.AddImage(new("Icon", 150), GetSprite("OpenFolderIcon")); + + var openProject = panel.AddButton(new("OpenProjectBtn", 1050, -150, 250), VanillaSprites.EditBtn, new Action(() => ProcessHelper.OpenFile(Path.Combine(path, name + ".sln")))); + + + // -- DOESN'T WORK-- (idk why) + /*if (iconSprite != null) + { + panel.AddImage(new("Icon", -1900, 0, 500), iconSprite); + }*/ + + return panel; + } + } +} diff --git a/BloonsTD6 Mod Helper/UI/Menus/ModsMenu.cs b/BloonsTD6 Mod Helper/UI/Menus/ModsMenu.cs index 784a70ad2..6375a9988 100644 --- a/BloonsTD6 Mod Helper/UI/Menus/ModsMenu.cs +++ b/BloonsTD6 Mod Helper/UI/Menus/ModsMenu.cs @@ -135,6 +135,7 @@ Would you like to export this mod's current localization? ModHelper.Localize(nameof(LocalizationGeneratedBody), "Would you like to view the generated file?"); private static readonly string LocalizationFailed = ModHelper.Localize(nameof(LocalizationFailed), "Localization failed to generate, see console for details."); + private static readonly string ModSources = ModHelper.Localize(nameof(ModSources), "Mod Sources"); /// public override bool OnMenuOpened(Object data) @@ -228,6 +229,19 @@ private static void CreateExtraButtons(ExtraSettingsScreen gameMenu) modBrowserButton.AddText(new Info("Text", 0, -200, 500, 150), BrowseMods, 60f); modBrowserButton.SetActive(InGame.instance == null); + var modSourcesButton = bottomButtonGroup.AddButton(new("ModSourcesButton", 225, Padding * 2 + 400, 400) + { + Anchor = Vector2.zero, + Pivot = new Vector2(0.5f, 0) + }, VanillaSprites.WoodenRoundButton, new Action(() => + { + Open(); + })); + + modSourcesButton.AddImage(new("ChallengesIcon", InfoPreset.FillParent), VanillaSprites.ChallengesIcon); + + modSourcesButton.AddText(new("Text", 0, -200, 500, 100), ModSources, 60f); + var createModButton = bottomButtonGroup.AddButton(new Info("CreateModButton", 225, Padding, 400) { Anchor = Vector2.zero, From dab67b88581f3845e00c46555e65acbf0a80c119 Mon Sep 17 00:00:00 2001 From: DarkTerraYT Date: Sun, 20 Oct 2024 01:10:45 -0400 Subject: [PATCH 2/4] Add XML comments. --- .../Api/Components/ModHelperText.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs b/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs index ecd74ce45..9abbf8a6d 100644 --- a/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs +++ b/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs @@ -37,17 +37,31 @@ public void SetText(string text) } } + /// + /// Enables auto sizing on the text component + /// public void EnableAutoSizing() { Text.enableAutoSizing = true; } + /// + /// Enables auto sizing on the text component. + /// Changes the maximum font size. + /// + /// New max font size public void EnableAutoSizing(float fontSizeMax) { EnableAutoSizing(); Text.fontSizeMax = fontSizeMax; } + /// + /// Enables auto sizing on the text component. + /// Changes the maximum and minimum font size. + /// + /// New max font size + /// New min font size public void EnableAutoSizing(float fontSizeMax, float fontSizeMin) { EnableAutoSizing(fontSizeMax); From 0d48ea14a9f8db9389b39cebd19894548cf45e72 Mon Sep 17 00:00:00 2001 From: DarkTerraYT Date: Sun, 20 Oct 2024 01:17:34 -0400 Subject: [PATCH 3/4] Fix Header Text --- BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs b/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs index bc8c1d0d4..d56fb1f44 100644 --- a/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs +++ b/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs @@ -22,7 +22,6 @@ internal class ModSourcesMenu : ModGameMenu private static ModHelperScrollPanel sourcesScroll; - private static readonly string ModSources = ModHelper.Localize(nameof(ModSources), "Mod Sources"); private static readonly string FoundModSources = ModHelper.Localize(nameof(FoundModSources), "Found Mod Sources"); private static bool currentlyLoadingSources = false; @@ -43,7 +42,7 @@ bool CheckSource(string path) public override bool OnMenuOpened(Il2CppSystem.Object data) { GameMenu.gameObject.DestroyAllChildren(); - CommonForegroundHeader.SetText(ModSources); + CommonForegroundHeader.SetText("Mod Sources"); CommonForegroundHeader.AutoLocalize = true; var panel = GameMenu.gameObject.AddModHelperPanel(new("Panel", 0, -150, 3300, 1900), VanillaSprites.MainBGPanelBlue); From 810931b8e412e637d8703bfbae9746aa291a3d88 Mon Sep 17 00:00:00 2001 From: DarkTerraYT Date: Thu, 24 Oct 2024 19:42:44 -0400 Subject: [PATCH 4/4] Add click sounds to the buttons, use EnableAutoSizing method instead of the usual way. --- .../UI/Menus/ModSourcesMenu.cs | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs b/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs index d56fb1f44..e54282fb7 100644 --- a/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs +++ b/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs @@ -5,13 +5,11 @@ using Il2CppAssets.Scripts.Unity.UI_New.Popups; using Il2CppAssets.Scripts.Unity.UI_New.Settings; using Il2CppNinjaKiwi.Common; -using Newtonsoft.Json; -using NfdSharp; using System; using System.Collections; -using System.Collections.Generic; using System.IO; using System.Linq; +using Il2CppAssets.Scripts.Unity.Menu; using UnityEngine; namespace BTD_Mod_Helper.UI.Menus @@ -25,8 +23,8 @@ internal class ModSourcesMenu : ModGameMenu private static readonly string FoundModSources = ModHelper.Localize(nameof(FoundModSources), "Found Mod Sources"); private static bool currentlyLoadingSources = false; - - bool CheckSource(string path) + + bool IsModSource(string path) { foreach (var file in Directory.GetFiles(path)) { @@ -43,7 +41,6 @@ public override bool OnMenuOpened(Il2CppSystem.Object data) { GameMenu.gameObject.DestroyAllChildren(); CommonForegroundHeader.SetText("Mod Sources"); - CommonForegroundHeader.AutoLocalize = true; var panel = GameMenu.gameObject.AddModHelperPanel(new("Panel", 0, -150, 3300, 1900), VanillaSprites.MainBGPanelBlue); @@ -111,7 +108,15 @@ internal void CreateExtraElements(ModHelperPanel panel) { string searchText = ""; - var searchBtn = panel.AddButton(new("SearchBtn", -1500, 700, 175), VanillaSprites.BlueBtn, new Action(() => { if(!string.IsNullOrEmpty(searchText) && !string.IsNullOrWhiteSpace(searchText)) MelonCoroutines.Start(GenerateScrollContent(searchText)); })); + var searchBtn = panel.AddButton(new("SearchBtn", -1500, 700, 175), VanillaSprites.BlueBtn, new Action(() => + { + if (!string.IsNullOrEmpty(searchText) && !string.IsNullOrWhiteSpace(searchText)) + { + MelonCoroutines.Start(GenerateScrollContent(searchText)); + } + + MenuManager.instance.buttonClickSound.Play("ClickSounds"); + })); searchBtn.AddImage(new("Image", 125), VanillaSprites.SearchIcon); var searchBar = panel.AddInputField(new("SearchBar", -650, 700, 1500, 125), searchText, VanillaSprites.BlueInsertPanel, new Action(input => @@ -122,7 +127,11 @@ internal void CreateExtraElements(ModHelperPanel panel) } }), 75, Il2CppTMPro.TMP_InputField.CharacterValidation.Alphanumeric, Il2CppTMPro.TextAlignmentOptions.Left, "", 20); - var refreshButton = panel.AddButton(new("RefreshBtn", 1400, 750, 250), VanillaSprites.RestartBtn, new Action(() => MelonCoroutines.Start(GenerateScrollContent()))); + var refreshButton = panel.AddButton(new("RefreshBtn", 1400, 750, 250), VanillaSprites.RestartBtn, new Action(() => + { + MelonCoroutines.Start(GenerateScrollContent()); + MenuManager.instance.buttonClickSound.Play("ClickSounds"); + })); } private ModHelperPanel CreateSourcePanel(string name, string path, Sprite iconSprite) @@ -130,17 +139,24 @@ private ModHelperPanel CreateSourcePanel(string name, string path, Sprite iconSp var panel = ModHelperPanel.Create(new("SourcePanel_" + name, 2500, 600), VanillaSprites.MainBGPanelBlue); var nameText = panel.AddText(new("Name", 100, 100, 1500, 200), name.Localize()); - nameText.Text.fontSizeMax = 200; - nameText.Text.enableAutoSizing = true; + nameText.EnableAutoSizing(200); var pathText = panel.AddText(new("Path", 100, -100, 1500, 150), path); - nameText.Text.fontSizeMax = 150; - nameText.Text.enableAutoSizing = true; - - var openFolder = panel.AddButton(new("OpenFolderButton", 1050, 150, 250), VanillaSprites.BlueBtn, new Action(() => ProcessHelper.OpenFolder(path))); + pathText.EnableAutoSizing(150); + var openFolder = panel.AddButton(new("OpenFolderButton", 1050, 150, 250), VanillaSprites.BlueBtn, new Action(() => + { + ProcessHelper.OpenFolder(path); + MenuManager.instance.buttonClick2Sound.Play("ClickSounds"); + + })); openFolder.AddImage(new("Icon", 150), GetSprite("OpenFolderIcon")); - var openProject = panel.AddButton(new("OpenProjectBtn", 1050, -150, 250), VanillaSprites.EditBtn, new Action(() => ProcessHelper.OpenFile(Path.Combine(path, name + ".sln")))); + var openProject = panel.AddButton(new("OpenProjectBtn", 1050, -150, 250), VanillaSprites.EditBtn, new Action( + () => + { + ProcessHelper.OpenFile(Path.Combine(path, name + ".sln")); + MenuManager.instance.buttonClick2Sound.Play("ClickSounds"); + })); // -- DOESN'T WORK-- (idk why)