From 0cb0527ddfe491379a2de020bab98c35703490d4 Mon Sep 17 00:00:00 2001 From: Atony <75191600+AtonyGit@users.noreply.github.com> Date: Sat, 19 Sep 2026 13:18:36 -0500 Subject: [PATCH 1/3] Fix null component errors for custom multi menu --- MiraAPI/Hud/CustomMultiSelectMenu.cs | 3 ++- MiraAPI/Hud/CustomPhoneMenu.cs | 8 +++++++ MiraAPI/Hud/CustomPlayerMenu.cs | 31 ++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/MiraAPI/Hud/CustomMultiSelectMenu.cs b/MiraAPI/Hud/CustomMultiSelectMenu.cs index 0e87ade..c57ad8b 100644 --- a/MiraAPI/Hud/CustomMultiSelectMenu.cs +++ b/MiraAPI/Hud/CustomMultiSelectMenu.cs @@ -69,9 +69,10 @@ public abstract class CustomMultiSelectMenu : CustomPhoneMenu(); button.OnClick.RemoveAllListeners(); - button.OnClick.AddListener((UnityAction)customMenu.OnCompleteSelection); + button.OnClick.AddListener((UnityAction)customMenu.OnCompleteSelection);*/ customMenu.activeColor = activeColor; diff --git a/MiraAPI/Hud/CustomPhoneMenu.cs b/MiraAPI/Hud/CustomPhoneMenu.cs index 38edd89..a632798 100644 --- a/MiraAPI/Hud/CustomPhoneMenu.cs +++ b/MiraAPI/Hud/CustomPhoneMenu.cs @@ -169,6 +169,14 @@ public abstract class CustomPhoneMenu : ICustomMenu Component.Close(); } + /// + /// Forcibly closes the menu. + /// + public void ForceClose() + { + Component.ForceClose(); + } + /// /// Creates a . /// diff --git a/MiraAPI/Hud/CustomPlayerMenu.cs b/MiraAPI/Hud/CustomPlayerMenu.cs index a0b57a2..26c3b94 100644 --- a/MiraAPI/Hud/CustomPlayerMenu.cs +++ b/MiraAPI/Hud/CustomPlayerMenu.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using MiraAPI.Utilities.Assets; using UnityEngine; namespace MiraAPI.Hud; @@ -28,6 +29,36 @@ public class CustomPlayerMenu : CustomMultiSelectMenu return Create(); } + /// + /// Creates a . + /// + /// New object. + /// The to use when an entry is selected but not hovered over. + /// The to use when an entry is hovered over while not selected. + /// The to use when an entry is hovered over while not selected. + /// The to use when an entry is hovered over while selected. + /// The to use when an entry is hovered over while selected. + /// Function that can optionally be run when the mouse is moved outside a menu panel. + /// Function that can optionally be run when the mouse is moved over a menu panel. + public static CustomPlayerMenu Create( + Color? activeColor, + LoadableAsset? hoverSelectSprite = null, + Color? hoverSelectColor = null, + LoadableAsset? hoverDeselectSprite = null, + Color? hoverDeselectColor = null, + PanelButtonOnMouse? onMouseOut = null, + PanelButtonOnMouse? onMouseOver = null) + { + return Create( + activeColor, + hoverSelectSprite, + hoverSelectColor, + hoverDeselectSprite, + hoverDeselectColor, + onMouseOut, + onMouseOver); + } + /// /// Begins/opens the custom player menu. /// From d41ab95fa4912e3dc18bf8389caba9143b663439 Mon Sep 17 00:00:00 2001 From: Atony <75191600+AtonyGit@users.noreply.github.com> Date: Sat, 19 Sep 2026 15:16:09 -0500 Subject: [PATCH 2/3] Allow older mods to fallback med text to tab text --- MiraAPI/Patches/Options/NotificationPopperPatch.cs | 2 +- MiraAPI/Roles/ICustomRole.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MiraAPI/Patches/Options/NotificationPopperPatch.cs b/MiraAPI/Patches/Options/NotificationPopperPatch.cs index 8024ea4..8b0023c 100644 --- a/MiraAPI/Patches/Options/NotificationPopperPatch.cs +++ b/MiraAPI/Patches/Options/NotificationPopperPatch.cs @@ -31,7 +31,7 @@ public static class NotificationPopperPatch icon, "", textColor, - TranslationController.Instance.GetString(key), + customRole.RoleName, "" ), "" + roleCount + "", diff --git a/MiraAPI/Roles/ICustomRole.cs b/MiraAPI/Roles/ICustomRole.cs index 50a9224..adda079 100644 --- a/MiraAPI/Roles/ICustomRole.cs +++ b/MiraAPI/Roles/ICustomRole.cs @@ -48,7 +48,7 @@ public interface ICustomRole : IOptionable /// /// Gets the medium description of the role. Used in the role guide and options menu. /// - string RoleMedDescription => MiraLocaleManager.Get(RoleMedDescriptionLocale); + string RoleMedDescription => MiraLocaleManager.Get(RoleMedDescriptionLocale, RoleLongDescription); /// /// Gets the role's medium description id for localization. From 003d577a0955d7853b074032e6abdf43fc725424 Mon Sep 17 00:00:00 2001 From: Atony <75191600+AtonyGit@users.noreply.github.com> Date: Sat, 19 Sep 2026 16:26:35 -0500 Subject: [PATCH 3/3] Create masked variants of tmp icons --- MiraAPI/Utilities/Assets/TmpSpriteUtils.cs | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/MiraAPI/Utilities/Assets/TmpSpriteUtils.cs b/MiraAPI/Utilities/Assets/TmpSpriteUtils.cs index 6160a01..061587b 100644 --- a/MiraAPI/Utilities/Assets/TmpSpriteUtils.cs +++ b/MiraAPI/Utilities/Assets/TmpSpriteUtils.cs @@ -30,6 +30,10 @@ public static class TmpSpriteUtils spriteAsset.name = assetName; spriteAsset.spriteSheet = sourceTexture; + TMP_SpriteAsset spriteAssetMasked = ScriptableObject.CreateInstance(); + spriteAssetMasked.name = assetName + ".Masked"; + spriteAssetMasked.spriteSheet = sourceTexture; + if (!_spriteShader) { _spriteShader = Shader.Find("TextMeshPro/Sprite"); @@ -40,7 +44,6 @@ public static class TmpSpriteUtils name = assetName + " Material", }; material.SetTexture(ShaderUtilities.ID_MainTex, sourceTexture); - // TODO: Using these values, the icons will NOT clip through chatboxes. However, this breaks quite literally every other tmp text that isn't masked. Please fix this if a good solution is found. /*material.SetFloat(ShaderUtilities.ID_StencilComp, 4); material.SetFloat(ShaderUtilities.ID_StencilID, 1);*/ material.SetFloat(ShaderUtilities.ID_StencilComp, 0); @@ -53,15 +56,36 @@ public static class TmpSpriteUtils spriteAsset.spriteInfoList = new Il2CppSystem.Collections.Generic.List(); + var maskedMaterial = new Material(_spriteShader) + { + name = assetName + " Masked Material", + }; + maskedMaterial.SetTexture(ShaderUtilities.ID_MainTex, sourceTexture); + maskedMaterial.SetFloat(ShaderUtilities.ID_StencilComp, 4); + maskedMaterial.SetFloat(ShaderUtilities.ID_StencilID, 1); + maskedMaterial.SetFloat(ShaderUtilities.ID_StencilOp, 0); + maskedMaterial.SetFloat(ShaderUtilities.ID_StencilWriteMask, 255); + maskedMaterial.SetFloat(ShaderUtilities.ID_StencilReadMask, 255); + maskedMaterial.SetFloat(ShaderUtilities.ShaderTag_CullMode, 0); + spriteAssetMasked.material = maskedMaterial; + + spriteAssetMasked.spriteInfoList = new Il2CppSystem.Collections.Generic.List(); + AddSpriteToAsset(spriteAsset, rect, assetName, scale); + AddSpriteToAsset(spriteAssetMasked, rect, assetName + ".Masked", scale); spriteAsset.DontUnload().DontDestroy(); spriteAsset.UpdateLookupTables(); spriteAsset.fallbackSpriteAssets = new(); + spriteAssetMasked.DontUnload().DontDestroy(); + spriteAssetMasked.UpdateLookupTables(); + spriteAssetMasked.fallbackSpriteAssets = new(); AssetHolder.fallbackSpriteAssets.Add(spriteAsset); + AssetHolder.fallbackSpriteAssets.Add(spriteAssetMasked); AssetHolder.UpdateLookupTables(); LoadedSprites.Add(assetName, spriteAsset); + LoadedSprites.Add(assetName + ".Masked", spriteAssetMasked); return spriteAsset; }