Fix LoopingMode::AUTO_REVERSE behavior when LoopCount is 1 68/154268/5
authorEunki Hong <eunkiki.hong@samsung.com>
Tue, 10 Oct 2017 02:41:13 +0000 (11:41 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Wed, 11 Oct 2017 11:05:39 +0000 (20:05 +0900)
Let's think some animation s.t. start = 0, target = 2, duration = 2.
if LoopingMode is RESTART, animation will works like

RESTART       +---------------------------------> t
LoopCount = 0 | 0 - 1 - 2`- 1 - 2`- 1 - 2`- 1 - ...
LoopCount = 3 | 0 - 1 - 2`- 1 - 2`- 1 - 2 - 2 - ...
LoopCount = 2 | 0 - 1 - 2`- 1 - 2 - 2 - 2 - 2 - ...
LoopCount = 1 | 0 - 1 - 2 - 2 - 2 - 2 - 2 - 2 - ...
(2` mean value become 0 after value become 2)

But if Looping Mode is AUTO_REVERSE, animation will works like

AUTO_REVERSE  +---------------------------------> t
LoopCount = 0 | 0 - 2 - 0 - 2 - 0 - 2 - 0 - 2 - ...
LoopCount = 3 | 0 - 2 - 0 - 2 - 0 - 2 - 0 - 0 - ...
LoopCount = 2 | 0 - 2 - 0 - 2 - 0 - 0 - 0 - 0 - ...
LoopCount = 1 | 0 - 1 - 2 - 2 - 2 - 2 - 2 - 2 - ...

Previous code think that LoopCount == 1 is not looping mode.
But "ONLY IF LoopCount == 1, We don't auto reversing your animation" is non-sense

This patch change animation works like

AUTO_REVERSE  +---------------------------------> t
LoopCount = 1 | 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - ...

Note : Patch set 4 is previous code. so, Fail at UtcDaliAnimationSetLoopingModeP3

Change-Id: Ie938864ba17c1b923021f87c29859f98f7241a43
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali/utc-Dali-Animation.cpp
dali/internal/update/animation/scene-graph-animator.h

index 3327cb7..d9f1934 100644 (file)
@@ -11819,6 +11819,125 @@ int UtcDaliAnimationSetLoopingModeP2(void)
   END_TEST;
 }
 
+int UtcDaliAnimationSetLoopingModeP3(void)
+{
+  // Test Loop Count is 1 (== default) and Loop mode being set
+  TestApplication application;
+  Stage stage( Stage::GetCurrent() );
+
+  // LoopingMode::AUTO_REVERSE
+  {
+    Actor actor = Actor::New();
+    stage.Add( actor );
+
+    float durationSeconds( 1.0f );
+    Animation animation = Animation::New( durationSeconds );
+    DALI_TEST_CHECK(1 == animation.GetLoopCount());
+
+    bool signalReceived( false );
+    AnimationFinishCheck finishCheck( signalReceived );
+    animation.FinishedSignal().Connect( &application, finishCheck );
+    application.SendNotification();
+
+    Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+    animation.AnimateTo( Property( actor, Actor::Property::POSITION ), targetPosition );
+
+    animation.SetLoopingMode( Animation::AUTO_REVERSE );
+    DALI_TEST_CHECK( animation.GetLoopingMode() == Animation::AUTO_REVERSE );
+
+    // Start the animation
+    animation.Play();
+    application.Render(0);
+    application.SendNotification();
+
+    application.Render( static_cast< unsigned int >( durationSeconds * 0.5f * 1000.0f )/* 50% time progress */ );
+    application.SendNotification();
+    finishCheck.CheckSignalNotReceived();
+
+    // AUTO_REVERSE mode means, for Animation duration time, the actor starts from the beginning, passes the targetPosition,
+    // and arrives at the beginning.
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+    application.SendNotification();
+    application.Render( static_cast< unsigned int >( durationSeconds * 0.5f * 1000.0f )/* 100% time progress */ );
+
+    application.SendNotification();
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), TEST_LOCATION );
+
+    application.SendNotification();
+    application.Render( static_cast< unsigned int >( durationSeconds * 1.0f * 1000.0f ) + 1u /*just beyond the animation duration*/ );
+
+    application.SendNotification();
+    application.Render(0);
+    application.SendNotification();
+    finishCheck.CheckSignalReceived();
+
+    // After all animation finished, arrives at the beginning.
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), TEST_LOCATION );
+
+    finishCheck.Reset();
+  }
+
+  // LoopingMode::AUTO_REVERSE in Reverse mode, which begin from the end
+  {
+    Actor actor = Actor::New();
+    stage.Add( actor );
+
+    float durationSeconds( 1.0f );
+    Animation animation = Animation::New( durationSeconds );
+    DALI_TEST_CHECK(1 == animation.GetLoopCount());
+
+    bool signalReceived( false );
+    AnimationFinishCheck finishCheck( signalReceived );
+    animation.FinishedSignal().Connect( &application, finishCheck );
+    application.SendNotification();
+
+    // Specify a negative multiplier to play the animation in reverse
+    animation.SetSpeedFactor( -1.0f );
+
+    Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+    animation.AnimateTo( Property( actor, Actor::Property::POSITION ), targetPosition );
+
+    animation.SetLoopingMode( Animation::AUTO_REVERSE );
+    DALI_TEST_CHECK( animation.GetLoopingMode() == Animation::AUTO_REVERSE );
+
+    // Start the animation
+    animation.Play();
+    application.Render(0);
+    application.SendNotification();
+
+    application.Render( static_cast< unsigned int >( durationSeconds * 0.5f * 1000.0f )/* 50% time progress */ );
+    application.SendNotification();
+    finishCheck.CheckSignalNotReceived();
+
+    // Setting a negative speed factor is to play the animation in reverse.
+    // So, when LoopingMode::AUTO_REVERSE and SetSpeedFactor( -1.0f ) is, for Animation duration time,
+    // the actor starts from the targetPosition, passes the beginning, and arrives at the targetPosition.
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), TEST_LOCATION );
+
+    application.SendNotification();
+    application.Render( static_cast< unsigned int >( durationSeconds * 0.5f * 1000.0f )/* 100% time progress */ );
+
+    application.SendNotification();
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+    application.SendNotification();
+    application.Render( static_cast< unsigned int >( durationSeconds * 1.0f * 1000.0f ) + 1u /*just beyond the animation duration*/ );
+
+    application.SendNotification();
+    application.Render(0);
+    application.SendNotification();
+    finishCheck.CheckSignalReceived();
+
+    // After all animation finished, arrives at the target.
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+    finishCheck.Reset();
+  }
+
+  END_TEST;
+}
+
 int UtcDaliAnimationGetLoopingModeP(void)
 {
   TestApplication application;
index 19d4ecc..aff2b2c 100644 (file)
@@ -140,6 +140,10 @@ public:
         value = 2.0f * std::abs( progress - 0.5f );
       }
     }
+    else
+    {
+      value = progress;
+    }
 
     return value;
   }
@@ -509,7 +513,7 @@ public:
    */
   virtual void Update( BufferIndex bufferIndex, float progress, bool bake )
   {
-    if( mLoopCount != 1 ) // Looping mode
+    if( mLoopCount >= 0 )
     {
       // Update the progress value
       progress = SetProgress( progress );
@@ -668,7 +672,7 @@ public:
    */
   virtual void Update( BufferIndex bufferIndex, float progress, bool bake )
   {
-    if( mLoopCount != 1 ) // Looping mode
+    if( mLoopCount >= 0 )
     {
       // Update the progress value
       progress = SetProgress( progress );