Added funcionality to play animations from an specified initial progress 94/24094/1
authorFerran Sole <ferran.sole@samsung.com>
Fri, 20 Jun 2014 08:47:07 +0000 (09:47 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Tue, 8 Jul 2014 13:19:39 +0000 (14:19 +0100)
[problem]     Lack of functionality to play an animation from an specified
              initial progress
[cause]       N/A
[solution]    Added new API to retrieve the current progress and to play
              animations from an specified initial cursor

Change-Id: I2777961e0ae6a9b18ddb16e62920c68cb3eb39a3
Signed-off-by: Adeel Kazmi <adeel.kazmi@samsung.com>
automated-tests/src/dali/tct-dali-core.h
automated-tests/src/dali/utc-Dali-Animation.cpp
capi/dali/public-api/animation/animation.h
dali/internal/event/animation/animation-impl.cpp
dali/internal/event/animation/animation-impl.h
dali/internal/update/animation/scene-graph-animation.cpp
dali/internal/update/animation/scene-graph-animation.h
dali/public-api/animation/animation.cpp

index a2c2f6a..07833ed 100644 (file)
@@ -286,6 +286,8 @@ extern int UtcDaliAnimationPlay(void);
 extern int UtcDaliAnimationPlayOffStage(void);
 extern int UtcDaliAnimationPlayDiscardHandle(void);
 extern int UtcDaliAnimationPlayStopDiscardHandle(void);
+extern int UtcDaliAnimationPlayFrom(void);
+extern int UtcDaliAnimationSetCurrentProgress(void);
 extern int UtcDaliAnimationPause(void);
 extern int UtcDaliAnimationStop(void);
 extern int UtcDaliAnimationStopSetPosition(void);
@@ -1514,6 +1516,8 @@ testcase tc_array[] = {
     {"UtcDaliAnimationPlayOffStage", UtcDaliAnimationPlayOffStage, utc_dali_animation_startup, utc_dali_animation_cleanup},
     {"UtcDaliAnimationPlayDiscardHandle", UtcDaliAnimationPlayDiscardHandle, utc_dali_animation_startup, utc_dali_animation_cleanup},
     {"UtcDaliAnimationPlayStopDiscardHandle", UtcDaliAnimationPlayStopDiscardHandle, utc_dali_animation_startup, utc_dali_animation_cleanup},
+    {"UtcDaliAnimationPlayFrom", UtcDaliAnimationPlayFrom, utc_dali_animation_startup, utc_dali_animation_cleanup},
+    {"UtcDaliAnimationSetCurrentProgress", UtcDaliAnimationSetCurrentProgress, utc_dali_animation_startup, utc_dali_animation_cleanup},
     {"UtcDaliAnimationPause", UtcDaliAnimationPause, utc_dali_animation_startup, utc_dali_animation_cleanup},
     {"UtcDaliAnimationStop", UtcDaliAnimationStop, utc_dali_animation_startup, utc_dali_animation_cleanup},
     {"UtcDaliAnimationStopSetPosition", UtcDaliAnimationStopSetPosition, utc_dali_animation_startup, utc_dali_animation_cleanup},
index 1d85c0d..b3aa783 100644 (file)
@@ -853,6 +853,154 @@ int UtcDaliAnimationPlayStopDiscardHandle(void)
   END_TEST;
 }
 
+int UtcDaliAnimationPlayFrom(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.MoveTo(actor, targetPosition, AlphaFunctions::Linear);
+
+  //PlayFrom with an argument outside the range [0..1] will be ignored
+  animation.PlayFrom(-1.0f);
+  application.SendNotification();
+  DALI_TEST_EQUALS(0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  animation.PlayFrom(100.0f);
+  application.SendNotification();
+  DALI_TEST_EQUALS(0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  // Start the animation from 40% progress
+  animation.PlayFrom( 0.4f );
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION );
+
+  animation.Play(); // Test that calling play has no effect, when animation is already playing
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/);
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationSetCurrentProgress(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  Animation animation = Animation::New(0.0f);
+  animation.Play();
+
+  //Test GetCurrentProgress return 0.0 as the duration is 0.0
+  DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  animation.SetCurrentProgress( 0.5f );
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(100.0f));
+
+  //Progress should still be 0.0
+  DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  //Set duration
+  float durationSeconds(1.0f);
+  animation.SetDuration(durationSeconds);
+  application.SendNotification();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.MoveTo(actor, targetPosition, AlphaFunctions::Linear);
+
+  //Trying to set the current cursor outside the range [0..1] is ignored
+  animation.SetCurrentProgress( -1.0f);
+  application.SendNotification();
+  DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  animation.SetCurrentProgress( 100.0f);
+  application.SendNotification();
+  DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  // Start the animation from 40% progress
+  animation.SetCurrentProgress( 0.4f );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION );
+  DALI_TEST_EQUALS( 0.6f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  animation.Play(); // Test that calling play has no effect, when animation is already playing
+  application.SendNotification();
+
+  //Set the progress to 70%
+  animation.SetCurrentProgress( 0.7f );
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 80% progress */);
+  DALI_TEST_EQUALS( 0.8f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION );
+  DALI_TEST_EQUALS( 0.8f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  //
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/);
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+
 int UtcDaliAnimationPause(void)
 {
   TestApplication application;
index 7921495..9843cd0 100644 (file)
@@ -259,11 +259,32 @@ public:
   AlphaFunction GetDefaultAlphaFunction() const;
 
   /**
+  * @brief Retrieve the current progress of the animation.
+  *
+  * @return The current progress as a normalized value between [0,1].
+  */
+  float GetCurrentProgress();
+
+  /*
+   * @brief Sets the progress of the animation.
+   * The animation will play (or continue playing) from this point
+   *
+   * @param[in] progress The new progress as a normalized value between [0,1].
+   */
+  void SetCurrentProgress( float progress );
+
+  /**
    * @brief Play the animation.
    */
   void Play();
 
   /**
+   * @brief Play the animation from a given point.
+   * @param[in] progress A value between [0,1] form where the animation should start playing
+   */
+  void PlayFrom( float progress );
+
+  /**
    * @brief Pause the animation.
    */
   void Pause();
index 464efff..4129c3d 100644 (file)
@@ -225,6 +225,18 @@ void Animation::Play()
   PlayAnimationMessage( mUpdateManager.GetEventToUpdate(), *mAnimation );
 }
 
+void Animation::PlayFrom( float progress )
+{
+  if( progress >= 0.0f && progress <= 1.0f )
+  {
+    // Update the current playlist
+    mPlaylist.OnPlay( *this );
+
+    // mAnimation is being used in a separate thread; queue a Play message
+    PlayAnimationFromMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, progress );
+  }
+}
+
 void Animation::Pause()
 {
   // mAnimation is being used in a separate thread; queue a Pause message
@@ -1241,6 +1253,25 @@ bool Animation::DoAction(BaseObject* object, const std::string& actionName, cons
   return done;
 }
 
+float Animation::GetCurrentProgress()
+{
+  if( mAnimation )
+  {
+    return mAnimation->GetCurrentProgress();
+  }
+
+  return 0.0f;
+}
+
+void Animation::SetCurrentProgress(float progress)
+{
+  if( mAnimation && progress >= 0.0f && progress <= 1.0f )
+  {
+    // mAnimation is being used in a separate thread; queue a message to set the current progress
+    SetCurrentProgressMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, progress );
+  }
+}
+
 } // namespace Internal
 
 } // namespace Dali
