[Tizen] Use Dali::KeyFrames during AnimateBetween
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / animation-impl.h
index 7239ed4..73972b0 100644 (file)
@@ -1,8 +1,8 @@
-#ifndef __DALI_INTERNAL_ANIMATION_H__
-#define __DALI_INTERNAL_ANIMATION_H__
+#ifndef DALI_INTERNAL_ANIMATION_H
+#define DALI_INTERNAL_ANIMATION_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 // INTERNAL INCLUDES
-#include <dali/public-api/common/vector-wrapper.h>
-#include <dali/public-api/object/ref-object.h>
+#include <dali/devel-api/animation/animation-devel.h>
+#include <dali/devel-api/common/owner-container.h>
+#include <dali/internal/event/common/event-thread-services.h>
 #include <dali/public-api/animation/animation.h>
+#include <dali/public-api/animation/key-frames.h>
+#include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/object/base-object.h>
-#include <dali/internal/event/animation/animator-connector-base.h>
-#include <dali/internal/event/animation/key-frames-impl.h>
-#include <dali/internal/event/animation/path-impl.h>
+#include <dali/public-api/object/ref-object.h>
 
 namespace Dali
 {
-
 namespace Internal
 {
-
 namespace SceneGraph
 {
 class Animation;
 class UpdateManager;
-}
+} // namespace SceneGraph
 
 class Actor;
 class Animation;
 class AnimationPlaylist;
+class AnimatorConnectorBase;
 class Object;
+class Path;
 
-typedef IntrusivePtr<Animation> AnimationPtr;
-typedef std::vector<AnimationPtr> AnimationContainer;
+using AnimationPtr       = IntrusivePtr<Animation>;
+using AnimationContainer = std::vector<AnimationPtr>;
 
-typedef AnimationContainer::iterator AnimationIter;
-typedef AnimationContainer::const_iterator AnimationConstIter;
+using AnimationIter      = AnimationContainer::iterator;
+using AnimationConstIter = AnimationContainer::const_iterator;
 
 /**
  * Animation is a proxy for a SceneGraph::Animation object.
@@ -58,11 +59,15 @@ typedef AnimationContainer::const_iterator AnimationConstIter;
 class Animation : public BaseObject
 {
 public:
+  enum Type : uint8_t
+  {
+    TO,     ///< Animating TO the given value
+    BY,     ///< Animating BY the given value
+    BETWEEN ///< Animating BETWEEN key-frames
+  };
 
-  typedef Dali::Animation::EndAction EndAction;
-  typedef Dali::Animation::Interpolation Interpolation;
-
-  typedef void (*FinishedCallback)(Object* object);
+  using EndAction     = Dali::Animation::EndAction;
+  using Interpolation = Dali::Animation::Interpolation;
 
   /**
    * Create a new Animation object.
@@ -77,6 +82,16 @@ public:
   void SetDuration(float seconds);
 
   /**
+   * @copydoc Dali::DevelAnimation::SetProgressNotification()
+   */
+  void SetProgressNotification(float progress);
+
+  /**
+   * @copydoc Dali::DevelAnimation::GetProgressNotification()
+   */
+  float GetProgressNotification();
+
+  /**
    * @copydoc Dali::Animation::GetDuration()
    */
   float GetDuration() const;
@@ -89,17 +104,17 @@ public:
   /**
    * @copydoc Dali::Animation::SetLoopCount()
    */
-  void SetLoopCount(int count);
+  void SetLoopCount(int32_t count);
 
   /**
    * @copydoc Dali::Animation::GetLoopCount()
    */
-  int GetLoopCount();
+  int32_t GetLoopCount();
 
   /**
    * @copydoc Dali::Animation::GetCurrentLoop()
    */
-  int GetCurrentLoop();
+  int32_t GetCurrentLoop();
 
   /**
    * @copydoc Dali::Animation::IsLooping()
@@ -150,7 +165,12 @@ public:
   /**
    * @copydoc Dali::Animation::PlayFrom()
    */
-  void PlayFrom( float progress );
+  void PlayFrom(float progress);
+
+  /**
+   * @copydoc Dali::Animation::PlayAfter()
+   */
+  void PlayAfter(float delaySeconds);
 
   /**
    * @copydoc Dali::Animation::Pause()
@@ -185,11 +205,21 @@ public:
   Dali::Animation::AnimationSignalType& FinishedSignal();
 
   /**
+   * @copydoc Dali::DevelAnimation::ProgressHasBeenReachedSignal()
+   */
+  Dali::Animation::AnimationSignalType& ProgressReachedSignal();
+
+  /**
    * Emit the Finished signal
    */
   void EmitSignalFinish();
 
   /**
+   * Emit the ProgressReached signal
+   */
+  void EmitSignalProgressReached();
+
+  /**
    * Connects a callback function with the object's signals.
    * @param[in] object The object providing the signal.
    * @param[in] tracker Used to disconnect the signal.
@@ -198,7 +228,7 @@ public:
    * @return True if the signal was connected.
    * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
    */
-  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+  static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
 
   /**
    * Performs actions as requested using the action name.
@@ -210,124 +240,106 @@ public:
   static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes);
 
   /**
-   * This callback is intended for internal use only, to avoid the overhead of using a signal.
-   * @param[in] callback The callback function to connect.
-   * @param[in] object The internal object requesting the callback, or NULL.
-   */
-  void SetFinishedCallback( FinishedCallback callback, Object* object );
-
-  /**
    * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue)
    */
-  void AnimateBy(Property& target, Property::Value& relativeValue);
+  void AnimateBy(Property& target, Property::Value relativeValue);
 
   /**
    * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha)
    */
-  void AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha);
+  void AnimateBy(Property& target, Property::Value relativeValue, AlphaFunction alpha);
 
   /**
    * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, TimePeriod period)
    */
