DALi Version 2.2.14
[platform/core/uifw/dali-core.git] / dali / internal / update / animation / scene-graph-animator.h
1 #ifndef DALI_INTERNAL_SCENE_GRAPH_ANIMATOR_H
2 #define DALI_INTERNAL_SCENE_GRAPH_ANIMATOR_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 // EXTERNAL INCLUDES
22 #include <cmath>
23 #include <functional>
24
25 // INTERNAL INCLUDES
26 #include <dali/devel-api/common/owner-container.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/internal/event/animation/key-frames-impl.h>
29 #include <dali/internal/event/animation/path-impl.h>
30 #include <dali/internal/update/animation/property-accessor.h>
31 #include <dali/internal/update/common/property-base.h>
32 #include <dali/internal/update/nodes/node.h>
33 #include <dali/public-api/animation/alpha-function.h>
34 #include <dali/public-api/animation/animation.h>
35 #include <dali/public-api/animation/time-period.h>
36 #include <dali/public-api/common/constants.h>
37 #include <dali/public-api/common/dali-common.h>
38 #include <dali/public-api/math/quaternion.h>
39 #include <dali/public-api/math/radian.h>
40
41 namespace Dali
42 {
43 namespace Internal
44 {
45 using Interpolation = Dali::Animation::Interpolation;
46
47 namespace SceneGraph
48 {
49 /**
50  * An abstract base class for Animators, which can be added to scene graph animations.
51  * Each animator changes a single property of an object in the scene graph.
52  */
53 class AnimatorBase : public PropertyOwner::Observer
54 {
55 public:
56   using AlphaFunc = float (*)(float progress); ///< Definition of an alpha function
57
58   /**
59    * Observer to determine when the animator is no longer present
60    */
61   class LifecycleObserver
62   {
63   public:
64     /**
65      * Called shortly before the animator is destroyed.
66      */
67     virtual void ObjectDestroyed() = 0;
68
69   protected:
70     /**
71      * Virtual destructor, no deletion through this interface
72      */
73     virtual ~LifecycleObserver() = default;
74   };
75
76   /**
77    * Constructor.
78    */
79   AnimatorBase(PropertyOwner*    propertyOwner,
80                AlphaFunction     alphaFunction,
81                const TimePeriod& timePeriod)
82   : mLifecycleObserver(nullptr),
83     mPropertyOwner(propertyOwner),
84     mDurationSeconds(timePeriod.durationSeconds),
85     mIntervalDelaySeconds(timePeriod.delaySeconds),
86     mSpeedFactor(1.0f),
87     mCurrentProgress(0.f),
88     mAlphaFunction(alphaFunction),
89     mDisconnectAction(Dali::Animation::BAKE_FINAL),
90     mAnimationPlaying(false),
91     mEnabled(true),
92     mConnectedToSceneGraph(false),
93     mAutoReverseEnabled(false)
94   {
95   }
96
97   /**
98    * Virtual destructor.
99    */
100   ~AnimatorBase() override
101   {
102     if(mPropertyOwner && mConnectedToSceneGraph)
103     {
104       mPropertyOwner->RemoveObserver(*this);
105     }
106     if(mLifecycleObserver != nullptr)
107     {
108       mLifecycleObserver->ObjectDestroyed();
109     }
110   }
111
112   void AddLifecycleObserver(LifecycleObserver& observer)
113   {
114     mLifecycleObserver = &observer;
115   }
116
117   void RemoveLifecycleObserver(LifecycleObserver& observer)
118   {
119     mLifecycleObserver = nullptr;
120   }
121
122 private: // From PropertyOwner::Observer
123   /**
124    * @copydoc PropertyOwner::Observer::PropertyOwnerConnected( PropertyOwner& owner )
125    */
126   void PropertyOwnerConnected(PropertyOwner& owner) final
127   {
128     mEnabled = true;
129   }
130
131   /**
132    * @copydoc PropertyOwner::Observer::PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
133    */
134   void PropertyOwnerDisconnected(BufferIndex bufferIndex, PropertyOwner& owner) final
135   {
136     // If we are active, then bake the value if required
137     if(mAnimationPlaying && mDisconnectAction != Dali::Animation::DISCARD)
138     {
139       // Bake to target-value if BakeFinal, otherwise bake current value
140       Update(bufferIndex, (mDisconnectAction == Dali::Animation::BAKE ? mCurrentProgress : 1.0f), true);
141     }
142
143     mEnabled = false;
144   }
145
146   /**
147    * @copydoc PropertyOwner::Observer::PropertyOwnerDestroyed( PropertyOwner& owner )
148    */
149   void PropertyOwnerDestroyed(PropertyOwner& owner) final
150   {
151     mPropertyOwner = nullptr;
152   }
153
154 public:
155   /**
156    * Called when Animator is added to the scene-graph in update-thread.
157    */
158   void ConnectToSceneGraph()
159   {
160     mConnectedToSceneGraph = true;
161     mPropertyOwner->AddObserver(*this);
162
163     // Enable if the target object is valid and connected to the scene graph.
164     mEnabled = mPropertyOwner->IsAnimationPossible();
165   }
166
167   /**
168    * Set the duration of the animator.
169    * @pre durationSeconds must be zero or greater; zero is useful when animating boolean values.
170    * @param [in] seconds Duration in seconds.
171    */
172   void SetDuration(float seconds)
173   {
174     DALI_ASSERT_DEBUG(seconds >= 0.0f);
175
176     mDurationSeconds = seconds;
177   }
178
179   /**
180    * Retrieve the duration of the animator.
181    * @return The duration in seconds.
182    */
183   float GetDuration() const
184   {
185     return mDurationSeconds;
186   }
187
188   void SetSpeedFactor(float factor)
189   {
190     mSpeedFactor = factor;
191   }
192
193   void SetLoopCount(int32_t loopCount)
194   {
195     mLoopCount = loopCount;
196   }
197
198   float SetProgress(float progress)
199   {
200     float value = 0.0f;
201
202     if(mAutoReverseEnabled)
203     {
204       if(mSpeedFactor > 0.0f)
205       {
206         value = 1.0f - 2.0f * std::abs(progress - 0.5f);
207       }
208       // Reverse mode
209       else if(mSpeedFactor < 0.0f)
210       {
211         value = 2.0f * std::abs(progress - 0.5f);
212       }
213     }
214     else
215     {
216       value = progress;
217     }
218
219     return value;
220   }
221
222   /**
223    * Set the delay before the animator should take effect.
224    * The default is zero i.e. no delay.
225    * @param [in] seconds The delay in seconds.
226    */
227   void SetIntervalDelay(float seconds)
228   {
229     mIntervalDelaySeconds = seconds;
230   }
231
232   /**
233    * Retrieve the delay before the animator should take effect.
234    * @return The delay in seconds.
235    */
236   float GetIntervalDelay() const
237   {
238     return mIntervalDelaySeconds;
239   }
240
241   /**
242    * Set the alpha function for an animator.
243    * @param [in] alphaFunc The alpha function to apply to the animation progress.
244    */
245   void SetAlphaFunction(const AlphaFunction& alphaFunction)
246   {
247     mAlphaFunction = alphaFunction;
248   }
249
250   /**
251    * Retrieve the alpha function of an animator.
252    * @return The function.
253    */
254   AlphaFunction GetAlphaFunction() const
255   {
256     return mAlphaFunction;
257   }
258
259   /**
260    * Applies the alpha function to the specified progress
261    * @param[in] Current progress
262    * @return The progress after the alpha function has been aplied
263    */
264   float ApplyAlphaFunction(float progress) const
265   {
266     float result = progress;
267
268     AlphaFunction::Mode alphaFunctionMode(mAlphaFunction.GetMode());
269     if(alphaFunctionMode == AlphaFunction::BUILTIN_FUNCTION)
270     {
271       switch(mAlphaFunction.GetBuiltinFunction())
272       {
273         case AlphaFunction::DEFAULT:
274         case AlphaFunction::LINEAR:
275         {
276           break;
277         }
278         case AlphaFunction::REVERSE:
279         {
280           result = 1.0f - progress;
281           break;
282         }
283         case AlphaFunction::EASE_IN_SQUARE:
284         {
285           result = progress * progress;
286           break;
287         }
288         case AlphaFunction::EASE_OUT_SQUARE:
289         {
290           result = 1.0f - (1.0f - progress) * (1.0f - progress);
291           break;
292         }
293         case AlphaFunction::EASE_IN:
294         {
295           result = progress * progress * progress;
296           break;
297         }
298         case AlphaFunction::EASE_OUT:
299         {
300           result = (progress - 1.0f) * (progress - 1.0f) * (progress - 1.0f) + 1.0f;
301           break;
302         }
303         case AlphaFunction::EASE_IN_OUT:
304         {
305           result = progress * progress * (3.0f - 2.0f * progress);
306           break;
307         }
308         case AlphaFunction::EASE_IN_SINE:
309         {
310           result = -1.0f * cosf(progress * Math::PI_2) + 1.0f;
311           break;
312         }
313         case AlphaFunction::EASE_OUT_SINE:
314         {
315           result = sinf(progress * Math::PI_2);
316           break;
317         }
318         case AlphaFunction::EASE_IN_OUT_SINE:
319         {
320           result = -0.5f * (cosf(Math::PI * progress) - 1.0f);
321           break;
322         }
323         case AlphaFunction::BOUNCE:
324         {
325           result = sinf(progress * Math::PI);
326           break;
327         }
328         case AlphaFunction::SIN:
329         {
330           result = 0.5f - cosf(progress * 2.0f * Math::PI) * 0.5f;
331           break;
332         }
333         case AlphaFunction::EASE_OUT_BACK:
334         {
335           const float sqrt2 = 1.70158f;
336           progress -= 1.0f;
337           result = 1.0f + progress * progress * ((sqrt2 + 1.0f) * progress + sqrt2);
338           break;
339         }
340         case AlphaFunction::COUNT:
341         {
342           break;
343         }
344       }
345     }
346     else if(alphaFunctionMode == AlphaFunction::CUSTOM_FUNCTION)
347     {
348       AlphaFunctionPrototype customFunction = mAlphaFunction.GetCustomFunction();
349       if(customFunction)
350       {
351         result = customFunction(progress);
352       }
353     }
354     else
355     {
356       //If progress is very close to 0 or very close to 1 we don't need to evaluate the curve as the result will
357       //be almost 0 or almost 1 respectively
358       if((progress > Math::MACHINE_EPSILON_1) && ((1.0f - progress) > Math::MACHINE_EPSILON_1))
359       {
360         Dali::Vector4 controlPoints = mAlphaFunction.GetBezierControlPoints();
361
362         static const float tolerance = 0.001f; //10 iteration max
363
364         //Perform a binary search on the curve
365         float lowerBound(0.0f);
366         float upperBound(1.0f);
367         float currentT(0.5f);
368         float currentX = EvaluateCubicBezier(controlPoints.x, controlPoints.z, currentT);
369         while(fabsf(progress - currentX) > tolerance)
370         {
371           if(progress > currentX)
372           {
373             lowerBound = currentT;
374           }
375           else
376           {
377             upperBound = currentT;
378           }
379           currentT = (upperBound + lowerBound) * 0.5f;
380           currentX = EvaluateCubicBezier(controlPoints.x, controlPoints.z, currentT);
381         }
382         result = EvaluateCubicBezier(controlPoints.y, controlPoints.w, currentT);
383       }
384     }
385
386     return result;
387   }
388
389   /**
390    * Whether to bake the animation if attached property owner is disconnected.
391    * Property is only baked if the animator is active.
392    * @param [in] action The disconnect action.
393    */
394   void SetDisconnectAction(Dali::Animation::EndAction action)
395   {
396     mDisconnectAction = action;
397   }
398
399   /**
400    * Retrieve the disconnect action of an animator.
401    * @return The disconnect action.
402    */
403   Dali::Animation::EndAction GetDisconnectAction() const
404   {
405     return mDisconnectAction;
406   }
407
408   /**
409    * Whether the animator is active or not.
410    * @param [in] active The new active state.
411    * @post When the animator becomes active, it applies the disconnect-action if the property owner is then disconnected.
412    * @note When the property owner is disconnected, the active state is set to false.
413    */
414   void SetActive(bool active)
415   {
416     mAnimationPlaying = active;
417   }
418
419   /**
420    * Whether the animator's target object is valid and on the stage.
421    * @return The enabled state.
422    */
423   bool IsEnabled() const
424   {
425     return mEnabled;
426   }
427
428   /**
429    * @brief Sets the looping mode.
430    * @param[in] loopingMode True when the looping mode is AUTO_REVERSE
431    */
432   void SetLoopingMode(bool loopingMode)
433   {
434     mAutoReverseEnabled = loopingMode;
435   }
436
437   /**
438    * Returns wheter the target object of the animator is still valid
439    * or has been destroyed.
440    * @return True if animator is orphan, false otherwise   *
441    * @note The SceneGraph::Animation will delete any orphan animator in its Update method.
442    */
443   bool Orphan()
444   {
445     return (mPropertyOwner == nullptr);
446   }
447
448   /**
449    * Update the scene object attached to the animator.
450    * @param[in] bufferIndex The buffer to animate.
451    * @param[in] progress A value from 0 to 1, where 0 is the start of the animation, and 1 is the end point.
452    * @param[in] bake Bake.
453    */
454   void Update(BufferIndex bufferIndex, float progress, bool bake)
455   {
456     if(mLoopCount >= 0)
457     {
458       // Update the progress value
459       progress = SetProgress(progress);
460     }
461
462     if(mPropertyOwner)
463     {
464       mPropertyOwner->SetUpdated(true);
465     }
466
467     float alpha = ApplyAlphaFunction(progress);
468
469     // PropertyType specific part
470     DoUpdate(bufferIndex, bake, alpha);
471
472     mCurrentProgress = progress;
473   }
474
475   /**
476    * Type specific part of the animator
477    * @param bufferIndex index to use
478    * @param bake whether to bake or not
479    * @param alpha value from alpha based on progress
480    */
481   virtual void DoUpdate(BufferIndex bufferIndex, bool bake, float alpha) = 0;
482
483 protected:
484   /**
485    * Helper function to evaluate a cubic bezier curve assuming first point is at 0.0 and last point is at 1.0
486    * @param[in] p0 First control point of the bezier curve
487    * @param[in] p1 Second control point of the bezier curve
488    * @param[in] t A floating point value between 0.0 and 1.0
489    * @return Value of the curve at progress t
490    */
491   inline float EvaluateCubicBezier(float p0, float p1, float t) const
492   {
493     float tSquare = t * t;
494     return 3.0f * (1.0f - t) * (1.0f - t) * t * p0 + 3.0f * (1.0f - t) * tSquare * p1 + tSquare * t;
495   }
496
497   LifecycleObserver* mLifecycleObserver;
498   PropertyOwner*     mPropertyOwner;
499
500   float mDurationSeconds;
501   float mIntervalDelaySeconds;
502   float mSpeedFactor;
503   float mCurrentProgress;
504
505   AlphaFunction mAlphaFunction;
506
507   int32_t                    mLoopCount{1};
508   Dali::Animation::EndAction mDisconnectAction;          ///< EndAction to apply when target object gets disconnected from the stage.
509   bool                       mAnimationPlaying : 1;      ///< whether disconnect has been applied while it's running.
510   bool                       mEnabled : 1;               ///< Animator is "enabled" while its target object is valid and on the stage.
511   bool                       mConnectedToSceneGraph : 1; ///< True if ConnectToSceneGraph() has been called in update-thread.
512   bool                       mAutoReverseEnabled : 1;
513 };
514
515 /**
516  * An animator for a specific property type PropertyType.
517  */
518 template<typename PropertyType, typename PropertyAccessorType>
519 class Animator final : public AnimatorBase
520 {
521   using AnimatorFunction = std::function<PropertyType(float, const PropertyType&)>;
522
523   AnimatorFunction mAnimatorFunction;
524
525 public:
526   /**
527    * Construct a new property animator.
528    * @param[in] property The animatable property; only valid while the Animator is attached.
529    * @param[in] animatorFunction The function used to animate the property.
530    * @param[in] alphaFunction The alpha function to apply.
531    * @param[in] timePeriod The time period of this animation.
532    * @return A newly allocated animator.
533    */
534   static AnimatorBase* New(const PropertyOwner& propertyOwner,
535                            const PropertyBase&  property,
536                            AnimatorFunction     animatorFunction,
537                            AlphaFunction        alphaFunction,
538                            const TimePeriod&    timePeriod)
539   {
540     // The property was const in the actor-thread, but animators are used in the scene-graph thread.
541     return new Animator(const_cast<PropertyOwner*>(&propertyOwner),
542                         const_cast<PropertyBase*>(&property),
543                         std::move(animatorFunction),
544                         alphaFunction,
545                         timePeriod);
546   }
547
548   /**
549    * @copydoc AnimatorBase::DoUpdate( BufferIndex bufferIndex, bool bake, float alpha )
550    */
551   void DoUpdate(BufferIndex bufferIndex, bool bake, float alpha) final
552   {
553     const PropertyType& current = mPropertyAccessor.Get(bufferIndex);
554
555     // need to cast the return value in case property is integer
556     const PropertyType result = static_cast<PropertyType>(mAnimatorFunction(alpha, current));
557
558     if(bake)
559     {
560       mPropertyAccessor.Bake(bufferIndex, result);
561     }
562     else
563     {
564       mPropertyAccessor.Set(bufferIndex, result);
565     }
566   }
567
568 private:
569   /**
570    * Private constructor; see also Animator::New().
571    */
572   Animator(PropertyOwner*    propertyOwner,
573            PropertyBase*     property,
574            AnimatorFunction  animatorFunction,
575            AlphaFunction     alphaFunction,
576            const TimePeriod& timePeriod)
577   : AnimatorBase(propertyOwner, alphaFunction, timePeriod),
578     mAnimatorFunction(std::move(animatorFunction)),
579     mPropertyAccessor(property)
580   {
581     // WARNING - this object is created in the event-thread
582     // The scene-graph mPropertyOwner object cannot be observed here
583   }
584
585   // Undefined
586   Animator(const Animator&);
587
588   // Undefined
589   Animator& operator=(const Animator&);
590
591 protected:
592   PropertyAccessorType mPropertyAccessor;
593 };
594
595 /**
596  * An animator for a specific property type PropertyType.
597  */
598 template<typename PropertyType, typename PropertyAccessorType>
599 class AnimatorTransformProperty final : public AnimatorBase
600 {
601   using AnimatorFunction = std::function<PropertyType(float, const PropertyType&)>;
602
603   AnimatorFunction mAnimatorFunction;
604
605 public:
606   /**
607    * Construct a new property animator.
608    * @param[in] property The animatable property; only valid while the Animator is attached.
609    * @param[in] animatorFunction The function used to animate the property.
610    * @param[in] alphaFunction The alpha function to apply.
611    * @param[in] timePeriod The time period of this animation.
612    * @return A newly allocated animator.
613    */
614   static AnimatorBase* New(const PropertyOwner& propertyOwner,
615                            const PropertyBase&  property,
616                            AnimatorFunction     animatorFunction,
617                            AlphaFunction        alphaFunction,
618                            const TimePeriod&    timePeriod)
619   {
620     // The property was const in the actor-thread, but animators are used in the scene-graph thread.
621     return new AnimatorTransformProperty(const_cast<PropertyOwner*>(&propertyOwner),
622                                          const_cast<PropertyBase*>(&property),
623                                          std::move(animatorFunction),
624                                          alphaFunction,
625                                          timePeriod);
626   }
627
628   /**
629    * @copydoc AnimatorBase::DoUpdate( BufferIndex bufferIndex, bool bake, float alpha )
630    */
631   void DoUpdate(BufferIndex bufferIndex, bool bake, float alpha) final
632   {
633     const PropertyType& current = mPropertyAccessor.Get(bufferIndex);
634
635     // need to cast the return value in case property is integer
636     const PropertyType result = static_cast<PropertyType>(mAnimatorFunction(alpha, current));
637
638     if(bake)
639     {
640       mPropertyAccessor.Bake(bufferIndex, result);
641     }
642     else
643     {
644       mPropertyAccessor.Set(bufferIndex, result);
645     }
646   }
647
648 private:
649   /**
650    * Private constructor; see also Animator::New().
651    */
652   AnimatorTransformProperty(PropertyOwner*    propertyOwner,
653                             PropertyBase*     property,
654                             AnimatorFunction  animatorFunction,
655                             AlphaFunction     alphaFunction,
656                             const TimePeriod& timePeriod)
657   : AnimatorBase(propertyOwner, alphaFunction, timePeriod),
658     mAnimatorFunction(std::move(animatorFunction)),
659     mPropertyAccessor(property)
660   {
661     // WARNING - this object is created in the event-thread
662     // The scene-graph mPropertyOwner object cannot be observed here
663   }
664
665   // Undefined
666   AnimatorTransformProperty()                                 = delete;
667   AnimatorTransformProperty(const AnimatorTransformProperty&) = delete;
668   AnimatorTransformProperty& operator=(const AnimatorTransformProperty&) = delete;
669
670 protected:
671   PropertyAccessorType mPropertyAccessor;
672 };
673
674 } // namespace SceneGraph
675
676 // Update functions
677
678 struct AnimateByInteger
679 {
680   AnimateByInteger(const int& relativeValue)
681   : mRelative(relativeValue)
682   {
683   }
684
685   float operator()(float alpha, const int32_t& property)
686   {
687     // integers need to be correctly rounded
688     return roundf(static_cast<float>(property) + static_cast<float>(mRelative) * alpha);
689   }
690
691   int32_t mRelative;
692 };
693
694 struct AnimateToInteger
695 {
696   AnimateToInteger(const int& targetValue)
697   : mTarget(targetValue)
698   {
699   }
700
701   float operator()(float alpha, const int32_t& property)
702   {
703     // integers need to be correctly rounded
704     return roundf(static_cast<float>(property) + (static_cast<float>(mTarget - property) * alpha));
705   }
706
707   int32_t mTarget;
708 };
709
710 struct AnimateByFloat
711 {
712   AnimateByFloat(const float& relativeValue)
713   : mRelative(relativeValue)
714   {
715   }
716
717   float operator()(float alpha, const float& property)
718   {
719     return float(property + mRelative * alpha);
720   }
721
722   float mRelative;
723 };
724
725 struct AnimateToFloat
726 {
727   AnimateToFloat(const float& targetValue)
728   : mTarget(targetValue)
729   {
730   }
731
732   float operator()(float alpha, const float& property)
733   {
734     return float(property + ((mTarget - property) * alpha));
735   }
736
737   float mTarget;
738 };
739
740 struct AnimateByVector2
741 {
742   AnimateByVector2(const Vector2& relativeValue)
743   : mRelative(relativeValue)
744   {
745   }
746
747   Vector2 operator()(float alpha, const Vector2& property)
748   {
749     return Vector2(property + mRelative * alpha);
750   }
751
752   Vector2 mRelative;
753 };
754
755 struct AnimateToVector2
756 {
757   AnimateToVector2(const Vector2& targetValue)
758   : mTarget(targetValue)
759   {
760   }
761
762   Vector2 operator()(float alpha, const Vector2& property)
763   {
764     return Vector2(property + ((mTarget - property) * alpha));
765   }
766
767   Vector2 mTarget;
768 };
769
770 struct AnimateByVector3
771 {
772   AnimateByVector3(const Vector3& relativeValue)
773   : mRelative(relativeValue)
774   {
775   }
776
777   Vector3 operator()(float alpha, const Vector3& property)
778   {
779     return Vector3(property + mRelative * alpha);
780   }
781
782   Vector3 mRelative;
783 };
784
785 struct AnimateToVector3
786 {
787   AnimateToVector3(const Vector3& targetValue)
788   : mTarget(targetValue)
789   {
790   }
791
792   Vector3 operator()(float alpha, const Vector3& property)
793   {
794     return Vector3(property + ((mTarget - property) * alpha));
795   }
796
797   Vector3 mTarget;
798 };
799
800 struct AnimateByVector4
801 {
802   AnimateByVector4(const Vector4& relativeValue)
803   : mRelative(relativeValue)
804   {
805   }
806
807   Vector4 operator()(float alpha, const Vector4& property)
808   {
809     return Vector4(property + mRelative * alpha);
810   }
811
812   Vector4 mRelative;
813 };
814
815 struct AnimateToVector4
816 {
817   AnimateToVector4(const Vector4& targetValue)
818   : mTarget(targetValue)
819   {
820   }
821
822   Vector4 operator()(float alpha, const Vector4& property)
823   {
824     return Vector4(property + ((mTarget - property) * alpha));
825   }
826
827   Vector4 mTarget;
828 };
829
830 struct AnimateByOpacity
831 {
832   AnimateByOpacity(const float& relativeValue)
833   : mRelative(relativeValue)
834   {
835   }
836
837   Vector4 operator()(float alpha, const Vector4& property)
838   {
839     Vector4 result(property);
840     result.a += mRelative * alpha;
841
842     return result;
843   }
844
845   float mRelative;
846 };
847
848 struct AnimateToOpacity
849 {
850   AnimateToOpacity(const float& targetValue)
851   : mTarget(targetValue)
852   {
853   }
854
855   Vector4 operator()(float alpha, const Vector4& property)
856   {
857     Vector4 result(property);
858     result.a = property.a + ((mTarget - property.a) * alpha);
859
860     return result;
861   }
862
863   float mTarget;
864 };
865
866 struct AnimateByBoolean
867 {
868   AnimateByBoolean(bool relativeValue)
869   : mRelative(relativeValue)
870   {
871   }
872
873   bool operator()(float alpha, const bool& property)
874   {
875     // Alpha is not useful here, just keeping to the same template as other update functors
876     return bool(alpha >= 1.0f ? (property || mRelative) : property);
877   }
878
879   bool mRelative;
880 };
881
882 struct AnimateToBoolean
883 {
884   AnimateToBoolean(bool targetValue)
885   : mTarget(targetValue)
886   {
887   }
888
889   bool operator()(float alpha, const bool& property)
890   {
891     // Alpha is not useful here, just keeping to the same template as other update functors
892     return bool(alpha >= 1.0f ? mTarget : property);
893   }
894
895   bool mTarget;
896 };
897
898 struct RotateByAngleAxis
899 {
900   RotateByAngleAxis(const Radian& angleRadians, const Vector3& axis)
901   : mAngleRadians(angleRadians),
902     mAxis(axis.x, axis.y, axis.z)
903   {
904   }
905
906   Quaternion operator()(float alpha, const Quaternion& rotation)
907   {
908     if(alpha > 0.0f)
909     {
910       return rotation * Quaternion(mAngleRadians * alpha, mAxis);
911     }
912
913     return rotation;
914   }
915
916   Radian  mAngleRadians;
917   Vector3 mAxis;
918 };
919
920 struct RotateToQuaternion
921 {
922   RotateToQuaternion(const Quaternion& targetValue)
923   : mTarget(targetValue)
924   {
925   }
926
927   Quaternion operator()(float alpha, const Quaternion& rotation)
928   {
929     return Quaternion::Slerp(rotation, mTarget, alpha);
930   }
931
932   Quaternion mTarget;
933 };
934
935 struct KeyFrameBooleanFunctor
936 {
937   KeyFrameBooleanFunctor(KeyFrameBoolean keyFrames)
938   : mKeyFrames(std::move(keyFrames))
939   {
940   }
941
942   bool operator()(float progress, const bool& property)
943   {
944     if(mKeyFrames.IsActive(progress))
945     {
946       return mKeyFrames.GetValue(progress, Dali::Animation::LINEAR);
947     }
948     return property;
949   }
950
951   KeyFrameBoolean mKeyFrames;
952 };
953
954 struct KeyFrameIntegerFunctor
955 {
956   KeyFrameIntegerFunctor(KeyFrameInteger keyFrames, Interpolation interpolation)
957   : mKeyFrames(std::move(keyFrames)),
958     mInterpolation(interpolation)
959   {
960   }
961
962   float operator()(float progress, const int32_t& property)
963   {
964     if(mKeyFrames.IsActive(progress))
965     {
966       return static_cast<float>(mKeyFrames.GetValue(progress, mInterpolation));
967     }
968     return static_cast<float>(property);
969   }
970
971   KeyFrameInteger mKeyFrames;
972   Interpolation   mInterpolation;
973 };
974
975 struct KeyFrameNumberFunctor
976 {
977   KeyFrameNumberFunctor(KeyFrameNumber keyFrames, Interpolation interpolation)
978   : mKeyFrames(std::move(keyFrames)),
979     mInterpolation(interpolation)
980   {
981   }
982
983   float operator()(float progress, const float& property)
984   {
985     if(mKeyFrames.IsActive(progress))
986     {
987       return mKeyFrames.GetValue(progress, mInterpolation);
988     }
989     return property;
990   }
991
992   KeyFrameNumber mKeyFrames;
993   Interpolation  mInterpolation;
994 };
995
996 struct KeyFrameVector2Functor
997 {
998   KeyFrameVector2Functor(KeyFrameVector2 keyFrames, Interpolation interpolation)
999   : mKeyFrames(std::move(keyFrames)),
1000     mInterpolation(interpolation)
1001   {
1002   }
1003
1004   Vector2 operator()(float progress, const Vector2& property)
1005   {
1006     if(mKeyFrames.IsActive(progress))
1007     {
1008       return mKeyFrames.GetValue(progress, mInterpolation);
1009     }
1010     return property;
1011   }
1012
1013   KeyFrameVector2 mKeyFrames;
1014   Interpolation   mInterpolation;
1015 };
1016
1017 struct KeyFrameVector3Functor
1018 {
1019   KeyFrameVector3Functor(KeyFrameVector3 keyFrames, Interpolation interpolation)
1020   : mKeyFrames(std::move(keyFrames)),
1021     mInterpolation(interpolation)
1022   {
1023   }
1024
1025   Vector3 operator()(float progress, const Vector3& property)
1026   {
1027     if(mKeyFrames.IsActive(progress))
1028     {
1029       return mKeyFrames.GetValue(progress, mInterpolation);
1030     }
1031     return property;
1032   }
1033
1034   KeyFrameVector3 mKeyFrames;
1035   Interpolation   mInterpolation;
1036 };
1037
1038 struct KeyFrameVector4Functor
1039 {
1040   KeyFrameVector4Functor(KeyFrameVector4 keyFrames, Interpolation interpolation)
1041   : mKeyFrames(std::move(keyFrames)),
1042     mInterpolation(interpolation)
1043   {
1044   }
1045
1046   Vector4 operator()(float progress, const Vector4& property)
1047   {
1048     if(mKeyFrames.IsActive(progress))
1049     {
1050       return mKeyFrames.GetValue(progress, mInterpolation);
1051     }
1052     return property;
1053   }
1054
1055   KeyFrameVector4 mKeyFrames;
1056   Interpolation   mInterpolation;
1057 };
1058
1059 struct KeyFrameQuaternionFunctor
1060 {
1061   KeyFrameQuaternionFunctor(KeyFrameQuaternion keyFrames)
1062   : mKeyFrames(std::move(keyFrames))
1063   {
1064   }
1065
1066   Quaternion operator()(float progress, const Quaternion& property)
1067   {
1068     if(mKeyFrames.IsActive(progress))
1069     {
1070       return mKeyFrames.GetValue(progress, Dali::Animation::LINEAR);
1071     }
1072     return property;
1073   }
1074
1075   KeyFrameQuaternion mKeyFrames;
1076 };
1077
1078 struct PathPositionFunctor
1079 {
1080   PathPositionFunctor(PathPtr path)
1081   : mPath(path)
1082   {
1083   }
1084
1085   Vector3 operator()(float progress, const Vector3& property)
1086   {
1087     Vector3 position(property);
1088     static_cast<void>(mPath->SamplePosition(progress, position));
1089     return position;
1090   }
1091
1092   PathPtr mPath;
1093 };
1094
1095 struct PathRotationFunctor
1096 {
1097   PathRotationFunctor(PathPtr path, const Vector3& forward)
1098   : mPath(path),
1099     mForward(forward)
1100   {
1101     mForward.Normalize();
1102   }
1103
1104   Quaternion operator()(float progress, const Quaternion& property)
1105   {
1106     Vector3 tangent;
1107     if(mPath->SampleTangent(progress, tangent))
1108     {
1109       return Quaternion(mForward, tangent);
1110     }
1111     else
1112     {
1113       return property;
1114     }
1115   }
1116
1117   PathPtr mPath;
1118   Vector3 mForward;
1119 };
1120
1121 } // namespace Internal
1122
1123 } // namespace Dali
1124
1125 #endif // DALI_INTERNAL_SCENE_GRAPH_ANIMATOR_H