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; + } +}