| New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using UnityEngine; |
| | | using UnityEngine.UI; |
| | | |
| | | /// <summary> |
| | | /// 图片组件类型枚举 |
| | | /// </summary> |
| | | public enum ImageComponentType |
| | | { |
| | | None = 0, |
| | | Image = 1, |
| | | ImageEx = 2 |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 单个语言的图片排版和适配数据节点 |
| | | /// </summary> |
| | | [Serializable] |
| | | public class ImageLanguageConfigItem |
| | | { |
| | | [Header("RectTransform 配置")] |
| | | public Vector2 anchoredPosition = Vector2.zero; |
| | | public Vector2 sizeDelta = new Vector2(100f, 100f); |
| | | 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("Image 配置")] |
| | | public bool enabled = true; |
| | | public Color color = Color.white; |
| | | public Image.Type type = Image.Type.Simple; |
| | | public bool fillCenter = true; |
| | | public Image.FillMethod fillMethod = Image.FillMethod.Horizontal; |
| | | public float fillAmount = 1f; |
| | | public int fillOrigin = 0; |
| | | public bool preserveAspect = true; |
| | | public float alphaHitTestMinimumThreshold = 0f; |
| | | public bool useSpriteMesh = false; |
| | | public float pixelsPerUnitMultiplier = 1f; |
| | | |
| | | 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 ApplyToImage(Image img) |
| | | { |
| | | if (img == null) return; |
| | | img.color = color; |
| | | img.type = type; |
| | | img.fillCenter = fillCenter; |
| | | img.fillMethod = fillMethod; |
| | | img.fillAmount = fillAmount; |
| | | img.fillOrigin = fillOrigin; |
| | | img.preserveAspect = preserveAspect; |
| | | img.alphaHitTestMinimumThreshold = alphaHitTestMinimumThreshold; |
| | | img.useSpriteMesh = useSpriteMesh; |
| | | img.pixelsPerUnitMultiplier = pixelsPerUnitMultiplier; |
| | | } |
| | | |
| | | public void ReadFromImage(Image img) |
| | | { |
| | | if (img == null) return; |
| | | color = img.color; |
| | | type = img.type; |
| | | fillCenter = img.fillCenter; |
| | | fillMethod = img.fillMethod; |
| | | fillAmount = img.fillAmount; |
| | | fillOrigin = img.fillOrigin; |
| | | preserveAspect = img.preserveAspect; |
| | | alphaHitTestMinimumThreshold = img.alphaHitTestMinimumThreshold; |
| | | useSpriteMesh = img.useSpriteMesh; |
| | | pixelsPerUnitMultiplier = img.pixelsPerUnitMultiplier; |
| | | } |
| | | |
| | | public ImageLanguageConfigItem Clone() => (ImageLanguageConfigItem)MemberwiseClone(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 支持 Unity 序列化的字典 |
| | | /// </summary> |
| | | [Serializable] |
| | | public class ImageLanguageConfigDictionary |
| | | { |
| | | public List<string> keys = new List<string>(); |
| | | public List<ImageLanguageConfigItem> values = new List<ImageLanguageConfigItem>(); |
| | | |
| | | public ImageLanguageConfigItem 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, ImageLanguageConfigItem 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 ImageLanguageAdapter : MonoBehaviour |
| | | { |
| | | public const string DefaultLangId = "default"; |
| | | |
| | | [SerializeField, Tooltip("语言配置字典")] |
| | | private ImageLanguageConfigDictionary m_LanguageConfigs = new ImageLanguageConfigDictionary(); |
| | | |
| | | [SerializeField, Tooltip("目标图片组件类型")] |
| | | private ImageComponentType m_TargetImageType = ImageComponentType.None; |
| | | |
| | | [SerializeField, Tooltip("关联的图片组件引用")] |
| | | private Component m_TargetImageComponent; |
| | | |
| | | private bool m_IsApplied = false; |
| | | |
| | | public ImageComponentType TargetImageType |
| | | { |
| | | get => m_TargetImageType; |
| | | set => m_TargetImageType = value; |
| | | } |
| | | public Component TargetImageComponent |
| | | { |
| | | get => m_TargetImageComponent; |
| | | set => m_TargetImageComponent = value; |
| | | } |
| | | public ImageLanguageConfigDictionary 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 ImageLanguageConfigItem GetConfig(string languageId) => m_LanguageConfigs.Get(languageId); |
| | | public void SetConfig(string languageId, ImageLanguageConfigItem 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_TargetImageComponent != null) |
| | | { |
| | | m_TargetImageComponent.gameObject.SetActive(config.enabled); |
| | | } |
| | | |
| | | if (m_TargetImageComponent is Image img) |
| | | { |
| | | config.ApplyToImage(img); |
| | | } |
| | | |
| | | m_IsApplied = true; |
| | | } |
| | | |
| | | public void ReadCurrentToConfig(string languageId) |
| | | { |
| | | var config = new ImageLanguageConfigItem(); |
| | | config.ReadFromRectTransform(GetComponent<RectTransform>()); |
| | | |
| | | if (m_TargetImageComponent is Image img) |
| | | { |
| | | config.ReadFromImage(img); |
| | | } |
| | | |
| | | 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_TargetImageComponent != null) |
| | | { |
| | | DetermineImageType(m_TargetImageComponent); |
| | | return; |
| | | } |
| | | |
| | | m_TargetImageComponent = GetComponent<ImageEx>() ?? GetComponentInChildren<ImageEx>(true) as Component |
| | | ?? GetComponent<Image>() ?? GetComponentInChildren<Image>(true) as Component; |
| | | |
| | | DetermineImageType(m_TargetImageComponent); |
| | | } |
| | | |
| | | private void DetermineImageType(Component component) |
| | | { |
| | | m_TargetImageType = component switch |
| | | { |
| | | ImageEx _ => ImageComponentType.ImageEx, |
| | | Image _ => ImageComponentType.Image, |
| | | _ => ImageComponentType.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 |
| | | } |