UI相关优化补充
This commit is contained in:
99
Assets/_Game/Scripts/UI/Theme/UIThemeApplier.cs
Normal file
99
Assets/_Game/Scripts/UI/Theme/UIThemeApplier.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/_Game/Scripts/UI/Theme/UIThemeApplier.cs.meta
Normal file
11
Assets/_Game/Scripts/UI/Theme/UIThemeApplier.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50572ad108fd3354da04ea8fba66370b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
39
Assets/_Game/Scripts/UI/Theme/UIThemeRole.cs
Normal file
39
Assets/_Game/Scripts/UI/Theme/UIThemeRole.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.UI.Theme
|
||||
{
|
||||
/// <summary>主题角色种类。控制 <see cref="UIThemeApplier"/> 应用何种令牌到目标组件。</summary>
|
||||
public enum UIThemeRoleKind
|
||||
{
|
||||
// Graphic(Image / RawImage / Panel 等)
|
||||
Graphic_Primary,
|
||||
Graphic_Secondary,
|
||||
Graphic_Accent,
|
||||
Graphic_Background,
|
||||
Graphic_Success,
|
||||
Graphic_Warning,
|
||||
Graphic_Danger,
|
||||
|
||||
// TMP_Text
|
||||
Text_Primary,
|
||||
Text_Secondary,
|
||||
Text_Header,
|
||||
Text_Disabled,
|
||||
|
||||
// Button(应用 ColorBlock)
|
||||
Button,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标记组件:告诉 <see cref="UIThemeApplier"/> 当前节点扮演的视觉角色。
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class UIThemeRole : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private UIThemeRoleKind _kind = UIThemeRoleKind.Text_Primary;
|
||||
[SerializeField] private bool _overrideFontSize = false;
|
||||
|
||||
public UIThemeRoleKind Kind => _kind;
|
||||
public bool OverrideFontSize => _overrideFontSize;
|
||||
}
|
||||
}
|
||||
11
Assets/_Game/Scripts/UI/Theme/UIThemeRole.cs.meta
Normal file
11
Assets/_Game/Scripts/UI/Theme/UIThemeRole.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fa7f5f3910b010489199ef7ddee773e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
46
Assets/_Game/Scripts/UI/Theme/UIThemeSO.cs
Normal file
46
Assets/_Game/Scripts/UI/Theme/UIThemeSO.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
namespace BaseGames.UI.Theme
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局 UI 主题资产(架构 10_UIModule §1 视觉风格统一)。
|
||||
///
|
||||
/// 设计动机:避免每个 Prefab 各自硬编码颜色 / 字体,统一替换或本地化主题成本极低。
|
||||
/// 通过 <see cref="UIThemeApplier"/> 在运行时拉取并应用到子节点。
|
||||
///
|
||||
/// 资产路径建议:Assets/Data/UI/Themes/UI_Theme_Default.asset
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "BaseGames/UI/Theme")]
|
||||
public class UIThemeSO : ScriptableObject
|
||||
{
|
||||
[Header("Palette")]
|
||||
public Color Primary = new Color(0.10f, 0.55f, 0.95f);
|
||||
public Color Secondary = new Color(0.20f, 0.20f, 0.25f);
|
||||
public Color Accent = new Color(1.00f, 0.78f, 0.20f);
|
||||
public Color Background = new Color(0.06f, 0.07f, 0.10f);
|
||||
public Color TextPrimary = Color.white;
|
||||
public Color TextSecondary = new Color(0.75f, 0.78f, 0.82f);
|
||||
public Color TextDisabled = new Color(0.40f, 0.42f, 0.45f);
|
||||
public Color Success = new Color(0.30f, 0.85f, 0.45f);
|
||||
public Color Warning = new Color(0.95f, 0.70f, 0.10f);
|
||||
public Color Danger = new Color(0.95f, 0.30f, 0.30f);
|
||||
|
||||
[Header("Typography")]
|
||||
public TMP_FontAsset HeaderFont;
|
||||
public TMP_FontAsset BodyFont;
|
||||
[Min(8)] public float HeaderFontSize = 36f;
|
||||
[Min(8)] public float BodyFontSize = 20f;
|
||||
[Min(8)] public float SmallFontSize = 14f;
|
||||
|
||||
[Header("Button States")]
|
||||
public Color ButtonNormal = new Color(0.10f, 0.55f, 0.95f);
|
||||
public Color ButtonHighlighted = new Color(0.20f, 0.65f, 1.00f);
|
||||
public Color ButtonPressed = new Color(0.05f, 0.40f, 0.80f);
|
||||
public Color ButtonDisabled = new Color(0.30f, 0.30f, 0.32f);
|
||||
|
||||
[Header("Audio (可选)")]
|
||||
public AudioClip ClickSound;
|
||||
public AudioClip HoverSound;
|
||||
}
|
||||
}
|
||||
11
Assets/_Game/Scripts/UI/Theme/UIThemeSO.cs.meta
Normal file
11
Assets/_Game/Scripts/UI/Theme/UIThemeSO.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1d97086a1337cc47a5d2ee9c85a944d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user