-  void AnimateBy(Property& target, Property::Value& relativeValue, TimePeriod period);
+  void AnimateBy(Property& target, Property::Value relativeValue, TimePeriod period);
 
   /**
    * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period)
    */
-  void AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period);
+  void AnimateBy(Property& target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period);
 
   /**
    * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue)
    */
-  void AnimateTo(Property& target, Property::Value& destinationValue);
+  void AnimateTo(Property& target, Property::Value destinationValue);
 
   /**
    * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha)
    */
-  void AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha);
+  void AnimateTo(Property& target, Property::Value destinationValue, AlphaFunction alpha);
 
   /**
    * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, TimePeriod period)
    */
-  void AnimateTo(Property& target, Property::Value& destinationValue, TimePeriod period);
+  void AnimateTo(Property& target, Property::Value destinationValue, TimePeriod period);
 
   /**
    * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period)
    */
-  void AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period);
-
-  /**
-   * Animate a property to a destination value.
-   * @param [in] targetObject The target object to animate.
-   * @param [in] targetPropertyIndex The index of the target property.
-   * @param [in] componentIndex Index to a sub component of a property, for use with Vector2, Vector3 and Vector4
-   * @param [in] destinationValue The destination value.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] period The effect will occur during this time period.
-   */
-  void AnimateTo(Object& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period);
+  void AnimateTo(Property& target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period);
 
   /**
-   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames)
+   * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames)
    */
-  void AnimateBetween(Property target, const KeyFrames& keyFrames);
+  void AnimateBetween(Property target, Dali::KeyFrames keyFrames);
 
   /**
-   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, Interpolation interpolation)
+   * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, Interpolation interpolation)
    */
-  void AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation );
+  void AnimateBetween(Property target, Dali::KeyFrames keyFrames, Interpolation interpolation);
 
   /**
-   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period)
+   * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, TimePeriod period)
    */
-  void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period);
+  void AnimateBetween(Property target, Dali::KeyFrames keyFrames, TimePeriod period);
 
   /**
-   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
+   * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, TimePeriod period, Interpolation interpolation)
    */
-  void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation);
+  void AnimateBetween(Property target, Dali::KeyFrames keyFrames, TimePeriod period, Interpolation interpolation);
 
   /**
-   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha)
+   * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha)
    */
-  void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha);
+  void AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha);
 
   /**
-   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
+   * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, Interpolation interpolation)
    */
-  void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation);
+  void AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, Interpolation interpolation);
 
   /**
-   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
+   * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, TimePeriod period)
    */
-  void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period);
+  void AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, TimePeriod period);
 
   /**
-   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation )
+   * @copydoc Dali::Animation::AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation )
    */
-  void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation );
+  void AnimateBetween(Property target, Dali::KeyFrames keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation);
 
   // Actor-specific convenience functions
 
   /**
    * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward )
    */
-  void Animate( Actor& actor, const Path& path, const Vector3& forward );
+  void Animate(Actor& actor, const Path& path, const Vector3& forward);
 
   /**
    * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha )
    */
-  void Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha );
+  void Animate(Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha);
 
   /**
    * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period )
    */
-  void Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period );
+  void Animate(Actor& actor, const Path& path, const Vector3& forward, TimePeriod period);
 
   /**
    * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
    */
-  void Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period);
+  void Animate(Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period);
 
   /**
    * @copydoc Dali::Animation::Show()
@@ -339,43 +351,62 @@ public:
    */
   void Hide(Actor& actor, float delaySeconds);
 
-  /*
+  /**
    * @copydoc Dali::Animation::SetCurrentProgress()
    */
   void SetCurrentProgress(float progress);
 
-  /*
+  /**
    * @copydoc Dali::Animation::GetCurrentProgress()
    */
   float GetCurrentProgress();
 
