(Animation) Ensure animator has been activated before performing the disconnect action 22/28322/2
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 2 Oct 2014 13:02:03 +0000 (14:02 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 2 Oct 2014 13:06:24 +0000 (14:06 +0100)
[problem]  Animations can be created, therefore creating animators, but not played. If the
           property owner was disconnected before the animation was played, the disconnect
           action was still applied.
[solution] Set a state on the animator to state whether it is active or not and only apply
           the disconnect action (if required) if it was active.

Change-Id: Idd615938182a22f0fd91425bc2d2e83aeea18480

automated-tests/src/dali/utc-Dali-Animation.cpp
dali/internal/update/animation/scene-graph-animation.cpp
dali/internal/update/animation/scene-graph-animation.h
dali/internal/update/animation/scene-graph-animator.h
dali/public-api/animation/animation.h

index 893fc32..ad84012 100644 (file)
@@ -616,6 +616,29 @@ int UtcDaliAnimationSetDisconnectAction(void)
     DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
   }
 
+  // Don't play the animation: disconnect action should not be applied
+  {
+    Actor actor = Actor::New();
+    stage.Add(actor);
+
+    // Build the animation
+    float durationSeconds(1.0f);
+    Animation animation = Animation::New(durationSeconds);
+
+    Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+    animation.MoveTo(actor, targetPosition, AlphaFunctions::Linear);
+
+    application.SendNotification();
+    application.Render(static_cast<unsigned int>(durationSeconds*0.5f*1000.0f)/*Only half the animation*/);
+
+    actor.Unparent();
+
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+  }
+
   END_TEST;
 }
 
index bb50413..7c4b744 100644 (file)
@@ -103,6 +103,8 @@ void Animation::Play()
   {
     mElapsedSeconds = mPlayRange.y * mDurationSeconds;
   }
+
+  SetAnimatorsActive( true );
 }
 
 void Animation::PlayFrom( float progress )
@@ -112,6 +114,8 @@ void Animation::PlayFrom( float progress )
   {
     mElapsedSeconds = progress * mDurationSeconds;
     mState = Playing;
+
+    SetAnimatorsActive( true );
   }
 }
 
@@ -137,7 +141,15 @@ void Animation::Bake(BufferIndex bufferIndex, EndAction action)
     }
   }
 
-  UpdateAnimators(bufferIndex, true/*bake the final result*/);
+  UpdateAnimators( bufferIndex, true/*bake the final result*/, true /*animation finished*/ );
+}
+
+void Animation::SetAnimatorsActive( bool active )
+{
+  for ( AnimatorIter iter = mAnimators.Begin(), endIter = mAnimators.End(); iter != endIter; ++iter )
+  {
+    (*iter)->SetActive( active );
+  }
 }
 
 bool Animation::Stop(BufferIndex bufferIndex)
@@ -151,6 +163,12 @@ bool Animation::Stop(BufferIndex bufferIndex)
     if( mEndAction != Dali::Animation::Discard )
     {
       Bake( bufferIndex, mEndAction );
+
+      // Animators are automatically set to inactive in Bake
+    }
+    else
+    {
+      SetAnimatorsActive( false );
     }
 
     // The animation has now been played to completion
@@ -170,6 +188,12 @@ void Animation::OnDestroy(BufferIndex bufferIndex)
     if (mEndAction != Dali::Animation::Discard)
     {
       Bake( bufferIndex, mEndAction );
+
+      // Animators are automatically set to inactive in Bake
+    }
+    else
+    {
+      SetAnimatorsActive( false );
     }
   }
 
@@ -216,7 +240,7 @@ bool Animation::Update(BufferIndex bufferIndex, float elapsedSeconds)
                                ( mSpeedFactor < 0.0f && mElapsedSeconds < playRangeSeconds.x ))
                               );
 
-  UpdateAnimators(bufferIndex, animationFinished && (mEndAction != Dali::Animation::Discard));
+  UpdateAnimators(bufferIndex, animationFinished && (mEndAction != Dali::Animation::Discard), animationFinished);
 
   if (animationFinished)
   {
@@ -230,7 +254,7 @@ bool Animation::Update(BufferIndex bufferIndex, float elapsedSeconds)
   return animationFinished;
 }
 
