Files
zeling_v2/Assets/_Game/Scripts/UI/Theme/UIThemeApplier.cs
2026-05-25 13:21:41 +08:00

100 lines
4.2 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 UnityEngine;
using UnityEngine.UI;
using TMPro;
namespace BaseGames.UI.Theme
{
/// <summary>
/// 将 <see cref="UIThemeSO"/> 中的视觉令牌应用到当前 GameObject 及其子节点。
///
/// 用法:
/// 1. 在 Prefab 根节点挂载此组件并指定 <see cref="_theme"/>
/// 2. 在每个需要主题化的子节点添加 <see cref="UIThemeRole"/> 组件指定角色;
/// 3. <see cref="Apply"/> 会被 <see cref="OnEnable"/> 自动调用一次,
/// 也可在主题切换后手动调用。
///
/// 性能:使用 <see cref="Component.GetComponentsInChildren{T}(bool)"/> 一次性收集,
/// 仅在 Enable / 显式刷新时执行;运行时无每帧成本。
/// </summary>
[DisallowMultipleComponent]
public class UIThemeApplier : MonoBehaviour
{
[SerializeField] private UIThemeSO _theme;
[Tooltip("启用时自动应用一次。运行时切换主题可手动调用 Apply()。")]
[SerializeField] private bool _applyOnEnable = true;
private void OnEnable()
{
if (_applyOnEnable) Apply();
}
/// <summary>用当前 <see cref="_theme"/> 覆盖子节点上所有 <see cref="UIThemeRole"/> 标记。</summary>
public void Apply()
{
if (_theme == null) return;
var roles = GetComponentsInChildren<UIThemeRole>(includeInactive: true);
for (int i = 0; i < roles.Length; i++)
ApplyRole(roles[i], _theme);
}
/// <summary>运行时切换主题。</summary>
public void SetTheme(UIThemeSO theme)
{
_theme = theme;
Apply();
}
private static void ApplyRole(UIThemeRole role, UIThemeSO theme)
{
if (role == null) return;
switch (role.Kind)
{
case UIThemeRoleKind.Graphic_Primary: SetGraphicColor(role, theme.Primary); break;
case UIThemeRoleKind.Graphic_Secondary: SetGraphicColor(role, theme.Secondary); break;
case UIThemeRoleKind.Graphic_Accent: SetGraphicColor(role, theme.Accent); break;
case UIThemeRoleKind.Graphic_Background: SetGraphicColor(role, theme.Background); break;
case UIThemeRoleKind.Graphic_Success: SetGraphicColor(role, theme.Success); break;
case UIThemeRoleKind.Graphic_Warning: SetGraphicColor(role, theme.Warning); break;
case UIThemeRoleKind.Graphic_Danger: SetGraphicColor(role, theme.Danger); break;
case UIThemeRoleKind.Text_Primary: SetTextStyle(role, theme.TextPrimary, theme.BodyFont, theme.BodyFontSize); break;
case UIThemeRoleKind.Text_Secondary: SetTextStyle(role, theme.TextSecondary, theme.BodyFont, theme.SmallFontSize); break;
case UIThemeRoleKind.Text_Header: SetTextStyle(role, theme.TextPrimary, theme.HeaderFont, theme.HeaderFontSize); break;
case UIThemeRoleKind.Text_Disabled: SetTextStyle(role, theme.TextDisabled, theme.BodyFont, theme.BodyFontSize); break;
case UIThemeRoleKind.Button: SetButtonColors(role, theme); break;
}
}
private static void SetGraphicColor(UIThemeRole role, Color c)
{
var g = role.GetComponent<Graphic>();
if (g != null) g.color = c;
}
private static void SetTextStyle(UIThemeRole role, Color c, TMP_FontAsset font, float size)
{
var tmp = role.GetComponent<TMP_Text>();
if (tmp != null)
{
tmp.color = c;
if (font != null) tmp.font = font;
if (role.OverrideFontSize) tmp.fontSize = size;
}
}
private static void SetButtonColors(UIThemeRole role, UIThemeSO theme)
{
var btn = role.GetComponent<Button>();
if (btn == null) return;
var cb = btn.colors;
cb.normalColor = theme.ButtonNormal;
cb.highlightedColor = theme.ButtonHighlighted;
cb.pressedColor = theme.ButtonPressed;
cb.disabledColor = theme.ButtonDisabled;
btn.colors = cb;
}
}
}