From ee1960ba00c2e6703fa891ce8a72440f6c3e66ed Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Tue, 27 Mar 2018 15:08:13 +0800 Subject: [PATCH] =?UTF-8?q?Finally,=20finally=20fix=20the=20linear=20param?= =?UTF-8?q?etric=20interpolation=20for=20DoubleKeyFrames=20=F0=9F=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Credits to Georgia Tech's keyframe slides : https://www.cc.gatech.edu/classes/AY2012/cs4496_spring/slides/Keyframe.pdf --- samples/RenderTest/Pages/AnimationsPage.xaml | 16 ++--- .../Keyframes/DoubleKeyFrames.cs | 59 +++++++++++-------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/samples/RenderTest/Pages/AnimationsPage.xaml b/samples/RenderTest/Pages/AnimationsPage.xaml index 5532383aac..f8d486bfc4 100644 --- a/samples/RenderTest/Pages/AnimationsPage.xaml +++ b/samples/RenderTest/Pages/AnimationsPage.xaml @@ -7,7 +7,6 @@ - - - - - - - - Hover to activate Transform Keyframe Animations. + + + Hover to activate Transform Keyframe Animations. + diff --git a/src/Avalonia.Animation/Keyframes/DoubleKeyFrames.cs b/src/Avalonia.Animation/Keyframes/DoubleKeyFrames.cs index 107b736b8b..6c23658d40 100644 --- a/src/Avalonia.Animation/Keyframes/DoubleKeyFrames.cs +++ b/src/Avalonia.Animation/Keyframes/DoubleKeyFrames.cs @@ -30,43 +30,56 @@ namespace Avalonia.Animation.Keyframes // Get a pair of keyframes to make the interpolation. KeyValuePair firstCue, lastCue; - firstCue = sortedkeyValues.First(); - lastCue = sortedkeyValues.Last(); + // This should be changed later for a much more efficient one if (sortedkeyValues.Count() > 2) { - bool isWithinRange_Start = DoubleUtils.AboutEqual(x, 0.0) || x > 0.0; - bool isWithinRange_End = DoubleUtils.AboutEqual(x, 1.0) || x < 1.0; + bool OutsideRange_Start = DoubleUtils.AboutEqual(x, 0.0) || x < 0.0; + bool OutsideRange_End = DoubleUtils.AboutEqual(x, 1.0) || x > 1.0; + var kyF = sortedkeyValues.ToArray(); - if (isWithinRange_Start && isWithinRange_End) - { - firstCue = sortedkeyValues.Where(j => j.Key <= x).Last(); - lastCue = sortedkeyValues.Where(j => j.Key >= x).First(); - } - else if (!isWithinRange_Start) + if (OutsideRange_Start) { - firstCue = sortedkeyValues.First(); - lastCue = sortedkeyValues.Skip(1).First(); + firstCue = kyF[0]; + lastCue = kyF[1]; } - else if (!isWithinRange_End) + else if (OutsideRange_End) { - firstCue = sortedkeyValues.Skip(sortedkeyValues.Count() - 1).First(); - lastCue = sortedkeyValues.Last(); + var count = kyF.Count(); + firstCue = kyF[count - 2]; + lastCue = kyF[count - 1]; } else { - throw new InvalidOperationException - ($"Can't find KeyFrames within the specified Easing time {x}"); + firstCue = sortedkeyValues.Where(j => j.Key <= x).Last(); + lastCue = sortedkeyValues.Where(j => j.Key >= x).First(); } } + else + { + firstCue = sortedkeyValues.First(); + lastCue = sortedkeyValues.Last(); + } + + double x0, y0, x1, y1; - // Piecewise Linear interpolation, courtesy of wikipedia - var y0 = firstCue.Value; - var x0 = firstCue.Key; - var y1 = lastCue.Value; - var x1 = lastCue.Key; - var y = ((y0 * (x1 - x)) + (y1 * (x - x0))) / x1 - x0; + // Swap interpolants if its descending + // if (firstCue.Value > lastCue.Value) + // // { + // y1 = firstCue.Value; + // x1 = firstCue.Key; + // y0 = lastCue.Value; + // x0 = lastCue.Key; + // } + // else + // { + y0 = firstCue.Value; + x0 = firstCue.Key; + y1 = lastCue.Value; + x1 = lastCue.Key; + + var y = y0 + ((x - x0)/(x1 - x0)) * (y1-y0); return y; }