(Animation) Allow the value to be baked upon property owner disconnection, DestroyEnd... 49/28149/8
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 26 Sep 2014 16:28:23 +0000 (17:28 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Tue, 30 Sep 2014 09:19:25 +0000 (10:19 +0100)
[Problem]  If property owner is removed from the stage and even if Bake is set as the EndAction,
           the value is never baked.
[Cause]    We just disconnect with the current value set.
[Solution] If one of the bake options is selected then we jump to the final value
           Destroy end action deprecated as it is redundant

Change-Id: I9aab5cf6676a6fb1bcda9e9c90c644a3f3a1c57c

automated-tests/src/dali/utc-Dali-Animation.cpp
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/internal/update/animation/scene-graph-animator.h
dali/public-api/animation/animation.cpp
dali/public-api/animation/animation.h

index 3d1a11f..893fc32 100644 (file)
@@ -530,17 +530,106 @@ int UtcDaliAnimationGetEndAction(void)
   END_TEST;
 }
 
-int UtcDaliAnimationGetDestroyAction(void)
+int UtcDaliAnimationSetDisconnectAction(void)
+{
+  TestApplication application;
+  Stage stage( Stage::GetCurrent() );
+
+  // Default: BakeFinal
+  {
+    Actor actor = Actor::New();
+    stage.Add(actor);
+
+    // Build the animation
+    float durationSeconds(1.0f);
+    Animation animation = Animation::New(durationSeconds);
+    DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::BakeFinal);
+
+    Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+    animation.MoveTo(actor, targetPosition, AlphaFunctions::Linear);
+
+    // Start the animation
+    animation.Play();
+
+    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(), targetPosition, TEST_LOCATION );
+  }
+
+  // Bake
+  {
+    Actor actor = Actor::New();
+    stage.Add(actor);
+
+    // Build the animation
+    float durationSeconds(1.0f);
+    Animation animation = Animation::New(durationSeconds);
+    animation.SetDisconnectAction( Animation::Bake );
+
+    Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+    animation.MoveTo(actor, targetPosition, AlphaFunctions::Linear);
+
+    // Start the animation
+    animation.Play();
+
+    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(), targetPosition*0.5f, TEST_LOCATION );
+  }
+
+  // Discard
+  {
+    Actor actor = Actor::New();
+    stage.Add(actor);
+
+    // Build the animation
+    float durationSeconds(1.0f);
+    Animation animation = Animation::New(durationSeconds);
+    animation.SetDisconnectAction( Animation::Discard );
+
+    Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+    animation.MoveTo(actor, targetPosition, AlphaFunctions::Linear);
+
+    // Start the animation
+    animation.Play();
+
+    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;
+}
+
+int UtcDaliAnimationGetDisconnectAction(void)
 {
   TestApplication application;
   Animation animation = Animation::New(1.0f);
-  DALI_TEST_CHECK(animation.GetDestroyAction() == Animation::Bake); // default!
+  DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::BakeFinal); // default!
 
-  animation.SetDestroyAction(Animation::Discard);
-  DALI_TEST_CHECK(animation.GetDestroyAction() == Animation::Discard);
+  animation.SetDisconnectAction(Animation::Discard);
+  DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::Discard);
 
-  animation.SetDestroyAction(Animation::BakeFinal);
-  DALI_TEST_CHECK(animation.GetDestroyAction() == Animation::BakeFinal);
+  animation.SetDisconnectAction(Animation::Bake);
+  DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::Bake);
 
   END_TEST;
 }
@@ -836,6 +925,7 @@ int UtcDaliAnimationPlayOffStage(void)
   // Build the animation
   float durationSeconds(1.0f);
   Animation animation = Animation::New(durationSeconds);
+  animation.SetDisconnectAction( Animation::Discard );
   Vector3 targetPosition(100.0f, 100.0f, 100.0f);
   animation.MoveTo(actor, targetPosition, AlphaFunctions::Linear);
 
index b238c0b..1b40dd0 100644 (file)
@@ -65,35 +65,28 @@ TypeAction action1( mType, Dali::Animation::ACTION_PLAY, &Animation::DoAction );
 TypeAction action2( mType, Dali::Animation::ACTION_STOP, &Animation::DoAction );
 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 );