-  /*
+  /**
    * @copydoc Dali::Animation::SetSpeedFactor()
    */
-  void SetSpeedFactor( float factor );
+  void SetSpeedFactor(float factor);
 
-  /*
+  /**
    * @copydoc Dali::Animation::GetSpeedFactor()
    */
   float GetSpeedFactor() const;
 
-  /*
+  /**
    * @copydoc Dali::Animation::SetPlayRange()
    */
-  void SetPlayRange( const Vector2& range );
+  void SetPlayRange(const Vector2& range);
 
-  /*
-   * @copydoc Dali::Animation::GetPlayRange
+  /**
+   * @copydoc Dali::Animation::GetPlayRange()
    */
   Vector2 GetPlayRange() const;
 
-public: // For connecting animators to animations
+  /**
+   * @copydoc Dali::Animation::SetBlendPoint()
+   */
+  void SetBlendPoint(float blendPoint);
 
   /**
+   * @copydoc Dali::Animation::GetBlendPoint()
+   */
+  float GetBlendPoint() const;
+
+  /**
+   * @copydoc Dali::Animation::SetLoopingMode()
+   */
+  void SetLoopingMode(Dali::Animation::LoopingMode loopingMode);
+
+  /**
+   * @copydoc Dali::Animation::GetLoopingMode()
+   */
+  Dali::Animation::LoopingMode GetLoopingMode() const;
+
+public: // For connecting animators to animations
+  /**
    * Add an animator connector.
    * @param[in] connector The animator connector.
    */
-  void AddAnimatorConnector( AnimatorConnectorBase* connector );
+  void AddAnimatorConnector(AnimatorConnectorBase* connector);
 
   /**
    * Retrieve the SceneGraph::Animation object.
@@ -396,7 +427,6 @@ public: // For connecting animators to animations
   }
 
 protected:
-
   /**
    * Construct a new Animation.
    * @param[in] eventThreadServices The interface for sending messages to the scene graph
@@ -406,12 +436,12 @@ protected:
    * @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( EventThreadServices& eventThreadServices,
-             AnimationPlaylist& playlist,
-             float durationSeconds,
-             EndAction endAction,
-             EndAction disconnectAction,
-             AlphaFunction defaultAlpha);
+  Animation(EventThreadServices& eventThreadServices,
+            AnimationPlaylist&   playlist,
+            float                durationSeconds,
+            EndAction            endAction,
+            EndAction            disconnectAction,
+            AlphaFunction        defaultAlpha);
 
   /**
    * Second-phase constructor.
@@ -431,15 +461,14 @@ protected:
   /**
    * A reference counted object may only be deleted by calling Unreference()
    */
-  virtual ~Animation();
+  ~Animation() override;
 
 private:
-
   /**
    * Extends the duration when an animator is added with TimePeriod that exceeds current duration.
    * @param[in] timePeriod The time period for an animator.
    */
-  void ExtendDuration( const TimePeriod& timePeriod );
+  void ExtendDuration(const TimePeriod& timePeriod);
 
   // Undefined
   Animation(const Animation&);
@@ -448,40 +477,106 @@ private:
   Animation& operator=(const Animation& rhs);
 
 private:
-
   struct ConnectorTargetValues
   {
-    unsigned int connectorIndex;
+    ConnectorTargetValues() = default;
+
+    ConnectorTargetValues(Property::Value value, TimePeriod time, std::size_t index, Animation::Type type)
+    : targetValue(std::move(value)),
+      timePeriod(time),
+      connectorIndex(index),
+      animatorType(type)
+    {
+    }
+
+    // Move operations
+    ConnectorTargetValues(ConnectorTargetValues&& rhs) noexcept
+    : targetValue(std::move(rhs.targetValue)),
+      timePeriod(std::move(rhs.timePeriod)),
+      connectorIndex(rhs.connectorIndex),
+      animatorType(rhs.animatorType)
+    {
+    }
+
+    ConnectorTargetValues& operator=(ConnectorTargetValues&& rhs) noexcept
+    {
+      targetValue    = std::move(rhs.targetValue);
+      timePeriod     = std::move(rhs.timePeriod);
+      connectorIndex = rhs.connectorIndex;
+      animatorType   = rhs.animatorType;
+      return *this;
+    }
+
     Property::Value targetValue;
+    TimePeriod      timePeriod{0.f};
+    std::size_t     connectorIndex{0};
+    Animation::Type animatorType{TO};
   };
 
-  EventThreadServices& mEventThreadServices;
-  AnimationPlaylist& mPlaylist;
-
-  const SceneGraph::Animation* mAnimation;
+  enum class Notify : uint8_t
+  {
+    USE_CURRENT_VALUE,   ///< Set the current value for the property
+    USE_TARGET_VALUE,    ///< Set the animator's target value for the property
+    FORCE_CURRENT_VALUE, ///< Set the current value for the property even if the end action is to discard
+  };
 
