[Problem] Key-frame animations only supports linear interpolation between key values
[Cause] n/a
[Solution] Allow the user to specify which interpolation method to use [Linear,Cubic]
Added unit tests for cubic interpolation
Change-Id: I152fbd2211d4b7fa52fd44f315c05869cccdd684
END_TEST;
}
+int UtcDaliAnimationAnimateBetweenActorColorAlphaCubic(void)
+{
+ TestApplication application;
+
+ float startValue(1.0f);
+ Actor actor = Actor::New();
+ actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+ Stage::GetCurrent().Add(actor);
+
+ DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+
+ KeyFrames keyFrames = KeyFrames::New();
+ keyFrames.Add(0.0f, 0.1f);
+ keyFrames.Add(0.2f, 0.5f);
+ keyFrames.Add(0.4f, 0.0f);
+ keyFrames.Add(0.6f, 1.0f);
+ keyFrames.Add(0.8f, 0.7f);
+ keyFrames.Add(1.0f, 0.9f);
+
+ animation.AnimateBetween( Property(actor, Actor::COLOR_ALPHA), keyFrames, Animation::Cubic );
+
+ // Start the animation
+ animation.Play();
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+ DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.1f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 10% progress */);
+ application.SendNotification();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 0.36f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.36f, 0.01f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 30% progress */);
+ application.SendNotification();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 0.21f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.21f, 0.01f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 40% progress */);
+ application.SendNotification();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 0.0f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.0f, 0.01f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*400.0f)/* 80% progress */);
+ application.SendNotification();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 0.7f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.7f, 0.01f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 90% progress */);
+ application.SendNotification();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 0.76f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.76f, 0.01f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*100.0f)+1/* 100% progress */);
+ application.SendNotification();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 0.9f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.9f, 0.01f, TEST_LOCATION );
+
+ // We did expect the animation to finish
+
+ finishCheck.CheckSignalReceived();
+ END_TEST;
+}
int UtcDaliAnimationAnimateBetweenActorColor(void)
{
END_TEST;
}
-int UtcDaliAnimationAnimateBetweenActorVisible01(void)
+int UtcDaliAnimationAnimateBetweenActorColorCubic(void)
+{
+ TestApplication application;
+
+ float startValue(1.0f);
+ Actor actor = Actor::New();
+ actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+ Stage::GetCurrent().Add(actor);
+
+ DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), startValue, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+
+ KeyFrames keyFrames = KeyFrames::New();
+ keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f));
+ keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f));
+ keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
+
+ animation.AnimateBetween( Property(actor, Actor::COLOR), keyFrames, Animation::Cubic );
+
+ // Start the animation
+ animation.Play();
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), 0.1f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), 0.3f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+ application.SendNotification();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), 0.55f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), 0.525f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), 0.506f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 0.4875f, 0.01f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+ application.SendNotification();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), 0.9f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), 0.7f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+ application.SendNotification();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), 0.99375f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), 0.925f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), 0.85625f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 0.7875f, 0.01f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+ application.SendNotification();
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_RED), 1.0f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_BLUE), 1.0f, 0.01f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION );
+
+ // We did expect the animation to finish
+
+ finishCheck.CheckSignalReceived();
+ END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorVisible(void)
{
TestApplication application;
END_TEST;
}
+int UtcDaliAnimationAnimateBetweenActorVisibleCubic(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ AngleAxis aa(Degree(90), Vector3::XAXIS);
+ actor.SetRotation(aa.angle, aa.axis);
+ Stage::GetCurrent().Add(actor);
+
+ application.SendNotification();
+ application.Render(0);
+
+ DALI_TEST_EQUALS( actor.IsVisible(), true, TEST_LOCATION );
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+
+ KeyFrames keyFrames = KeyFrames::New();
+ keyFrames.Add(0.0f, false);
+ keyFrames.Add(0.2f, true);
+ keyFrames.Add(0.4f, true);
+ keyFrames.Add(0.8f, false);
+ keyFrames.Add(1.0f, true);
+
+ //Cubic interpolation for boolean values should be ignored
+ animation.AnimateBetween( Property(actor, Actor::VISIBLE), keyFrames, Animation::Cubic );
+
+ // Start the animation
+ animation.Play();
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+ application.SendNotification();
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*500.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*500.0f)+1);
+ application.SendNotification();
+
+ DALI_TEST_EQUALS( actor.IsVisible(), true, TEST_LOCATION);
+ finishCheck.CheckSignalReceived();
+ END_TEST;
+}
+
int UtcDaliAnimationAnimateBetweenActorRotation01(void)
{
TestApplication application;
END_TEST;
}
+int UtcDaliAnimationAnimateBetweenActorRotation01Cubic(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ AngleAxis aa(Degree(90), Vector3::XAXIS);
+ actor.SetRotation(aa.angle, aa.axis);
+ Stage::GetCurrent().Add(actor);
+
+ application.SendNotification();
+ application.Render(0);
+ Quaternion start(Radian(aa.angle), aa.axis);
+ DALI_TEST_EQUALS( actor.GetCurrentRotation(), start, 0.001f, TEST_LOCATION );
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+
+ KeyFrames keyFrames = KeyFrames::New();
+ keyFrames.Add(0.0f, AngleAxis(Degree(60), Vector3::ZAXIS));
+
+ //Cubic interpolation should be ignored for quaternions
+ animation.AnimateBetween( Property(actor, Actor::ROTATION), keyFrames, Animation::Cubic );
+
+ // Start the animation
+ animation.Play();
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+ application.SendNotification();
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*500.0f));
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*500.0f)+1);
+ application.SendNotification();
+
+ Quaternion check = Quaternion::FromAxisAngle(Vector4::ZAXIS, Radian(Degree(60)));
+
+ DALI_TEST_EQUALS( actor.GetCurrentRotation(), check, 0.001f, TEST_LOCATION );
+ finishCheck.CheckSignalReceived();
+ END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorRotation02Cubic(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ AngleAxis aa(Degree(90), Vector3::XAXIS);
+ actor.SetRotation(aa.angle, aa.axis);
+ application.SendNotification();
+ application.Render(0);
+ Stage::GetCurrent().Add(actor);
+
+ Quaternion start(Radian(aa.angle), aa.axis);
+ DALI_TEST_EQUALS( actor.GetCurrentRotation(), start, 0.001f, TEST_LOCATION );
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+
+ KeyFrames keyFrames = KeyFrames::New();
+ keyFrames.Add(0.0f, AngleAxis(Degree(60), Vector3::XAXIS));
+ keyFrames.Add(0.5f, AngleAxis(Degree(120), Vector3::XAXIS));
+ keyFrames.Add(1.0f, AngleAxis(Degree(120), Vector3::YAXIS));
+
+ //Cubic interpolation should be ignored for quaternions
+ animation.AnimateBetween( Property(actor, Actor::ROTATION), keyFrames, Animation::Cubic );
+
+ // Start the animation
+ animation.Play();
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ Quaternion check(Radian(Degree(60)), Vector3::XAXIS);
+ DALI_TEST_EQUALS( actor.GetCurrentRotation(), check, 0.001f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+ application.SendNotification();
+ check = Quaternion::FromAxisAngle(Vector4::XAXIS, Radian(Degree(90)));
+ DALI_TEST_EQUALS( actor.GetCurrentRotation(), check, 0.001f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+ application.SendNotification();
+ check = Quaternion::FromAxisAngle(Vector4::XAXIS, Radian(Degree(120)));
+ DALI_TEST_EQUALS( actor.GetCurrentRotation(), check, 0.001f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+ application.SendNotification();
+ check = Quaternion::FromAxisAngle(Vector4(0.5f, 0.5f, 0.0f, 0.0f), Radian(Degree(101.5)));
+ DALI_TEST_EQUALS( actor.GetCurrentRotation(), check, 0.001f, TEST_LOCATION );
+
+ application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+ application.SendNotification();
+ check = Quaternion::FromAxisAngle(Vector4::YAXIS, Radian(Degree(120)));
+ DALI_TEST_EQUALS( actor.GetCurrentRotation(), check, 0.001f, TEST_LOCATION );
+
+ // We did expect the animation to finish
+
+ finishCheck.CheckSignalReceived();
+ END_TEST;
+}
+
+
int UtcDaliAnimationMoveByFloat3(void)
{
TestApplication application;
const Dali::Animation::EndAction DEFAULT_END_ACTION( Dali::Animation::Bake );
const Dali::Animation::EndAction DEFAULT_DISCONNECT_ACTION( Dali::Animation::BakeFinal );
+const Dali::Animation::Interpolation DEFAULT_INTERPOLATION( Dali::Animation::Linear );
} // anon namespace
void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames)
{
- AnimateBetween(target, keyFrames, mDefaultAlpha, mDurationSeconds);
+ AnimateBetween(target, keyFrames, mDefaultAlpha, mDurationSeconds, DEFAULT_INTERPOLATION );
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation )
+{
+ AnimateBetween(target, keyFrames, mDefaultAlpha, mDurationSeconds, interpolation );
}
void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period)
{
- AnimateBetween(target, keyFrames, mDefaultAlpha, period);
+ AnimateBetween(target, keyFrames, mDefaultAlpha, period, DEFAULT_INTERPOLATION);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
+{
+ AnimateBetween(target, keyFrames, mDefaultAlpha, period, interpolation);
}
void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha)
{
- AnimateBetween(target, keyFrames, alpha, mDurationSeconds);
+ AnimateBetween(target, keyFrames, alpha, mDurationSeconds, DEFAULT_INTERPOLATION);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
+{
+ AnimateBetween(target, keyFrames, alpha, mDurationSeconds, interpolation);
}
void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
+{
+ AnimateBetween(target, keyFrames, alpha, period, DEFAULT_INTERPOLATION);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation)
{
ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
AddAnimatorConnector( AnimatorConnector<float>::New( proxy,
target.propertyIndex,
target.componentIndex,
- KeyFrameNumberFunctor(kfCopy),
+ KeyFrameNumberFunctor(kfCopy,interpolation),
alpha,
period ) );
break;
AddAnimatorConnector( AnimatorConnector<int>::New( proxy,
target.propertyIndex,
target.componentIndex,
- KeyFrameIntegerFunctor(kfCopy),
+ KeyFrameIntegerFunctor(kfCopy,interpolation),
alpha,
period ) );
break;
AddAnimatorConnector( AnimatorConnector<Vector2>::New( proxy,
target.propertyIndex,
target.componentIndex,
- KeyFrameVector2Functor(kfCopy),
+ KeyFrameVector2Functor(kfCopy,interpolation),
alpha,
period ) );
break;
AddAnimatorConnector( AnimatorConnector<Vector3>::New( proxy,
target.propertyIndex,
target.componentIndex,
- KeyFrameVector3Functor(kfCopy),
+ KeyFrameVector3Functor(kfCopy,interpolation),
alpha,
period ) );
break;
AddAnimatorConnector( AnimatorConnector<Vector4>::New( proxy,
target.propertyIndex,
target.componentIndex,
- KeyFrameVector4Functor(kfCopy),
+ KeyFrameVector4Functor(kfCopy,interpolation),
alpha,
period ) );
break;
public:
typedef Dali::Animation::EndAction EndAction;
+ typedef Dali::Animation::Interpolation Interpolation;
typedef void (*FinishedCallback)(Object* object);
*/
void AnimateBetween(Property target, const KeyFrames& keyFrames);
+ /**
+ * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, Interpolation interpolation)
+ */
+ void AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation );
+
/**
* @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period)
*/
void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period);
+ /**
+ * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
+ */
+ void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation);
+
/**
* @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha)
*/
void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha);
+ /**
+ * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
+ */
+ void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation);
+
/**
* @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
*/
void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period);
+ /**
+ * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation )
+ */
+ void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation );
+
// Actor-specific convenience functions
/**
*/
// INTERNAL INCLUDES
-#include <dali/public-api/common/vector-wrapper.h>
#include <dali/internal/event/animation/progress-value.h>
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/common/vector-wrapper.h>
namespace Dali
{
bool IsActive (float progress);
- V GetValue(float progress) const;
+ V GetValue(float progress, Dali::Animation::Interpolation interpolation) const;
bool FindInterval(typename ProgressValues::iterator& start,
typename ProgressValues::iterator& end,
}
template <class V>
-V KeyFrameChannel<V>::GetValue (float progress) const
+V KeyFrameChannel<V>::GetValue (float progress, Dali::Animation::Interpolation interpolation) const
{
ProgressValue<V>& firstPV = mValues.front();
{
float frameProgress = (progress - start->GetProgress()) / (end->GetProgress() - start->GetProgress());
- interpolatedV = Interpolate(*start, *end, frameProgress);
+ if( interpolation == Dali::Animation::Linear )
+ {
+ Interpolate(interpolatedV, start->GetValue(), end->GetValue(), frameProgress);
+ }
+ else
+ {
+ //Calculate prev and next values
+ V prev;
+ if( start != mValues.begin() )
+ {
+ prev = (start-1)->GetValue();
+ }
+ else
+ {
+ //Project next value through start point
+ prev = start->GetValue() + (start->GetValue()-(start+1)->GetValue());
+ }
+
+ V next;
+ if( end != mValues.end()-1)
+ {
+ next = (end+1)->GetValue();
+ }
+ else
+ {
+ //Project prev value through end point
+ next = end->GetValue() + (end->GetValue()-(end-1)->GetValue());
+ }
+
+ CubicInterpolate(interpolatedV, prev, start->GetValue(), end->GetValue(), next, frameProgress);
+ }
}
return interpolatedV;
* @param[in] progress The progress to test
* @return The interpolated value
*/
- V GetValue(float progress) const
+ V GetValue(float progress, Dali::Animation::Interpolation interpolation) const
{
- return mKeyFrames->GetValue(progress);
+ return mKeyFrames->GetValue(progress, interpolation);
}
};
typedef ProgressValue<Vector4> ProgressVector4;
typedef std::vector<ProgressVector4> ProgressVector4Container;
-inline Quaternion Interpolate (ProgressQuaternion& a, ProgressQuaternion& b, float progress)
+inline void Interpolate (Quaternion& result, const Quaternion& a, const Quaternion& b, float progress)
{
- return Quaternion::Slerp(a.GetValue(), b.GetValue(), progress);
+ result = Quaternion::Slerp(a, b, progress);
}
-inline AngleAxis Interpolate (ProgressAngleAxis& a, ProgressAngleAxis& b, float progress)
+inline void Interpolate (AngleAxis& result, const AngleAxis& a, const AngleAxis& b, float progress)
{
- AngleAxis av(a.GetValue());
- AngleAxis bv(b.GetValue());
- Quaternion q1(Radian(av.angle), av.axis);
- Quaternion q2(Radian(bv.angle), bv.axis);
+ Quaternion q1(Radian(a.angle), a.axis);
+ Quaternion q2(Radian(b.angle), b.axis);
Quaternion iq = Quaternion::Slerp(q1, q2, progress);
- AngleAxis result;
iq.ToAxisAngle(result.axis, result.angle);
- return result;
}
-inline bool Interpolate (ProgressBoolean& a, ProgressBoolean& b, float progress)
+inline void Interpolate (bool& result, bool a, bool b, float progress)
{
- return progress < 0.5f ? a.GetValue() : b.GetValue();
+ result = progress < 0.5f ? a : b;
}
-inline float Interpolate (ProgressNumber& a, ProgressNumber& b, float progress)
+inline void Interpolate (float& result, float a, float b, float progress)
{
- return (a.GetValue() + (b.GetValue() - a.GetValue()) * progress);
+ result = a + (b-a) * progress;
}
-inline int Interpolate (ProgressInteger& a, ProgressInteger& b, float progress)
+inline void Interpolate (int& result, int a, int b, float progress)
{
- return static_cast<int>(a.GetValue() + (b.GetValue() - a.GetValue()) * progress + 0.5f);
+ result = static_cast<int>(a + (b - a) * progress + 0.5f);
}
-inline Vector2 Interpolate (ProgressVector2& a, ProgressVector2& b, float progress)
+inline void Interpolate (Vector2& result, const Vector2& a, const Vector2& b, float progress)
{
- return (a.GetValue() + (b.GetValue() - a.GetValue()) * progress);
+ result = a + (b-a) * progress;
}
-inline Vector3 Interpolate (ProgressVector3& a, ProgressVector3& b, float progress)
+inline void Interpolate (Vector3& result, const Vector3& a, const Vector3& b, float progress)
{
- return (a.GetValue() + (b.GetValue() - a.GetValue()) * progress);
+ result = a + (b-a) * progress;
}
-inline Vector4 Interpolate (ProgressVector4& a, ProgressVector4& b, float progress)
+inline void Interpolate (Vector4& result, const Vector4& a, const Vector4& b, float progress)
{
- return (a.GetValue() + (b.GetValue() - a.GetValue()) * progress);
+ result = a + (b-a) * progress;
+}
+
+/* Cubic Interpolation (Catmull-Rom spline) between values p1 and p2. p0 and p3 are prev and next values
+ * and are used as control points to calculate tangent of the curve at interpolation points.
+ *
+ * f(t) = a3*t^3 + a2*t^2 + a1*t + a0
+ * Restrictions: f(0)=p1 f(1)=p2 f'(0)=(p2-p0)*0.5 f'(1)=(p3-p1)*0.5
+ */
+
+inline void CubicInterpolate( int& result, int p0, int p1, int p2, int p3, float progress )
+{
+ float a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+ float a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+ float a1 = (p2-p0)*0.5f;
+
+ result = static_cast<int>( a3*progress*progress*progress + a2*progress*progress + a1*progress + p1 + 0.5f );
+}
+
+inline void CubicInterpolate( float& result, float p0, float p1, float p2, float p3, float progress )
+{
+ float a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+ float a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+ float a1 = (p2-p0)*0.5f;
+
+ result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1;
+}
+
+inline void CubicInterpolate( Vector2& result, const Vector2& p0, const Vector2& p1, const Vector2& p2, const Vector2& p3, float progress )
+{
+ Vector2 a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+ Vector2 a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+ Vector2 a1 = (p2-p0)*0.5f;
+
+ result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1;
+}
+
+inline void CubicInterpolate( Vector3& result, const Vector3& p0, const Vector3& p1, const Vector3& p2, const Vector3& p3, float progress )
+{
+ Vector3 a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+ Vector3 a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+ Vector3 a1 = (p2-p0)*0.5f;
+
+ result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1;
+}
+
+inline void CubicInterpolate( Vector4& result, const Vector4& p0, const Vector4& p1, const Vector4& p2, const Vector4& p3, float progress )
+{
+ Vector4 a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+ Vector4 a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+ Vector4 a1 = (p2-p0)*0.5f;
+
+ result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1;
+}
+
+inline void CubicInterpolate( bool& result, bool p0, bool p1, bool p2, bool p3, float progress )
+{
+ Interpolate( result, p1, p2, progress);
+}
+
+inline void CubicInterpolate( Quaternion& result, const Quaternion& p0, const Quaternion& p1, const Quaternion& p2, const Quaternion& p3, float progress )
+{
+ Interpolate( result, p1, p2, progress);
+}
+
+inline void CubicInterpolate( AngleAxis& result, const AngleAxis& p0, const AngleAxis& p1, const AngleAxis& p2, const AngleAxis& p3, float progress )
+{
+ Interpolate( result, p1, p2, progress);
}
} // namespace Internal
namespace Internal
{
+typedef Dali::Animation::Interpolation Interpolation;
+
namespace SceneGraph
{
{
if(mKeyFrames->IsActive(progress))
{
- return mKeyFrames->GetValue(progress);
+ return mKeyFrames->GetValue(progress, Dali::Animation::Linear);
}
return property;
}
struct KeyFrameNumberFunctor
{
- KeyFrameNumberFunctor(KeyFrameNumberPtr keyFrames)
- : mKeyFrames(keyFrames)
+ KeyFrameNumberFunctor(KeyFrameNumberPtr keyFrames, Interpolation interpolation)
+ : mKeyFrames(keyFrames),mInterpolation(interpolation)
{
}
{
if(mKeyFrames->IsActive(progress))
{
- return mKeyFrames->GetValue(progress);
+ return mKeyFrames->GetValue(progress, mInterpolation);
}
return property;
}
KeyFrameNumberPtr mKeyFrames;
+ Interpolation mInterpolation;
};
struct KeyFrameIntegerFunctor
{
- KeyFrameIntegerFunctor(KeyFrameIntegerPtr keyFrames)
- : mKeyFrames(keyFrames)
+ KeyFrameIntegerFunctor(KeyFrameIntegerPtr keyFrames, Interpolation interpolation)
+ : mKeyFrames(keyFrames),mInterpolation(interpolation)
{
}
{
if(mKeyFrames->IsActive(progress))
{
- return mKeyFrames->GetValue(progress);
+ return mKeyFrames->GetValue(progress, mInterpolation);
}
return property;
}
KeyFrameIntegerPtr mKeyFrames;
+ Interpolation mInterpolation;
};
struct KeyFrameVector2Functor
{
- KeyFrameVector2Functor(KeyFrameVector2Ptr keyFrames)
- : mKeyFrames(keyFrames)
+ KeyFrameVector2Functor(KeyFrameVector2Ptr keyFrames, Interpolation interpolation)
+ : mKeyFrames(keyFrames),mInterpolation(interpolation)
{
}
{
if(mKeyFrames->IsActive(progress))
{
- return mKeyFrames->GetValue(progress);
+ return mKeyFrames->GetValue(progress, mInterpolation);
}
return property;
}
KeyFrameVector2Ptr mKeyFrames;
+ Interpolation mInterpolation;
};
struct KeyFrameVector3Functor
{
- KeyFrameVector3Functor(KeyFrameVector3Ptr keyFrames)
- : mKeyFrames(keyFrames)
+ KeyFrameVector3Functor(KeyFrameVector3Ptr keyFrames, Interpolation interpolation)
+ : mKeyFrames(keyFrames),mInterpolation(interpolation)
{
}
{
if(mKeyFrames->IsActive(progress))
{
- return mKeyFrames->GetValue(progress);
+ return mKeyFrames->GetValue(progress, mInterpolation);
}
return property;
}
KeyFrameVector3Ptr mKeyFrames;
+ Interpolation mInterpolation;
};
struct KeyFrameVector4Functor
{
- KeyFrameVector4Functor(KeyFrameVector4Ptr keyFrames)
- : mKeyFrames(keyFrames)
+ KeyFrameVector4Functor(KeyFrameVector4Ptr keyFrames, Interpolation interpolation)
+ : mKeyFrames(keyFrames),mInterpolation(interpolation)
{
}
{
if(mKeyFrames->IsActive(progress))
{
- return mKeyFrames->GetValue(progress);
+ return mKeyFrames->GetValue(progress, mInterpolation);
}
return property;
}
KeyFrameVector4Ptr mKeyFrames;
+ Interpolation mInterpolation;
};
struct KeyFrameQuaternionFunctor
{
if(mKeyFrames->IsActive(progress))
{
- return mKeyFrames->GetValue(progress);
+ return mKeyFrames->GetValue(progress, Dali::Animation::Linear);
}
return property;
}
GetImplementation(*this).AnimateTo(target, destinationValue, alpha, period);
}
-void Animation::AnimateBetween(Property target, KeyFrames& keyFrames)
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames )
{
- GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames));
+ GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames) );
+}
+
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, Interpolation interpolation)
+{
+ GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), interpolation );
}
void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period)
GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), period);
}
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
+{
+ GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), period, interpolation );
+}
+
void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha)
{
GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), alpha);
}
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
+{
+ GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), alpha, interpolation);
+}
+
+
void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
{
GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), alpha, period);
}
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation)
+{
+ GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), alpha, period, interpolation);
+}
+
+
// Actor specific animations
void Animation::Animate( Actor actor, Path path, const Vector3& forward )
BakeFinal ///< If the animation is stopped, the animated property values are saved as if the animation had run to completion, otherwise behaves like Bake.
};
+ /**
+ * @brief What interpolation method to use on key-frame animations
+ */
+ enum Interpolation
+ {
+ Linear, ///< Values in between key frames are interpolated using a linear polynomial. (Default)
+ Cubic ///< Values in between key frames are interpolated using a cubic polynomial.
+ };
+
//Signal Names
static const char* const SIGNAL_FINISHED; ///< name "finished"
*/
void AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period);
- /**
+ /**
* @brief Animate a property between keyframes.
*
* @param [in] target The target object/property to animate.
*/
void AnimateBetween(Property target, KeyFrames& keyFrames);
+ /**
+ * @brief Animate a property between keyframes.
+ *
+ * @param [in] target The target object + property to animate
+ * @param [in] keyFrames The set of time / value pairs between which to animate.
+ * @param [in] interpolation The method used to interpolate between values.
+ */
+ void AnimateBetween(Property target, KeyFrames& keyFrames, Interpolation interpolation);
+
/**
* @brief Animate a property between keyframes.
*
*/
void AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha);
+ /**
+ * @brief Animate a property between keyframes.
+ *
+ * @param [in] target The target object + property to animate
+ * @param [in] keyFrames The set of time / value pairs between which to animate.
+ * @param [in] alpha The alpha function to apply.
+ * @param [in] interpolation The method used to interpolate between values.
+ */
+ void AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation);
+
/**
* @brief Animate a property between keyframes.
*
*/
void AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period);
+ /**
+ * @brief Animate a property between keyframes.
+ *
+ * @param [in] target The target object + property to animate
+ * @param [in] keyFrames The set of time / value pairs between which to animate.
+ * @param [in] period The effect will occur duing this time period.
+ * @param [in] interpolation The method used to interpolate between values.
+ */
+ void AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation);
+
/**
* @brief Animate a property between keyframes.
*
*/
void AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period);
+ /**
+ * @brief Animate a property between keyframes.
+ *
+ * @param [in] target The target object + property to animate
+ * @param [in] keyFrames The set of time / value pairs between which to animate.
+ * @param [in] alpha The alpha function to apply to the overall progress.
+ * @param [in] period The effect will occur duing this time period.
+ * @param [in] interpolation The method used to interpolate between values.
+ */
+ void AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation);
+
+
// Actor-specific convenience methods
/**