410929b01bdf6e1d9e820e3d7f4c7d80a9cebe22
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / animation-impl.h
1 #ifndef DALI_INTERNAL_ANIMATION_H
2 #define DALI_INTERNAL_ANIMATION_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // INTERNAL INCLUDES
22 #include <dali/devel-api/animation/animation-devel.h>
23 #include <dali/devel-api/common/owner-container.h>
24 #include <dali/internal/event/animation/key-frames-impl.h>
25 #include <dali/internal/event/common/event-thread-services.h>
26 #include <dali/public-api/animation/animation.h>
27 #include <dali/public-api/common/vector-wrapper.h>
28 #include <dali/public-api/object/base-object.h>
29 #include <dali/public-api/object/ref-object.h>
30
31 namespace Dali
32 {
33 namespace Internal
34 {
35 namespace SceneGraph
36 {
37 class Animation;
38 class UpdateManager;
39 } // namespace SceneGraph
40
41 class Actor;
42 class Animation;
43 class AnimationPlaylist;
44 class AnimatorConnectorBase;
45 class Object;
46 class Path;
47
48 using AnimationPtr       = IntrusivePtr<Animation>;
49 using AnimationContainer = std::vector<AnimationPtr>;
50
51 using AnimationIter      = AnimationContainer::iterator;
52 using AnimationConstIter = AnimationContainer::const_iterator;
53
54 /**
55  * Animation is a proxy for a SceneGraph::Animation object.
56  * The UpdateManager owns the Animation object, but the lifetime of the animation is
57  * indirectly controlled by the Animation.
58  */
59 class Animation : public BaseObject
60 {
61 public:
62   enum Type : uint8_t
63   {
64     TO,     ///< Animating TO the given value
65     BY,     ///< Animating BY the given value
66     BETWEEN ///< Animating BETWEEN key-frames
67   };
68
69   using EndAction     = Dali::Animation::EndAction;
70   using Interpolation = Dali::Animation::Interpolation;
71
72   /**
73    * Create a new Animation object.
74    * @param[in] durationSeconds The duration of the animation.
75    * @return A smart-pointer to the newly allocated Animation.
76    */
77   static AnimationPtr New(float durationSeconds);
78
79   /**
80    * @copydoc Dali::Animation::SetDuration()
81    */
82   void SetDuration(float seconds);
83
84   /**
85    * @copydoc Dali::DevelAnimation::SetProgressNotification()
86    */
87   void SetProgressNotification(float progress);
88
89   /**
90    * @copydoc Dali::DevelAnimation::GetProgressNotification()
91    */
92   float GetProgressNotification();
93
94   /**
95    * @copydoc Dali::Animation::GetDuration()
96    */
97   float GetDuration() const;
98
99   /**
100    * @copydoc Dali::Animation::SetLooping()
101    */
102   void SetLooping(bool on);
103
104   /**
105    * @copydoc Dali::Animation::SetLoopCount()
106    */
107   void SetLoopCount(int32_t count);
108
109   /**
110    * @copydoc Dali::Animation::GetLoopCount()
111    */
112   int32_t GetLoopCount();
113
114   /**
115    * @copydoc Dali::Animation::GetCurrentLoop()
116    */
117   int32_t GetCurrentLoop();
118
119   /**
120    * @copydoc Dali::Animation::IsLooping()
121    */
122   bool IsLooping() const;
123
124   /**
125    * @copydoc Dali::Animation::SetEndAction()
126    */
127   void SetEndAction(EndAction action);
128
129   /**
130    * @copydoc Dali::Animation::GetEndAction()
131    */
132   EndAction GetEndAction() const;
133
134   /**
135    * @copydoc Dali::Animation::SetDisconnectAction()
136    */
137   void SetDisconnectAction(EndAction action);
138
139   /**
140    * @copydoc Dali::Animation::GetDisconnectAction()
141    */
142   EndAction GetDisconnectAction() const;
143
144   /**
145    * @copydoc Dali::Animation::SetDefaultAlphaFunction()
146    */
147   void SetDefaultAlphaFunction(AlphaFunction alpha)
148   {
149     mDefaultAlpha = alpha;
150   }
151
152   /**
153    * @copydoc Dali::Animation::GetDefaultAlphaFunction()
154    */
155   AlphaFunction GetDefaultAlphaFunction() const
156   {
157     return mDefaultAlpha;
158   }
159
160   /**
161    * @copydoc Dali::Animation::Play()
162    */
163   void Play();
164
165   /**
166    * @copydoc Dali::Animation::PlayFrom()
167    */
168   void PlayFrom(float progress);
169
170   /**
171    * @copydoc Dali::Animation::PlayAfter()
172    */
173   void PlayAfter(float delaySeconds);
174
175   /**
176    * @copydoc Dali::Animation::Pause()
177    */
178   void Pause();
179
180   /**
181    * @copydoc Dali::Animation::GetState()
182    */
183   Dali::Animation::State GetState() const;
184
185   /**
186    * @copydoc Dali::Animation::Stop()
187    */
188   void Stop();
189
190   /**
191    * @copydoc Dali::Animation::Clear()
192    */
193   void Clear();
194
195   /**
196    * Query whether a Finished signal should be emitted for this animation.
197    * This should only be called by NotificationManager, before signals are emitted.
198    * @post HasFinished() will return false on subsequent calls, until the animation is replayed to completion.
199    */
200   bool HasFinished();
201
202   /**
203    * @copydoc Dali::Animation::FinishedSignal()
204    */
205   Dali::Animation::AnimationSignalType& FinishedSignal();
206
207   /**
208    * @copydoc Dali::DevelAnimation::ProgressHasBeenReachedSignal()
209    */
210   Dali::Animation::AnimationSignalType& ProgressReachedSignal();
211
212   /**
213    * Emit the Finished signal
214    */
215   void EmitSignalFinish();
216
217   /**
218    * Emit the ProgressReached signal
219    */
220   void EmitSignalProgressReached();
221
222   /**
223    * Connects a callback function with the object's signals.
224    * @param[in] object The object providing the signal.
225    * @param[in] tracker Used to disconnect the signal.
226    * @param[in] signalName The signal to connect to.
227    * @param[in] functor A newly allocated FunctorDelegate.
228    * @return True if the signal was connected.
229    * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
230    */
231   static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
232
233   /**
234    * Performs actions as requested using the action name.
235    * @param[in] object The object on which to perform the action.
236    * @param[in] actionName The action to perform.
237    * @param[in] attributes The attributes with which to perfrom this action.
238    * @return true if action was done
239    */
240   static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes);
241
242   /**
243    * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue)
244    */
245   void AnimateBy(Property& target, Property::Value relativeValue);
246
247   /**
248    * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha)
249    */
250   void AnimateBy(Property& target, Property::Value relativeValue, AlphaFunction alpha);
251
252   /**
253    * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, TimePeriod period)
254    */
255   void AnimateBy(Property& target, Property::Value relativeValue, TimePeriod period);
256
257   /**
258    * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period)
259    */
260   void AnimateBy(Property& target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period);
261
262   /**
263    * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue)
264    */
265   void AnimateTo(Property& target, Property::Value destinationValue);
266
267   /**
268    * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha)
269    */
270   void AnimateTo(Property& target, Property::Value destinationValue, AlphaFunction alpha);
271
272   /**
273    * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, TimePeriod period)
274    */
275   void AnimateTo(Property& target, Property::Value destinationValue, TimePeriod period);
276
277   /**
278    * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period)
279    */
280   void AnimateTo(Property& target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period);
281
282   /**
283    * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames)
284    */
285   void AnimateBetween(Property target, const KeyFrames& keyFrames);
286
287   /**
288    * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, Interpolation interpolation)
289    */
290   void AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation);
291
292   /**
293    * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period)
294    */
295   void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period);
296
297   /**
298    * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
299    */
300   void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation);
301
302   /**
303    * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha)
304    */
305   void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha);
306
307   /**
308    * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
309    */
310   void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation);
311
312   /**
313    * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
314    */
315   void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period);
316
317   /**
318    * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation )
319    */
320   void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation);
321
322   // Actor-specific convenience functions
323
324   /**
325    * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward )
326    */
327   void Animate(Actor& actor, const Path& path, const Vector3& forward);
328
329   /**
330    * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha )
331    */
332   void Animate(Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha);
333
334   /**
335    * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period )
336    */
337   void Animate(Actor& actor, const Path& path, const Vector3& forward, TimePeriod period);
338
339   /**
340    * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
341    */
342   void Animate(Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period);
343
344   /**
345    * @copydoc Dali::Animation::Show()
346    */
347   void Show(Actor& actor, float delaySeconds);
348
349   /**
350    * @copydoc Dali::Animation::Hide()
351    */
352   void Hide(Actor& actor, float delaySeconds);
353
354   /**
355    * @copydoc Dali::Animation::SetCurrentProgress()
356    */
357   void SetCurrentProgress(float progress);
358
359   /**
360    * @copydoc Dali::Animation::GetCurrentProgress()
361    */
362   float GetCurrentProgress();
363
364   /**
365    * @copydoc Dali::Animation::SetSpeedFactor()
366    */
367   void SetSpeedFactor(float factor);
368
369   /**
370    * @copydoc Dali::Animation::GetSpeedFactor()
371    */
372   float GetSpeedFactor() const;
373
374   /**
375    * @copydoc Dali::Animation::SetPlayRange()
376    */
377   void SetPlayRange(const Vector2& range);
378
379   /**
380    * @copydoc Dali::Animation::GetPlayRange()
381    */
382   Vector2 GetPlayRange() const;
383
384   /**
385    * @copydoc Dali::Animation::SetLoopingMode()
386    */
387   void SetLoopingMode(Dali::Animation::LoopingMode loopingMode);
388
389   /**
390    * @copydoc Dali::Animation::GetLoopingMode()
391    */
392   Dali::Animation::LoopingMode GetLoopingMode() const;
393
394 public: // For connecting animators to animations
395   /**
396    * Add an animator connector.
397    * @param[in] connector The animator connector.
398    */
399   void AddAnimatorConnector(AnimatorConnectorBase* connector);
400
401   /**
402    * Retrieve the SceneGraph::Animation object.
403    * @return The animation.
404    */
405   const SceneGraph::Animation* GetSceneObject()
406   {
407     return mAnimation;
408   }
409
410   /**
411    * Retrieve the event thread services object
412    * @return The interface for sending messages to the scene graph
413    */
414   EventThreadServices& GetEventThreadServices()
415   {
416     return mEventThreadServices;
417   }
418
419 protected:
420   /**
421    * Construct a new Animation.
422    * @param[in] eventThreadServices The interface for sending messages to the scene graph
423    * @param[in] playlist The list of currently playing animations.
424    * @param[in] durationSeconds The duration of the animation in seconds.
425    * @param[in] endAction The action to perform when the animation ends.
426    * @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected.
427    * @param[in] defaultAlpha The default alpha function to apply to animators.
428    */
429   Animation(EventThreadServices& eventThreadServices,
430             AnimationPlaylist&   playlist,
431             float                durationSeconds,
432             EndAction            endAction,
433             EndAction            disconnectAction,
434             AlphaFunction        defaultAlpha);
435
436   /**
437    * Second-phase constructor.
438    */
439   void Initialize();
440
441   /**
442    * Helper to create a scene-graph animation
443    */
444   void CreateSceneObject();
445
446   /**
447    * Helper to create a scene-graph animation
448    */
449   void DestroySceneObject();
450
451   /**
452    * A reference counted object may only be deleted by calling Unreference()
453    */
454   ~Animation() override;
455
456 private:
457   /**
458    * Extends the duration when an animator is added with TimePeriod that exceeds current duration.
459    * @param[in] timePeriod The time period for an animator.
460    */
461   void ExtendDuration(const TimePeriod& timePeriod);
462
463   // Undefined
464   Animation(const Animation&);
465
466   // Undefined
467   Animation& operator=(const Animation& rhs);
468
469 private:
470   struct ConnectorTargetValues
471   {
472     ConnectorTargetValues() = default;
473
474     ConnectorTargetValues(Property::Value value, TimePeriod time, std::size_t index, Animation::Type type)
475     : targetValue(std::move(value)),
476       timePeriod(time),
477       connectorIndex(index),
478       animatorType(type)
479     {
480     }
481
482     Property::Value targetValue;
483     TimePeriod      timePeriod{0.f};
484     std::size_t     connectorIndex{0};
485     Animation::Type animatorType{TO};
486   };
487
488   enum class Notify : uint8_t
489   {
490     USE_CURRENT_VALUE,   ///< Set the current value for the property
491     USE_TARGET_VALUE,    ///< Set the animator's target value for the property
492     FORCE_CURRENT_VALUE, ///< Set the current value for the property even if the end action is to discard
493   };
494
495 private:
496   /**
497    * Compares the end times of the animators returning true if lhs end time is less than rhs end time.
498    * @param[in] lhs The first comparator
499    * @param[in] rhs The second comparator
500    * @return True if end time of lhs is less, false otherwise.
501    */
502   static bool CompareConnectorEndTimes(const ConnectorTargetValues& lhs, const ConnectorTargetValues& rhs);
503
504   /**
505    * Notifies all the objects whose properties are being animated.
506    * @param[in] notifyValueType Whether we should set the current or target value
507    */
508   void NotifyObjects(Notify notifyValueType);
509
510   /**
511    * Sends message to SceneGraph with final progress value
512    */
513   void SendFinalProgressNotificationMessage();
514
515 private:
516   using AnimatorConnectorContainer     = OwnerContainer<AnimatorConnectorBase*>;
517   using ConnectorTargetValuesContainer = std::vector<ConnectorTargetValues>;
518
519   const SceneGraph::Animation* mAnimation{nullptr};
520
521   EventThreadServices& mEventThreadServices;
522   AnimationPlaylist&   mPlaylist;
523
524   Dali::Animation::AnimationSignalType mFinishedSignal{};
525   Dali::Animation::AnimationSignalType mProgressReachedSignal{};
526
527   AnimatorConnectorContainer     mConnectors{};            ///< Owned by the Animation
528   ConnectorTargetValuesContainer mConnectorTargetValues{}; //< Used to store animating property target value information
529
530   AlphaFunction          mDefaultAlpha;
531   Vector2                mPlayRange{0.0f, 1.0f};
532   float                  mDurationSeconds;
533   float                  mSpeedFactor{1.0f};
534   int32_t                mNotificationCount{0}; ///< Keep track of how many Finished signals have been emitted.
535   int32_t                mLoopCount{1};
536   int32_t                mCurrentLoop{0};
537   float                  mProgressReachedMarker{0.0f};
538   float                  mDelaySeconds{0.0f};
539   EndAction              mEndAction;
540   EndAction              mDisconnectAction;
541   Dali::Animation::State mState{Dali::Animation::STOPPED};
542   bool                   mAutoReverseEnabled{false}; ///< Flag to identify that the looping mode is auto reverse.
543 };
544
545 } // namespace Internal
546
547 // Helpers for public-api forwarding methods
548
549 inline Internal::Animation& GetImplementation(Dali::Animation& animation)
550 {
551   DALI_ASSERT_ALWAYS(animation && "Animation handle is empty");
552
553   BaseObject& handle = animation.GetBaseObject();
554
555   return static_cast<Internal::Animation&>(handle);
556 }
557
558 inline const Internal::Animation& GetImplementation(const Dali::Animation& animation)
559 {
560   DALI_ASSERT_ALWAYS(animation && "Animation handle is empty");
561
562   const BaseObject& handle = animation.GetBaseObject();
563
564   return static_cast<const Internal::Animation&>(handle);
565 }
566
567 } // namespace Dali
568
569 #endif // DALI_INTERNAL_ANIMATION_H