+
 } // anon namespace
 
 
 AnimationPtr Animation::New(float durationSeconds)
 {
-  return New(durationSeconds, Dali::Animation::Bake, Dali::Animation::Bake, Dali::AlphaFunctions::Linear);
-}
-
-AnimationPtr Animation::New(float durationSeconds, EndAction endAction, EndAction destroyAction)
-{
-  return New(durationSeconds, endAction, destroyAction, Dali::AlphaFunctions::Linear);
-}
-
-AnimationPtr Animation::New(float durationSeconds, EndAction endAction, EndAction destroyAction, AlphaFunction alpha)
-{
   ThreadLocalStorage& tls = ThreadLocalStorage::Get();
   UpdateManager& updateManager = tls.GetUpdateManager();
 
   AnimationPlaylist& playlist = Stage::GetCurrent()->GetAnimationPlaylist();
 
-  AnimationPtr progress = new Animation( updateManager, playlist, durationSeconds, endAction, destroyAction, alpha );
+  AnimationPtr animation = new Animation( updateManager, playlist, durationSeconds, DEFAULT_END_ACTION, DEFAULT_DISCONNECT_ACTION, Dali::AlphaFunctions::Linear );
 
   // Second-phase construction
-  progress->Initialize();
+  animation->Initialize();
 
-  return progress;
+  return animation;
 }
 
-Animation::Animation( UpdateManager& updateManager, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction destroyAction, AlphaFunction defaultAlpha )
+Animation::Animation( UpdateManager& updateManager, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction disconnectAction, AlphaFunction defaultAlpha )
 : mUpdateManager( updateManager ),
   mPlaylist( playlist ),
   mAnimation( NULL ),
@@ -105,7 +98,7 @@ Animation::Animation( UpdateManager& updateManager, AnimationPlaylist& playlist,
   mIsLooping( false ),
   mPlayRange( Vector2(0.0f,1.0f)),
   mEndAction( endAction ),
-  mDestroyAction( destroyAction ),
+  mDisconnectAction( disconnectAction ),
   mDefaultAlpha( defaultAlpha )
 {
 }
@@ -139,7 +132,7 @@ void Animation::CreateSceneObject()
   DALI_ASSERT_DEBUG( mAnimation == NULL );
 
   // Create a new animation, temporarily owned
-  SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mIsLooping, mEndAction, mDestroyAction );
+  SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mIsLooping, mEndAction, mDisconnectAction );
 
   // Keep a const pointer to the animation.
   mAnimation = animation;
@@ -203,19 +196,19 @@ Dali::Animation::EndAction Animation::GetEndAction() const
   return mEndAction;
 }
 
-void Animation::SetDestroyAction(EndAction action)
+void Animation::SetDisconnectAction(EndAction action)
 {
   // Cache for public getters
-  mDestroyAction = action;
+  mDisconnectAction = action;
 
   // mAnimation is being used in a separate thread; queue a message to set the value
-  SetDestroyActionMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, action );
+  SetDisconnectActionMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, action );
 }
 
-Dali::Animation::EndAction Animation::GetDestroyAction() const
+Dali::Animation::EndAction Animation::GetDisconnectAction() const
 {
   // This is not animatable; the cached value is up-to-date.
-  return mDestroyAction;
+  return mDisconnectAction;
 }
 
 void Animation::Play()
index a207091..add8afb 100644 (file)
@@ -72,25 +72,6 @@ public:
   static AnimationPtr New(float durationSeconds);
 
   /**
-   * Create a new Animation object.
-   * @param[in] durationSeconds The duration of the animation.
-   * @param[in] endAction The action to perform when the animation ends.
-   * @param[in] destroyAction The action to perform when the animation ends.
-   * @return A smart-pointer to the newly allocated Animation.
-   */
-  static AnimationPtr New(float durationSeconds, EndAction endAction, EndAction destroyAction);
-
-  /**
-   * Create a new Animation object.
-   * @param[in] durationSeconds The duration of the animation.
-   * @param[in] endAction The action to perform when the animation ends.
-   * @param[in] destroyAction The action to perform when the animation ends.
-   * @param[in] alpha The default alpha function to apply to animators.
-   * @return A smart-pointer to the newly allocated Animation.
-   */
-  static AnimationPtr New(float durationSeconds, EndAction endAction, EndAction destroyAction, AlphaFunction alpha);
-
-  /**
    * Set the duration of an animation.
    * @pre durationSeconds must be greater than zero.
    * @param[in] seconds The duration in seconds.
@@ -127,15 +108,15 @@ public:
   EndAction GetEndAction() const;
 
   /**
-   * Set the destroy action of the animation.
-   * @param[in] action The destroy action.
+   * Set the disconnect action of the animation.
+   * @param[in] action The disconnect action.
    */