index 09ab46a..4cd86b9 100644 (file)
@@ -162,6 +162,12 @@ public:
   void Play();
 
   /**
+   * (Re)start the animation from a given point.
+   * @param[in] progress The progress between [0,1] from where the animation should start
+   */
+  void PlayFrom( float progress );
+
+  /**
    * Pause the animation.
    */
   void Pause();
@@ -901,6 +907,16 @@ public:
    */
   void AnimateProperty( ShaderEffect& shaderEffect, const std::string& name, Vector4 value, AlphaFunction alpha, float delaySeconds, float durationSeconds );
 
+  /*
+   * @copydoc Dali::Animation::GetCurrentProgress()
+   */
+  float GetCurrentProgress();
+
+  /*
+   * @copydoc Dali::Animation::SetCurrentProgress()
+   */
+  void SetCurrentProgress(float progress);
+
 public: // For connecting animators to animations
 
   /**
index 2f1c665..8b1b925 100644 (file)
@@ -82,6 +82,16 @@ void Animation::Play()
   mState = Playing;
 }
 
+void Animation::PlayFrom( float progress )
+{
+  //If the animation is already playing this has no effect
+  if( mState != Playing )
+  {
+    mElapsedSeconds = progress * mDurationSeconds;
+    mState = Playing;
+  }
+}
+
 void Animation::Pause()
 {
   if (mState == Playing)
index f6f619b..302763a 100644 (file)
@@ -94,6 +94,29 @@ public:
     return mDurationSeconds;
   }
 
+  /*
+   * Retrieve the current progress of the animation.
+   * @return The current progress as a normalized value between [0,1].
+   */
+  float GetCurrentProgress() const
+  {
+    if( mDurationSeconds > 0.0f )
+    {
+      return mElapsedSeconds / mDurationSeconds;
+    }
+
+    return 0.0f;
+  }
+
+  /*
+   * Sets the progress of the animation.
+   * @param[in] The new progress as a normalized value between [0,1]
+   */
+  void SetCurrentProgress( float progress )
+  {
+    mElapsedSeconds = mDurationSeconds * progress;
+  }
+
   /**
    * Set whether the animation will loop.
    * @param[in] looping True if the animation will loop.
@@ -146,6 +169,12 @@ public:
    */
   void Play();
 
