DrawHoverSheen measured its own elapsed time against DateTime.UtcNow and gave up after 0.65s, so a row stopped reacting while the pointer was still on it. There was no held value to interpolate colours against. HoverState keeps one 0..1 intensity per element, rising at 14/s and falling at 8/s. Slower out than in is what makes the fade read as deliberate. Query and advance are separate on purpose. Several SelfTest steps call Sidebar.Draw against the live tab list, so the same element gets submitted up to three times in one frame, twice from a window the mouse is not over. If the query advanced the value, the last caller would win and the fade would run backwards. Query only ORs the hover flag; BeginFrame does all the moving and the eviction. BeginFrame sits above the HideInLoadingScreens and New Game+ early returns, so a hidden main window still lets pop-out hovers fade out instead of freezing mid-blend. FrameLerp gains Ramp: Smooth approaches asymptotically and never arrives, so a value driven by it would never reach zero and never become evictable. ReduceMotion short-circuits before the map is touched, returning a hard 0 or 1. An infinite rate would produce NaN and poison the entry for the session.
24 lines
880 B
C#
24 lines
880 B
C#
namespace HellionChat.Util;
|
|
|
|
// State rules for the held hover value, split from HoverState so the build suite
|
|
// can pin them without an ImGui frame. Rates follow Lightless (Selune.cs:36-37):
|
|
// slower out than in is what makes a fade read as deliberate rather than laggy.
|
|
internal static class HoverMath
|
|
{
|
|
internal const float FadeInPerSecond = 14f;
|
|
internal const float FadeOutPerSecond = 8f;
|
|
|
|
// Below this an entry is indistinguishable from zero and can be dropped.
|
|
internal const float EvictBelow = 0.001f;
|
|
|
|
internal static float Step(float current, bool hovered, float deltaTime) =>
|
|
FrameLerp.Ramp(
|
|
current,
|
|
hovered ? 1f : 0f,
|
|
hovered ? FadeInPerSecond : FadeOutPerSecond,
|
|
deltaTime
|
|
);
|
|
|
|
internal static bool ShouldEvict(float value, bool hovered) => !hovered && value <= EvictBelow;
|
|
}
|