Add TMP icon support for roles

This commit is contained in:
Atony committed 2026-07-01 19:57:29 -05:00
1 parent 84321f290e
commit 2eecba2e51
10 files changed
+134 -2

No files matched your search

+3
View File
@@ -1,6 +1,7 @@
using AmongUs.GameOptions;
using MiraAPI.Patches.Stubs;
using MiraAPI.Roles;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities;
using TMPro;
using UnityEngine;
@@ -20,6 +21,8 @@ public class ChameloenRole : CrewmateRole, ICustomRole
public CustomRoleConfiguration Configuration => new(this)
{
OptionsScreenshot = ExampleAssets.Banner,
Icon = MiraAssets.CrewmateFile,
IconTmp = TmpSpriteUtils.CreateSpriteAsset(MiraAssets.CrewmateFile.LoadAsset(), "ApiExample.Role.Impostor.ChameleonRole"),
IntroSound = CustomRoleUtils.GetIntroSound(RoleTypes.Shapeshifter),
};
+3
View File
@@ -1,4 +1,5 @@
using MiraAPI.Roles;
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.Example.Roles;
@@ -13,6 +14,8 @@ public class FreezerRole : ImpostorRole, ICustomRole
public CustomRoleConfiguration Configuration => new CustomRoleConfiguration(this)
{
Icon = MiraAssets.ImpostorFile,
IconTmp = TmpSpriteUtils.CreateSpriteAsset(MiraAssets.ImpostorFile.LoadAsset(), "ApiExample.Role.Impostor.FreezerRole"),
OptionsScreenshot = ExampleAssets.Banner,
MaxRoleCount = 2,
};
@@ -26,9 +26,11 @@ public static class NotificationPopperPatch
var textColor = customRole.OptionsMenuColor.ToTextColor();
var icon = customRole.Configuration.IconTmp ? $"<sprite name=\"{customRole.Configuration.IconTmp.name}\">" : string.Empty;
var item = TranslationController.Instance.GetString(
StringNames.LobbyChangeSettingNotificationRole,
string.Concat(
icon,
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">",
textColor,
TranslationController.Instance.GetString(key, Array.Empty<Object>()),
@@ -437,8 +437,7 @@ public static class RoleSettingMenuPatches
roleSetting.Role.StringName,
roleSetting.RoleMaxCount,
roleSetting.RoleChance,
roleSetting.Role.TeamType,
false);
roleSetting.Role.TeamType);
if (AmongUsClient.Instance.AmHost)
{
+32
View File
@@ -0,0 +1,32 @@
using System.Linq;
using HarmonyLib;
using MiraAPI.Utilities.Assets;
using TMPro;
namespace MiraAPI.Patches;
[HarmonyPatch]
public static class TmpAwakePatch
{
[HarmonyPatch(typeof(TextMeshPro), nameof(TextMeshPro.Awake))]
[HarmonyPostfix]
public static void TmpAwakePostfix(TextMeshPro __instance)
{
if (!TmpSpriteUtils.AssetHolder || !__instance.m_spriteAsset)
{
return;
}
/*
if (__instance.m_spriteAsset.name == "RoleIcons")
{
Error($"Stencil Comp: {__instance.m_spriteAsset.material.GetFloat(ShaderUtilities.ID_StencilComp)}");
Error($"Stencil ID: {__instance.m_spriteAsset.material.GetFloat(ShaderUtilities.ID_StencilID)}");
Error($"Stencil Op: {__instance.m_spriteAsset.material.GetFloat(ShaderUtilities.ID_StencilOp)}");
Error($"Stencil Write: {__instance.m_spriteAsset.material.GetFloat(ShaderUtilities.ID_StencilWriteMask)}");
Error($"Stencil Read: {__instance.m_spriteAsset.material.GetFloat(ShaderUtilities.ID_StencilReadMask)}");
Error($"Cull Mode: {__instance.m_spriteAsset.material.GetFloat(ShaderUtilities.ShaderTag_CullMode)}");
}*/
__instance.m_spriteAsset.fallbackSpriteAssets.Add(TmpSpriteUtils.AssetHolder);
__instance.UpdateMeshPadding();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

+7
View File
@@ -3,6 +3,7 @@ using System;
using Il2CppInterop.Runtime.Attributes;
using MiraAPI.Patches.Freeplay;
using MiraAPI.Utilities.Assets;
using TMPro;
using UnityEngine;
namespace MiraAPI.Roles;
@@ -87,6 +88,12 @@ public record struct CustomRoleConfiguration
[HideFromIl2Cpp]
public LoadableAsset<Sprite>? Icon { get; set; } = null;
/// <summary>
/// Gets or sets the <see cref="TMP_SpriteAsset"/> for the Role Icon.
/// </summary>
[HideFromIl2Cpp]
public TMP_SpriteAsset IconTmp { get; set; }
/// <summary>
/// Gets or sets the Intro sound for the Role.
/// </summary>
+1
View File
@@ -5,6 +5,7 @@ using MiraAPI.GameOptions;
using MiraAPI.Modifiers;
using MiraAPI.PluginLoading;
using Reactor.Utilities;
using TMPro;
using UnityEngine;
namespace MiraAPI.Roles;
+2
View File
@@ -134,4 +134,6 @@ public static class MiraAssets
/// Gets the sprite used for timed modifier file in TaskAdderGame.
/// </summary>
public static LoadableResourceAsset TimedModifierFile { get; } = new("MiraAPI.Resources.TimedModifierFile.png");
internal static LoadableResourceAsset BlankSprite { get; } = new("MiraAPI.Resources.BlankSprite.png");
}
@@ -0,0 +1,83 @@
using System.Collections.Generic;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
namespace MiraAPI.Utilities.Assets;
public static class TmpSpriteUtils
{
private static Shader _spriteShader;
private static Dictionary<string, TMP_SpriteAsset> LoadedSprites = [];
public static TMP_SpriteAsset AssetHolder;
public static TMP_SpriteAsset CreateSpriteAsset(Sprite sprite, string assetName)
{
return CreateSpriteAsset(sprite.texture, sprite.rect, assetName);
}
public static TMP_SpriteAsset CreateSpriteAsset(Texture2D sourceTexture, Rect rect, string assetName)
{
if (LoadedSprites.TryGetValue(assetName, out var existingAsset))
{
return existingAsset;
}
if (!AssetHolder)
{
AssetHolder = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
AssetHolder.DontUnload().DontDestroy();
AssetHolder.fallbackSpriteAssets = new();
}
TMP_SpriteAsset spriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
spriteAsset.name = assetName;
spriteAsset.spriteSheet = sourceTexture;
if (!_spriteShader)
{
_spriteShader = Shader.Find("TextMeshPro/Sprite");
}
var material = new Material(_spriteShader)
{
name = assetName + " Material",
};
material.SetTexture(ShaderUtilities.ID_MainTex, sourceTexture);
material.SetFloat(ShaderUtilities.ID_StencilComp, 0);
material.SetFloat(ShaderUtilities.ID_StencilID, 0);
material.SetFloat(ShaderUtilities.ID_StencilOp, 0);
material.SetFloat(ShaderUtilities.ID_StencilWriteMask, 255);
material.SetFloat(ShaderUtilities.ID_StencilReadMask, 255);
material.SetFloat(ShaderUtilities.ShaderTag_CullMode, 0);
spriteAsset.material = material;
spriteAsset.spriteInfoList = new Il2CppSystem.Collections.Generic.List<TMP_Sprite>();
AddSpriteToAsset(spriteAsset, rect, assetName);
spriteAsset.DontUnload().DontDestroy();
spriteAsset.UpdateLookupTables();
spriteAsset.fallbackSpriteAssets = new();
AssetHolder.fallbackSpriteAssets.Add(spriteAsset);
AssetHolder.UpdateLookupTables();
LoadedSprites.Add(assetName, spriteAsset);
return spriteAsset;
}
private static void AddSpriteToAsset(TMP_SpriteAsset spriteAsset, Rect rect, string spriteName)
{
TMP_Sprite newSprite = new TMP_Sprite
{
name = spriteName,
hashCode = TMP_TextUtilities.GetSimpleHashCode(spriteName),
x = 0,
y = 0,
width = rect.width,
height = rect.height,
xOffset = -(rect.width / 3),
yOffset = rect.height / 1.25f,
xAdvance = rect.width,
scale = 1,
};
spriteAsset.spriteInfoList.Add(newSprite);
}
}