UnitTests/AltCurveTests.cs
using Sandbox;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using static AltCurves.AltCurve;
namespace AltCurves.Tests;
[TestClass]
public partial class AltCurveTests
{
[TestMethod]
public void KeyframeEquality()
{
// This is all overkill but if I'm going to test curves, I want to be certain this is acting like it should
var keyframe1 = new Keyframe( 0.0f, 10.0f, Interpolation.Linear );
var keyframe2 = new Keyframe( 0.0f, 10.0f, Interpolation.Linear );
Assert.AreEqual( keyframe1, keyframe2, "Keyframes with the same values should be equal." );
Assert.AreEqual( keyframe1.GetHashCode(), keyframe2.GetHashCode(), "Keyframes with the same values should have the same hash code." );
var keyframe3 = new Keyframe( 1.0f, 10.0f, Interpolation.Linear );
Assert.AreNotEqual( keyframe1, keyframe3, "Keyframes with different times should not be equal." );
Assert.AreNotEqual( keyframe1.GetHashCode(), keyframe3.GetHashCode(), "Keyframes with different times should have different hash codes." );
var keyframe4 = new Keyframe( 0.0f, 20.0f, Interpolation.Linear );
Assert.AreNotEqual( keyframe1, keyframe4, "Keyframes with different values should not be equal." );
Assert.AreNotEqual( keyframe1.GetHashCode(), keyframe4.GetHashCode(), "Keyframes with different values should have different hash codes." );
var keyframe5 = new Keyframe( 0.0f, 10.0f, Interpolation.Cubic );
Assert.AreNotEqual( keyframe1, keyframe5, "Keyframes with different interpolation should not be equal." );
Assert.AreNotEqual( keyframe1.GetHashCode(), keyframe5.GetHashCode(), "Keyframes with different interpolation should have different hash codes." );
var keyframe6 = new Keyframe( 0.0f, 10.0f, Interpolation.Linear, TangentMode.Mirrored, 1.0f, 1.0f );
var keyframe7 = new Keyframe( 0.0f, 10.0f, Interpolation.Linear, TangentMode.Mirrored, 1.0f, 1.0f );
Assert.AreEqual( keyframe6, keyframe7, "Keyframes with the same tangent settings should be equal." );
Assert.AreEqual( keyframe6.GetHashCode(), keyframe7.GetHashCode(), "Keyframes with the same tangent settings should have the same hash code." );
var keyframe8 = new Keyframe( 0.0f, 10.0f, Interpolation.Linear, TangentMode.Split, 1.0f, 1.0f );
Assert.AreNotEqual( keyframe6, keyframe8, "Keyframes with different tangent modes should not be equal." );
Assert.AreNotEqual( keyframe6.GetHashCode(), keyframe8.GetHashCode(), "Keyframes with different tangent modes should have different hash codes." );
}
[TestMethod]
public void AltCurveEquality()
{
var curve1 = new AltCurve( new List<Keyframe> { new( 0.0f, 10.0f, Interpolation.Linear ) }, Extrapolation.Constant, Extrapolation.Constant );
var curve2 = new AltCurve( new List<Keyframe> { new( 0.0f, 10.0f, Interpolation.Linear ) }, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreEqual( curve1, curve2 );
Assert.AreNotEqual( curve1, new AltCurve( new List<Keyframe> { new( 0.0f, 10.0f, Interpolation.Linear ) }, Extrapolation.Linear, Extrapolation.Constant ) );
Assert.AreNotEqual( curve1, new AltCurve( new List<Keyframe> { new( 0.0f, 10.0f, Interpolation.Linear ) }, Extrapolation.Constant, Extrapolation.Linear ) );
Assert.AreNotEqual( curve1, new AltCurve( new List<Keyframe> { new( 0.0f, 10.0f, Interpolation.Linear ) }, Extrapolation.Linear, Extrapolation.Linear ) );
Assert.AreNotEqual( curve1, new AltCurve( new List<Keyframe> { new( 1.0f, 10.0f, Interpolation.Linear ) }, Extrapolation.Constant, Extrapolation.Constant ) );
Assert.AreNotEqual( curve1, new AltCurve( new List<Keyframe> { new( 0.0f, 20.0f, Interpolation.Linear ) }, Extrapolation.Constant, Extrapolation.Constant ) );
Assert.AreNotEqual( curve1, new AltCurve( new List<Keyframe> { new( 0.0f, 10.0f, Interpolation.Constant ) }, Extrapolation.Constant, Extrapolation.Constant ) );
Assert.AreNotEqual( curve1, new AltCurve( new List<Keyframe>
{
new(0.0f, 10.0f, Interpolation.Linear),
new(1.0f, 15.0f, Interpolation.Linear)
}, Extrapolation.Constant, Extrapolation.Constant ) );
var cubicCurve1 = new AltCurve( new List<Keyframe> { new( 0.0f, 10.0f, Interpolation.Cubic, TangentMode.Mirrored, 1.0f, 1.0f ) }, Extrapolation.Constant, Extrapolation.Constant );
var cubicCurve2 = new AltCurve( new List<Keyframe> { new( 0.0f, 10.0f, Interpolation.Cubic, TangentMode.Split, 1.0f, 1.0f ) }, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreNotEqual( cubicCurve1, cubicCurve2 );
var cubicCurve3 = new AltCurve( new List<Keyframe> { new( 0.0f, 10.0f, Interpolation.Cubic, TangentMode.Mirrored, 2.0f, 1.0f ) }, Extrapolation.Constant, Extrapolation.Constant );
var cubicCurve4 = new AltCurve( new List<Keyframe> { new( 0.0f, 10.0f, Interpolation.Cubic, TangentMode.Mirrored, 1.0f, 2.0f ) }, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreNotEqual( cubicCurve3, cubicCurve4 );
var cubicCurve5 = new AltCurve( new List<Keyframe>
{
new(0.0f, 10.0f, Interpolation.Cubic, TangentMode.Split, 1.0f, 2.0f),
new(1.0f, 20.0f, Interpolation.Cubic, TangentMode.Split, 2.0f, 1.0f)
}, Extrapolation.Constant, Extrapolation.Constant );
var cubicCurve6 = new AltCurve( new List<Keyframe>
{
new(0.0f, 10.0f, Interpolation.Cubic, TangentMode.Mirrored, 1.0f, 1.0f),
new(1.0f, 20.0f, Interpolation.Cubic, TangentMode.Mirrored, 1.0f, 1.0f)
}, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreNotEqual( cubicCurve5, cubicCurve6 );
}
[TestMethod]
public void CurveConstruct()
{
// It's not valid to have a curve with 0 keyframes, trying to make such a curve will add 1 default key
var curve = new AltCurve();
Assert.AreEqual( 1, curve.Keyframes.Length );
Assert.AreEqual( Extrapolation.Constant, curve.PreInfinity );
Assert.AreEqual( Extrapolation.Constant, curve.PostInfinity );
}
[TestMethod]
public void SingleKeyframe()
{
var curve = new AltCurve( new List<Keyframe> { new() { Time = 0.0f, Value = 10.0f, Interpolation = Interpolation.Linear } }, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreEqual( 10, curve.Evaluate( 0 ) );
Assert.AreEqual( 10, curve.Evaluate( 1 ) );
Assert.AreEqual( 10, curve.Evaluate( -1 ) );
}
[TestMethod]
public void MultipleKeyframes()
{
var curve = new AltCurve( new List<Keyframe>
{
new(0, 10, Interpolation.Linear),
new(10, 20, Interpolation.Linear)
}, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreEqual( 10, curve.Evaluate( 0 ) );
Assert.AreEqual( 15, curve.Evaluate( 5 ) );
Assert.AreEqual( 20, curve.Evaluate( 10 ) );
}
[TestMethod]
public void ExtrapolationBeforeFirstKeyframe()
{
var curve = new AltCurve( new List<Keyframe> { new( 10, 20, Interpolation.Linear ) }, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreEqual( 20, curve.Evaluate( 5 ) );
}
[TestMethod]
public void ExtrapolationAfterLastKeyframe()
{
var curve = new AltCurve( new List<Keyframe> { new( 10, 20, Interpolation.Linear ) }, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreEqual( 20, curve.Evaluate( 15 ) );
}
[TestMethod]
public void TestInterpolation()
{
var curve = new AltCurve( new List<Keyframe>
{
new(0, 10, Interpolation.Linear),
new(10, 20, Interpolation.Linear)
}, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreEqual( 15, curve.Evaluate( 5 ) );
}
[TestMethod]
public void CubicInterpolation()
{
var curve = new AltCurve( new List<Keyframe>
{
new(0, 0, Interpolation.Cubic, TangentMode.Mirrored, 0, 0),
new(1, 1, Interpolation.Cubic, TangentMode.Mirrored, 1, 1),
new(2, 0, Interpolation.Cubic, TangentMode.Mirrored, 0, 0)
}, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreEqual( 0.0f, curve.Evaluate( 0.0f ), 0.01f );
Assert.AreEqual( 0.343f, curve.Evaluate( 0.5f ), 0.01f );
Assert.AreEqual( 1.0f, curve.Evaluate( 1.0f ), 0.01f );
Assert.AreEqual( 0.656f, curve.Evaluate( 1.5f ), 0.01f );
Assert.AreEqual( 0.0f, curve.Evaluate( 2.0f ), 0.01f );
}
[TestMethod]
public void JsonSerialization()
{
var keyframes = new List<Keyframe>
{
new Keyframe(0, 0, Interpolation.Linear),
new Keyframe(1, 10, Interpolation.Linear)
};
var curve = new AltCurve( keyframes, Extrapolation.Linear, Extrapolation.Linear );
var json = Json.Serialize( curve );
var deserializedCurve = Json.Deserialize<AltCurve>( json );
Assert.AreEqual( curve, deserializedCurve );
}
[TestMethod]
public void DeserializeSerializeConsistency()
{
// I'm paranoid about weird data issues causing differences... can you tell?
var data = """{"_ace_v":1,"pri":"Oscillate","poi":"CycleOffset","keys":[{"x":-491.8,"y":-1625},{"x":-398.1,"y":-250,"ti":3.3167496,"to":3.3167496},{"x":-190.3,"y":-625,"ti":1.8491124,"to":1.8491124},{"x":-60.1,"y":375,"i":"Constant","ti":-4.2390842,"to":-4.2390842},{"x":45.6,"y":-1625,"ti":-3.0151618,"to":-3.0151618},{"x":230.1,"y":-500,"ti":130.92972,"to":130.92972,"tm":"Mirrored"},{"x":335,"y":-1250,"ti":-0.5399568,"to":-0.5399568},{"x":461.6,"y":-625,"ti":-6.6666665,"to":-6.6666665},{"x":522.5,"y":-2500,"ti":-4.6159525,"to":-4.6159525},{"x":732.4,"y":-1875}]}""";
AltCurve expectedCurve = new( new List<Keyframe>
{
new() { Time = -491.8f, Value = -1625f },
new() { Time = -398.1f, Value = -250f, TangentIn = 3.3167496f, TangentOut = 3.3167496f },
new() { Time = -190.3f, Value = -625f, TangentIn = 1.8491124f, TangentOut = 1.8491124f },
new() { Time = -60.1f, Value = 375f, Interpolation = Interpolation.Constant, TangentIn = -4.2390842f, TangentOut = -4.2390842f },
new() { Time = 45.6f, Value = -1625f, TangentIn = -3.0151618f, TangentOut = -3.0151618f },
new() { Time = 230.1f, Value = -500f, Interpolation = Interpolation.Cubic, TangentMode = TangentMode.Mirrored, TangentIn = 130.92972f, TangentOut = 130.92972f },
new() { Time = 335f, Value = -1250f, TangentIn = -0.5399568f, TangentOut = -0.5399568f },
new() { Time = 461.6f, Value = -625f, TangentIn = -6.6666665f, TangentOut = -6.6666665f },
new() { Time = 522.5f, Value = -2500f, TangentIn = -4.6159525f, TangentOut = -4.6159525f },
new() { Time = 732.4f, Value = -1875f }
}, Extrapolation.Oscillate, Extrapolation.CycleOffset );
AltCurve deserializedCurve = Json.Deserialize<AltCurve>( data );
Assert.AreEqual( expectedCurve, deserializedCurve );
string serializedCurve = Json.Serialize( deserializedCurve );
AltCurve reDeserializedCurve = Json.Deserialize<AltCurve>( serializedCurve );
Assert.AreEqual( expectedCurve, reDeserializedCurve );
}
[TestMethod]
public void ExtrapolationTests()
{
var keyframes = new List<Keyframe>
{
new(0, 0, Interpolation.Cubic, TangentMode.Mirrored, 0, 0),
new(1, 2, Interpolation.Cubic, TangentMode.Mirrored, 1, 1),
new(2, -1, Interpolation.Cubic, TangentMode.Mirrored, -1, -1),
new(3, 3, Interpolation.Cubic, TangentMode.Mirrored, 2, 2)
};
// Validate the functionality of each extrapolation type
var constantCurve = new AltCurve( keyframes, Extrapolation.Constant, Extrapolation.Constant );
Assert.AreEqual( 0.0f, constantCurve.Evaluate( -1.0f ), 0.01f, "Constant extrapolation should use the first keyframe value before the range." );
Assert.AreEqual( 3.0f, constantCurve.Evaluate( 4.0f ), 0.01f, "Constant extrapolation should use the last keyframe value after the range." );
var linearCurve = new AltCurve( keyframes, Extrapolation.Linear, Extrapolation.Linear );
Assert.AreEqual( -2.0f, linearCurve.Evaluate( -1.0f ), 0.01f, "Linear extrapolation should extrapolate linearly before the range." );
Assert.AreEqual( 7.0f, linearCurve.Evaluate( 4.0f ), 0.01f, "Linear extrapolation should extrapolate linearly after the range." );
var cycleCurve = new AltCurve( keyframes, Extrapolation.Cycle, Extrapolation.Cycle );
Assert.AreEqual( -1.0f, cycleCurve.Evaluate( -1.0f ), 0.01f, "Cycle extrapolation should repeat the pattern before the range." );
Assert.AreEqual( 0.55, cycleCurve.Evaluate( -0.5f ), 0.01f, "Cycle extrapolation should repeat the pattern before the range." );
Assert.AreEqual( 0.85f, cycleCurve.Evaluate( 3.5f ), 0.01f, "Cycle extrapolation should repeat the pattern after the range." );
Assert.AreEqual( 2.0f, cycleCurve.Evaluate( 4.0f ), 0.01f, "Cycle extrapolation should repeat the pattern after the range." );
var cycleOffsetCurve = new AltCurve( keyframes, Extrapolation.CycleOffset, Extrapolation.CycleOffset );
Assert.AreEqual( -1233.0f, cycleOffsetCurve.Evaluate( -1233.0f ), 0.01f, "CycleOffset extrapolation should accumulate offset before the range." );
Assert.AreEqual( -19.0f, cycleOffsetCurve.Evaluate( -20.0f ), 0.01f, "CycleOffset extrapolation should accumulate offset before the range." );
Assert.AreEqual( -4.0f, cycleOffsetCurve.Evaluate( -1.0f ), 0.01f, "CycleOffset extrapolation should accumulate offset before the range." );
Assert.AreEqual( -2.452f, cycleOffsetCurve.Evaluate( -0.5f ), 0.01f, "CycleOffset extrapolation should accumulate offset before the range." );
Assert.AreEqual( 3.851f, cycleOffsetCurve.Evaluate( 3.5f ), 0.01f, "CycleOffset extrapolation should accumulate offset before the range." );
Assert.AreEqual( 5.0f, cycleOffsetCurve.Evaluate( 4.0f ), 0.01f, "CycleOffset extrapolation should accumulate offset after the range." );
Assert.AreEqual( 8.0f, cycleOffsetCurve.Evaluate( 7.0f ), 0.01f, "CycleOffset extrapolation should accumulate offset after the range." );
Assert.AreEqual( 5.0f, cycleOffsetCurve.Evaluate( 8.0f ), 0.01f, "CycleOffset extrapolation should accumulate offset after the range." );
var oscillateCurve = new AltCurve( keyframes, Extrapolation.Oscillate, Extrapolation.Oscillate );
Assert.AreEqual( 2.0f, oscillateCurve.Evaluate( -1.0f ), 0.01f, "Oscillate extrapolation should oscillate the pattern before the range." );
Assert.AreEqual( -1.0f, oscillateCurve.Evaluate( 4.0f ), 0.01f, "Oscillate extrapolation should oscillate the pattern after the range." );
Assert.AreEqual( 2.0f, oscillateCurve.Evaluate( 5.0f ), 0.01f, "Oscillate extrapolation should oscillate the pattern after the range." );
Assert.AreEqual( 2.0f, oscillateCurve.Evaluate( 1621297.0f ), 0.01f, "Oscillate extrapolation should oscillate the pattern after the range." );
}
//[TestMethod]
public void TimeTest1()
{
// Generate 1000 random x/y positions and 1000 random sample positions,
// We will use the stock sandbox curve, and our alt curve with the same input data and compare performance
var rand = new Random();
var positions = new List<Vector2>();
for ( int i = 0; i < 1; i++ )
{
positions.Add( new Vector2( Random.Shared.Float( -1000, 1000 ), Random.Shared.Float( -1000, 1000 ) ) );
}
var orderedPos = positions.OrderBy( x => x.x );
var altCurve = new AltCurve( orderedPos.Select( x => new Keyframe( x.x, x.y, Interpolation.Linear ) ).ToList(), Extrapolation.Constant, Extrapolation.Constant );
var baseCurve = new Curve( orderedPos.Select( x => new Curve.Frame( x.x, x.y ) ).ToList() );
var times = new List<float>();
for ( int i = 0; i < 1000; i++ )
times.Add( Random.Shared.Float( -1000, 1000 ) );
var baseTime = new Stopwatch();
var ourTime = new Stopwatch();
var baseTimeSamples = new List<long>();
var ourTimeSamples = new List<long>();
for ( int i = 0; i < 10000; i++ )
{
ourTime.Restart();
foreach ( var time in times ) altCurve.Evaluate( time );
ourTime.Stop();
baseTime.Restart();
foreach ( var time in times ) baseCurve.Evaluate( time );
baseTime.Stop();
baseTimeSamples.Add( baseTime.ElapsedTicks );
ourTimeSamples.Add( ourTime.ElapsedTicks );
}
var baseAverage = baseTimeSamples.Sum() / baseTimeSamples.Count;
var ourAverage = ourTimeSamples.Sum() / ourTimeSamples.Count;
Console.WriteLine( $"OurTime: {ourAverage}" );
Console.WriteLine( $"TheirTime: {baseAverage}" );
Console.WriteLine(
$"OurTime is {baseAverage / (float)ourAverage}x faster than TheirTime" );
// rough preliminary tests shows that our curves are more performant
// OurTime TheirTime
// With 1 key, 1000 evals:
// 30 653 21x faster
// 32 676 21x faster
// 33 660 21x faster
// 32 700 21x faster
// With 10 key, 1000 evals:
// 521 2121 4.0x faster
// 526 2338 4.4x faster
// 546 2394 4.4x faster
// 540 1973 3.6x faster
// With 50 key, 1000 evals:
// 704 4169 5.9x faster
// 735 4998 6.8x faster
// 728 4696 6.4x faster
// 710 4959 6.4x faster
// With 1000 key, 1000 evals:
// 1511 189953 125x faster
// 1560 188484 120x faster
// 1653 189336 114x faster
// 1500 194617 129x faster
// 1657 218923 132x faster
}
[TestMethod]
public void SanitizeCurveInput()
{
// Current sanitization rules so far are that we must have 1 keyframe, no keyframes may share a time, and keyframes must be in ascending time order.
AltCurve curveNoKeys = new( ImmutableArray.Create<Keyframe>(), Extrapolation.Linear, Extrapolation.Linear );
Assert.AreEqual( 1, curveNoKeys.Keyframes.Length, "Constructing a curve with no keyframes should result in 1 keyframe." );
var overlappingKeyframes = ImmutableArray.Create(
new Keyframe( 0.0f, 0.0f, Interpolation.Linear ),
new Keyframe( 1.0f, 1.0f, Interpolation.Linear ),
new Keyframe( 1.0f, 2.0f, Interpolation.Linear )
);
var sanitizedOverlap = SanitizeKeyframes( overlappingKeyframes );
Assert.AreNotEqual( sanitizedOverlap.Count(), overlappingKeyframes.Length, "Sanitizing keyframes should remove all duplicate times" );
Assert.AreEqual( 1.0f, sanitizedOverlap.ElementAt( 1 ).Value, 0.0001f, "If multiple times are provided we should always take the first instance." );
ImmutableArray<Keyframe> keyframesOutOfOrder = ImmutableArray.Create(
new Keyframe( 3.0f, 2.0f, Interpolation.Linear ),
new Keyframe( 0.0f, 1.0f, Interpolation.Linear ),
new Keyframe( 2.0f, 2.0f, Interpolation.Linear ),
new Keyframe( 1.0f, 1.0f, Interpolation.Linear )
);
var sanitizedOrder = SanitizeKeyframes( keyframesOutOfOrder );
Assert.AreEqual( keyframesOutOfOrder.Length, sanitizedOrder.Count(), "Sanitization shouldn't incorrectly remove a valid but out of order set of times." );
Assert.IsFalse( sanitizedOrder.SequenceEqual( keyframesOutOfOrder ), "Sanitization should correctly reorder out of order keyframes." );
Assert.IsTrue( sanitizedOrder.All( san => keyframesOutOfOrder.Contains( san ) ), "Sanitization should not alter any keyframes when reordering." );
}
[TestMethod]
public void ValidTimeSpan()
{
var keyframes = new List<Keyframe>
{
new( 5.0f, 0.0f, Interpolation.Linear ),
new( 10.0f, 1.0f, Interpolation.Linear ),
new( 15.0f, 2.0f, Interpolation.Linear ),
new( 20.0f, 3.0f, Interpolation.Linear )
};
AltCurve curve = new( keyframes, Extrapolation.Linear, Extrapolation.Linear );
Assert.AreEqual( curve.TimeSpan, 15.0f );
}
[TestMethod]
public void ValidTimeRange()
{
var keyframes = new List<Keyframe>
{
new( 5.0f, 0.0f, Interpolation.Linear ),
new( 10.0f, 1.0f, Interpolation.Linear ),
new( 15.0f, 2.0f, Interpolation.Linear ),
new( 20.0f, 3.0f, Interpolation.Linear )
};
AltCurve curve = new( keyframes, Extrapolation.Linear, Extrapolation.Linear );
Assert.AreEqual( curve.TimeRange.Min, 5.0f, float.Epsilon );
Assert.AreEqual( curve.TimeRange.Max, 20.0f, float.Epsilon );
}
[TestMethod]
public void ValidValueRange()
{
var keyframes = new List<Keyframe>
{
new( 5.0f, 10.0f, Interpolation.Linear ),
new( 10.0f, 51.0f, Interpolation.Linear ),
new( 15.0f, 92.0f, Interpolation.Linear ),
new( 20.0f, 167.0f, Interpolation.Linear )
};
AltCurve curve = new( keyframes, Extrapolation.Linear, Extrapolation.Linear );
Assert.AreEqual( curve.ValueRange.Min, 10.0f, float.Epsilon );
Assert.AreEqual( curve.ValueRange.Max, 167.0f, float.Epsilon );
}
[TestMethod]
public void ValidValueRangeCubic()
{
// The large slopes on the in/out middle tangents will cause a big curving arc that extents well above and below the input values
var keyframes = new List<Keyframe>
{
new( 5.0f, 10.0f, Interpolation.Linear ),
new( 10.0f, 51.0f, Interpolation.Cubic, tangentIn: 315f, tangentOut: 315f ),
new( 15.0f, 92.0f, Interpolation.Cubic, tangentIn: 315f, tangentOut: 315f ),
new( 20.0f, 167.0f, Interpolation.Linear )
};
AltCurve curve = new( keyframes, Extrapolation.Linear, Extrapolation.Linear );
Assert.IsTrue( curve.ValueRange.Min < -90.0f );
Assert.IsTrue( curve.ValueRange.Max > 300.0f );
}
[TestMethod]
public void ArgumentExceptionKeyframeOrder()
{
ImmutableArray<Keyframe> keyframesOutOfOrder = ImmutableArray.Create(
new Keyframe( 3.0f, 2.0f, Interpolation.Linear ),
new Keyframe( 0.0f, 1.0f, Interpolation.Linear ),
new Keyframe( 2.0f, 2.0f, Interpolation.Linear ),
new Keyframe( 1.0f, 1.0f, Interpolation.Linear )
);
Assert.ThrowsException<ArgumentException>( () => new AltCurve( keyframesOutOfOrder, Extrapolation.Linear, Extrapolation.Linear ),
"AltCurves must always be provided with ascending-time order keyframes" );
}
[TestMethod]
public void ArgumentExceptionKeyframeDuped()
{
ImmutableArray<Keyframe> keyframesSharedTime = ImmutableArray.Create(
new Keyframe( 0.0f, 1.0f, Interpolation.Linear ),
new Keyframe( 1.0f, 2.0f, Interpolation.Linear ),
new Keyframe( 2.0f, 2.0f, Interpolation.Linear ),
new Keyframe( 3.0f, 1.0f, Interpolation.Linear ),
new Keyframe( 3.0f, 6.0f, Interpolation.Linear )
);
Assert.ThrowsException<ArgumentException>( () => new AltCurve( keyframesSharedTime, Extrapolation.Linear, Extrapolation.Linear ),
"AltCurves must always be provided with unique time keyframes" );
}
}