Files
AquaDX/AquaMai/AquaMai.Mods/GameSystem/Assets/Fonts.cs
Menci 37044dae01 [RF] AquaMai configuration refactor (#82)
更新了配置文件格式,原有的配置文件将被自动无缝迁移,详情请见新的配置文件中的注释(例外:`SlideJudgeTweak` 不再默认启用)
旧配置文件将被重命名备份,如果更新到此版本遇到 Bug 请联系我们

Updated configuration file schema. The old config file will be migrated automatically and seamlessly. See the comments in the new configuration file for details. (Except for `SlideJudgeTweak` is no longer enabled by default)
Your old configuration file will be renamed as a backup. If you encounter any bug with this version, please contact us.
2024-11-25 01:25:19 +08:00

147 lines
5.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using System.Linq;
using AquaMai.Config.Attributes;
using AquaMai.Core.Helpers;
using HarmonyLib;
using MelonLoader;
using TMPro;
using UnityEngine;
using UnityEngine.TextCore.LowLevel;
namespace AquaMai.Mods.GameSystem.Assets;
[ConfigSection(
en: "Use custom font(s) as fallback or fully replace the original game font.",
zh: "使用自定义字体作为回退(解决中文字形缺失问题),或完全替换游戏原字体")]
public class Fonts
{
[ConfigEntry(
en: """
Font path(s).
Use semicolon to separate multiple paths for a fallback chain.
Microsoft YaHei Bold by default.
""",
zh: """
字体路径
使用分号分隔多个路径以构成 Fallback 链
默认为微软雅黑 Bold
""")]
private static readonly string paths = "%SYSTEMROOT%/Fonts/msyhbd.ttc";
[ConfigEntry(
en: "Add custom font(s) as fallback, use original game font when possible.",
zh: "将自定义字体作为游戏原字体的回退,尽可能使用游戏原字体")]
private static readonly bool addAsFallback = true;
private static List<TMP_FontAsset> fontAssets = [];
private static readonly List<TMP_FontAsset> processedFonts = [];
private static TMP_FontAsset replacementFontAsset;
private static List<TMP_FontAsset> fallbackFontAssets = [];
public static void OnBeforePatch()
{
var paths = Fonts.paths
.Split(';')
.Where(p => !string.IsNullOrWhiteSpace(p))
.Select(FileSystem.ResolvePath);
var fonts = paths
.Select(p =>
{
var font = new Font(p);
if (font == null)
{
MelonLogger.Warning($"[Fonts] Font not found: {p}");
}
return font;
})
.Where(f => f != null);
fontAssets = fonts
.Select(f => TMP_FontAsset.CreateFontAsset(f, 90, 9, GlyphRenderMode.SDFAA, 8192, 8192))
.ToList();
if (fontAssets.Count == 0)
{
MelonLogger.Warning("[Fonts] No font loaded.");
}
else if (addAsFallback)
{
fallbackFontAssets = fontAssets;
}
else
{
replacementFontAsset = fontAssets[0];
fallbackFontAssets = fontAssets.Skip(1).ToList();
}
}
[HarmonyPatch(typeof(TextMeshProUGUI), "Awake")]
[HarmonyPostfix]
public static void PostAwake(TextMeshProUGUI __instance)
{
if (fontAssets.Count == 0) return;
if (processedFonts.Contains(__instance.font)) return;
if (replacementFontAsset != null)
{
ProcessReplacement(__instance);
}
if (fallbackFontAssets.Count > 0)
{
ProcessFallback(__instance);
}
processedFonts.Add(__instance.font);
}
private static void ProcessReplacement(TextMeshProUGUI __instance)
{
# if DEBUG
MelonLogger.Msg($"{__instance.font.name} {__instance.text}");
# endif
var materialOrigin = __instance.fontMaterial;
var materialSharedOrigin = __instance.fontSharedMaterial;
__instance.font = replacementFontAsset;
# if DEBUG
MelonLogger.Msg($"shaderKeywords {materialOrigin.shaderKeywords.Join()} {__instance.fontMaterial.shaderKeywords.Join()}");
# endif
// __instance.fontSharedMaterial = materialSharedOrigin;
// 这样之后该有描边的地方整个字后面都是阴影,它不知道哪里是边
// materialOrigin.mainTexture = __instance.fontMaterial.mainTexture;
// materialOrigin.mainTextureOffset = __instance.fontMaterial.mainTextureOffset;
// materialOrigin.mainTextureScale = __instance.fontMaterial.mainTextureScale;
// __instance.fontMaterial.CopyPropertiesFromMaterial(materialOrigin);
// 这样了之后有描边了,但是描边很细
// __instance.fontMaterial.shader = materialOrigin.shader;
foreach (var keyword in materialOrigin.shaderKeywords)
{
__instance.fontMaterial.EnableKeyword(keyword);
}
// __instance.fontMaterial.globalIlluminationFlags = materialOrigin.globalIlluminationFlags;
// 原来是 underlay但是复制这三个属性之后就又变成整个字后面都是阴影了
// __instance.fontMaterial.SetFloat(ShaderUtilities.ID_UnderlayOffsetY, materialOrigin.GetFloat(ShaderUtilities.ID_UnderlayOffsetY));
// __instance.fontMaterial.SetFloat(ShaderUtilities.ID_UnderlayOffsetX, materialOrigin.GetFloat(ShaderUtilities.ID_UnderlayOffsetX));
// __instance.fontMaterial.SetFloat(ShaderUtilities.ID_UnderlayDilate, materialOrigin.GetFloat(ShaderUtilities.ID_UnderlayDilate));
// if(materialOrigin.shaderKeywords.Contains(ShaderUtilities.Keyword_Underlay))
// {
// __instance.fontMaterial.EnableKeyword(ShaderUtilities.Keyword_Glow);
// __instance.fontMaterial.SetFloat(ShaderUtilities.ID_GlowOuter, .5f);
// // __instance.fontMaterial.SetFloat(ShaderUtilities.ID_UnderlayOffsetX, materialOrigin.GetFloat(ShaderUtilities.ID_UnderlayOffsetX));
// }
}
private static void ProcessFallback(TextMeshProUGUI __instance)
{
foreach (var fontAsset in fallbackFontAssets)
{
__instance.font.fallbackFontAssetTable.Add(fontAsset);
}
}
}