-  int mNotificationCount; ///< Keep track of how many Finished signals have been emitted.
+private:
+  /**
+   * Compares the end times of the animators returning true if lhs end time is less than rhs end time.
+   * @param[in] lhs The first comparator
+   * @param[in] rhs The second comparator
+   * @return True if end time of lhs is less, false otherwise.
+   */
+  static bool CompareConnectorEndTimes(const ConnectorTargetValues& lhs, const ConnectorTargetValues& rhs);
 
-  Dali::Animation::AnimationSignalType mFinishedSignal;
+  /**
+   * Notifies all the objects whose properties are being animated.
+   * @param[in] notifyValueType Whether we should set the current or target value
+   */
+  void NotifyObjects(Notify notifyValueType);
 
-  FinishedCallback mFinishedCallback;
-  Object* mFinishedCallbackObject;
+  /**
+   * Sends message to SceneGraph with final progress value
+   */
+  void SendFinalProgressNotificationMessage();
 
-  AnimatorConnectorContainer mConnectors; ///< Owned by the Animation
+  /**
+   * @brief Append ConnectorTargetValues into the container.
+   *
+   * @param[in] connectorTargetValues moved ConnectorTargetValues that will be append end of container
+   */
+  void AppendConnectorTargetValues(ConnectorTargetValues&& connectorTargetValues);
 
-  std::vector< ConnectorTargetValues > mConnectorActorTargetValues; //< Store Actor target values and matchinf connector index that need to set value on Animation::Play
+private:
+  using AnimatorConnectorContainer     = OwnerContainer<AnimatorConnectorBase*>;
+  using ConnectorTargetValuesContainer = std::vector<ConnectorTargetValues>;
 
-  // Cached for public getters
-  float mDurationSeconds;
-  float mSpeedFactor;
-  int mLoopCount;
-  int mCurrentLoop;
-  Vector2 mPlayRange;
-  EndAction mEndAction;
-  EndAction mDisconnectAction;
-  AlphaFunction mDefaultAlpha;
-  Dali::Animation::State mState;
+  const SceneGraph::Animation* mAnimation{nullptr};
 
+  EventThreadServices& mEventThreadServices;
+  AnimationPlaylist&   mPlaylist;
+
+  Dali::Animation::AnimationSignalType mFinishedSignal{};
+  Dali::Animation::AnimationSignalType mProgressReachedSignal{};
+
+  AnimatorConnectorContainer     mConnectors{};            ///< Owned by the Animation
+  ConnectorTargetValuesContainer mConnectorTargetValues{}; //< Used to store animating property target value information
+
+  AlphaFunction          mDefaultAlpha;
+  Vector2                mPlayRange{0.0f, 1.0f};
+  float                  mBlendPoint{0.0f};
+  float                  mDurationSeconds;
+  float                  mSpeedFactor{1.0f};
+  int32_t                mNotificationCount{0}; ///< Keep track of how many Finished signals have been emitted.
+  int32_t                mLoopCount{1};
+  int32_t                mCurrentLoop{0};
+  float                  mProgressReachedMarker{0.0f};
+  float                  mDelaySeconds{0.0f};
+  EndAction              mEndAction;
+  EndAction              mDisconnectAction;
+  Dali::Animation::State mState{Dali::Animation::STOPPED};
+  bool                   mAutoReverseEnabled{false};                ///< Flag to identify that the looping mode is auto reverse.
+  bool                   mConnectorTargetValuesSortRequired{false}; ///< Flag to whether we need to sort mConnectorTargetValues or not
 };
 
 } // namespace Internal
@@ -490,7 +585,7 @@ private:
 
 inline Internal::Animation& GetImplementation(Dali::Animation& animation)
 {
-  DALI_ASSERT_ALWAYS( animation && "Animation handle is empty" );
+  DALI_ASSERT_ALWAYS(animation && "Animation handle is empty");
 
   BaseObject& handle = animation.GetBaseObject();
 
@@ -499,7 +594,7 @@ inline Internal::Animation& GetImplementation(Dali::Animation& animation)
 
 inline const Internal::Animation& GetImplementation(const Dali::Animation& animation)
 {
-  DALI_ASSERT_ALWAYS( animation && "Animation handle is empty" );
+  DALI_ASSERT_ALWAYS(animation && "Animation handle is empty");
 
   const BaseObject& handle = animation.GetBaseObject();
 
@@ -508,4 +603,4 @@ inline const Internal::Animation& GetImplementation(const Dali::Animation& anima
 
 } // namespace Dali
 
-#endif // __DALI_INTERNAL_ANIMATION_H__
+#endif // DALI_INTERNAL_ANIMATION_H