Added cubic interpolation for key-frame animations 24/31224/7
authorFerran Sole <ferran.sole@samsung.com>
Tue, 2 Dec 2014 16:46:20 +0000 (16:46 +0000)
committerFerran Sole <ferran.sole@samsung.com>
Thu, 11 Dec 2014 15:23:52 +0000 (15:23 +0000)
[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

automated-tests/src/dali/utc-Dali-Animation.cpp
dali/internal/event/animation/animation-impl.cpp
dali/internal/event/animation/animation-impl.h
dali/internal/event/animation/key-frame-channel.h
dali/internal/event/animation/key-frames-impl.h
dali/internal/event/animation/progress-value.h
dali/internal/update/animation/scene-graph-animator.h
dali/public-api/animation/animation.cpp
dali/public-api/animation/animation.h

index 69b2a56..84e541c 100644 (file)
@@ -6589,6 +6589,100 @@ int UtcDaliAnimationAnimateBetweenActorColorAlpha(void)
   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)
 {
@@ -6665,7 +6759,82 @@ 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;
 
@@ -6710,6 +6879,52 @@ int UtcDaliAnimationAnimateBetweenActorVisible01(void)
   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;
@@ -6818,6 +7033,117 @@ int UtcDaliAnimationAnimateBetweenActorRotation02(void)
   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;
index dad1f27..7a04d21 100644 (file)
@@ -65,6 +65,7 @@ TypeAction action3( mType, Dali::Animation::ACTION_PAUSE, &Animation::DoAction )
 
 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
 
@@ -504,21 +505,41 @@ void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPrope
 
 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) );
 
   ExtendDuration( period );
@@ -547,7 +568,7 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       AddAnimatorConnector( AnimatorConnector<float>::New( proxy,
                                                            target.propertyIndex,
                                                            target.componentIndex,
-                                                           KeyFrameNumberFunctor(kfCopy),
+                                                           KeyFrameNumberFunctor(kfCopy,interpolation),
                                                            alpha,
                                                            period ) );
       break;
@@ -561,7 +582,7 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       AddAnimatorConnector( AnimatorConnector<int>::New( proxy,
                                                          target.propertyIndex,
                                                          target.componentIndex,
-                                                         KeyFrameIntegerFunctor(kfCopy),
+                                                         KeyFrameIntegerFunctor(kfCopy,interpolation),
                                                          alpha,
                                                          period ) );
       break;
@@ -575,7 +596,7 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       AddAnimatorConnector( AnimatorConnector<Vector2>::New( proxy,
                                                              target.propertyIndex,
                                                              target.componentIndex,
-                                                             KeyFrameVector2Functor(kfCopy),
+                                                             KeyFrameVector2Functor(kfCopy,interpolation),
                                                              alpha,
                                                              period ) );
       break;
@@ -589,7 +610,7 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       AddAnimatorConnector( AnimatorConnector<Vector3>::New( proxy,
                                                              target.propertyIndex,
                                                              target.componentIndex,
-                                                             KeyFrameVector3Functor(kfCopy),
+                                                             KeyFrameVector3Functor(kfCopy,interpolation),
                                                              alpha,
                                                              period ) );
       break;
@@ -603,7 +624,7 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       AddAnimatorConnector( AnimatorConnector<Vector4>::New( proxy,
                                                              target.propertyIndex,
                                                              target.componentIndex,
-                                                             KeyFrameVector4Functor(kfCopy),
+                                                             KeyFrameVector4Functor(kfCopy,interpolation),
                                                              alpha,
                                                              period ) );
       break;
index 7d10295..43baa8f 100644 (file)
@@ -61,6 +61,7 @@ class Animation : public BaseObject
 public:
 
   typedef Dali::Animation::EndAction EndAction;
+  typedef Dali::Animation::Interpolation Interpolation;
 
   typedef void (*FinishedCallback)(Object* object);
 