-  void SetDestroyAction(EndAction action);
+  void SetDisconnectAction(EndAction action);
 
   /**
-   * Returns the destroy action of the animation.
+   * Returns the disconnect action of the animation.
    */
-  EndAction GetDestroyAction() const;
+  EndAction GetDisconnectAction() const;
 
   /**
    * Set the default alpha function for an animation.
@@ -851,14 +832,14 @@ protected:
    * @param[in] playlist The list of currently playing animations.
    * @param[in] durationSeconds The duration of the animation in seconds.
    * @param[in] endAction The action to perform when the animation ends.
-   * @param[in] destroyAction The action to perform when the animation is destroyed.
+   * @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected.
    * @param[in] defaultAlpha The default alpha function to apply to animators.
    */
   Animation( SceneGraph::UpdateManager& updateManager,
              AnimationPlaylist& playlist,
              float durationSeconds,
              EndAction endAction,
-             EndAction destroyAction,
+             EndAction disconnectAction,
              AlphaFunction defaultAlpha);
 
   /**
@@ -917,7 +898,7 @@ private:
   bool mIsLooping;
   Vector2 mPlayRange;
   EndAction mEndAction;
-  EndAction mDestroyAction;
+  EndAction mDisconnectAction;
   AlphaFunction mDefaultAlpha;
 
 };
index 77175f3..bb50413 100644 (file)
@@ -40,12 +40,12 @@ float DefaultAlphaFunc(float progress)
   return progress; // linear
 }
 
-Animation::Animation(float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, Dali::Animation::EndAction endAction, Dali::Animation::EndAction destroyAction)
+Animation::Animation( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, Dali::Animation::EndAction endAction, Dali::Animation::EndAction disconnectAction )
 : mDurationSeconds(durationSeconds),
   mSpeedFactor( speedFactor ),
   mLooping(isLooping),
   mEndAction(endAction),
-  mDestroyAction(destroyAction),
+  mDisconnectAction(disconnectAction),
   mState(Stopped),
   mElapsedSeconds(playRange.x*mDurationSeconds),
   mPlayCount(0),
@@ -74,9 +74,17 @@ void Animation::SetEndAction(Dali::Animation::EndAction action)
   mEndAction = action;
 }
 
-void Animation::SetDestroyAction(Dali::Animation::EndAction action)
+void Animation::SetDisconnectAction(Dali::Animation::EndAction action)
 {
-  mDestroyAction = action;
+  if ( mDisconnectAction != action )
+  {
+    mDisconnectAction = action;
+
+    for ( AnimatorIter iter = mAnimators.Begin(), endIter = mAnimators.End(); iter != endIter; ++iter )
+    {
+      (*iter)->SetDisconnectAction( action );
+    }
+  }
 }
 
 void Animation::SetPlayRange( const Vector2& range )
@@ -159,9 +167,9 @@ void Animation::OnDestroy(BufferIndex bufferIndex)
 {
   if (mState == Playing || mState == Paused)
   {
-    if (mDestroyAction != Dali::Animation::Discard)
+    if (mEndAction != Dali::Animation::Discard)
     {
-      Bake( bufferIndex, mDestroyAction );
+      Bake( bufferIndex, mEndAction );
     }
   }
 
@@ -171,6 +179,7 @@ void Animation::OnDestroy(BufferIndex bufferIndex)
 void Animation::AddAnimator( AnimatorBase* animator, PropertyOwner* propertyOwner )
 {
   animator->Attach( propertyOwner );
+  animator->SetDisconnectAction( mDisconnectAction );
 
   mAnimators.PushBack( animator );
 }
index 9635037..891e424 100644 (file)
@@ -67,12 +67,12 @@ public:
    * @param[in] playRange Minimum and maximum progress between which the animation will play.
    * @param[in] isLooping Whether the animation will loop.
    * @param[in] endAction The action to perform when the animation ends.
-   * @param[in] destroyAction The action to perform when the animation is destroyed.
+   * @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected.
    * @return A new Animation
    */
