Reduce overhead of notification (like AnimationFinished, PropertyNotify)
[platform/core/uifw/dali-core.git] / dali / internal / update / animation / scene-graph-animation.h
1 #ifndef DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H
2 #define DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H
3
4 /*
5  * Copyright (c) 2023 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/public-api/animation/animation.h>
23
24 #include <dali/internal/common/buffer-index.h>
25 #include <dali/internal/common/message.h>
26 #include <dali/internal/event/common/event-thread-services.h>
27 #include <dali/internal/event/common/notifier-interface.h>
28 #include <dali/internal/update/animation/scene-graph-animator.h>
29
30 namespace Dali
31 {
32 namespace Internal
33 {
34 namespace SceneGraph
35 {
36 /**
37  * Animations are used to change the properties of scene graph objects, as part of a scene
38  * managers "update" phase. An animation is a container of Animator objects; the actual setting
39  * of object values is done by the animators.
40  */
41 class Animation : public NotifierInterface
42 {
43 public:
44   using EndAction = Dali::Animation::EndAction;
45
46   enum State
47   {
48     Stopped,
49     Playing,
50     Paused,
51     Destroyed
52   };
53
54   /**
55    * Construct a new Animation.
56    * @param[in] durationSeconds The duration of the animation in seconds.
57    * @param[in] speedFactor Multiplier to the animation velocity.
58    * @param[in] playRange Minimum and maximum progress between which the animation will play.
59    * @param[in] loopCount The number of times the animation will loop. ( See SetLoopCount() )
60    * @param[in] endAction The action to perform when the animation ends.
61    * @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected.
62    * @return A new Animation
63    */
64   static Animation* New(float durationSeconds, float speedFactor, const Vector2& playRange, int32_t loopCount, EndAction endAction, EndAction disconnectAction);
65
66   /**
67    * Virtual destructor
68    */
69   virtual ~Animation();
70
71   /**
72    * Overriden delete operator
73    * Deletes the animation from its global memory pool
74    */
75   void operator delete(void* ptr);
76
77   /**
78    * Set the duration of an animation.
79    * @pre durationSeconds must be greater than zero.
80    * @param[in] durationSeconds The duration in seconds.
81    */
82   void SetDuration(float durationSeconds);
83
84   /**
85    * Set the progress marker to trigger notification
86    * @param[in] progress percent of progress to trigger notification, 0.0f < progress <= 1.0f
87    */
88   void SetProgressNotification(float progress);
89
90   /**
91    * Retrieve the duration of the animation.
92    * @return The duration in seconds.
93    */
94   float GetDuration() const
95   {
96     return mDurationSeconds;
97   }
98
99   /**
100    * Retrieve the current progress of the animation.
101    * @return The current progress as a normalized value between [0,1].
102    */
103   float GetCurrentProgress() const
104   {
105     if(mDurationSeconds > 0.0f)
106     {
107       return mElapsedSeconds / mDurationSeconds;
108     }
109
110     return 0.0f;
111   }
112
113   /**
114    * Sets the progress of the animation.
115    * @param[in] The new progress as a normalized value between [0,1]
116    */
117   void SetCurrentProgress(float progress)
118   {
119     mElapsedSeconds = mDurationSeconds * progress;
120   }
121
122   /**
123    * Specifies a speed factor for the animation.
124    * @param[in] factor A value which will multiply the velocity
125    */
126   void SetSpeedFactor(float factor)
127   {
128     mSpeedFactor = factor;
129   }
130
131   /**
132    * Set the animation loop count.
133    * 0 is loop forever, N loop play N times
134    * @param[in] loopCount The loop count
135    */
136   void SetLoopCount(int32_t loopCount);
137
138   /**
139    * Query whether the animation will loop.
140    * @return True if the animation will loop.
141    */
142   bool IsLooping() const
143   {
144     return mLoopCount != 1;
145   }
146
147   /**
148    * Get the loop count
149    * @return the loop count
150    */
151   int32_t GetLoopCount() const
152   {
153     return mLoopCount;
154   }
155
156   /**
157    * Set the end action of the animation.
158    * @param[in] action The end action.
159    */
160   void SetEndAction(EndAction action);
161
162   /**
163    * Retrieve the action performed when the animation ends.
164    * @return The end action.
165    */
166   EndAction GetEndAction()
167   {
168     return mEndAction;
169   }
170
171   /**
172    * Set the disconnect action of the animation when connected objects are disconnected.
173    * This action is performed during the next update when
174    * the connected object is disconnected.
175    * @param[in] action The disconnect action.
176    */
177   void SetDisconnectAction(EndAction action);
178
179   /**
180    * Retrieve the action performed when the animation is destroyed.
181    * @return The destroy action.
182    */
183   EndAction GetDisconnectAction()
184   {
185     return mDisconnectAction;
186   }
187
188   /**
189    * Set the playing range. The animation will only play between the minimum and maximum progress
190    * speficied.
191    *
192    * @param[in] range Two values between [0,1] to specify minimum and maximum progress.
193    */
194   void SetPlayRange(const Vector2& range);
195
196   /**
197    * @brief Sets the blend point to interpolate animate property
198    *
199    * @param[in] blendPoint A value between [0,1], If the value of the keyframe whose progress is 0 is different from the current value,
200    * the property is animated as it smoothly blends until the progress reaches the blendPoint.
201    * @note The blendPoint only affects animation registered with AnimateBetween. Other animations operate the same as when Play() is called.
202    */
203   void SetBlendPoint(float blendPoint);
204
205   /**
206    * Play the animation.
207    */
208   void Play();
209
210   /**
211    * Play the animation from a given point
212    * @param[in] progress A value between [0,1] form where the animation should start playing
213    */
214   void PlayFrom(float progress);
215
216   /**
217    * @brief Play the animation after a given delay time.
218    * @param[in] delaySeconds The delay time
219    */
220   void PlayAfter(float delaySeconds);
221
222   /**
223    * Pause the animation.
224    */
225   void Pause();
226
227   /**
228    * Stop the animation.
229    * @param[in] bufferIndex The buffer to update when mEndAction == Bake.
230    * @return True if the animation has finished (otherwise it wasn't playing)
231    */
232   bool Stop(BufferIndex bufferIndex);
233
234   /**
235    * Called shortly before the animation is destroyed.
236    * @param[in] bufferIndex The buffer to update when mEndAction == Bake.
237    */
238   void OnDestroy(BufferIndex bufferIndex);
239
240   /**
241    * Query whether the animation is playing, paused or stopped.
242    * Note that even when paused, the Update() method should be called,
243    * since the current progress must be reapplied each frame.
244    */
245   State GetState() const
246   {
247     return mState;
248   }
249
250   /**
251    * Retrive a count of the number of times the animation has been played to completion.
252    * This can be used to emit "Finised" signals from the public-api
253    */
254   int32_t GetPlayedCount() const
255   {
256     return mPlayedCount;
257   }
258
259   /**
260    * Get the current loop count from zero to GetLoopCount().
261    */
262   int32_t GetCurrentLoop() const
263   {
264     return mCurrentLoop;
265   }
266
267   /**
268    * Query whether the animation is currently active (i.e. at least one of the animators has been updated in either frame)
269    * @return True if the animation is currently active
270    */
271   bool IsActive() const
272   {
273     // As we have double buffering, if animator is updated in either frame, it needs to be rendered.
274     return mIsActive[0] || mIsActive[1];
275   }
276
277   /**
278    * @brief Sets the looping mode.
279    *
280    * Animation plays forwards and then restarts from the beginning or runs backwards again.
281    * @param[in] loopingMode True when the looping mode is AUTO_REVERSE
282    */
283   void SetLoopingMode(bool loopingMode);
284
285   /**
286    * Add a newly created animator.
287    * Animators are automatically removed, when orphaned from an animatable scene object.
288    * @param[in] animator The animator to add.
289    * @param[in] propertyOwner The scene-object that owns the animatable property.
290    * @post The animator is owned by this animation.
291    */
292   void AddAnimator(OwnerPointer<AnimatorBase>& animator);
293
294   /**
295    * This causes the animators to change the properties of objects in the scene graph.
296    * @pre The animation is playing or paused.
297    * @param[in] bufferIndex The buffer to update.
298    * @param[in] elapsedSeconds The time elapsed since the previous frame.
299    * @param[out] looped True if the animation looped
300    * @param[out] finished True if the animation has finished.
301    * @param[out] progressReached True if progress marker reached
302    */
303   void Update(BufferIndex bufferIndex, float elapsedSeconds, bool& looped, bool& finished, bool& progressReached);
304
305   static uint32_t GetMemoryPoolCapacity();
306
307 protected:
308   /**
309    * Protected constructor. See New()
310    */
311   Animation(float durationSeconds, float speedFactor, const Vector2& playRange, int32_t loopCount, EndAction endAction, EndAction disconnectAction);
312
313 private:
314   /**
315    * Helper for Update, also used to bake when the animation is stopped or destroyed.
316    * @param[in] bufferIndex The buffer to update.
317    * @param[in] bake True if the final result should be baked.
318    * @param[in] animationFinished True if the animation has finished.
319    */
320   void UpdateAnimators(BufferIndex bufferIndex, bool bake, bool animationFinished);
321
322   /**
323    * Helper function to bake the result of the animation when it is stopped or
324    * destroyed.
325    * @param[in] bufferIndex The buffer to update.
326    * @param[in] action The end action specified.
327    */
328   void Bake(BufferIndex bufferIndex, EndAction action);
329
330   /**
331    * Helper function to set active state of animators.
332    * @param[in] active Every animator is set to this state
333    */
334   void SetAnimatorsActive(bool active);
335
336   // Undefined
337   Animation(const Animation&);
338
339   // Undefined
340   Animation& operator=(const Animation& rhs);
341
342 protected:
343   OwnerContainer<AnimatorBase*> mAnimators;
344
345   Vector2 mPlayRange;
346
347   float mDurationSeconds;
348   float mDelaySeconds;
349   float mElapsedSeconds;
350   float mSpeedFactor;
351   float mProgressMarker; // Progress marker to trigger a notification
352   float mBlendPoint;
353
354   int32_t mPlayedCount; // Incremented at end of animation or completion of all loops
355                         // Never incremented when looping forever. Event thread tracks to signal end.
356   int32_t mLoopCount;   // N loop setting
357   int32_t mCurrentLoop; // Current loop number
358
359   EndAction mEndAction;
360   EndAction mDisconnectAction;
361
362   State mState;
363
364   bool mProgressReachedSignalRequired; // Flag to indicate the progress marker was hit
365   bool mAutoReverseEnabled;            // Flag to identify that the looping mode is auto reverse.
366   bool mAnimatorSortRequired;          // Flag to whether we need to sort animator or not.
367   bool mIsActive[2];                   // Flag to indicate whether the animation is active in the current frame (which is double buffered)
368   bool mIsFirstLoop;
369 };
370
371 }; // namespace SceneGraph
372
373 // value types used by messages
374 template<>
375 struct ParameterType<Dali::Animation::EndAction> : public BasicType<Dali::Animation::EndAction>
376 {
377 };
378
379 namespace SceneGraph
380 {
381 // Messages for Animation
382
383 inline void SetDurationMessage(EventThreadServices& eventThreadServices, const Animation& animation, float durationSeconds)
384 {
385   using LocalType = MessageValue1<Animation, float>;
386
387   // Reserve some memory inside the message queue
388   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
389
390   // Construct message in the message queue memory; note that delete should not be called on the return value
391   new(slot) LocalType(&animation, &Animation::SetDuration, durationSeconds);
392 }
393
394 inline void SetProgressNotificationMessage(EventThreadServices& eventThreadServices, const Animation& animation, float progress)
395 {
396   using LocalType = MessageValue1<Animation, float>;
397
398   // Reserve some memory inside the message queue
399   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
400
401   // Construct message in the message queue memory; note that delete should not be called on the return value
402   new(slot) LocalType(&animation, &Animation::SetProgressNotification, progress);
403 }
404
405 inline void SetLoopingMessage(EventThreadServices& eventThreadServices, const Animation& animation, int32_t loopCount)
406 {
407   using LocalType = MessageValue1<Animation, int32_t>;
408
409   // Reserve some memory inside the message queue
410   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
411
412   // Construct message in the message queue memory; note that delete should not be called on the return value
413   new(slot) LocalType(&animation, &Animation::SetLoopCount, loopCount);
414 }
415
416 inline void SetEndActionMessage(EventThreadServices& eventThreadServices, const Animation& animation, Dali::Animation::EndAction action)
417 {
418   using LocalType = MessageValue1<Animation, Dali::Animation::EndAction>;
419
420   // Reserve some memory inside the message queue
421   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
422
423   // Construct message in the message queue memory; note that delete should not be called on the return value
424   new(slot) LocalType(&animation, &Animation::SetEndAction, action);
425 }
426
427 inline void SetDisconnectActionMessage(EventThreadServices& eventThreadServices, const Animation& animation, Dali::Animation::EndAction action)
428 {
429   using LocalType = MessageValue1<Animation, Dali::Animation::EndAction>;
430
431   // Reserve some memory inside the message queue
432   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
433
434   // Construct message in the message queue memory; note that delete should not be called on the return value
435   new(slot) LocalType(&animation, &Animation::SetDisconnectAction, action);
436 }
437
438 inline void SetCurrentProgressMessage(EventThreadServices& eventThreadServices, const Animation& animation, float progress)
439 {
440   using LocalType = MessageValue1<Animation, float>;
441
442   // Reserve some memory inside the message queue
443   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
444
445   // Construct message in the message queue memory; note that delete should not be called on the return value
446   new(slot) LocalType(&animation, &Animation::SetCurrentProgress, progress);
447 }
448
449 inline void SetSpeedFactorMessage(EventThreadServices& eventThreadServices, const Animation& animation, float factor)
450 {
451   using LocalType = MessageValue1<Animation, float>;
452
453   // Reserve some memory inside the message queue
454   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
455
456   // Construct message in the message queue memory; note that delete should not be called on the return value
457   new(slot) LocalType(&animation, &Animation::SetSpeedFactor, factor);
458 }
459
460 inline void SetPlayRangeMessage(EventThreadServices& eventThreadServices, const Animation& animation, const Vector2& range)
461 {
462   using LocalType = MessageValue1<Animation, Vector2>;
463
464   // Reserve some memory inside the message queue
465   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
466
467   // Construct message in the message queue memory; note that delete should not be called on the return value
468   new(slot) LocalType(&animation, &Animation::SetPlayRange, range);
469 }
470
471 inline void SetBlendPointMessage(EventThreadServices& eventThreadServices, const Animation& animation, float blendPoint)
472 {
473   using LocalType = MessageValue1<Animation, float>;
474
475   // Reserve some memory inside the message queue
476   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
477
478   // Construct message in the message queue memory; note that delete should not be called on the return value
479   new(slot) LocalType(&animation, &Animation::SetBlendPoint, blendPoint);
480 }
481
482 inline void PlayAnimationMessage(EventThreadServices& eventThreadServices, const Animation& animation)
483 {
484   using LocalType = Message<Animation>;
485
486   // Reserve some memory inside the message queue
487   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
488
489   // Construct message in the message queue memory; note that delete should not be called on the return value
490   new(slot) LocalType(&animation, &Animation::Play);
491 }
492 inline void PlayAnimationFromMessage(EventThreadServices& eventThreadServices, const Animation& animation, float progress)
493 {
494   using LocalType = MessageValue1<Animation, float>;
495
496   // Reserve some memory inside the message queue
497   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
498
499   // Construct message in the message queue memory; note that delete should not be called on the return value
500   new(slot) LocalType(&animation, &Animation::PlayFrom, progress);
501 }
502
503 inline void PauseAnimationMessage(EventThreadServices& eventThreadServices, const Animation& animation)
504 {
505   using LocalType = Message<Animation>;
506
507   // Reserve some memory inside the message queue
508   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
509
510   // Construct message in the message queue memory; note that delete should not be called on the return value
511   new(slot) LocalType(&animation, &Animation::Pause);
512 }
513
514 inline void AddAnimatorMessage(EventThreadServices& eventThreadServices, const Animation& animation, AnimatorBase& animator)
515 {
516   using LocalType = MessageValue1<Animation, OwnerPointer<AnimatorBase> >;
517
518   // Reserve some memory inside the message queue
519   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
520
521   // Construct message in the message queue memory; note that delete should not be called on the return value
522   OwnerPointer<AnimatorBase> parameter(&animator);
523   new(slot) LocalType(&animation, &Animation::AddAnimator, parameter);
524 }
525
526 inline void PlayAfterMessage(EventThreadServices& eventThreadServices, const Animation& animation, float delaySeconds)
527 {
528   using LocalType = MessageValue1<Animation, float>;
529
530   // Reserve some memory inside the message queue
531   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
532
533   // Construct message in the message queue memory; note that delete should not be called on the return value
534   new(slot) LocalType(&animation, &Animation::PlayAfter, delaySeconds);
535 }
536
537 inline void SetLoopingModeMessage(EventThreadServices& eventThreadServices, const Animation& animation, bool loopingMode)
538 {
539   using LocalType = MessageValue1<Animation, bool>;
540
541   // Reserve some memory inside the message queue
542   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
543
544   // Construct message in the message queue memory; note that delete should not be called on the return value
545   new(slot) LocalType(&animation, &Animation::SetLoopingMode, loopingMode);
546 }
547
548 } // namespace SceneGraph
549
550 } // namespace Internal
551
552 } // namespace Dali
553
554 #endif // DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H