using System;
|
using System.Collections.Generic;
|
using UnityEngine;
|
using UnityEngine.UI;
|
|
/// <summary>文本组件类型枚举</summary>
|
public enum TextComponentType
|
{
|
None = 0,
|
Text = 1,
|
TextEx = 2,
|
GradientText = 3
|
}
|
|
/// <summary>单个语言的排版和适配数据节点</summary>
|
[Serializable]
|
public class LanguageConfigItem
|
{
|
[Header("RectTransform 配置")]
|
public Vector2 anchoredPosition = Vector2.zero;
|
public Vector2 sizeDelta = new Vector2(100f, 30f);
|
public Vector2 anchorMin = new Vector2(0.5f, 0.5f);
|
public Vector2 anchorMax = new Vector2(0.5f, 0.5f);
|
public Vector2 pivot = new Vector2(0.5f, 0.5f);
|
public Vector3 localScale = Vector3.one;
|
public Vector3 localRotation = Vector3.zero;
|
|
[Header("Text 排版与适配配置")]
|
public Font font;
|
public FontStyle fontStyle = FontStyle.Normal;
|
public int fontSize = 14;
|
public float lineSpacing = 1f;
|
public HorizontalWrapMode horizontalOverflow = HorizontalWrapMode.Wrap;
|
public VerticalWrapMode verticalOverflow = VerticalWrapMode.Truncate;
|
public bool resizeTextForBestFit = false;
|
public int resizeTextMinSize = 10;
|
public int resizeTextMaxSize = 40;
|
public TextAnchor alignment = TextAnchor.UpperLeft;
|
public bool alignByGeometry = false;
|
|
public void ApplyToRectTransform(RectTransform rt)
|
{
|
if (rt == null) return;
|
rt.anchorMin = anchorMin;
|
rt.anchorMax = anchorMax;
|
rt.pivot = pivot;
|
rt.anchoredPosition = anchoredPosition;
|
rt.sizeDelta = sizeDelta;
|
rt.localScale = localScale;
|
rt.localRotation = Quaternion.Euler(localRotation);
|
}
|
|
public void ReadFromRectTransform(RectTransform rt)
|
{
|
if (rt == null) return;
|
anchorMin = rt.anchorMin;
|
anchorMax = rt.anchorMax;
|
pivot = rt.pivot;
|
anchoredPosition = rt.anchoredPosition;
|
sizeDelta = rt.sizeDelta;
|
localScale = rt.localScale;
|
localRotation = rt.localRotation.eulerAngles;
|
}
|
|
public void ApplyToText(Text txt)
|
{
|
if (txt == null) return;
|
if (font != null) txt.font = font;
|
|
txt.fontStyle = fontStyle;
|
txt.fontSize = fontSize;
|
txt.lineSpacing = lineSpacing;
|
txt.horizontalOverflow = horizontalOverflow;
|
txt.verticalOverflow = verticalOverflow;
|
txt.resizeTextForBestFit = resizeTextForBestFit;
|
if (resizeTextForBestFit)
|
{
|
txt.resizeTextMinSize = resizeTextMinSize;
|
txt.resizeTextMaxSize = resizeTextMaxSize;
|
}
|
txt.alignment = alignment;
|
txt.alignByGeometry = alignByGeometry;
|
}
|
|
public void ReadFromText(Text txt)
|
{
|
if (txt == null) return;
|
font = txt.font;
|
fontStyle = txt.fontStyle;
|
fontSize = txt.fontSize;
|
lineSpacing = txt.lineSpacing;
|
horizontalOverflow = txt.horizontalOverflow;
|
verticalOverflow = txt.verticalOverflow;
|
resizeTextForBestFit = txt.resizeTextForBestFit;
|
resizeTextMinSize = txt.resizeTextMinSize;
|
resizeTextMaxSize = txt.resizeTextMaxSize;
|
alignment = txt.alignment;
|
alignByGeometry = txt.alignByGeometry;
|
}
|
|
public LanguageConfigItem Clone() => (LanguageConfigItem)MemberwiseClone();
|
}
|
|
/// <summary>支持 Unity 序列化的字典</summary>
|
[Serializable]
|
public class LanguageConfigDictionary
|
{
|
public List<string> keys = new List<string>();
|
public List<LanguageConfigItem> values = new List<LanguageConfigItem>();
|
|
public LanguageConfigItem Get(string key)
|
{
|
if (string.IsNullOrEmpty(key)) return null;
|
int index = keys.IndexOf(key);
|
return index >= 0 ? values[index] : null;
|
}
|
|
public void Set(string key, LanguageConfigItem value)
|
{
|
int index = keys.IndexOf(key);
|
if (index >= 0) values[index] = value;
|
else
|
{
|
keys.Add(key);
|
values.Add(value);
|
}
|
}
|
|
public bool ContainsKey(string key) => keys.Contains(key);
|
|
public void Remove(string key)
|
{
|
int index = keys.IndexOf(key);
|
if (index >= 0)
|
{
|
keys.RemoveAt(index);
|
values.RemoveAt(index);
|
}
|
}
|
}
|
|
/// <summary>多语言排版适配器</summary>
|
[RequireComponent(typeof(RectTransform))]
|
public class TextLanguageAdapter : MonoBehaviour
|
{
|
public const string DefaultLangId = "default";
|
|
[SerializeField, Tooltip("语言配置字典")]
|
private LanguageConfigDictionary m_LanguageConfigs = new LanguageConfigDictionary();
|
|
[SerializeField, Tooltip("目标文本组件类型")]
|
private TextComponentType m_TargetTextType = TextComponentType.None;
|
|
[SerializeField, Tooltip("关联的文本组件引用")]
|
private Component m_TargetTextComponent;
|
|
private bool m_IsApplied = false;
|
|
public TextComponentType TargetTextType => m_TargetTextType;
|
public Component TargetTextComponent => m_TargetTextComponent;
|
public LanguageConfigDictionary LanguageConfigs => m_LanguageConfigs;
|
|
private void Awake() => DetectTargetComponent();
|
|
private void OnEnable()
|
{
|
if (!Application.isPlaying || !m_IsApplied)
|
{
|
string langId = Application.isPlaying ? Language.Id : DefaultLangId;
|
ApplyConfig(langId);
|
}
|
}
|
|
#if UNITY_EDITOR
|
private void Reset()
|
{
|
DetectTargetComponent();
|
if (!HasConfig(DefaultLangId)) ReadCurrentToConfig(DefaultLangId);
|
}
|
#endif
|
|
public LanguageConfigItem GetConfig(string languageId) => m_LanguageConfigs.Get(languageId);
|
public void SetConfig(string languageId, LanguageConfigItem config) => m_LanguageConfigs.Set(languageId, config);
|
public void RemoveConfig(string languageId) => m_LanguageConfigs.Remove(languageId);
|
public bool HasConfig(string languageId) => m_LanguageConfigs.ContainsKey(languageId);
|
public List<string> GetConfiguredLanguages() => new List<string>(m_LanguageConfigs.keys);
|
|
public void ApplyConfig(string languageId)
|
{
|
var config = GetConfig(languageId);
|
if (config == null) return;
|
|
config.ApplyToRectTransform(GetComponent<RectTransform>());
|
if (m_TargetTextComponent is Text txt) config.ApplyToText(txt);
|
|
m_IsApplied = true;
|
}
|
|
public void ReadCurrentToConfig(string languageId)
|
{
|
var config = new LanguageConfigItem();
|
config.ReadFromRectTransform(GetComponent<RectTransform>());
|
if (m_TargetTextComponent is Text txt) config.ReadFromText(txt);
|
|
SetConfig(languageId, config);
|
}
|
|
public static string GetLanguageShowName(string languageId)
|
{
|
if (Language.languageShowDict != null && Language.languageShowDict.TryGetValue(languageId, out string showName))
|
return showName;
|
return languageId;
|
}
|
|
private void DetectTargetComponent()
|
{
|
if (m_TargetTextComponent != null)
|
{
|
DetermineTextType(m_TargetTextComponent);
|
return;
|
}
|
|
m_TargetTextComponent = GetComponent<GradientText>() ?? GetComponentInChildren<GradientText>(true) as Component
|
?? GetComponent<TextEx>() ?? GetComponentInChildren<TextEx>(true) as Component
|
?? GetComponent<Text>() ?? GetComponentInChildren<Text>(true) as Component;
|
|
DetermineTextType(m_TargetTextComponent);
|
}
|
|
private void DetermineTextType(Component component)
|
{
|
m_TargetTextType = component switch
|
{
|
GradientText _ => TextComponentType.GradientText,
|
TextEx _ => TextComponentType.TextEx,
|
Text _ => TextComponentType.Text,
|
_ => TextComponentType.None
|
};
|
}
|
|
#if UNITY_EDITOR
|
[ContextMenu("刷新组件检测")]
|
public void Editor_ForceRefreshDetection()
|
{
|
DetectTargetComponent();
|
UnityEditor.EditorUtility.SetDirty(this);
|
}
|
|
[ContextMenu("读取当前配置")]
|
public void Editor_ReadCurrentConfig()
|
{
|
ReadCurrentToConfig(DefaultLangId);
|
UnityEditor.EditorUtility.SetDirty(this);
|
}
|
|
[ContextMenu("应用默认配置")]
|
public void Editor_ApplyDefaultConfig() => ApplyConfig(DefaultLangId);
|
#endif
|
}
|