Append Stopped animation notify list at Update Animation time
[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) 2024 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    * Clear the animator. It will stop animation, clear all animators, and make this animation never played before.
236    * @param[in] bufferIndex The buffer to update when mEndAction == Bake.
237    */
238   void ClearAnimator(BufferIndex bufferIndex);
239
240   /**
241    * Called shortly before the animation is destroyed.
242    * @param[in] bufferIndex The buffer to update when mEndAction == Bake.
243    */
244   void OnDestroy(BufferIndex bufferIndex);
245
246   /**
247    * Query whether the animation is playing, paused or stopped.
248    * Note that even when paused, the Update() method should be called,
249    * since the current progress must be reapplied each frame.
250    */
251   State GetState() const
252   {
253     return mState;
254   }
255
256   /**
257    * Retrive a count of the number of times the animation has been played to completion.
258    * This can be used to emit "Finised" signals from the public-api
259    */
260   int32_t GetPlayedCount() const
261   {
262     return mPlayedCount;
263   }
264
265   /**
266    * Get the current loop count from zero to GetLoopCount().
267    */
268   int32_t GetCurrentLoop() const
269   {
270     return mCurrentLoop;
271   }
272
273   /**
274    * Query whether the animation is currently active (i.e. at least one of the animators has been updated in either frame)
275    * @return True if the animation is currently active
276    */
277   bool IsActive() const
278   {
279     // As we have double buffering, if animator is updated in either frame, it needs to be rendered.
280     return mIsActive[0] || mIsActive[1];
281   }
282
283   /**
284    * @brief Sets the looping mode.
285    *
286    * Animation plays forwards and then restarts from the beginning or runs backwards again.
287    * @param[in] loopingMode True when the looping mode is AUTO_REVERSE
288    */
289   void SetLoopingMode(bool loopingMode);
290
291   /**
292    * Add a newly created animator.
293    * Animators are automatically removed, when orphaned from an animatable scene object.
294    * @param[in] animator The animator to add.
295    * @param[in] propertyOwner The scene-object that owns the animatable property.
296    * @post The animator is owned by this animation.
297    */
298   void AddAnimator(OwnerPointer<AnimatorBase>& animator);
299
300   /**
301    * This causes the animators to change the properties of objects in the scene graph.
302    * @pre The animation is playing or paused.
303    * @param[in] bufferIndex The buffer to update.
304    * @param[in] elapsedSeconds The time elapsed since the previous frame.
305    * @param[out] stopped True if the animation stopped this loop
306    * @param[out] finished True if the animation has finished.
307    * @param[out] progressReached True if progress marker reached
308    */
309   void Update(BufferIndex bufferIndex, float elapsedSeconds, bool& stopped, bool& finished, bool& progressReached);
310
311   static uint32_t GetMemoryPoolCapacity();
312
313 protected:
314   /**
315    * Protected constructor. See New()
316    */
317   Animation(float durationSeconds, float speedFactor, const Vector2& playRange, int32_t loopCount, EndAction endAction, EndAction disconnectAction);
318
319 private:
320   /**
321    * Helper for Update, also used to bake when the animation is stopped or destroyed.
322    * @param[in] bufferIndex The buffer to update.
323    * @param[in] bake True if the final result should be baked.
324    * @param[in] animationFinished True if the animation has finished.
325    */
326   void UpdateAnimators(BufferIndex bufferIndex, bool bake, bool animationFinished);
327
328   /**
329    * Helper function to bake the result of the animation when it is stopped or
330    * destroyed.
331    * @param[in] bufferIndex The buffer to update.
332    * @param[in] action The end action specified.
333    */
334   void Bake(BufferIndex bufferIndex, EndAction action);
335
336   /**
337    * Helper function to set active state of animators.
338    * @param[in] active Every animator is set to this state
339    */
340   void SetAnimatorsActive(bool active);
341
342   // Undefined
343   Animation(const Animation&);
344
345   // Undefined
346   Animation& operator=(const Animation& rhs);
347
348 protected:
349   OwnerContainer<AnimatorBase*> mAnimators;
350
351   Vector2 mPlayRange;
352
353   float mDurationSeconds;
354   float mDelaySeconds;
355   float mElapsedSeconds;
356   float mSpeedFactor;
357   float mProgressMarker; // Progress marker to trigger a notification
358   float mBlendPoint;
359
360   int32_t mPlayedCount; // Incremented at end of animation or completion of all loops
361                         // Never incremented when looping forever. Event thread tracks to signal end.
362   int32_t mLoopCount;   // N loop setting
363   int32_t mCurrentLoop; // Current loop number
364
365   EndAction mEndAction;
366   EndAction mDisconnectAction;
367
368   State mState;
369
370   bool mProgressReachedSignalRequired; // Flag to indicate the progress marker was hit
371   bool mAutoReverseEnabled;            // Flag to identify that the looping mode is auto reverse.
372   bool mAnimatorSortRequired;          // Flag to whether we need to sort animator or not.
373   bool mIsActive[2];                   // Flag to indicate whether the animation is active in the current frame (which is double buffered)
374   bool mIsFirstLoop;
375   bool mIsStopped; // Flag to whether this animation call stoped by user at this frame.
376 };
377
378 }; // namespace SceneGraph
379
380 // value types used by messages
381 template<>
382 struct ParameterType<Dali::Animation::EndAction> : public BasicType<Dali::Animation::EndAction>
383 {
384 };
385
386 namespace SceneGraph
387 {
388 // Messages for Animation
389
390 inline void SetDurationMessage(EventThreadServices& eventThreadServices, const Animation& animation, float durationSeconds)
391 {
392   using LocalType = MessageValue1<Animation, float>;
393
394   // Reserve some memory inside the message queue
395   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
396
397   // Construct message in the message queue memory; note that delete should not be called on the return value
398   new(slot) LocalType(&animation, &Animation::SetDuration, durationSeconds);
399 }
400
401 inline void SetProgressNotificationMessage(EventThreadServices& eventThreadServices, const Animation& animation, float progress)
402 {
403   using LocalType = MessageValue1<Animation, float>;
404
405   // Reserve some memory inside the message queue
406   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
407
408   // Construct message in the message queue memory; note that delete should not be called on the return value
409   new(slot) LocalType(&animation, &Animation::SetProgressNotification, progress);
410 }
411
412 inline void SetLoopingMessage(EventThreadServices& eventThreadServices, const Animation& animation, int32_t loopCount)
413 {
414   using LocalType = MessageValue1<Animation, int32_t>;
415
416   // Reserve some memory inside the message queue
417   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
418
419   // Construct message in the message queue memory; note that delete should not be called on the return value
420   new(slot) LocalType(&animation, &Animation::SetLoopCount, loopCount);
421 }
422
423 inline void SetEndActionMessage(EventThreadServices& eventThreadServices, const Animation& animation, Dali::Animation::EndAction action)
424 {
425   using LocalType = MessageValue1<Animation, Dali::Animation::EndAction>;
426
427   // Reserve some memory inside the message queue
428   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
429
430   // Construct message in the message queue memory; note that delete should not be called on the return value
431   new(slot) LocalType(&animation, &Animation::SetEndAction, action);
432 }
433
434 inline void SetDisconnectActionMessage(EventThreadServices& eventThreadServices, const Animation& animation, Dali::Animation::EndAction action)
435 {
436   using LocalType = MessageValue1<Animation, Dali::Animation::EndAction>;
437
438   // Reserve some memory inside the message queue
439   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
440
441   // Construct message in the message queue memory; note that delete should not be called on the return value
442   new(slot) LocalType(&animation, &Animation::SetDisconnectAction, action);
443 }
444
445 inline void SetCurrentProgressMessage(EventThreadServices& eventThreadServices, const Animation& animation, float progress)
446 {
447   using LocalType = MessageValue1<Animation, float>;
448
449   // Reserve some memory inside the message queue
450   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
451
452   // Construct message in the message queue memory; note that delete should not be called on the return value
453   new(slot) LocalType(&animation, &Animation::SetCurrentProgress, progress);
454 }
455
456 inline void SetSpeedFactorMessage(EventThreadServices& eventThreadServices, const Animation& animation, float factor)
457 {
458   using LocalType = MessageValue1<Animation, float>;
459
460   // Reserve some memory inside the message queue
461   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
462
463   // Construct message in the message queue memory; note that delete should not be called on the return value
464   new(slot) LocalType(&animation, &Animation::SetSpeedFactor, factor);
465 }
466
467 inline void SetPlayRangeMessage(EventThreadServices& eventThreadServices, const Animation& animation, const Vector2& range)
468 {
469   using LocalType = MessageValue1<Animation, Vector2>;
470
471   // Reserve some memory inside the message queue
472   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
473
474   // Construct message in the message queue memory; note that delete should not be called on the return value
475   new(slot) LocalType(&animation, &Animation::SetPlayRange, range);
476 }
477
478 inline void SetBlendPointMessage(EventThreadServices& eventThreadServices, const Animation& animation, float blendPoint)
479 {
480   using LocalType = MessageValue1<Animation, float>;
481
482   // Reserve some memory inside the message queue
483   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
484
485   // Construct message in the message queue memory; note that delete should not be called on the return value
486   new(slot) LocalType(&animation, &Animation::SetBlendPoint, blendPoint);
487 }
488
489 inline void PlayAnimationMessage(EventThreadServices& eventThreadServices, const Animation& animation)
490 {
491   using LocalType = Message<Animation>;
492
493   // Reserve some memory inside the message queue
494   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
495
496   // Construct message in the message queue memory; note that delete should not be called on the return value
497   new(slot) LocalType(&animation, &Animation::Play);
498 }
499
500 inline void PlayAnimationFromMessage(EventThreadServices& eventThreadServices, const Animation& animation, float progress)
501 {
502   using LocalType = MessageValue1<Animation, float>;
503
504   // Reserve some memory inside the message queue
505   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
506
507   // Construct message in the message queue memory; note that delete should not be called on the return value
508   new(slot) LocalType(&animation, &Animation::PlayFrom, progress);
509 }
510
511 inline void PauseAnimationMessage(EventThreadServices& eventThreadServices, const Animation& animation)
512 {
513   using LocalType = Message<Animation>;
514
515   // Reserve some memory inside the message queue
516   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
517
518   // Construct message in the message queue memory; note that delete should not be called on the return value
519   new(slot) LocalType(&animation, &Animation::Pause);
520 }
521
522 inline void AddAnimatorMessage(EventThreadServices& eventThreadServices, const Animation& animation, AnimatorBase& animator)
523 {
524   using LocalType = MessageValue1<Animation, OwnerPointer<AnimatorBase> >;
525
526   // Reserve some memory inside the message queue
527   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
528
529   // Construct message in the message queue memory; note that delete should not be called on the return value
530   OwnerPointer<AnimatorBase> parameter(&animator);
531   new(slot) LocalType(&animation, &Animation::AddAnimator, parameter);
532 }
533
534 inline void PlayAfterMessage(EventThreadServices& eventThreadServices, const Animation& animation, float delaySeconds)
535 {
536   using LocalType = MessageValue1<Animation, float>;
537
538   // Reserve some memory inside the message queue
539   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
540
541   // Construct message in the message queue memory; note that delete should not be called on the return value
542   new(slot) LocalType(&animation, &Animation::PlayAfter, delaySeconds);
543 }
544
545 inline void SetLoopingModeMessage(EventThreadServices& eventThreadServices, const Animation& animation, bool loopingMode)
546 {
547   using LocalType = MessageValue1<Animation, bool>;
548
549   // Reserve some memory inside the message queue
550   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
551
552   // Construct message in the message queue memory; note that delete should not be called on the return value
553   new(slot) LocalType(&animation, &Animation::SetLoopingMode, loopingMode);
554 }
555
556 } // namespace SceneGraph
557
558 } // namespace Internal
559
560 } // namespace Dali
561
562 #endif // DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H