-  static Animation* New( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction destroyAction )
+  static Animation* New( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction disconnectAction )
   {
-    return new Animation( durationSeconds, speedFactor, playRange, isLooping, endAction, destroyAction );
+    return new Animation( durationSeconds, speedFactor, playRange, isLooping, endAction, disconnectAction );
   }
 
   /**
@@ -155,20 +155,20 @@ public:
   }
 
   /**
-   * Set the destroy action of the animation.
+   * Set the disconnect action of the animation when connected objects are disconnected.
    * This action is performed during the next update when
-   * the animation is destroyed.
-   * @param[in] action The destroy action.
+   * the connected object is disconnected.
+   * @param[in] action The disconnect action.
    */
-  void SetDestroyAction(EndAction action);
+  void SetDisconnectAction(EndAction action);
 
   /**
    * Retrieve the action performed when the animation is destroyed.
    * @return The destroy action.
    */
-  EndAction GetDestroyAction()
+  EndAction GetDisconnectAction()
   {
-    return mDestroyAction;
+    return mDisconnectAction;
   }
 
   /**
@@ -204,7 +204,7 @@ public:
 
   /**
    * Called shortly before the animation is destroyed.
-   * @param[in] bufferIndex The buffer to update when mDestroyAction == Bake.
+   * @param[in] bufferIndex The buffer to update when mEndAction == Bake.
    */
   void OnDestroy(BufferIndex bufferIndex);
 
@@ -260,7 +260,7 @@ protected:
   /**
    * Protected constructor. See New()
    */
-  Animation( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction destroyAction );
+  Animation( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction disconnectAction );
 
 
 private:
@@ -292,7 +292,7 @@ protected:
   float mSpeedFactor;
   bool mLooping;
   EndAction mEndAction;
-  EndAction mDestroyAction;
+  EndAction mDisconnectAction;
 
   State mState;
   float mElapsedSeconds;
@@ -345,7 +345,7 @@ inline void SetEndActionMessage( EventToUpdate& eventToUpdate, const Animation&
   new (slot) LocalType( &animation, &Animation::SetEndAction, action );
 }
 
-inline void SetDestroyActionMessage( EventToUpdate& eventToUpdate, const Animation& animation, Dali::Animation::EndAction action )
+inline void SetDisconnectActionMessage( EventToUpdate& eventToUpdate, const Animation& animation, Dali::Animation::EndAction action )
 {
   typedef MessageValue1< Animation, Dali::Animation::EndAction > LocalType;
 
@@ -353,7 +353,7 @@ inline void SetDestroyActionMessage( EventToUpdate& eventToUpdate, const Animati
   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::SetDestroyAction, action );
+  new (slot) LocalType( &animation, &Animation::SetDisconnectAction, action );
 }
 
 inline void SetCurrentProgressMessage( EventToUpdate& eventToUpdate, const Animation& animation, float progress )
index 55877b3..7bedebc 100644 (file)
@@ -28,6 +28,7 @@
 #include <dali/internal/update/common/property-base.h>
 #include <dali/internal/common/observer-pointer.h>
 #include <dali/public-api/animation/alpha-functions.h>
+#include <dali/public-api/animation/animation.h>
 #include <dali/public-api/animation/time-period.h>
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/math/quaternion.h>
@@ -66,7 +67,7 @@ public:
   : mDurationSeconds(1.0f),
     mInitialDelaySeconds(0.0f),
     mAlphaFunc(AlphaFunctions::Linear),
-    mRelative(false)
+    mDisconnectAction(Dali::Animation::BakeFinal)
   {
   }
 
