Code/Utility/Interpolator.cs
using System;
namespace Sandbox.MovieMaker;
#nullable enable
/// <summary>
/// Interpolates between two values of the same type.
/// </summary>
/// <typeparam name="T">Value type to interpolate.</typeparam>
public interface IInterpolator<T>
{
/// <summary>
/// Interpolate between two values.
/// </summary>
/// <param name="a">Value to return when <paramref name="t"/> is <c>0</c>.</param>
/// <param name="b">Value to return when <paramref name="t"/> is <c>1</c>.</param>
/// <param name="t">Fraction between <c>0</c> and <c>1</c> (inclusive).</param>
T Interpolate( T a, T b, float t );
}
/// <summary>
/// Helper for accessing <see cref="IInterpolator{T}"/> implementations,
/// for interpolating between two values of the same type
/// </summary>
public static class Interpolator
{
/// <summary>
/// Attempts to find a default interpolator for type <typeparamref name="T"/>,
/// returning <see langword="null"/> if not found.
/// </summary>
/// <typeparam name="T">Value type to interpolate.</typeparam>
public static IInterpolator<T>? GetDefault<T>()
{
// TODO: type library lookup?
return DefaultInterpolator.Instance as IInterpolator<T>;
}
public static IInterpolator<T> GetDefaultOrThrow<T>() =>
GetDefault<T>() ?? throw new Exception( $"Type {typeof(T)} can't be interpolated." );
}
// TODO: special float interpolators for degrees / radians? special vector interpolators for normals?
/// <summary>
/// Interpolator for common types.
/// </summary>
file sealed class DefaultInterpolator :
IInterpolator<float>, IInterpolator<double>,
IInterpolator<Vector2>, IInterpolator<Vector3>, IInterpolator<Vector4>,
IInterpolator<Rotation>, IInterpolator<Angles>,
IInterpolator<Color>
{
public static DefaultInterpolator Instance { get; } = new();
public float Interpolate( float a, float b, float delta ) => a + (b - a) * delta;
public double Interpolate( double a, double b, float delta ) => a + (b - a) * delta;
public Vector2 Interpolate( Vector2 a, Vector2 b, float delta ) => a + (b - a) * delta;
public Vector3 Interpolate( Vector3 a, Vector3 b, float delta ) => a + (b - a) * delta;
public Vector4 Interpolate( Vector4 a, Vector4 b, float delta ) => a + (b - a) * delta;
public Rotation Interpolate( Rotation a, Rotation b, float delta ) => a.SlerpTo( b, delta );
public Angles Interpolate( Angles a, Angles b, float delta ) => a.LerpTo( b, delta );
public Color Interpolate( Color a, Color b, float delta ) => a + (b - a) * delta;
}