TH1/Unity/Assets/Scripts/TH1_Logic/Multilingual/MultilingualTextMono.cs
2026-05-29 17:32:44 +08:00

176 lines
6.6 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.

/*
* @Author: 白哉
* @Description:
* @Date: 2025年05月26日 星期一 14:05:50
* @Modify:
*/
using System.Collections.Generic;
using System.Text.RegularExpressions;
using TMPro;
using UnityEngine;
namespace Logic.Multilingual
{
[DisallowMultipleComponent]
public class MultilingualTextMono : MonoBehaviour
{
public bool Ban;
public bool NoExport = false;
public bool FontBan = false;
// 全局文本样式预设:让多个 TMP 共享一套多语言字号/行距方案
// None=不使用预设,仅依赖 TextCfg 里的 override保持原有行为
// 三级 fallback 优先级TextCfg 命中 > Preset 命中 > 不动
public TH1_DataAssetsScript.TextStylePreset Preset = TH1_DataAssetsScript.TextStylePreset.None;
[HideInInspector]
public uint ID = 0;
[HideInInspector]
public uint FontID = 0;
[HideInInspector]
public List<MultiTextConfig> TextCfg = new List<MultiTextConfig>();
private List<string> _paramList;
public MultilingualType PreviewType
{
get => _previewType;
set => _previewType = value;
}
private MultilingualType _previewType = MultilingualType.ZH;
public List<string> ParamList
{
get => _paramList ??= new List<string>();
set => _paramList = value;
}
private void OnEnable()
{
OnMultilingualChanged();
}
public void OnMultilingualChanged()
{
var text = GetComponent<TextMeshProUGUI>();
if (!text) return;
if (!FontBan)
{
BindFontID();
if (FontID != 0)
{
var font = MultilingualManager.Instance.GetMultilingualFont(FontID);
if (font)text.font = font;
MatchTextCfg(text, MultilingualManager.Instance.CurrentType);
}
}
if (!Ban)
{
if (ID != 0) text.text = MultilingualManager.Instance.GetMultilingualText(ID);
if (_paramList != null && _paramList.Count != 0)
{
int index = 0;
text.text = Regex.Replace(text.text, "{param}", m =>
index < _paramList.Count ? _paramList[index++] : m.Value);
}
ApplyDefaultEmbeddedColor(text);
// RTL 方向切换:阿语/希伯来语开 RTL其他语言关掉。
// 注意:仅控制字符排列方向,不做 shaping(字母连写);连写需第三方库 ArabicFixer 预处理字符串。
ApplyRTLDirection(text, MultilingualManager.Instance.CurrentType);
}
}
// 仅阿拉伯语 / 希伯来语开启 TMP 内置 RTL其他语言显式关掉
// 避免切语言时阿语切走后 isRightToLeftText 残留导致下一种语言反向显示
private static void ApplyRTLDirection(TextMeshProUGUI text, MultilingualType type)
{
text.isRightToLeftText = (type == MultilingualType.AR || type == MultilingualType.HE);
}
public void BindFontID()
{
if (FontBan) return;
if (FontID != 0) return;
var text = GetComponent<TextMeshProUGUI>();
if (!text) return;
FontID = MultilingualManager.Instance.GetFontGroupID(text.font);
}
public MultiTextConfig GetMultiTextConfig(MultilingualType type)
{
foreach (var cfg in TextCfg)
{
if (cfg.Type != type) continue;
return cfg;
}
return null;
}
private void MatchTextCfg(TextMeshProUGUI text, MultilingualType type)
{
// 仅 5 主语言ZH/TDZH/EN/JP/KR使用各自的样式键
// 其他所有语言RU/FR/DE/AR/泰语/Custom 等)一律转成 EN 来查询样式,
// 避免每个语言单独配同一份方案。
MultilingualType lookupType = IsPrimaryLanguageCfg(type) ? type : MultilingualType.EN;
// 第 1 级prefab 上的 TextCfg局部 override
// 只接受 lookupType 精确命中;不回退到 TextCfg 里的 EN避免"配了 EN 就吃掉所有非 EN 语言"
// 命中后用 ExcuteConfigForce 强写 5 个字段,无视 ApplyXxx 开关
// 语义:在 prefab 上手动配 override 就是要全字段生效
foreach (var cfg in TextCfg)
{
if (cfg.Type != lookupType) continue;
cfg.ExcuteConfigForce(text);
return;
}
// 第 2 级:全局 TextStylePresetDataAssets按 Preset + lookupType 查表)
// preset 走 ExcuteConfig看 ApplyXxx 开关),未勾选的字段保留 prefab 原值
// None 也是一种 Preset作为"默认通用方案"参与查表,所有 TMP 默认就是 None让全局规则不需要每个 TMP 单独标
{
var presetData = Table.Instance?.TextStylePresetDataAssets;
var picked = presetData?.GetConfig(Preset, lookupType);
picked?.ExcuteConfig(text);
}
// 第 3 级:都没找到 → 不动 TMP保持 prefab 上的字号/行距原值)
}
// 5 主语言才走自己的 TextCfg其他全部走 EN
private static bool IsPrimaryLanguageCfg(MultilingualType type)
{
return type == MultilingualType.ZH
|| type == MultilingualType.TDZH
|| type == MultilingualType.EN
|| type == MultilingualType.JP
|| type == MultilingualType.KR;
}
public void SetMultilingualText(string str, MultilingualType type, TMP_FontAsset font)
{
var text = GetComponent<TextMeshProUGUI>();
if (!text) return;
text.text = str;
ApplyDefaultEmbeddedColor(text);
if (font != null) text.font = font;
MatchTextCfg(text, type);
ApplyRTLDirection(text, type);
}
private static void ApplyDefaultEmbeddedColor(TextMeshProUGUI text)
{
var colorTag = $"<color={MultilingualRichTextColors.DefaultEmbeddedHex}>";
text.text = text.text.Replace("<color=yellow>", colorTag);
text.text = text.text.Replace("<color=orange>", colorTag);
text.text = text.text.Replace("**<", colorTag);
text.text = text.text.Replace(">**", "</color>");
}
}
}