diff --git a/Runtime/Core/StyleSheetUI/StyleRefreshManager.cs b/Runtime/Core/StyleSheetUI/StyleRefreshManager.cs new file mode 100644 index 0000000..a8048d8 --- /dev/null +++ b/Runtime/Core/StyleSheetUI/StyleRefreshManager.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; + +using UnityEngine; + +namespace XericUI.Core.StyleSheetUI +{ + /// + /// 标记可被全局刷新的样式组件。 + /// 实现此接口的组件应在 OnEnable 调用 RegisterForStyleRefresh, + /// 在 OnDisable 调用 UnregisterForStyleRefresh。 + /// + public interface IStyleRefreshable + { + void RefreshStyle(); + } + + /// + /// 全局样式刷新管理器——维护所有活跃的 IStyleRefreshable 组件。 + /// 当外部样式表文件更新后,调用 ForceRefreshAll() 可一键刷新所有组件。 + /// + public static class StyleRefreshManager + { + private static readonly HashSet s_Components = new HashSet(); + + /// 注册一个样式组件 + public static void Register(IStyleRefreshable component) + { + if (component != null) + s_Components.Add(component); + } + + /// 注销一个样式组件 + public static void Unregister(IStyleRefreshable component) + { + if (component != null) + s_Components.Remove(component); + } + + /// + /// 强制刷新所有已注册的样式组件。 + /// 先调用 StyleManager.ForceRefresh() 同步样式表数据, + /// 再遍历所有组件重新读取并应用样式值。 + /// + public static void ForceRefreshAll() + { +#if XERIC_STYLESHEET_ENABLED + XericLibrary.Runtime.SuperStyleSheet.StyleManager.ForceRefresh(); +#endif + + int count = 0; + foreach (var c in s_Components) + { + try { c.RefreshStyle(); } catch { } + count++; + } + +#if UNITY_EDITOR + Debug.Log($"[StyleRefresh] 已刷新 {count} 个样式组件。"); +#endif + } + + /// 当前注册的组件数 + public static int RegisteredCount => s_Components.Count; + } +} diff --git a/Runtime/Core/StyleSheetUI/StyleRefreshManager.cs.meta b/Runtime/Core/StyleSheetUI/StyleRefreshManager.cs.meta new file mode 100644 index 0000000..127e6ca --- /dev/null +++ b/Runtime/Core/StyleSheetUI/StyleRefreshManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 65395d6526aed354f9b5344410621aa9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/OverrideUI/XericStyleButton.cs b/Runtime/OverrideUI/XericStyleButton.cs index 45e7ff5..fd8c5b7 100644 --- a/Runtime/OverrideUI/XericStyleButton.cs +++ b/Runtime/OverrideUI/XericStyleButton.cs @@ -14,7 +14,7 @@ namespace XericUI.OverrideUI /// 替代 Unity 内置的 ColorBlock 和 SpriteState。 /// [AddComponentMenu("Xeric UI Vessel/UI/Style Button", 51)] - public class XericStyleButton : Button + public class XericStyleButton : Button, IStyleRefreshable { #region 序列化字段 @@ -59,11 +59,14 @@ namespace XericUI.OverrideUI m_ColorState?.SubscribeAll(OnStyleChanged); m_TextureState?.SubscribeAll(OnStyleChanged); + StyleRefreshManager.Register(this); ApplyForState(m_CurrentState); } protected override void OnDisable() { + StyleRefreshManager.Unregister(this); + m_ColorState?.UnsubscribeAll(OnStyleChanged); m_TextureState?.UnsubscribeAll(OnStyleChanged); m_ColorState?.UnregisterAll(); @@ -92,6 +95,11 @@ namespace XericUI.OverrideUI #region 样式应用 + public void RefreshStyle() + { + ApplyForState(m_CurrentState, false); + } + private void ApplyForState(StyleSheetSelectionState state, bool instant = false) { // 颜色 @@ -134,6 +142,12 @@ namespace XericUI.OverrideUI #region 组件替换 #if UNITY_EDITOR + [UnityEditor.MenuItem("CONTEXT/XericStyleButton/Xeric UI/强制刷新样式", false, 1)] + private static void ForceRefreshStyle(UnityEditor.MenuCommand command) + { + StyleRefreshManager.ForceRefreshAll(); + } + [UnityEditor.MenuItem("CONTEXT/Button/Replace To/Xeric (Style)", true)] private static bool ValidateReplaceToStyleButton(UnityEditor.MenuCommand command) => command.context is Button and not XericStyleButton; diff --git a/Runtime/OverrideUI/XericStyleImage.cs b/Runtime/OverrideUI/XericStyleImage.cs index e175f14..2a964d9 100644 --- a/Runtime/OverrideUI/XericStyleImage.cs +++ b/Runtime/OverrideUI/XericStyleImage.cs @@ -2,6 +2,7 @@ using UnityEngine; using UnityEngine.UI; using XericLibrary.Runtime.SuperStyleSheet; +using XericUI.Core.StyleSheetUI; using XericUI.Helper; namespace XericUI.OverrideUI diff --git a/Runtime/OverrideUI/XericStyleToggle.cs b/Runtime/OverrideUI/XericStyleToggle.cs index 6c0b83a..5472e5c 100644 --- a/Runtime/OverrideUI/XericStyleToggle.cs +++ b/Runtime/OverrideUI/XericStyleToggle.cs @@ -13,7 +13,7 @@ namespace XericUI.OverrideUI /// 额外支持 isOn 覆盖和 Checkmark 样式。 /// [AddComponentMenu("Xeric UI Vessel/UI/Style Toggle", 52)] - public class XericStyleToggle : Toggle + public class XericStyleToggle : Toggle, IStyleRefreshable { #region 序列化字段 @@ -86,12 +86,15 @@ namespace XericUI.OverrideUI m_CheckmarkStyle?.Register(); m_CheckmarkStyle.OnValueChanged += OnStyleChanged; + StyleRefreshManager.Register(this); onValueChanged.AddListener(OnToggleValueChanged); ApplyForState(m_CurrentState); } protected override void OnDisable() { + StyleRefreshManager.Unregister(this); + onValueChanged.RemoveListener(OnToggleValueChanged); m_ColorState?.UnsubscribeAll(OnStyleChanged); @@ -130,6 +133,11 @@ namespace XericUI.OverrideUI #region 样式应用 + public void RefreshStyle() + { + ApplyForState(m_CurrentState, false); + } + private void ApplyForState(StyleSheetSelectionState state, bool instant = false) { // 颜色:On 覆盖优先 @@ -181,6 +189,12 @@ namespace XericUI.OverrideUI #region 组件替换 #if UNITY_EDITOR + [UnityEditor.MenuItem("CONTEXT/XericStyleToggle/Xeric UI/强制刷新样式", false, 1)] + private static void ForceRefreshStyle(UnityEditor.MenuCommand command) + { + StyleRefreshManager.ForceRefreshAll(); + } + [UnityEditor.MenuItem("CONTEXT/Toggle/Replace To/Xeric (Style)", true)] private static bool ValidateReplaceToStyleToggle(UnityEditor.MenuCommand command) => command.context is Toggle and not XericStyleToggle;