From 0bfe3a62cbb7172bcd0b8395f112abc4ed55a76b Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Wed, 20 May 2026 13:26:16 +0200 Subject: [PATCH] feat: add FrameLerp helper and per-tab hover-alpha fields FrameLerp.Smooth is the framerate-independent smoothing path -- a Umbra-style v += (target - v) * factor with the factor clamped to 1 so a stalled frame snaps cleanly instead of overshooting. Tab gets two NonSerialized fields (_hoverAlpha, _cardHoverAlpha) that the v1.5.4 render loops drive. --- HellionChat/Configuration.cs | 11 +++++++++++ HellionChat/Util/FrameLerp.cs | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 HellionChat/Util/FrameLerp.cs diff --git a/HellionChat/Configuration.cs b/HellionChat/Configuration.cs index ea925fa..e93adaa 100755 --- a/HellionChat/Configuration.cs +++ b/HellionChat/Configuration.cs @@ -485,6 +485,17 @@ public class Tab [NonSerialized] internal string? _cachedTellIcon; + // PM-3 hover-lerp state. Default 0f means "not hovered". Sidebar + // path animates per tab; card-mode-border path is tab-aggregate + // (any card-row hover ramps the alpha for all cards in this tab). + // Lerp speed lives in the render loop, not here, so the same field + // serves both sites at the same animation curve. + [NonSerialized] + internal float _hoverAlpha; + + [NonSerialized] + internal float _cardHoverAlpha; + public bool Matches(Message message) { if (!message.Matches(SelectedChannels, ExtraChatAll, ExtraChatChannels)) diff --git a/HellionChat/Util/FrameLerp.cs b/HellionChat/Util/FrameLerp.cs new file mode 100644 index 0000000..2593f6f --- /dev/null +++ b/HellionChat/Util/FrameLerp.cs @@ -0,0 +1,17 @@ +namespace HellionChat.Util; + +// Framerate-independent smoothing for per-frame hover and motion +// values. Pattern anchor: Umbra Toolbar.Autohide.cs:55 +// (`v += (target - v) * deltaTime`). The Math.Min(1f, speed*dt) +// clamp is a deliberate HellionChat addition -- on Wine/DXVK a +// stalled frame can push deltaTime well over 16ms, which would +// otherwise let the raw factor exceed 1.0 and overshoot the target. +// Clamping makes a stalled frame land exactly on target instead. +internal static class FrameLerp +{ + public static float Smooth(float current, float target, float speed, float deltaTime) + { + var factor = Math.Min(1f, speed * deltaTime); + return current + (target - current) * factor; + } +}