diff --git a/src/Avalonia.Animation/AnimatorKeyFrame.cs b/src/Avalonia.Animation/AnimatorKeyFrame.cs
index 0276c6fa92..0dc15da49c 100644
--- a/src/Avalonia.Animation/AnimatorKeyFrame.cs
+++ b/src/Avalonia.Animation/AnimatorKeyFrame.cs
@@ -29,6 +29,7 @@ namespace Avalonia.Animation
Cue = cue;
}
+ internal bool isNeutral;
public Type AnimatorType { get; }
public Cue Cue { get; }
public AvaloniaProperty Property { get; private set; }
diff --git a/src/Avalonia.Animation/Animator`1.cs b/src/Avalonia.Animation/Animator`1.cs
index 8079ac69b5..7631a11d9c 100644
--- a/src/Avalonia.Animation/Animator`1.cs
+++ b/src/Avalonia.Animation/Animator`1.cs
@@ -19,7 +19,7 @@ namespace Avalonia.Animation
///
/// List of type-converted keyframes.
///
- private readonly SortedList _convertedKeyframes = new SortedList();
+ private readonly List _convertedKeyframes = new List();
private bool isVerfifiedAndConverted;
@@ -58,41 +58,49 @@ namespace Avalonia.Animation
/// The time parameter, relative to the total animation time
protected (double IntraKFTime, KeyFramePair KFPair) GetKFPairAndIntraKFTime(double t)
{
- KeyValuePair firstCue, lastCue;
+ AnimatorKeyFrame firstCue, lastCue ;
int kvCount = _convertedKeyframes.Count;
if (kvCount > 2)
{
if (DoubleUtils.AboutEqual(t, 0.0) || t < 0.0)
{
- firstCue = _convertedKeyframes.First();
- lastCue = _convertedKeyframes.Skip(1).First();
+ firstCue = _convertedKeyframes[0];
+ lastCue = _convertedKeyframes[1];
}
else if (DoubleUtils.AboutEqual(t, 1.0) || t > 1.0)
{
- firstCue = _convertedKeyframes.Skip(kvCount - 2).First();
- lastCue = _convertedKeyframes.Last();
+ firstCue = _convertedKeyframes[_convertedKeyframes.Count - 2];
+ lastCue = _convertedKeyframes[_convertedKeyframes.Count - 1];
}
else
{
- firstCue = _convertedKeyframes.Last(j => j.Key <= t);
- lastCue = _convertedKeyframes.First(j => j.Key >= t);
+ (double time, int index) maxval = (0.0d, 0);
+ for (int i = 0; i < _convertedKeyframes.Count; i++)
+ {
+ var comp = _convertedKeyframes[i].Cue.CueValue;
+ if (t >= comp)
+ {
+ maxval = (comp, i);
+ }
+ }
+ firstCue = _convertedKeyframes[maxval.index];
+ lastCue = _convertedKeyframes[maxval.index + 1];
}
}
else
{
- firstCue = _convertedKeyframes.First();
- lastCue = _convertedKeyframes.Last();
+ firstCue = _convertedKeyframes[0];
+ lastCue = _convertedKeyframes[1];
}
- double t0 = firstCue.Key;
- double t1 = lastCue.Key;
+ double t0 = firstCue.Cue.CueValue;
+ double t1 = lastCue.Cue.CueValue;
var intraframeTime = (t - t0) / (t1 - t0);
- var firstFrameData = (firstCue.Value.frame.GetTypedValue(), firstCue.Value.isNeutral);
- var lastFrameData = (lastCue.Value.frame.GetTypedValue(), lastCue.Value.isNeutral);
+ var firstFrameData = (firstCue.GetTypedValue(), firstCue.isNeutral);
+ var lastFrameData = (lastCue.GetTypedValue(), lastCue.isNeutral);
return (intraframeTime, new KeyFramePair(firstFrameData, lastFrameData));
}
-
///
/// Runs the KeyFrames Animation.
///
@@ -113,16 +121,25 @@ namespace Avalonia.Animation
protected abstract T DoInterpolation(double time, T neutralValue);
///
- /// Verifies and converts keyframe values according to this class's target type.
+ /// Verifies, converts and sorts keyframe values according to this class's target type.
///
private void VerifyConvertKeyFrames()
{
foreach (AnimatorKeyFrame keyframe in this)
{
- _convertedKeyframes.Add(keyframe.Cue.CueValue, (keyframe, false));
+ _convertedKeyframes.Add(keyframe);
}
AddNeutralKeyFramesIfNeeded();
+
+ var copy = _convertedKeyframes.ToList().OrderBy(p => p.Cue.CueValue);
+ _convertedKeyframes.Clear();
+
+ foreach (AnimatorKeyFrame keyframe in copy)
+ {
+ _convertedKeyframes.Add(keyframe);
+ }
+
isVerfifiedAndConverted = true;
}
@@ -133,13 +150,13 @@ namespace Avalonia.Animation
hasStartKey = hasEndKey = false;
// Check if there's start and end keyframes.
- foreach (var converted in _convertedKeyframes.Keys)
+ foreach (var frame in _convertedKeyframes)
{
- if (DoubleUtils.AboutEqual(converted, 0.0))
+ if (DoubleUtils.AboutEqual(frame.Cue.CueValue, 0.0))
{
hasStartKey = true;
}
- else if (DoubleUtils.AboutEqual(converted, 1.0))
+ else if (DoubleUtils.AboutEqual(frame.Cue.CueValue, 1.0))
{
hasEndKey = true;
}
@@ -153,12 +170,12 @@ namespace Avalonia.Animation
{
if (!hasStartKey)
{
- _convertedKeyframes.Add(0.0d, (new AnimatorKeyFrame { Value = default(T) }, true));
+ _convertedKeyframes.Add(new AnimatorKeyFrame(null, new Cue(0.0d)) { Value = default(T), isNeutral = true });
}
if (!hasEndKey)
{
- _convertedKeyframes.Add(1.0d, (new AnimatorKeyFrame { Value = default(T) }, true));
+ _convertedKeyframes.Add(new AnimatorKeyFrame(null, new Cue(1.0d)) { Value = default(T), isNeutral = true });
}
}
}
diff --git a/src/Avalonia.Animation/Cue.cs b/src/Avalonia.Animation/Cue.cs
index 5a95c108e3..de77475c2c 100644
--- a/src/Avalonia.Animation/Cue.cs
+++ b/src/Avalonia.Animation/Cue.cs
@@ -7,7 +7,7 @@ using System.Text;
namespace Avalonia.Animation
{
///
- /// A Cue object for .
+ /// Determines the time index for a .
///
[TypeConverter(typeof(CueTypeConverter))]
public readonly struct Cue : IEquatable, IEquatable
@@ -84,5 +84,4 @@ namespace Avalonia.Animation
return Cue.Parse((string)value, culture);
}
}
-
-}
+}
\ No newline at end of file