diff --git a/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs b/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs index 16a6b918b..9abbf8a6d 100644 --- a/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs +++ b/BloonsTD6 Mod Helper/Api/Components/ModHelperText.cs @@ -37,6 +37,37 @@ 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); + 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 000000000..6d38217a0 Binary files /dev/null and b/BloonsTD6 Mod Helper/Resources/OpenFolderIcon.png differ diff --git a/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs b/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs new file mode 100644 index 000000000..e54282fb7 --- /dev/null +++ b/BloonsTD6 Mod Helper/UI/Menus/ModSourcesMenu.cs @@ -0,0 +1,171 @@ +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 System; +using System.Collections; +using System.IO; +using System.Linq; +using Il2CppAssets.Scripts.Unity.Menu; +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 FoundModSources = ModHelper.Localize(nameof(FoundModSources), "Found Mod Sources"); + + private static bool currentlyLoadingSources = false; + + bool IsModSource(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("Mod Sources"); + + 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)); + } + + 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 => + { + 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()); + MenuManager.instance.buttonClickSound.Play("ClickSounds"); + })); + } + + 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.EnableAutoSizing(200); + + var pathText = panel.AddText(new("Path", 100, -100, 1500, 150), 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")); + MenuManager.instance.buttonClick2Sound.Play("ClickSounds"); + })); + + + // -- 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 940d9dd7d..7ef356d47 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,