From 0141dfdea449ff280dc2280859884db321f2f131 Mon Sep 17 00:00:00 2001 From: ang-xd Date: Fri, 14 Aug 2026 03:12:04 -0400 Subject: [PATCH] Update gamemodes info panel to show mod icon --- MiraAPI.Example/ExamplePlugin.cs | 3 + MiraAPI/GameModes/CustomGameModeManager.cs | 11 +++ .../Patches/Options/GameOptionsMenuPatch.cs | 71 ++++++++++++++++--- MiraAPI/PluginLoading/IMiraPlugin.cs | 7 ++ 4 files changed, 84 insertions(+), 8 deletions(-) diff --git a/MiraAPI.Example/ExamplePlugin.cs b/MiraAPI.Example/ExamplePlugin.cs index b20ec41..ff4efb1 100644 --- a/MiraAPI.Example/ExamplePlugin.cs +++ b/MiraAPI.Example/ExamplePlugin.cs @@ -3,9 +3,11 @@ using BepInEx.Configuration; using BepInEx.Unity.IL2CPP; using HarmonyLib; using MiraAPI.PluginLoading; +using MiraAPI.Utilities.Assets; using Reactor; using Reactor.Networking; using Reactor.Networking.Attributes; +using UnityEngine; namespace MiraAPI.Example; @@ -18,6 +20,7 @@ public partial class ExamplePlugin : BasePlugin, IMiraPlugin { public Harmony Harmony { get; } = new(Id); public string OptionsTitleText => "Mira API\nExample Mod"; + public LoadableAsset? ModIcon => ExampleAssets.ExampleButton; public ConfigFile GetConfigFile() => Config; public override void Load() { diff --git a/MiraAPI/GameModes/CustomGameModeManager.cs b/MiraAPI/GameModes/CustomGameModeManager.cs index 90a96a1..d14a841 100644 --- a/MiraAPI/GameModes/CustomGameModeManager.cs +++ b/MiraAPI/GameModes/CustomGameModeManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using MiraAPI.PluginLoading; using Reactor.Utilities; @@ -76,6 +77,16 @@ public static class CustomGameModeManager /// The gamemode matching that ID. public static AbstractGameMode GetMode(uint id) => IdToModeMap[id]; + /// + /// Finds the parent mod of a custom gamemode. + /// + /// The object. + /// A object representing the parent mod of the gamemode. + public static MiraPluginInfo? FindParentMod(AbstractGameMode gameMode) + { + return MiraPluginManager.Instance.RegisteredPlugins.FirstOrDefault(plugin => plugin.GameModes.ContainsValue(gameMode)); + } + internal static void RegisterDefaultMode() { var defaultMode = new ClassicMode(); diff --git a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs index 5e5b27e..aeed200 100644 --- a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs +++ b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs @@ -32,6 +32,8 @@ internal static class GameOptionsMenuPatch private static System.Collections.Generic.Dictionary> _gameModeOptions = new(); private static System.Collections.Generic.Dictionary> _gameModeHeaders = new(); private static TextMeshPro _gamemodeDescription = null!; + private static SpriteRenderer _modIcon = null!; + [HarmonyPrefix] [HarmonyPatch(nameof(GameOptionsMenu.Initialize))] // ReSharper disable once InconsistentNaming @@ -84,6 +86,30 @@ internal static class GameOptionsMenuPatch { instance.Children.Add(opt); } + + var mod = CustomGameModeManager.FindParentMod(gameMode); + if (mod is { MiraPlugin.ModIcon: not null }) + { + _modIcon.gameObject.SetActive(true); + _gamemodeDescription.transform.localPosition = new Vector3(0.3f, 0, -0.01f); + _gamemodeDescription.horizontalAlignment = HorizontalAlignmentOptions.Left; + var texture = mod.MiraPlugin.ModIcon.LoadAsset().texture; + var newSprite = Sprite.Create( + texture, + new Rect(0, 0, 128, 128), + Vector2.one / 2, + 100 + ); + _modIcon.sprite = newSprite; + _modIcon.drawMode = SpriteDrawMode.Sliced; + } + else + { + _gamemodeDescription.transform.localPosition = new Vector3(0f, 0, -0.01f); + _gamemodeDescription.horizontalAlignment = HorizontalAlignmentOptions.Center; + _modIcon.gameObject.SetActive(false); + } + _gamemodeDescription.text = gameMode.Description; if (gameMode.ShowNormalGameSettings) { @@ -155,6 +181,8 @@ internal static class GameOptionsMenuPatch } instance.scrollBar.SetYBoundsMax(-num - 1.65f); } + + private static void CreateSettings(GameOptionsMenu instance, Transform container) { float num = 0.713f; @@ -197,16 +225,43 @@ internal static class GameOptionsMenuPatch GameModeOption.Values.ElementAt(i).Value); } - var gamemodeTextObj = Object.Instantiate(GameModeOption.OptionBehaviour.transform.GetChild(1).gameObject, Vector3.zero, Quaternion.identity, container); - gamemodeTextObj.transform.localPosition = new Vector3(1, -0.675f, -2f); - gamemodeTextObj.transform.localScale = new Vector3(2.6f, 2.6f, 1); + var modeInfoHolder = new GameObject("GamemodeInfo") + { + transform = + { + parent = container, + localPosition = new Vector3(1.2f, -0.675f, 1), + localScale = Vector3.one, + }, + layer = container.gameObject.layer, + }.transform; + + var gamemodeBg = Object.Instantiate(GameModeOption.OptionBehaviour.transform.GetChild(0).gameObject, Vector3.zero, Quaternion.identity, modeInfoHolder); + gamemodeBg.transform.localPosition = Vector3.zero; + gamemodeBg.transform.localScale = new Vector3(1.35f, 0.85f, 1); + gamemodeBg.name = "Background"; + + var modIconObj = new GameObject("ModIcon") + { + transform = + { + parent = modeInfoHolder, + localPosition = new Vector3(-1.75f, 0, -0.1f), + localScale = new Vector3(0.4f, 0.4f, 1), + }, + layer = gamemodeBg.layer, + }; + _modIcon = modIconObj.AddComponent(); + _modIcon.sprite = MiraAssets.BlankSprite.LoadAsset(); + + var gamemodeTextObj = Object.Instantiate(GameModeOption.OptionBehaviour.transform.GetChild(1).gameObject, Vector3.zero, Quaternion.identity, modeInfoHolder); + gamemodeTextObj.transform.localPosition = new Vector3(0.3f, 0, -0.01f); + gamemodeTextObj.transform.localScale = new Vector3(2.12f, 2.12f, 1); _gamemodeDescription = gamemodeTextObj.GetComponentInChildren(); - _gamemodeDescription.fontSizeMin = 0.5f; - _gamemodeDescription.fontSizeMax = 1; + _gamemodeDescription.fontSizeMin = 0.65f; + _gamemodeDescription.fontSizeMax = 0.9f; + _gamemodeDescription.alignment = TextAlignmentOptions.Left; - var gamemodeBg = Object.Instantiate(GameModeOption.OptionBehaviour.transform.GetChild(0).gameObject, Vector3.zero, Quaternion.identity, gamemodeTextObj.transform); - gamemodeBg.transform.localPosition = new Vector3(0, 0, 0.01f); - gamemodeBg.transform.localScale = new Vector3(0.61f, 0.375f, 1); num -= 1.3f; AdditionalVanillaScrollNum = 0f; foreach (RulesCategory rulesCategory in GameManager.Instance.GameSettingsList.AllCategories) diff --git a/MiraAPI/PluginLoading/IMiraPlugin.cs b/MiraAPI/PluginLoading/IMiraPlugin.cs index ad5a992..bb3e29d 100644 --- a/MiraAPI/PluginLoading/IMiraPlugin.cs +++ b/MiraAPI/PluginLoading/IMiraPlugin.cs @@ -1,5 +1,7 @@ using System.Linq; using BepInEx.Configuration; +using MiraAPI.Utilities.Assets; +using UnityEngine; namespace MiraAPI.PluginLoading; @@ -52,6 +54,11 @@ public interface IMiraPlugin /// public virtual string CustomOptionMenuTwoDescription => "Apply game settings for this mod!"; + /// + /// Gets the icon of the mod. + /// + public virtual LoadableAsset? ModIcon => null; + /// /// Gets the for the plugin. ///