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