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.
This commit is contained in:
2026-05-20 13:26:16 +02:00
parent 01a7f9b4ec
commit 0bfe3a62cb
2 changed files with 28 additions and 0 deletions
+11
View File
@@ -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))
+17
View File
@@ -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;
}
}