From 3785eabdd6fad1417602b4ad78f4f46ab6b4a985 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Mon, 21 Oct 2019 18:45:49 -0700 Subject: [PATCH 1/4] Create Calculated Animation which allows for animations that don't follow Bezier curves --- .../Animated/CalculatedAnimationDriver.cpp | 66 +++++++++++++++ .../Animated/CalculatedAnimationDriver.h | 27 ++++++ .../Modules/Animated/DecayAnimationDriver.cpp | 59 ++++--------- .../Modules/Animated/DecayAnimationDriver.h | 12 +-- .../Animated/SpringAnimationDriver.cpp | 82 ++++--------------- .../Modules/Animated/SpringAnimationDriver.h | 17 ++-- vnext/ReactUWP/ReactUWP.vcxproj | 4 +- 7 files changed, 145 insertions(+), 122 deletions(-) create mode 100644 vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp create mode 100644 vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h diff --git a/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp new file mode 100644 index 00000000000..3cb89f1cf78 --- /dev/null +++ b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" + +#include +#include "CalculatedAnimationDriver.h" + +namespace react { +namespace uwp { + +std::tuple +CalculatedAnimationDriver::MakeAnimation(const folly::dynamic &config) { + const auto [scopedBatch, animation, easingFunction] = []() { + const auto compositor = winrt::Window::Current().Compositor(); + return std::make_tuple( + compositor.CreateScopedBatch( + winrt::CompositionBatchTypes::AllAnimations), + compositor.CreateScalarKeyFrameAnimation(), + compositor.CreateLinearEasingFunction()); + }(); + + m_startValue = GetAnimatedValue()->Value(); + std::vector keyFrames = [this]() { + std::vector keyFrames; + bool done = false; + double time = 0; + while (!done) { + time += 1.0f / 60.0f; + auto [currentValue, currentVelocity] = + GetValueAndVelocityForTime(time); + keyFrames.push_back(currentValue); + if (IsAnimationDone(currentValue, currentVelocity)) { + done = true; + } + } + return keyFrames; + }(); + + std::chrono::milliseconds duration( + static_cast(keyFrames.size() / 60.0f * 1000.0f)); + animation.Duration(duration); + auto normalizedProgress = 0.0f; + // We are animating the values offset property which should start at 0. + animation.InsertKeyFrame(normalizedProgress, 0.0f, easingFunction); + for (const auto keyFrame : keyFrames) { + normalizedProgress = + std::min(normalizedProgress + 1.0f / keyFrames.size(), 1.0f); + animation.InsertKeyFrame( + normalizedProgress, + keyFrame - static_cast(m_startValue), + easingFunction); + } + + if (m_iterations == -1) { + animation.IterationBehavior(winrt::AnimationIterationBehavior::Forever); + } else { + animation.IterationCount(static_cast(m_iterations)); + animation.IterationBehavior(winrt::AnimationIterationBehavior::Count); + } + + return std::make_tuple(animation, scopedBatch); +} + +} // namespace uwp +} // namespace react diff --git a/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h new file mode 100644 index 00000000000..5dc41d9db37 --- /dev/null +++ b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +#include +#include "AnimatedNode.h" +#include "AnimationDriver.h" +#include + +namespace react { +namespace uwp { +class CalculatedAnimationDriver : public AnimationDriver { + public: + using AnimationDriver::AnimationDriver; + + std::tuple + MakeAnimation(const folly::dynamic &config) override; + + protected: + virtual std::tuple GetValueAndVelocityForTime( + double time) = 0; + + virtual bool IsAnimationDone(double currentValue, double currentVelocity) = 0; + double m_startValue{0}; +}; +} // namespace uwp +} // namespace react diff --git a/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp b/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp index 700c43c0bc5..1187d88227c 100644 --- a/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp +++ b/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp @@ -14,51 +14,30 @@ DecayAnimationDriver::DecayAnimationDriver( const Callback &endCallback, const folly::dynamic &config, const std::shared_ptr &manager) - : AnimationDriver(id, animatedValueTag, endCallback, config, manager) { + : CalculatedAnimationDriver( + id, + animatedValueTag, + endCallback, + config, + manager) { m_deceleration = config.find(s_decelerationName).dereference().second.asDouble(); assert(m_deceleration > 0); m_velocity = config.find(s_velocityName).dereference().second.asDouble(); } -std::tuple -DecayAnimationDriver::MakeAnimation(const folly::dynamic &config) { - const auto [scopedBatch, animation] = []() { - const auto compositor = winrt::Window::Current().Compositor(); - return std::make_tuple( - compositor.CreateScopedBatch( - winrt::CompositionBatchTypes::AllAnimations), - compositor.CreateScalarKeyFrameAnimation()); - }(); - - std::chrono::milliseconds duration( - static_cast(m_velocity / -m_deceleration * 1000)); - animation.Duration(duration); - - const auto compositor = winrt::Window::Current().Compositor(); - animation.SetScalarParameter( - s_velocityParameterName, static_cast(m_velocity)); - animation.SetScalarParameter( - s_decelerationParameterName, static_cast(m_deceleration)); - animation.SetScalarParameter( - s_durationName, static_cast(m_velocity / -m_deceleration) * 1000); - // Offset = (Velocity*time) + (0.5*Acceleration*Time^2) - animation.InsertExpressionKeyFrame( - 1.0f, - static_cast(L"(") + s_durationName + L" * " + - s_velocityParameterName + L") + (0.5 * " + - s_decelerationParameterName + L" * " + s_durationName + L" * " + - s_durationName + L")", - compositor.CreateCubicBezierEasingFunction({0, 1}, {0, 1})); - - if (m_iterations == -1) { - animation.IterationBehavior(winrt::AnimationIterationBehavior::Forever); - } else { - animation.IterationCount(static_cast(m_iterations)); - animation.IterationBehavior(winrt::AnimationIterationBehavior::Count); - } +std::tuple DecayAnimationDriver::GetValueAndVelocityForTime( + double time) { + const auto value = m_startValue + + m_velocity / (1 - m_deceleration) * + (1 - std::exp(-(1 - m_deceleration) * (1000*time))); + return std::make_tuple(static_cast(value), 42.0f); // we don't need the velocity +} - return std::make_tuple(animation, scopedBatch); +bool DecayAnimationDriver::IsAnimationDone( + double currentValue, + double currentVelocity) { + return (std::abs(ToValue() - currentValue) < 0.1); } double DecayAnimationDriver::ToValue() { @@ -72,9 +51,7 @@ double DecayAnimationDriver::ToValue() { return 0.0; }(); - auto const duration = m_velocity / -m_deceleration; - return startValue + m_velocity * duration + - (0.5 * -m_deceleration * duration * duration); + return m_startValue + m_velocity / (1 - m_deceleration); } } // namespace uwp diff --git a/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.h b/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.h index dea9cd6002b..82c16dcab8a 100644 --- a/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.h +++ b/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.h @@ -4,11 +4,11 @@ #pragma once #include #include "AnimatedNode.h" -#include "AnimationDriver.h" +#include "CalculatedAnimationDriver.h" namespace react { namespace uwp { -class DecayAnimationDriver : public AnimationDriver { +class DecayAnimationDriver : public CalculatedAnimationDriver { public: DecayAnimationDriver( int64_t id, @@ -17,11 +17,13 @@ class DecayAnimationDriver : public AnimationDriver { const folly::dynamic &config, const std::shared_ptr &manager); - std::tuple - MakeAnimation(const folly::dynamic &config) override; - double ToValue() override; + protected: + std::tuple GetValueAndVelocityForTime( + double time) override; + bool IsAnimationDone(double currentValue, double currentVelocity) override; + private: double m_velocity{0}; double m_deceleration{0}; diff --git a/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.cpp b/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.cpp index d446d401c16..d75ebed4b52 100644 --- a/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.cpp +++ b/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.cpp @@ -17,7 +17,7 @@ SpringAnimationDriver::SpringAnimationDriver( const std::shared_ptr &manager, const folly::dynamic &dynamicToValues) : m_dynamicToValues(dynamicToValues), - AnimationDriver(id, animatedValueTag, endCallback, config, manager) { + CalculatedAnimationDriver(id, animatedValueTag, endCallback, config, manager) { m_springStiffness = config.find(s_springStiffnessParameterName) .dereference() .second.asDouble(); @@ -45,71 +45,22 @@ SpringAnimationDriver::SpringAnimationDriver( config.find(s_iterationsParameterName).dereference().second.asDouble()); } -std::tuple -SpringAnimationDriver::MakeAnimation(const folly::dynamic &config) { - const auto [scopedBatch, animation, easingFunction] = []() { - const auto compositor = winrt::Window::Current().Compositor(); - return std::make_tuple( - compositor.CreateScopedBatch( - winrt::CompositionBatchTypes::AllAnimations), - compositor.CreateScalarKeyFrameAnimation(), - compositor.CreateLinearEasingFunction()); - }(); - - const auto startValue = GetAnimatedValue()->Value(); - std::vector keyFrames = [this, startValue]() { - std::vector keyFrames; - bool done = false; - double time = 0; - while (!done) { - time += 1.0f / 60.0f; - auto [currentValue, currentVelocity] = - GetValueAndVelocityForTime(time, startValue); - keyFrames.push_back(currentValue); - if (IsAtRest(currentVelocity, currentValue, m_endValue) || - (m_overshootClampingEnabled && - IsOvershooting(currentValue, startValue))) { - done = true; - } - } - return keyFrames; - }(); - - std::chrono::milliseconds duration( - static_cast(keyFrames.size() / 60.0f * 1000.0f)); - animation.Duration(duration); - - auto normalizedProgress = 0.0f; - // We are animating the values offset property which should start at 0. - animation.InsertKeyFrame(normalizedProgress, 0.0f, easingFunction); - for (const auto keyFrame : keyFrames) { - normalizedProgress = - std::min(normalizedProgress + 1.0f / keyFrames.size(), 1.0f); - animation.InsertKeyFrame( - normalizedProgress, - keyFrame - static_cast(startValue), - easingFunction); - } - - if (m_iterations == -1) { - animation.IterationBehavior(winrt::AnimationIterationBehavior::Forever); - } else { - animation.IterationCount(static_cast(m_iterations)); - animation.IterationBehavior(winrt::AnimationIterationBehavior::Count); - } - - return std::make_tuple(animation, scopedBatch); +bool SpringAnimationDriver::IsAnimationDone( + double currentValue, + double currentVelocity) { + return ( + IsAtRest(currentVelocity, currentValue, m_endValue) || + (m_overshootClampingEnabled && IsOvershooting(currentValue))); } std::tuple SpringAnimationDriver::GetValueAndVelocityForTime( - double time, - double startValue) { - const auto toValue = [this, time, startValue]() { + double time) { + const auto toValue = [this, time]() { const auto frameFromTime = static_cast(time * 60.0); if (frameFromTime < static_cast(m_dynamicToValues.size())) { - return startValue + + return m_startValue + (m_dynamicToValues[frameFromTime].asDouble() * - (m_endValue - startValue)); + (m_endValue - m_startValue)); } return m_endValue; }(); @@ -121,7 +72,7 @@ std::tuple SpringAnimationDriver::GetValueAndVelocityForTime( const auto zeta = c / (2 * std::sqrt(k * m)); const auto omega0 = std::sqrt(k / m); const auto omega1 = omega0 * std::sqrt(1.0 - (zeta * zeta)); - const auto x0 = toValue - startValue; + const auto x0 = toValue - m_startValue; if (zeta < 1) { const auto envelope = std::exp(-zeta * omega0 * time); @@ -140,7 +91,7 @@ std::tuple SpringAnimationDriver::GetValueAndVelocityForTime( } else { const auto envelope = std::exp(-omega0 * time); const auto value = static_cast( - toValue * (v0 * (time * omega0 - 1) + time * x0 * (omega0 * omega0))); + m_endValue - envelope * (x0 + (v0 + omega0 * x0) * time)); const auto velocity = envelope * (v0 * (time * omega0 - 1) + time * x0 * (omega0 * omega0)); return std::make_tuple(value, velocity); @@ -157,11 +108,10 @@ bool SpringAnimationDriver::IsAtRest( } bool SpringAnimationDriver::IsOvershooting( - double currentValue, - double startValue) { + double currentValue) { return m_springStiffness > 0 && - ((startValue < m_endValue && currentValue > m_endValue) || - (startValue > m_endValue && currentValue < m_endValue)); + ((m_startValue < m_endValue && currentValue > m_endValue) || + (m_startValue > m_endValue && currentValue < m_endValue)); } double SpringAnimationDriver::ToValue() { diff --git a/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.h b/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.h index dc07515a690..7cbd88d0968 100644 --- a/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.h +++ b/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.h @@ -5,11 +5,11 @@ #pragma once #include #include "AnimatedNode.h" -#include "AnimationDriver.h" +#include "CalculatedAnimationDriver.h" namespace react { namespace uwp { -class SpringAnimationDriver : public AnimationDriver { +class SpringAnimationDriver : public CalculatedAnimationDriver { public: SpringAnimationDriver( int64_t id, @@ -19,18 +19,17 @@ class SpringAnimationDriver : public AnimationDriver { const std::shared_ptr &manager, const folly::dynamic &dynamicToValues = folly::dynamic::array()); - std::tuple - MakeAnimation(const folly::dynamic &config) override; - double ToValue() override; - private: + protected: std::tuple GetValueAndVelocityForTime( - double time, - double startValue); + double time) override; + bool IsAnimationDone(double currentValue, double currentVelocity) override; + + private: bool IsAtRest(double currentVelocity, double currentPosition, double endValue); - bool IsOvershooting(double currentValue, double startValue); + bool IsOvershooting(double currentValue); double m_springStiffness{0}; double m_springDamping{0}; diff --git a/vnext/ReactUWP/ReactUWP.vcxproj b/vnext/ReactUWP/ReactUWP.vcxproj index 9df13685d41..5bfbd4d2a76 100644 --- a/vnext/ReactUWP/ReactUWP.vcxproj +++ b/vnext/ReactUWP/ReactUWP.vcxproj @@ -164,6 +164,7 @@ + @@ -271,6 +272,7 @@ + @@ -405,7 +407,7 @@ {a62d504a-16b8-41d2-9f19-e2e86019e5e4} - + {17DD1B17-3094-40DD-9373-AC2497932ECA} From f479c072e7efa1fea771a59a05b88698b175f707 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Mon, 21 Oct 2019 18:46:29 -0700 Subject: [PATCH 2/4] Change files --- ...-windows-2019-10-21-18-46-29-calculatedanimation.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 change/react-native-windows-2019-10-21-18-46-29-calculatedanimation.json diff --git a/change/react-native-windows-2019-10-21-18-46-29-calculatedanimation.json b/change/react-native-windows-2019-10-21-18-46-29-calculatedanimation.json new file mode 100644 index 00000000000..1c6d1d86b0a --- /dev/null +++ b/change/react-native-windows-2019-10-21-18-46-29-calculatedanimation.json @@ -0,0 +1,9 @@ +{ + "type": "none", + "comment": "Create Calculated Animation which allows for animations that don't follow Bezier curves", + "packageName": "react-native-windows", + "email": "asklar@winse.microsoft.com", + "commit": "3785eabdd6fad1417602b4ad78f4f46ab6b4a985", + "date": "2019-10-22T01:46:28.972Z", + "file": "F:\\rnw\\change\\react-native-windows-2019-10-21-18-46-29-calculatedanimation.json" +} \ No newline at end of file From 176ac0fbd0fdb8ea4159ced714ade9c3e5d5b06a Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Mon, 21 Oct 2019 23:26:03 -0700 Subject: [PATCH 3/4] clang format --- .../Modules/Animated/CalculatedAnimationDriver.cpp | 3 +-- .../Modules/Animated/CalculatedAnimationDriver.h | 7 +++---- .../ReactUWP/Modules/Animated/DecayAnimationDriver.cpp | 5 +++-- vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.h | 3 +-- .../Modules/Animated/SpringAnimationDriver.cpp | 10 +++++++--- .../ReactUWP/Modules/Animated/SpringAnimationDriver.h | 3 +-- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp index 3cb89f1cf78..8dfc3d954eb 100644 --- a/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp +++ b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.cpp @@ -27,8 +27,7 @@ CalculatedAnimationDriver::MakeAnimation(const folly::dynamic &config) { double time = 0; while (!done) { time += 1.0f / 60.0f; - auto [currentValue, currentVelocity] = - GetValueAndVelocityForTime(time); + auto [currentValue, currentVelocity] = GetValueAndVelocityForTime(time); keyFrames.push_back(currentValue); if (IsAnimationDone(currentValue, currentVelocity)) { done = true; diff --git a/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h index 5dc41d9db37..7d7dcbeeb61 100644 --- a/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h +++ b/vnext/ReactUWP/Modules/Animated/CalculatedAnimationDriver.h @@ -3,22 +3,21 @@ #pragma once #include +#include #include "AnimatedNode.h" #include "AnimationDriver.h" -#include namespace react { namespace uwp { class CalculatedAnimationDriver : public AnimationDriver { public: - using AnimationDriver::AnimationDriver; + using AnimationDriver::AnimationDriver; std::tuple MakeAnimation(const folly::dynamic &config) override; protected: - virtual std::tuple GetValueAndVelocityForTime( - double time) = 0; + virtual std::tuple GetValueAndVelocityForTime(double time) = 0; virtual bool IsAnimationDone(double currentValue, double currentVelocity) = 0; double m_startValue{0}; diff --git a/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp b/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp index 1187d88227c..365fc6fa325 100644 --- a/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp +++ b/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp @@ -30,8 +30,9 @@ std::tuple DecayAnimationDriver::GetValueAndVelocityForTime( double time) { const auto value = m_startValue + m_velocity / (1 - m_deceleration) * - (1 - std::exp(-(1 - m_deceleration) * (1000*time))); - return std::make_tuple(static_cast(value), 42.0f); // we don't need the velocity + (1 - std::exp(-(1 - m_deceleration) * (1000 * time))); + return std::make_tuple( + static_cast(value), 42.0f); // we don't need the velocity } bool DecayAnimationDriver::IsAnimationDone( diff --git a/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.h b/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.h index 82c16dcab8a..f2a5d5ab75b 100644 --- a/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.h +++ b/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.h @@ -20,8 +20,7 @@ class DecayAnimationDriver : public CalculatedAnimationDriver { double ToValue() override; protected: - std::tuple GetValueAndVelocityForTime( - double time) override; + std::tuple GetValueAndVelocityForTime(double time) override; bool IsAnimationDone(double currentValue, double currentVelocity) override; private: diff --git a/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.cpp b/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.cpp index d75ebed4b52..d729105de5e 100644 --- a/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.cpp +++ b/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.cpp @@ -17,7 +17,12 @@ SpringAnimationDriver::SpringAnimationDriver( const std::shared_ptr &manager, const folly::dynamic &dynamicToValues) : m_dynamicToValues(dynamicToValues), - CalculatedAnimationDriver(id, animatedValueTag, endCallback, config, manager) { + CalculatedAnimationDriver( + id, + animatedValueTag, + endCallback, + config, + manager) { m_springStiffness = config.find(s_springStiffnessParameterName) .dereference() .second.asDouble(); @@ -107,8 +112,7 @@ bool SpringAnimationDriver::IsAtRest( m_springStiffness == 0); } -bool SpringAnimationDriver::IsOvershooting( - double currentValue) { +bool SpringAnimationDriver::IsOvershooting(double currentValue) { return m_springStiffness > 0 && ((m_startValue < m_endValue && currentValue > m_endValue) || (m_startValue > m_endValue && currentValue < m_endValue)); diff --git a/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.h b/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.h index 7cbd88d0968..09d53853616 100644 --- a/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.h +++ b/vnext/ReactUWP/Modules/Animated/SpringAnimationDriver.h @@ -22,8 +22,7 @@ class SpringAnimationDriver : public CalculatedAnimationDriver { double ToValue() override; protected: - std::tuple GetValueAndVelocityForTime( - double time) override; + std::tuple GetValueAndVelocityForTime(double time) override; bool IsAnimationDone(double currentValue, double currentVelocity) override; private: From 4755d0a5f2b0a526fc0458ea3391f4849eac9b8e Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Tue, 22 Oct 2019 11:42:28 -0700 Subject: [PATCH 4/4] edit comment --- vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp b/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp index 365fc6fa325..3bf82d9852e 100644 --- a/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp +++ b/vnext/ReactUWP/Modules/Animated/DecayAnimationDriver.cpp @@ -32,7 +32,8 @@ std::tuple DecayAnimationDriver::GetValueAndVelocityForTime( m_velocity / (1 - m_deceleration) * (1 - std::exp(-(1 - m_deceleration) * (1000 * time))); return std::make_tuple( - static_cast(value), 42.0f); // we don't need the velocity + static_cast(value), + 42.0f); // we don't need the velocity, so set it to a dummy value } bool DecayAnimationDriver::IsAnimationDone(