-void Animation::UpdateAnimators(BufferIndex bufferIndex, bool bake)
+void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animationFinished )
 {
   float elapsedSecondsClamped = Clamp( mElapsedSeconds, mPlayRange.x * mDurationSeconds,mPlayRange.y * mDurationSeconds );
   for ( AnimatorIter iter = mAnimators.Begin(); iter != mAnimators.End(); )
@@ -254,6 +278,11 @@ void Animation::UpdateAnimators(BufferIndex bufferIndex, bool bake)
       applied = animator->Update(bufferIndex, progress, bake);
     }
 
+    if ( animationFinished )
+    {
+      animator->SetActive( false );
+    }
+
     // Animators are automatically removed, when orphaned from animatable scene objects.
     if (!applied)
     {
index 891e424..a6c1a5d 100644 (file)
@@ -269,8 +269,9 @@ private:
    * Helper for Update, also used to bake when the animation is stopped or destroyed.
    * @param[in] bufferIndex The buffer to update.
    * @param[in] bake True if the final result should be baked.
+   * @param[in] animationFinished True if the animation has finished.
    */
-  void UpdateAnimators(BufferIndex bufferIndex, bool bake);
+  void UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animationFinished );
 
   /**
    * Helper function to bake the result of the animation when it is stopped or
@@ -280,6 +281,12 @@ private:
    */
   void Bake(BufferIndex bufferIndex, EndAction action );
 
+  /**
+   * Helper function to set active state of animators.
+   * @param[in] active Every animator is set to this state
+   */
+  void SetAnimatorsActive( bool active );
+
   // Undefined
   Animation(const Animation&);
 
index 7bedebc..89afaa5 100644 (file)
@@ -67,7 +67,8 @@ public:
   : mDurationSeconds(1.0f),
     mInitialDelaySeconds(0.0f),
     mAlphaFunc(AlphaFunctions::Linear),
-    mDisconnectAction(Dali::Animation::BakeFinal)
+    mDisconnectAction(Dali::Animation::BakeFinal),
+    mActive(false)
   {
   }
 
@@ -138,6 +139,7 @@ public:
 
   /**
    * Whether to bake the animation if attached property owner is disconnected.
+   * Property is only baked if the animator is active.
    * @param [in] action The disconnect action.
    */
   void SetDisconnectAction( Dali::Animation::EndAction action )
@@ -146,6 +148,35 @@ public:
   }
 
   /**
+   * Retrieve the disconnect action of an animator.
+   * @return The disconnect action.
+   */
+  Dali::Animation::EndAction GetDisconnectAction() const
+  {
+    return mDisconnectAction;
+  }
+
+  /**
+   * Whether the animator is active or not.
+   * @param [in] action The disconnect action.
+   * @post When the animator becomes active, it applies the disconnect-action if the property owner is then disconnected.
+   * @note When the property owner is disconnected, the active state is set to false.
+   */
+  void SetActive( bool active )
+  {
+    mActive = active;
+  }
+
+  /**
+   * Retrieve whether the animator has been set to active or not.
+   * @return The active state.
+   */
+  bool GetActive() const
+  {
+    return mActive;
+  }
+
+  /**
    * This must be called when the animator is attached to the scene-graph.
    * @pre The animatable scene object must also be attached to the scene-graph.
    * @param[in] propertyOwner The scene-object that owns the animatable property.
@@ -176,6 +207,7 @@ protected:
   AlphaFunc mAlphaFunc;
 
   Dali::Animation::EndAction mDisconnectAction;
+  bool mActive:1;
 };
 
 /**
@@ -281,13 +313,14 @@ public:
    */
   virtual void PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
   {
-    // Bake the value if required
-    if ( mDisconnectAction != Dali::Animation::Discard )
+    // If we are active, then bake the value if required
+    if ( mActive && mDisconnectAction != Dali::Animation::Discard )
     {
       // Bake to target-value if BakeFinal, otherwise bake current value
       Update( bufferIndex, ( mDisconnectAction == Dali::Animation::Bake ? mCurrentProgress : 1.0f ), true );
     }
 
+    mActive = false;
     mPropertyOwner = NULL;
     mPropertyAccessor.Reset();
   }
index 5097a0d..5d20fec 100644 (file)
@@ -246,7 +246,7 @@ public:
   /**
    * @brief Set the disconnect action.
    *
-   * If any of the animated property owners are disconnected from the stage, then this action is performed.
+   * If any of the animated property owners are disconnected from the stage while the animation is being played, then this action is performed.
    * Default action is to BakeFinal.
    * @param[in] disconnectAction The disconnect action.
    */