From a35067f80ac0808482a7a80bc464b5edda0d3991 Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Wed, 20 May 2026 10:36:33 +0200 Subject: [PATCH] feat(ui): wire ThemeRegistry crossfade into PushGlobal Switch picks a lerped AbgrCache during the 300ms crossfade window (ReduceMotion bypass keeps the snap path). Plugin-load init path switches to SwitchSilent so opening the plugin no longer fades from the default theme. WindowBg/ChildBg RGBA path stays bound to the user's per-window opacity override and never fades. PushGlobal takes the ThemeRegistry as a parameter -- it is an instance member on Plugin, not static, so the single Plugin.Draw call-site threads it through alongside the active theme. --- .../Hosting/InitHostedServices.cs | 2 +- HellionChat/Plugin.cs | 1 + HellionChat/Ui/HellionStyle.cs | 27 +++++++++++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/HellionChat/Infrastructure/Hosting/InitHostedServices.cs b/HellionChat/Infrastructure/Hosting/InitHostedServices.cs index 5d2a772..b7729f6 100644 --- a/HellionChat/Infrastructure/Hosting/InitHostedServices.cs +++ b/HellionChat/Infrastructure/Hosting/InitHostedServices.cs @@ -19,7 +19,7 @@ internal sealed class ThemeRegistryInitHostedService(ThemeRegistry registry) : I // warm cache; otherwise the first Switch falls through to the built-in // default when Config.Theme points at a custom slug. foreach (var _ in registry.AllCustom()) { } - registry.Switch(Plugin.Config.Theme); + registry.SwitchSilent(Plugin.Config.Theme); return Task.CompletedTask; } diff --git a/HellionChat/Plugin.cs b/HellionChat/Plugin.cs index 912bc7c..8ad1595 100755 --- a/HellionChat/Plugin.cs +++ b/HellionChat/Plugin.cs @@ -912,6 +912,7 @@ public sealed class Plugin : IAsyncDalamudPlugin // Theme engine is always active; Classic is a theme, not a disabled state. using IDisposable _style = HellionStyle.PushGlobal( ThemeRegistry.Active, + ThemeRegistry, Config.WindowOpacity ); diff --git a/HellionChat/Ui/HellionStyle.cs b/HellionChat/Ui/HellionStyle.cs index 96a6b7f..4e6481b 100644 --- a/HellionChat/Ui/HellionStyle.cs +++ b/HellionChat/Ui/HellionStyle.cs @@ -33,11 +33,34 @@ internal static class HellionStyle // Global color and style stack pushed once per frame. // windowOpacity: window background alpha (0.5-1.0). - internal static IDisposable PushGlobal(Theme theme, float windowOpacity = 1.0f) + internal static IDisposable PushGlobal( + Theme theme, + ThemeRegistry registry, + float windowOpacity = 1.0f + ) { var c = theme.Colors; var l = theme.Layout; - var a = theme.AbgrCache; + + // Crossfade: PM-1 reads a lerped snapshot during the 300ms window + // following a Switch (TryGetActiveCrossfade returns false outside + // the window or while ReduceMotion is on). Only the ABGR-slot path + // crossfades -- WindowBg/ChildBg RGBA stays bound to the user's + // per-window opacity override and must not fade. See + // feedback_dalamud_pinning_override. + ThemeAbgrCache a; + if ( + !Plugin.Config.ReduceMotion + && registry.TryGetActiveCrossfade(out var lerped) + ) + { + a = lerped; + } + else + { + a = theme.AbgrCache; + } + var stack = new StackHandle(); var alphaByte = (uint)Math.Clamp((int)(windowOpacity * 255f), 0x55, 0xFF);