+  /*
+   * Play the animation from a given point
+   * @param[in] progress A value between [0,1] form where the animation should start playing
+   */
+  void PlayFrom( float progress );
+
   /**
    * Pause the animation.
    */
@@ -302,6 +331,17 @@ inline void SetDestroyActionMessage( EventToUpdate& eventToUpdate, const Animati
   new (slot) LocalType( &animation, &Animation::SetDestroyAction, action );
 }
 
+inline void SetCurrentProgressMessage( EventToUpdate& eventToUpdate, const Animation& animation, float progress )
+{
+  typedef MessageValue1< Animation, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::SetCurrentProgress, progress );
+}
+
 inline void PlayAnimationMessage( EventToUpdate& eventToUpdate, const Animation& animation )
 {
   typedef Message< Animation > LocalType;
@@ -313,6 +353,17 @@ inline void PlayAnimationMessage( EventToUpdate& eventToUpdate, const Animation&
   new (slot) LocalType( &animation, &Animation::Play );
 }
 
+inline void PlayAnimationFromMessage( EventToUpdate& eventToUpdate, const Animation& animation, float progress )
+{
+  typedef MessageValue1< Animation,float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::PlayFrom, progress );
+}
+
 inline void PauseAnimationMessage( EventToUpdate& eventToUpdate, const Animation& animation )
 {
   typedef Message< Animation > LocalType;
index 05470d2..07ebff4 100644 (file)
@@ -117,6 +117,12 @@ void Animation::Play()
   GetImplementation(*this).Play();
 }
 
+void Animation::PlayFrom(float progress)
+{
+  GetImplementation(*this).PlayFrom(progress);
+}
+
+
 void Animation::Pause()
 {
   GetImplementation(*this).Pause();
@@ -464,4 +470,14 @@ void Animation::Resize(Actor actor, Vector3 size, AlphaFunction alpha, float del
   GetImplementation(*this).Resize(GetImplementation(actor), size, alpha, delaySeconds, durationSeconds);
 }
 
+float Animation::GetCurrentProgress()
+{
+  return GetImplementation(*this).GetCurrentProgress();
+}
+
+void Animation::SetCurrentProgress( float progress )
+{
+  return GetImplementation(*this).SetCurrentProgress( progress );
+}
+
 } // namespace Dali