Value-type record that tracks a 2D glide/banked-offset animation for UI layout transitions. It stores a Tween, elapsed time, and banked offset, provides Offset and IsActive getters, and methods to Bank a jump and Advance the clock.
using Sandbox;
namespace Goo.Animation;
/// <summary>Banked-offset glide for layout position transitions; pure value type, caller owns the clock.</summary>
public record struct GlideState
{
Vector2 _banked;
float _elapsed;
Tween _tween;
bool _active;
const float SettleSq = 0.25f;
/// <summary>Creates a glide with duration in milliseconds and optional easing (defaults to EaseOut).</summary>
public GlideState(float ms, Sandbox.Utility.Easing.Function? easing = null)
{
_tween = new Tween(easing ?? Easing.EaseOut, ms / 1000f);
_banked = Vector2.Zero;
_elapsed = 0f;
_active = false;
}
/// <summary>Current visual displacement from the layout slot; exactly zero when settled.</summary>
public readonly Vector2 Offset => _active ? _banked * (1f - _tween.Eval(_elapsed)) : Vector2.Zero;
/// <summary>True while the glide is still animating toward zero.</summary>
public readonly bool IsActive => _active;
/// <summary>Banks a layout jump; a mid-flight bank preserves the current visual offset and restarts the clock.</summary>
public void Bank(Vector2 jump)
{
if (_tween.Duration <= 0f) return;
var next = Offset + jump;
_elapsed = 0f;
if (next.LengthSquared < SettleSq) { _banked = Vector2.Zero; _active = false; return; }
_banked = next;
_active = true;
}
/// <summary>Steps the animation forward by dt seconds; settles when the offset drops below 0.5px.</summary>
public void Advance(float dt)
{
if (!_active) return;
_elapsed += dt;
if (Offset.LengthSquared < SettleSq) { _banked = Vector2.Zero; _active = false; }
}
}