diff --git a/Assets/CamoDecal.png b/Assets/CamoDecal.png new file mode 100644 index 0000000..ac1197d Binary files /dev/null and b/Assets/CamoDecal.png differ diff --git a/Assets/DefaultTemplate.cstmbln b/Assets/DefaultTemplate.cstmbln new file mode 100644 index 0000000..bb38b02 --- /dev/null +++ b/Assets/DefaultTemplate.cstmbln @@ -0,0 +1,153 @@ +{ + "Guid": "1119f64d-4989-44d4-955d-8f11f37e7c25", + "Name": "Bloon", + "modules": [ + { + "$type": "BloonFactory.Modules.Core.BloonModule, BloonFactory", + "Id": "ad6bb6d7-748a-4b15-8c0d-05947da96450", + "PropertiesData": { + "Name": "Custom Bloon", + "Health": 5, + "Speed": 18.0, + "Damage": 1 + }, + "Outputs": [ + { + "Name": "Visuals", + "Id": "ee8871a8-9a12-4985-99a2-d7317059e68c", + "Type": "BloonFactory.LinkTypes.Visuals, BloonFactory, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "InputsGuids": [ + "bc5c65f3-ec44-4e67-b83b-8214edc22586" + ] + }, + { + "Name": "Bloon", + "Id": "4246f3a7-3c85-45f0-8b7a-9858939dc9b9", + "Type": "Il2CppAssets.Scripts.Models.Bloons.BloonModel, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", + "InputsGuids": [ + "938505a6-f385-49b3-8b79-2fbe48170148", + "f2b42e3a-73b5-4185-9573-a76d341f69b0" + ] + }, + { + "Name": "Roundset", + "Id": "987491a9-97a7-4667-b18c-7ac7f49db8bc", + "Type": "Il2CppAssets.Scripts.Models.Rounds.RoundSetModel, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", + "InputsGuids": [] + } + ], + "Inputs": [], + "XPosition": 0, + "YPosition": 0, + "Name": "Bloon", + "IsRemovable": false, + "Description": "Adds the base functionality of your custom bloon." + }, + { + "$type": "BloonFactory.Modules.Behaviors.AddChildrenModule, BloonFactory", + "Id": "92558238-e733-4366-bfd3-fcf73f7493bd", + "PropertiesData": { + "Bloon": 134, + "Count": 3, + "BloonId": "Red" + }, + "Outputs": [], + "Inputs": [ + { + "Name": "Bloon", + "Id": "938505a6-f385-49b3-8b79-2fbe48170148", + "Type": "Il2CppAssets.Scripts.Models.Bloons.BloonModel, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", + "OutputGuid": "4246f3a7-3c85-45f0-8b7a-9858939dc9b9" + } + ], + "XPosition": 2427.6753, + "YPosition": -904.11255, + "Name": "Add Children", + "IsRemovable": true, + "Description": "" + }, + { + "$type": "BloonFactory.Modules.Display.SimpleDisplayModule, BloonFactory", + "Id": "6963cfac-503f-4e23-a3b6-57a4d33d685e", + "PropertiesData": {}, + "Outputs": [ + { + "Name": "Texture", + "Id": "03fb67ce-aeaa-4a51-970d-3b4190956755", + "Type": "BloonFactory.LinkTypes.BloonTexture, BloonFactory, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "InputsGuids": [ + "7b5caf92-8aa8-40eb-b5ae-fa0a0e79e5cc" + ] + } + ], + "Inputs": [ + { + "Name": "Visuals", + "Id": "bc5c65f3-ec44-4e67-b83b-8214edc22586", + "Type": "BloonFactory.LinkTypes.Visuals, BloonFactory, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "OutputGuid": "ee8871a8-9a12-4985-99a2-d7317059e68c" + } + ], + "XPosition": 2429.0137, + "YPosition": -161.29633, + "Name": "Simple Display", + "IsRemovable": true, + "Description": "" + }, + { + "$type": "BloonFactory.Modules.Display.BloonTextureModule, BloonFactory", + "Id": "ae92b115-beb5-49c1-9858-22237c129e94", + "PropertiesData": { + "Color": { + "$type": "FactoryCore.API.ModuleProperties.SavedColor, FactoryCore", + "r": 1.0, + "g": 1.0, + "b": 1.0, + "a": 1.0 + } + }, + "Outputs": [ + { + "Name": "Texture", + "Id": "561198d3-c28b-4e10-8d7c-d13c8aabe2a2", + "Type": "BloonFactory.LinkTypes.BloonTexture, BloonFactory, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "InputsGuids": [] + } + ], + "Inputs": [ + { + "Name": "Texture", + "Id": "7b5caf92-8aa8-40eb-b5ae-fa0a0e79e5cc", + "Type": "BloonFactory.LinkTypes.BloonTexture, BloonFactory, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "OutputGuid": "03fb67ce-aeaa-4a51-970d-3b4190956755" + } + ], + "XPosition": 3968.8193, + "YPosition": -185.531, + "Name": "Bloon Texture", + "IsRemovable": true, + "Description": "" + }, + { + "$type": "BloonFactory.Modules.Behaviors.CashOnPopModule, BloonFactory", + "Id": "948a1fca-47a0-4d89-a391-b7b517a96a70", + "PropertiesData": { + "Cash": 1 + }, + "Outputs": [], + "Inputs": [ + { + "Name": "Bloon", + "Id": "f2b42e3a-73b5-4185-9573-a76d341f69b0", + "Type": "Il2CppAssets.Scripts.Models.Bloons.BloonModel, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", + "OutputGuid": "4246f3a7-3c85-45f0-8b7a-9858939dc9b9" + } + ], + "XPosition": 2431.2456, + "YPosition": -1327.9586, + "Name": "Cash On Pop", + "IsRemovable": true, + "Description": "" + } + ] +} \ No newline at end of file diff --git a/Assets/HorizontalSplitDecal.png b/Assets/HorizontalSplitDecal.png new file mode 100644 index 0000000..dcb3eaa Binary files /dev/null and b/Assets/HorizontalSplitDecal.png differ diff --git a/Assets/HorizontalStripesDecal.png b/Assets/HorizontalStripesDecal.png new file mode 100644 index 0000000..8b2b22e Binary files /dev/null and b/Assets/HorizontalStripesDecal.png differ diff --git a/Assets/VerticalSplitDecal.png b/Assets/VerticalSplitDecal.png new file mode 100644 index 0000000..69dfbfc Binary files /dev/null and b/Assets/VerticalSplitDecal.png differ diff --git a/Assets/VerticalStripesDecal.png b/Assets/VerticalStripesDecal.png new file mode 100644 index 0000000..d720838 Binary files /dev/null and b/Assets/VerticalStripesDecal.png differ diff --git a/BloonFactory.csproj b/BloonFactory.csproj index 84873f6..5b7b1dd 100644 --- a/BloonFactory.csproj +++ b/BloonFactory.csproj @@ -9,9 +9,15 @@ False embedded + + + + + + ..\..\SteamLibrary\steamapps\common\BloonsTD6\Mods\FactoryCore.dll diff --git a/Categories/BehaviorsCategory.cs b/Categories/BehaviorsCategory.cs index c8492f2..c40a010 100644 --- a/Categories/BehaviorsCategory.cs +++ b/Categories/BehaviorsCategory.cs @@ -12,6 +12,6 @@ internal class BehaviorsCategory : Category { public override string Name => "Behaviors"; - public override Type[] Modules => [typeof(DamageReductionModule), typeof(QuickEntryModule), typeof(SpeedUpNearbyBloonsModule), typeof(CashOnPopModule)]; + public override Type[] Modules => [typeof(DamageReductionModule), typeof(QuickEntryModule), typeof(SpeedUpNearbyBloonsModule), typeof(CashOnPopModule), typeof(AddChildrenModule)]; } } diff --git a/CustomBloon.cs b/CustomBloon.cs index abbcf2a..513615b 100644 --- a/CustomBloon.cs +++ b/CustomBloon.cs @@ -8,8 +8,10 @@ using Il2CppAssets.Scripts.Models.Rounds; using Il2CppNinjaKiwi.Common.ResourceUtils; using MelonLoader; +using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; diff --git a/ModuleProperties/BloonTextureModuleProperty.cs b/ModuleProperties/BloonTextureModuleProperty.cs index c2db424..b90fd37 100644 --- a/ModuleProperties/BloonTextureModuleProperty.cs +++ b/ModuleProperties/BloonTextureModuleProperty.cs @@ -12,6 +12,7 @@ using UnityEngine; using UnityEngine.Assertions; using static Il2CppNinjaKiwi.GUTS.Models.BossRushRandomizerSettings; +using TaskScheduler = BTD_Mod_Helper.Api.TaskScheduler; namespace BloonFactory.ModuleProperties { @@ -32,7 +33,10 @@ public override ModHelperPanel GetVisual(ModHelperPanel root) { UpdateImage(image); })); - UpdateImage(image); + TaskScheduler.ScheduleTask(() => + { + UpdateImage(image); + }, ScheduleType.WaitForFrames, 5); return panel; } diff --git a/Modules/Actions/SpawnBloonsActionModule.cs b/Modules/Actions/SpawnBloonsActionModule.cs index 8f5edab..c73fc55 100644 --- a/Modules/Actions/SpawnBloonsActionModule.cs +++ b/Modules/Actions/SpawnBloonsActionModule.cs @@ -6,6 +6,8 @@ using Il2CppAssets.Scripts.Models.Bloons.Behaviors; using Il2CppAssets.Scripts.Unity; using Il2CppInterop.Runtime.InteropTypes.Arrays; +using MelonLoader; +using System; using System.Linq; namespace BloonFactory.Modules.Actions @@ -15,9 +17,15 @@ internal class SpawnBloonsActionModule : Module public override string Name => "Spawn Bloons"; public override void GetModuleProperties() { - AddProperty(new EnumModuleProperty("Bloon", Game.instance.model.bloons.Select(a => a.name).ToArray(), 0)); + AddProperty(new EnumModuleProperty("Bloon", Game.instance.model.bloons.Select(a => a.name).ToArray(), 0, new Action((value) => + { + SetValue(Game.instance.model.bloons[GetValue("Bloon")].id, "BloonId"); + }))); AddProperty(new IntModuleProperty("Count", 10, 0, int.MaxValue)); AddProperty(new FloatModuleProperty("Distance Ahead", 45, float.MinValue, float.MaxValue)); + + if (!HasValue("BloonId")) + SetValue(Game.instance.model.bloons[0].id, "BloonId"); } public override void GetLinkNodes() { @@ -26,9 +34,21 @@ public override void GetLinkNodes() public override void ProcessModule() { - var trigger = GetInputValue("Trigger"); - trigger.bloonModel.AddBehavior(new SpawnBloonsActionModel("SpawnBloonsActionModel", Id.ToString(), Game.instance.model.bloons[GetValue("Bloon")].id, GetValue("Count"), 0.02f - , GetValue("Distance Ahead"), 0, 0, new Il2CppStringArray(["BloonariusAttackSpew"]), new Il2CppStringArray(["BloonariusAttackSpewMoab"]), 1.5f, false, "Bloonarius")); + try + { + var trigger = GetInputValue("Trigger"); + string id = GetValue("BloonId"); + + if (!Game.instance.model.bloons.Any(a => a.id == id)) + return; + + trigger.bloonModel.AddBehavior(new SpawnBloonsActionModel("SpawnBloonsActionModel", Id.ToString(), id, GetValue("Count"), 0.02f + , GetValue("Distance Ahead"), 0, 0, new Il2CppStringArray(["BloonariusAttackSpew"]), new Il2CppStringArray(["BloonariusAttackSpewMoab"]), 1.5f, false, "Bloonarius")); + } + catch (Exception ex) + { + MelonLogger.Error($"Failed to add action. {ex}"); + } } } diff --git a/Modules/Behaviors/AddChildrenModule.cs b/Modules/Behaviors/AddChildrenModule.cs new file mode 100644 index 0000000..db17046 --- /dev/null +++ b/Modules/Behaviors/AddChildrenModule.cs @@ -0,0 +1,51 @@ +using BloonFactory.LinkTypes; +using BTD_Mod_Helper.Extensions; +using FactoryCore.API; +using FactoryCore.API.ModuleProperties; +using FactoryCore.API.ModuleValues; +using Il2CppAssets.Scripts.Models.Bloons; +using Il2CppAssets.Scripts.Models.Bloons.Behaviors; +using Il2CppAssets.Scripts.Unity; +using Il2CppInterop.Runtime.InteropTypes.Arrays; +using MelonLoader; +using System; +using System.Linq; +using static Il2CppNinjaKiwi.GUTS.Models.BossRushRandomizerSettings; + +namespace BloonFactory.Modules.Behaviors +{ + internal class AddChildrenModule : Module + { + public override string Name => "Add Children"; + public override void GetModuleProperties() + { + AddProperty(new EnumModuleProperty("Bloon", Game.instance.model.bloons.Select(a => a.name).ToArray(), 0, new Action((value) => + { + SetValue(Game.instance.model.bloons[GetValue("Bloon")].id, "BloonId"); + }))); + AddProperty(new IntModuleProperty("Count", 10, 0, int.MaxValue)); + + if (!HasValue("BloonId")) + SetValue("", "BloonId"); + } + public override void GetLinkNodes() + { + AddInput("Bloon"); + } + + public override void ProcessModule() + { + try + { + string id = GetValue("BloonId"); + if (Game.instance.model.bloons.Any(a => a.id == id)) + GetInputValue("Bloon").AddToChildren(id, GetValue("Count")); + } + catch (Exception ex) + { + MelonLogger.Error($"Failed to add action. {ex}"); + } + + } + } +} diff --git a/Modules/Core/BloonModule.cs b/Modules/Core/BloonModule.cs index 7d4e2e2..1c57c30 100644 --- a/Modules/Core/BloonModule.cs +++ b/Modules/Core/BloonModule.cs @@ -21,7 +21,6 @@ internal class BloonModule : Module public RoundSetModel currentRoundSet; public override void GetModuleProperties() { - AddProperty(new StringModuleProperty("Name", "Custom Bloon", 20)); AddProperty(new IntModuleProperty("Health", 1, 1, int.MaxValue)); AddProperty(new FloatModuleProperty("Speed", 25, 1, float.MaxValue)); AddProperty(new IntModuleProperty("Damage", 1, 1, int.MaxValue)); diff --git a/Modules/Display/DecalModule.cs b/Modules/Display/DecalModule.cs index bb3401a..d63f5ae 100644 --- a/Modules/Display/DecalModule.cs +++ b/Modules/Display/DecalModule.cs @@ -14,15 +14,19 @@ namespace BloonFactory.Modules.Display { internal class DecalModule : Module { - public static string[] FileNameFromDecal => ["FortifiedDecal"]; + public static string[] FileNameFromDecal => ["FortifiedDecal", "CamoDecal", "HorizontalStripesDecal", "VerticalStripesDecal", "HorizontalSplitDecal", "VerticalSplitDecal"]; public override string Name => "Decal"; + + BloonTexture bloonTexture; public override void GetLinkNodes() { AddInput("Texture"); + AddOutput("Texture", () => bloonTexture); } public override void GetModuleProperties() { - AddProperty(new EnumModuleProperty("Decal", ["Fortified"], 0)); + AddProperty(new EnumModuleProperty("Decal", ["Fortified", "Camo", "Horizontal Stripes", "Vertical Stripes", "Horizontal Split", "Vertical Split"], 0)); + AddProperty(new ColorModuleProperty("Color", Color.white, false)); } public override void ProcessModule() { @@ -30,17 +34,28 @@ public override void ProcessModule() if (texture.texture == null) return; + Color color = GetValue("Color"); var decalTexture = ModContent.GetTexture(FileNameFromDecal[GetValue("Decal")]); for (int x = 0; x < decalTexture.width; x++) { for (int y = 0; y < decalTexture.height; y++) { - Color decalColor = decalTexture.GetPixel(x, y); + Color decalColor = decalTexture.GetPixel(x, y) * color; Color textureColor = texture.texture.GetPixel(x, y); - texture.texture.SetPixel(x, y, decalColor.a < 0.1f ? textureColor : decalColor); + texture.texture.SetPixel(x, y, OverlayColor(textureColor, decalColor)); } } texture.texture.Apply(); + + bloonTexture = texture; + GetOutputsModules("Texture").ProcessAll(); + } + public Color OverlayColor(Color baseColor, Color overlayColor) + { + float a = overlayColor.a; + var color = overlayColor; + color.a = 1; + return Color.Lerp(baseColor, color, a); } } } diff --git a/Modules/Display/SimpleDisplayModule.cs b/Modules/Display/SimpleDisplayModule.cs index 8579b94..0b5ec81 100644 --- a/Modules/Display/SimpleDisplayModule.cs +++ b/Modules/Display/SimpleDisplayModule.cs @@ -17,7 +17,6 @@ internal class SimpleDisplayModule : Module internal BloonTexture bloonTexture; public override void GetLinkNodes() { - AddInput("Visuals"); AddOutput("Texture", () => bloonTexture); } @@ -34,18 +33,13 @@ public override void ProcessModule() } public Texture2D GenerateTexture() { + var outputs = GetOutputsModules("Texture"); + bloonTexture = new BloonTexture(); - var outputs = GetOutputsModules("Texture"); - if (outputs.Count != 0) - { - outputs.ProcessAll(); - } - else - { - var baseBloon = ModContent.GetTexture("BaseBloon"); - bloonTexture.texture = baseBloon; - } + var baseBloon = ModContent.GetTexture("BaseBloon"); + bloonTexture.texture = baseBloon; + outputs.ProcessAll(); return bloonTexture.texture; } } diff --git a/Modules/Tags/FortifiedTagModule.cs b/Modules/Tags/FortifiedTagModule.cs index 1ac8930..5d32ad4 100644 --- a/Modules/Tags/FortifiedTagModule.cs +++ b/Modules/Tags/FortifiedTagModule.cs @@ -12,7 +12,7 @@ namespace BloonFactory.Modules.Tags { internal class FortifiedTagModule : Module { - public override string Name => "Camo Tag"; + public override string Name => "Fortified Tag"; public override void GetModuleProperties() { diff --git a/Modules/Triggers/HealthPercentTriggerModule.cs b/Modules/Triggers/HealthPercentTriggerModule.cs index a6d8235..493494c 100644 --- a/Modules/Triggers/HealthPercentTriggerModule.cs +++ b/Modules/Triggers/HealthPercentTriggerModule.cs @@ -4,6 +4,7 @@ using FactoryCore.API.ModuleValues; using Il2CppAssets.Scripts.Models.Bloons.Behaviors; using Il2CppInterop.Runtime.InteropTypes.Arrays; +using MelonLoader; using System; using System.Collections.Generic; using System.Linq; @@ -18,7 +19,6 @@ internal class HealthPercentTriggerModule : TriggerModule public override void GetModuleProperties() { - AddProperty(new FloatModuleProperty("Interval", 5, 0, float.MaxValue)); AddProperty(new IntSliderModuleProperty("Percentage", 50, 0, 100)); } @@ -30,7 +30,9 @@ public override void GetLinkNodes() public override void ProcessModule() { var guids = new Il2CppStringArray(GetOutputsModules("Trigger").AsGuids()); - currentModel.AddBehavior(new HealthPercentTriggerModel("HealthPercentTriggerModel", false, new float[GetValue("Percentage") / 100], guids, true)); + + float value = (float)GetValue("Percentage") / 100; + currentModel.AddBehavior(new HealthPercentTriggerModel("HealthPercentTriggerModel", false, new float[] { value }, guids, true)); GetOutputsModules("Trigger").ProcessAll(); } diff --git a/SerializationHandler.cs b/SerializationHandler.cs index 3c6f8dc..17217b2 100644 --- a/SerializationHandler.cs +++ b/SerializationHandler.cs @@ -1,14 +1,17 @@ using BloonFactory.Modules.Core; +using BTD_Mod_Helper; +using BTD_Mod_Helper.Api; +using BTD_Mod_Helper.Extensions; using FactoryCore.API; using Il2CppSystem.Security.Cryptography; +using MelonLoader; using MelonLoader.Utils; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Reflection; namespace BloonFactory { @@ -34,7 +37,11 @@ internal static void SaveTemplate(BloonTemplate template) var path = Path.Combine(FolderDirectory, template.Guid.ToString() + FileExtention); File.WriteAllText(path, content); } - internal static BloonTemplate LoadTemplate(string path) + internal static bool ContainGuid(Guid guid) + { + return Templates.Any(a => a.Guid == guid); + } + internal static BloonTemplate GetTemplateFromPath(string path) { EnsureFolderExists(); @@ -44,27 +51,39 @@ internal static BloonTemplate LoadTemplate(string path) var content = JsonConvert.DeserializeObject(File.ReadAllText(path), Settings); return content; } + internal static void LoadTemplate(BloonTemplate template) + { + if (!ContainGuid(template.Guid)) + { + template.SetReferences(); + Templates.Add(template); + } + + } internal static void LoadAllTemplates() { EnsureFolderExists(); foreach (var path in Directory.GetFiles(FolderDirectory).Where(f => f.EndsWith(".cstmbln"))) { - var template = LoadTemplate(path); - if (!Templates.Any(a => a.Guid == template.Guid)) - { - template.LoadModules(); - Templates.Add(template); - } + var template = GetTemplateFromPath(path); + LoadTemplate(template); } HasLoaded = true; } internal static BloonTemplate CreateTemplate(string name) { EnsureFolderExists(); + foreach (string thing in Assembly.GetCallingAssembly().GetManifestResourceNames()) + { + MelonLogger.Msg(thing); + } + var template = JsonConvert.DeserializeObject(Assembly.GetCallingAssembly().GetEmbeddedText("DefaultTemplate" + FileExtention), Settings); - var template = new BloonTemplate() { IsLoaded = false, Guid = Guid.NewGuid(), Name = name }; - template.AddModule(new BloonModule()); + template.IsLoaded = false; + template.Name = name; + template.Guid = Guid.NewGuid(); + template.SetReferences(); SaveTemplate(template); Templates.Add(template); return template; diff --git a/UI/BloonBrowserUI.cs b/UI/BloonBrowserUI.cs deleted file mode 100644 index e200a61..0000000 --- a/UI/BloonBrowserUI.cs +++ /dev/null @@ -1,19 +0,0 @@ -using BTD_Mod_Helper.Api; -using BTD_Mod_Helper.Api.Legends; -using Il2CppAssets.Scripts.Unity.UI_New.ChallengeEditor; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace BloonFactory.UI -{ - internal class BloonBrowserUI : ModGameMenu - { - public override bool OnMenuOpened(Il2CppSystem.Object data) - { - - } - } -} diff --git a/UI/BloonEditorUI.cs b/UI/BloonEditorUI.cs index 8e65022..c7cb9ad 100644 --- a/UI/BloonEditorUI.cs +++ b/UI/BloonEditorUI.cs @@ -1,4 +1,5 @@ using BloonFactory.Categories; +using BloonFactory.Modules.Core; using FactoryCore.API; using FactoryCore.UI; using System; @@ -13,6 +14,8 @@ internal class BloonEditorUI : EditorUI { public override List Categories => [new TagsCategory(), new BehaviorsCategory(), new TriggerCategory(), new ActionCategory(), new DisplayCategory(), new SpawningCategory() ]; + public override Type CenteredModule => typeof(BloonModule); + public override void SaveTemplate() { SerializationHandler.SaveTemplate((BloonTemplate)Template); diff --git a/UI/EditSelectorUI.cs b/UI/EditSelectorUI.cs index d32dbfe..4d7b44f 100644 --- a/UI/EditSelectorUI.cs +++ b/UI/EditSelectorUI.cs @@ -9,9 +9,12 @@ using Il2CppAssets.Scripts.Unity.UI_New.Main.PowersSelect; using Il2CppAssets.Scripts.Unity.UI_New.Popups; using Il2CppAssets.Scripts.Unity.UI_New.Settings; +using Il2CppNewtonsoft.Json; using Il2CppNinjaKiwi.Common; +using NfdSharp; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -47,14 +50,14 @@ public void CreateMainContent(ModHelperPanel root) mainPanelAnimator = panel.AddComponent(); mainPanelAnimator.runtimeAnimatorController = Animations.PopupAnim; mainPanelAnimator.speed = .55f; - mainPanelAnimator.Play("PopupSlideIn"); + mainPanelAnimator.Play("PopupScaleIn"); AddContent(); } public void CreateExtraContent(ModHelperPanel root) { var panel = root.AddPanel(new Info("Panel", InfoPreset.FillParent)); - var newBloon = panel.AddButton(new Info("CreateNewBloon", 0, 250, 800, 300, new Vector2(0.5f, 0)), VanillaSprites.GreenBtnLong, new Action(() => + var newBloon = panel.AddButton(new Info("CreateNewBloon", 450, 250, 800, 300, new Vector2(0.5f, 0)), VanillaSprites.GreenBtnLong, new Action(() => { MenuManager.instance.buttonClickSound.Play("ClickSounds"); PopupScreen.instance.SafelyQueue(screen => screen.ShowSetNamePopup("Create Bloon", "Name of bloon to create.\n", new Action(name => @@ -73,12 +76,34 @@ public void CreateExtraContent(ModHelperPanel root) })); newBloon.AddText(new Info("Text", 0, 0, 700, 250), "Create", 120); - //var openBrowser = panel.AddButton(new Info("BloonDownloader", 0, 0, 0, 0)) + var importBloon = panel.AddButton(new Info("ImportBloon", -450, 250, 800, 300, new Vector2(0.5f, 0)), VanillaSprites.GreenBtnLong, new Action(() => + { + MenuManager.instance.buttonClickSound.Play("ClickSounds"); + + FileDialogHelper.PrepareNativeDlls(); + + if (Nfd.OpenDialog("cstmbln", "", out string path) == Nfd.NfdResult.NFD_OKAY) + { + try + { + var template = SerializationHandler.GetTemplateFromPath(path); + if (SerializationHandler.ContainGuid(template.Guid)) + return; + SerializationHandler.LoadTemplate(template); + SerializationHandler.SaveTemplate(template); + } + catch + { + PopupScreen.instance.SafelyQueue(screen => screen.ShowPopup(PopupScreen.Placement.menuCenter, "Failed Import.", "Failed to import bloon.", null, "Ok", null, null, Popup.TransitionAnim.Scale)); + } + } + })); + importBloon.AddText(new Info("Text", 0, 0, 700, 250), "Import", 120); bottomGroupAnimator = panel.AddComponent(); bottomGroupAnimator.runtimeAnimatorController = Animations.PopupAnim; bottomGroupAnimator.speed = .55f; - bottomGroupAnimator.Play("PopupScaleIn"); + bottomGroupAnimator.Play("PopupSlideIn"); } public void AddContent() {