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