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