@@ -136,6 +137,15 @@ public:
   }
 
   /**
+   * Whether to bake the animation if attached property owner is disconnected.
+   * @param [in] action The disconnect action.
+   */
+  void SetDisconnectAction( Dali::Animation::EndAction action )
+  {
+    mDisconnectAction = action;
+  }
+
+  /**
    * 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.
@@ -165,7 +175,7 @@ protected:
 
   AlphaFunc mAlphaFunc;
 
-  bool mRelative;
+  Dali::Animation::EndAction mDisconnectAction;
 };
 
 /**
@@ -251,6 +261,8 @@ public:
       {
         mPropertyAccessor.Set( bufferIndex, result );
       }
+
+      mCurrentProgress = progress;
     }
 
     return IsAttached(); // return false if orphaned
@@ -269,6 +281,13 @@ public:
    */
   virtual void PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
   {
+    // Bake the value if required
+    if ( mDisconnectAction != Dali::Animation::Discard )
+    {
+      // Bake to target-value if BakeFinal, otherwise bake current value
+      Update( bufferIndex, ( mDisconnectAction == Dali::Animation::Bake ? mCurrentProgress : 1.0f ), true );
+    }
+
     mPropertyOwner = NULL;
     mPropertyAccessor.Reset();
   }
@@ -291,7 +310,8 @@ private:
             AnimatorFunction animatorFunction )
   : mPropertyOwner( NULL ),
     mPropertyAccessor( property ),
-    mAnimatorFunction( animatorFunction )
+    mAnimatorFunction( animatorFunction ),
+    mCurrentProgress( 0.0f )
   {
   }
 
@@ -307,6 +327,7 @@ protected:
   PropertyAccessorType mPropertyAccessor;
 
   AnimatorFunction mAnimatorFunction;
+  float mCurrentProgress;
 };
 
 } // namespace SceneGraph
index f09fab0..0a1a088 100644 (file)
@@ -112,12 +112,24 @@ Dali::Animation::EndAction Animation::GetEndAction() const
 
 void Animation::SetDestroyAction(Dali::Animation::EndAction destroyAction)
 {
-  GetImplementation(*this).SetDestroyAction(destroyAction);
+  // Deprecated
+  GetImplementation(*this).SetEndAction(destroyAction);
 }
 
 Dali::Animation::EndAction Animation::GetDestroyAction() const
 {
-  return GetImplementation(*this).GetDestroyAction();
+  // Deprecated
+  return GetImplementation(*this).GetEndAction();
+}
+
+void Animation::SetDisconnectAction( Animation::EndAction disconnectAction )
+{
+  GetImplementation(*this).SetDisconnectAction( disconnectAction );
+}
+
+Animation::EndAction Animation::GetDisconnectAction() const
+{
+  return GetImplementation(*this).GetDisconnectAction();
 }
 
 void Animation::SetDefaultAlphaFunction(AlphaFunction alpha)
index b2837d1..1935863 100644 (file)
@@ -230,7 +230,7 @@ public:
   /**
    * @brief Set the end action of the animation.
    *
-   * This action is performed when the animation ends.
+   * This action is performed when the animation ends or if it is stopped.
    * Default end action is bake
    * @param[in] action The end action.
    */
@@ -244,22 +244,40 @@ public:
   EndAction GetEndAction() const;
 
   /**
-   * @brief Set the destroy action of the animation.
+   * @brief Deprecated
    *
-   * If the animation is destroyed this action is performed on the following update.
-   * Default destroy action is bake
    * @param[in] action The destroy action.
+   *
+   * @deprecated Use SetEndAction
    */
   void SetDestroyAction(EndAction action);
 
   /**
-   * @brief Returns the destroy action of the animation.
+   * @brief Deprecated
    *
    * @return The destroy action.
+   *
+   * @deprecated Use GetEndAction
    */
   EndAction GetDestroyAction() const;
 
   /**
+   * @brief Set the disconnect action.
+   *
+   * If any of the animated property owners are disconnected from the stage, then this action is performed.
+   * Default action is to BakeFinal.
+   * @param[in] disconnectAction The disconnect action.
+   */
+  void SetDisconnectAction( EndAction disconnectAction );
+
+  /**
+   * @brief Returns the disconnect action.
+   *
+   * @return The disconnect action.
+   */
+  EndAction GetDisconnectAction() const;
+
+  /**
    * @brief Set the default alpha function for an animation.
    *
    * This is applied to individual property animations, if no further alpha functions are supplied.