@@ -253,20 +254,40 @@ public:
   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
 
   /**
index 8c7b570..bba814f 100644 (file)
@@ -19,8 +19,9 @@
  */
 
 // 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
 {
@@ -75,7 +76,7 @@ public:
 
   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,
@@ -139,7 +140,7 @@ bool KeyFrameChannel<V>::FindInterval(
 }
 
 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();
 
@@ -155,7 +156,37 @@ V KeyFrameChannel<V>::GetValue (float progress) const
   {
     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;
index b102b88..4f55c9f 100644 (file)
@@ -232,9 +232,9 @@ public:
    * @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);
   }
 };
 
index b7fd320..30b6877 100644 (file)
@@ -86,53 +86,116 @@ typedef std::vector<ProgressVector3>                    ProgressVector3Container
 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
index 13c245f..d6ee8f1 100644 (file)
@@ -40,6 +40,8 @@ namespace Dali
 namespace Internal
 {
 
+typedef Dali::Animation::Interpolation Interpolation;
+
 namespace SceneGraph
 {
 
@@ -635,7 +637,7 @@ struct KeyFrameBooleanFunctor
   {
     if(mKeyFrames->IsActive(progress))
     {
-      return mKeyFrames->GetValue(progress);
+      return mKeyFrames->GetValue(progress, Dali::Animation::Linear);
     }
     return property;
   }
@@ -645,8 +647,8 @@ struct KeyFrameBooleanFunctor
 
 struct KeyFrameNumberFunctor
 {
-  KeyFrameNumberFunctor(KeyFrameNumberPtr keyFrames)
-  : mKeyFrames(keyFrames)
+  KeyFrameNumberFunctor(KeyFrameNumberPtr keyFrames, Interpolation interpolation)
+  : mKeyFrames(keyFrames),mInterpolation(interpolation)
   {
   }
 
@@ -654,18 +656,19 @@ struct KeyFrameNumberFunctor
   {
     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)
   {
   }
 
@@ -673,18 +676,19 @@ struct KeyFrameIntegerFunctor
   {
     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)
   {
   }
 
@@ -692,19 +696,20 @@ struct KeyFrameVector2Functor
   {
     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)
   {
   }
 
@@ -712,18 +717,19 @@ struct KeyFrameVector3Functor
   {
     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)
   {
   }
 
@@ -731,12 +737,13 @@ struct KeyFrameVector4Functor
   {
     if(mKeyFrames->IsActive(progress))
     {
-      return mKeyFrames->GetValue(progress);
+      return mKeyFrames->GetValue(progress, mInterpolation);
     }
     return property;
   }
 
   KeyFrameVector4Ptr mKeyFrames;
+  Interpolation mInterpolation;
 };
 
 struct KeyFrameQuaternionFunctor
@@ -750,7 +757,7 @@ struct KeyFrameQuaternionFunctor
   {
     if(mKeyFrames->IsActive(progress))
     {
-      return mKeyFrames->GetValue(progress);
+      return mKeyFrames->GetValue(progress, Dali::Animation::Linear);
     }
     return property;
   }
index 40c1e26..b07cb72 100644 (file)
@@ -194,9 +194,14 @@ void Animation::AnimateTo(Property target, Property::Value destinationValue, Alp
   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)
@@ -204,16 +209,33 @@ void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod
   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 )
index 51470f1..17a2789 100644 (file)
@@ -116,6 +116,15 @@ public:
     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"
 
@@ -423,7 +432,7 @@ public:
    */
   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.
@@ -434,6 +443,15 @@ public:
   /**
    * @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.
+   *
    * @param [in] target The target object/property to animate.
    * @param [in] keyFrames The key frames
    * @param [in] alpha The alpha function to apply.
@@ -443,6 +461,16 @@ public:
   /**
    * @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.
+   *
    * @param [in] target The target object/property to animate.
    * @param [in] keyFrames The key frames
    * @param [in] period The effect will occur during this time period.
@@ -452,6 +480,16 @@ public:
   /**
    * @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.
+   *
    * @param [in] target The target object/property to animate.
    * @param [in] keyFrames The key frames
    * @param [in] alpha The alpha function to apply.
@@ -459,6 +497,18 @@ public:
    */
   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
 
   /**