Added api function to specify speed factor of an animation
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / animation-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/animation/animation-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/animation/alpha-functions.h>
23 #include <dali/public-api/animation/time-period.h>
24 #include <dali/public-api/common/dali-common.h>
25 #include <dali/public-api/object/type-registry.h>
26 #include <dali/public-api/math/vector2.h>
27 #include <dali/public-api/math/radian.h>
28 #include <dali/internal/event/actors/actor-impl.h>
29 #include <dali/internal/event/common/stage-impl.h>
30 #include <dali/internal/event/animation/animator-connector.h>
31 #include <dali/internal/event/animation/animation-playlist.h>
32 #include <dali/internal/event/common/notification-manager.h>
33 #include <dali/internal/update/manager/update-manager.h>
34 #include <dali/internal/event/effects/shader-effect-impl.h>
35 #include <dali/internal/event/common/thread-local-storage.h>
36
37 using namespace std;
38
39 using Dali::Internal::SceneGraph::UpdateManager;
40 using Dali::Internal::SceneGraph::AnimatorBase;
41 using Dali::Internal::SceneGraph::Shader;
42
43 namespace Dali
44 {
45
46 namespace Internal
47 {
48
49 static bool SHOW_VALUE = true;
50 static bool HIDE_VALUE = false;
51
52 namespace
53 {
54
55 BaseHandle Create()
56 {
57   return Dali::Animation::New(0.f);
58 }
59
60 TypeRegistration mType( typeid(Dali::Animation), typeid(Dali::BaseHandle), Create );
61
62 SignalConnectorType signalConnector1( mType, Dali::Animation::SIGNAL_FINISHED, &Animation::DoConnectSignal );
63
64 TypeAction action1( mType, Dali::Animation::ACTION_PLAY, &Animation::DoAction );
65 TypeAction action2( mType, Dali::Animation::ACTION_STOP, &Animation::DoAction );
66 TypeAction action3( mType, Dali::Animation::ACTION_PAUSE, &Animation::DoAction );
67
68 } // anon namespace
69
70
71 AnimationPtr Animation::New(float durationSeconds)
72 {
73   return New(durationSeconds, Dali::Animation::Bake, Dali::Animation::Bake, Dali::AlphaFunctions::Linear);
74 }
75
76 AnimationPtr Animation::New(float durationSeconds, EndAction endAction, EndAction destroyAction)
77 {
78   return New(durationSeconds, endAction, destroyAction, Dali::AlphaFunctions::Linear);
79 }
80
81 AnimationPtr Animation::New(float durationSeconds, EndAction endAction, EndAction destroyAction, AlphaFunction alpha)
82 {
83   ThreadLocalStorage& tls = ThreadLocalStorage::Get();
84   UpdateManager& updateManager = tls.GetUpdateManager();
85
86   AnimationPlaylist& playlist = Stage::GetCurrent()->GetAnimationPlaylist();
87
88   AnimationPtr progress = new Animation( updateManager, playlist, durationSeconds, endAction, destroyAction, alpha );
89
90   // Second-phase construction
91   progress->Initialize();
92
93   return progress;
94 }
95
96 Animation::Animation( UpdateManager& updateManager, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction destroyAction, AlphaFunction defaultAlpha )
97 : mUpdateManager( updateManager ),
98   mPlaylist( playlist ),
99   mAnimation( NULL ),
100   mNotificationCount( 0 ),
101   mFinishedCallback( NULL ),
102   mFinishedCallbackObject( NULL ),
103   mDurationSeconds( durationSeconds ),
104   mSpeedFactor(1.0f),
105   mIsLooping( false ),
106   mEndAction( endAction ),
107   mDestroyAction( destroyAction ),
108   mDefaultAlpha( defaultAlpha )
109 {
110 }
111
112 void Animation::Initialize()
113 {
114   // Connect to the animation playlist
115   mPlaylist.AnimationCreated( *this );
116
117   CreateSceneObject();
118
119   RegisterObject();
120 }
121
122 Animation::~Animation()
123 {
124   // Guard to allow handle destruction after Core has been destroyed
125   if ( Stage::IsInstalled() )
126   {
127     // Disconnect from the animation playlist
128     mPlaylist.AnimationDestroyed( *this );
129
130     DestroySceneObject();
131
132     UnregisterObject();
133   }
134 }
135
136 void Animation::CreateSceneObject()
137 {
138   DALI_ASSERT_DEBUG( mAnimation == NULL );
139
140   // Create a new animation, temporarily owned
141   SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mIsLooping, mEndAction, mDestroyAction );
142
143   // Keep a const pointer to the animation.
144   mAnimation = animation;
145
146   // Transfer animation ownership to the update manager through a message
147   AddAnimationMessage( mUpdateManager, animation );
148 }
149
150 void Animation::DestroySceneObject()
151 {
152   if ( mAnimation != NULL )
153   {
154     // Remove animation using a message to the update manager
155     RemoveAnimationMessage( mUpdateManager, *mAnimation );
156     mAnimation = NULL;
157   }
158 }
159
160 void Animation::SetDuration(float seconds)
161 {
162   // Cache for public getters
163   mDurationSeconds = seconds;
164
165   // mAnimation is being used in a separate thread; queue a message to set the value
166   SetDurationMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, seconds );
167 }
168
169 float Animation::GetDuration() const
170 {
171   // This is not animatable; the cached value is up-to-date.
172   return mDurationSeconds;
173 }
174
175 void Animation::SetLooping(bool looping)
176 {
177   // Cache for public getters
178   mIsLooping = looping;
179
180   // mAnimation is being used in a separate thread; queue a message to set the value
181   SetLoopingMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, looping );
182 }
183
184 bool Animation::IsLooping() const
185 {
186   // This is not animatable; the cached value is up-to-date.
187   return mIsLooping;
188 }
189
190 void Animation::SetEndAction(EndAction action)
191 {
192   // Cache for public getters
193   mEndAction = action;
194
195   // mAnimation is being used in a separate thread; queue a message to set the value
196   SetEndActionMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, action );
197 }
198
199 Dali::Animation::EndAction Animation::GetEndAction() const
200 {
201   // This is not animatable; the cached value is up-to-date.
202   return mEndAction;
203 }
204
205 void Animation::SetDestroyAction(EndAction action)
206 {
207   // Cache for public getters
208   mDestroyAction = action;
209
210   // mAnimation is being used in a separate thread; queue a message to set the value
211   SetDestroyActionMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, action );
212 }
213
214 Dali::Animation::EndAction Animation::GetDestroyAction() const
215 {
216   // This is not animatable; the cached value is up-to-date.
217   return mDestroyAction;
218 }
219
220 void Animation::Play()
221 {
222   // Update the current playlist
223   mPlaylist.OnPlay( *this );
224
225   // mAnimation is being used in a separate thread; queue a Play message
226   PlayAnimationMessage( mUpdateManager.GetEventToUpdate(), *mAnimation );
227 }
228
229 void Animation::PlayFrom( float progress )
230 {
231   if( progress >= 0.0f && progress <= 1.0f )
232   {
233     // Update the current playlist
234     mPlaylist.OnPlay( *this );
235
236     // mAnimation is being used in a separate thread; queue a Play message
237     PlayAnimationFromMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, progress );
238   }
239 }
240
241 void Animation::Pause()
242 {
243   // mAnimation is being used in a separate thread; queue a Pause message
244   PauseAnimationMessage( mUpdateManager.GetEventToUpdate(), *mAnimation );
245 }
246
247 void Animation::Stop()
248 {
249   // mAnimation is being used in a separate thread; queue a Stop message
250   StopAnimationMessage( mUpdateManager, *mAnimation );
251 }
252
253 void Animation::Clear()
254 {
255   DALI_ASSERT_DEBUG(mAnimation);
256
257   // Remove all the connectors
258   mConnectors.Clear();
259
260   // Replace the old scene-object with a new one
261   DestroySceneObject();
262   CreateSceneObject();
263
264   // Reset the notification count, since the new scene-object has never been played
265   mNotificationCount = 0;
266
267   // Update the current playlist
268   mPlaylist.OnClear( *this );
269 }
270
271 void Animation::AnimateBy(Property& target, Property::Value& relativeValue)
272 {
273   AnimateBy(target, relativeValue, AlphaFunctions::Default, mDurationSeconds);
274 }
275
276 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha)
277 {
278   AnimateBy(target, relativeValue, alpha, mDurationSeconds);
279 }
280
281 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, TimePeriod period)
282 {
283   AnimateBy(target, relativeValue, AlphaFunctions::Default, period);
284 }
285
286 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period)
287 {
288   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
289
290   ExtendDuration( period );
291
292   switch ( relativeValue.GetType() )
293   {
294     case Property::BOOLEAN:
295     {
296       AddAnimatorConnector( AnimatorConnector<bool>::New( proxy,
297                                                           target.propertyIndex,
298                                                           target.componentIndex,
299                                                           AnimateByBoolean(relativeValue.Get<bool>()),
300                                                           alpha,
301                                                           period ) );
302       break;
303     }
304
305     case Property::FLOAT:
306     {
307       AddAnimatorConnector( AnimatorConnector<float>::New( proxy,
308                                                            target.propertyIndex,
309                                                            target.componentIndex,
310                                                            AnimateByFloat(relativeValue.Get<float>()),
311                                                            alpha,
312                                                            period ) );
313       break;
314     }
315
316     case Property::INTEGER:
317     {
318       AddAnimatorConnector( AnimatorConnector<int>::New( proxy,
319                                                          target.propertyIndex,
320                                                          target.componentIndex,
321                                                          AnimateByInteger(relativeValue.Get<int>()),
322                                                          alpha,
323                                                          period ) );
324       break;
325     }
326
327     case Property::VECTOR2:
328     {
329       AddAnimatorConnector( AnimatorConnector<Vector2>::New( proxy,
330                                                              target.propertyIndex,
331                                                              target.componentIndex,
332                                                              AnimateByVector2(relativeValue.Get<Vector2>()),
333                                                              alpha,
334                                                              period ) );
335       break;
336     }
337
338     case Property::VECTOR3:
339     {
340       AddAnimatorConnector( AnimatorConnector<Vector3>::New( proxy,
341                                                              target.propertyIndex,
342                                                              target.componentIndex,
343                                                              AnimateByVector3(relativeValue.Get<Vector3>()),
344                                                              alpha,
345                                                              period ) );
346       break;
347     }
348
349     case Property::VECTOR4:
350     {
351       AddAnimatorConnector( AnimatorConnector<Vector4>::New( proxy,
352                                                              target.propertyIndex,
353                                                              target.componentIndex,
354                                                              AnimateByVector4(relativeValue.Get<Vector4>()),
355                                                              alpha,
356                                                              period ) );
357       break;
358     }
359
360     case Property::ROTATION:
361     {
362       AngleAxis angleAxis = relativeValue.Get<AngleAxis>();
363
364       AddAnimatorConnector( AnimatorConnector<Quaternion>::New( proxy,
365                                                                 target.propertyIndex,
366                                                                 target.componentIndex,
367                                                                 RotateByAngleAxis(angleAxis.angle, angleAxis.axis),
368                                                                 alpha,
369                                                                 period ) );
370       break;
371     }
372
373     default:
374       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here
375       break;
376   }
377 }
378
379 void Animation::AnimateTo(Property& target, Property::Value& destinationValue)
380 {
381   AnimateTo(target, destinationValue, AlphaFunctions::Default, mDurationSeconds);
382 }
383
384 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha)
385 {
386   AnimateTo(target, destinationValue, alpha, mDurationSeconds);
387 }
388
389 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, TimePeriod period)
390 {
391   AnimateTo(target, destinationValue, AlphaFunctions::Default, period);
392 }
393
394 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
395 {
396   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
397
398   AnimateTo( proxy, target.propertyIndex, target.componentIndex, destinationValue, alpha, period );
399 }
400
401 void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
402 {
403   Property::Type type = targetObject.GetPropertyType(targetPropertyIndex);
404   if(componentIndex != Property::INVALID_COMPONENT_INDEX)
405   {
406     if( type == Property::VECTOR2
407         || type == Property::VECTOR3
408         || type == Property::VECTOR4 )
409     {
410       type = Property::FLOAT;
411     }
412   }
413   DALI_ASSERT_ALWAYS( type == destinationValue.GetType() && "DestinationValue does not match Target Property type" );
414
415   ExtendDuration( period );
416
417   switch (destinationValue.GetType())
418   {
419     case Property::BOOLEAN:
420     {
421       AddAnimatorConnector( AnimatorConnector<bool>::New(targetObject,
422                                                          targetPropertyIndex,
423                                                          componentIndex,
424                                                          AnimateToBoolean(destinationValue.Get<bool>()),
425                                                          alpha,
426                                                          period) );
427       break;
428     }
429
430     case Property::FLOAT:
431     {
432       AddAnimatorConnector( AnimatorConnector<float>::New(targetObject,
433                                                           targetPropertyIndex,
434                                                           componentIndex,
435                                                           AnimateToFloat(destinationValue.Get<float>()),
436                                                           alpha,
437                                                           period) );
438       break;
439     }
440
441     case Property::INTEGER:
442     {
443       AddAnimatorConnector( AnimatorConnector<int>::New(targetObject,
444                                                         targetPropertyIndex,
445                                                         componentIndex,
446                                                         AnimateToInteger(destinationValue.Get<int>()),
447                                                         alpha,
448                                                         period) );
449       break;
450     }
451
452     case Property::VECTOR2:
453     {
454       AddAnimatorConnector( AnimatorConnector<Vector2>::New(targetObject,
455                                                             targetPropertyIndex,
456                                                             componentIndex,
457                                                             AnimateToVector2(destinationValue.Get<Vector2>()),
458                                                             alpha,
459                                                             period) );
460       break;
461     }
462
463     case Property::VECTOR3:
464     {
465       if ( Dali::Actor::SIZE == targetPropertyIndex )
466       {
467         // Test whether this is actually an Actor
468         Actor* maybeActor = dynamic_cast<Actor*>( &targetObject );
469         if ( maybeActor )
470         {
471           // Notify the actor that its size is being animated
472           maybeActor->OnSizeAnimation( *this, destinationValue.Get<Vector3>() );
473         }
474       }
475
476       AddAnimatorConnector( AnimatorConnector<Vector3>::New(targetObject,
477                                                             targetPropertyIndex,
478                                                             componentIndex,
479                                                             AnimateToVector3(destinationValue.Get<Vector3>()),
480                                                             alpha,
481                                                             period) );
482       break;
483     }
484
485     case Property::VECTOR4:
486     {
487       AddAnimatorConnector( AnimatorConnector<Vector4>::New(targetObject,
488                                                             targetPropertyIndex,
489                                                             componentIndex,
490                                                             AnimateToVector4(destinationValue.Get<Vector4>()),
491                                                             alpha,
492                                                             period) );
493       break;
494     }
495
496     case Property::ROTATION:
497     {
498       AddAnimatorConnector( AnimatorConnector<Quaternion>::New(targetObject,
499                                                                targetPropertyIndex,
500                                                                componentIndex,
501                                                                RotateToQuaternion(destinationValue.Get<Quaternion>()),
502                                                                alpha,
503                                                                period) );
504       break;
505     }
506
507     default:
508       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here
509       break;
510   }
511 }
512
513 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames)
514 {
515   AnimateBetween(target, keyFrames, mDefaultAlpha, mDurationSeconds);
516 }
517
518 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period)
519 {
520   AnimateBetween(target, keyFrames, mDefaultAlpha, period);
521 }
522
523 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha)
524 {
525   AnimateBetween(target, keyFrames, alpha, mDurationSeconds);
526 }
527
528 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
529 {
530   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
531
532   ExtendDuration( period );
533
534   switch(keyFrames.GetType())
535   {
536     case Dali::Property::BOOLEAN:
537     {
538       const KeyFrameBoolean* kf;
539       GetSpecialization(keyFrames, kf);
540       KeyFrameBooleanPtr kfCopy = KeyFrameBoolean::Clone(*kf);
541       AddAnimatorConnector( AnimatorConnector<bool>::New( proxy,
542                                                           target.propertyIndex,
543                                                           target.componentIndex,
544                                                           KeyFrameBooleanFunctor(kfCopy),
545                                                           alpha,
546                                                           period ) );
547       break;
548     }
549
550     case Dali::Property::FLOAT:
551     {
552       const KeyFrameNumber* kf;
553       GetSpecialization(keyFrames, kf);
554       KeyFrameNumberPtr kfCopy = KeyFrameNumber::Clone(*kf);
555       AddAnimatorConnector( AnimatorConnector<float>::New( proxy,
556                                                            target.propertyIndex,
557                                                            target.componentIndex,
558                                                            KeyFrameNumberFunctor(kfCopy),
559                                                            alpha,
560                                                            period ) );
561       break;
562     }
563
564     case Dali::Property::INTEGER:
565     {
566       const KeyFrameInteger* kf;
567       GetSpecialization(keyFrames, kf);
568       KeyFrameIntegerPtr kfCopy = KeyFrameInteger::Clone(*kf);
569       AddAnimatorConnector( AnimatorConnector<int>::New( proxy,
570                                                          target.propertyIndex,
571                                                          target.componentIndex,
572                                                          KeyFrameIntegerFunctor(kfCopy),
573                                                          alpha,
574                                                          period ) );
575       break;
576     }
577
578     case Dali::Property::VECTOR2:
579     {
580       const KeyFrameVector2* kf;
581       GetSpecialization(keyFrames, kf);
582       KeyFrameVector2Ptr kfCopy = KeyFrameVector2::Clone(*kf);
583       AddAnimatorConnector( AnimatorConnector<Vector2>::New( proxy,
584                                                              target.propertyIndex,
585                                                              target.componentIndex,
586                                                              KeyFrameVector2Functor(kfCopy),
587                                                              alpha,
588                                                              period ) );
589       break;
590     }
591
592     case Dali::Property::VECTOR3:
593     {
594       const KeyFrameVector3* kf;
595       GetSpecialization(keyFrames, kf);
596       KeyFrameVector3Ptr kfCopy = KeyFrameVector3::Clone(*kf);
597       AddAnimatorConnector( AnimatorConnector<Vector3>::New( proxy,
598                                                              target.propertyIndex,
599                                                              target.componentIndex,
600                                                              KeyFrameVector3Functor(kfCopy),
601                                                              alpha,
602                                                              period ) );
603       break;
604     }
605
606     case Dali::Property::VECTOR4:
607     {
608       const KeyFrameVector4* kf;
609       GetSpecialization(keyFrames, kf);
610       KeyFrameVector4Ptr kfCopy = KeyFrameVector4::Clone(*kf);
611       AddAnimatorConnector( AnimatorConnector<Vector4>::New( proxy,
612                                                              target.propertyIndex,
613                                                              target.componentIndex,
614                                                              KeyFrameVector4Functor(kfCopy),
615                                                              alpha,
616                                                              period ) );
617       break;
618     }
619
620     case Dali::Property::ROTATION:
621     {
622       const KeyFrameQuaternion* kf;
623       GetSpecialization(keyFrames, kf);
624       KeyFrameQuaternionPtr kfCopy = KeyFrameQuaternion::Clone(*kf);
625       AddAnimatorConnector( AnimatorConnector<Quaternion>::New( proxy,
626                                                                 target.propertyIndex,
627                                                                 target.componentIndex,
628                                                                 KeyFrameQuaternionFunctor(kfCopy),
629                                                                 alpha,
630                                                                 period ) );
631       break;
632     }
633
634     default: // not all property types are animateable
635       break;
636   }
637 }
638
639 void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func )
640 {
641   Animate( target, targetType, func, mDefaultAlpha, mDurationSeconds );
642 }
643
644 void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func, AlphaFunction& alpha )
645 {
646   Animate( target, targetType, func, alpha, mDurationSeconds );
647 }
648
649 void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func, TimePeriod period )
650 {
651   Animate( target, targetType, func, mDefaultAlpha, period );
652 }
653
654 void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func, AlphaFunction& alpha, TimePeriod period )
655 {
656   Property::Type type = target.object.GetPropertyType(target.propertyIndex);
657   if(target.componentIndex != Property::INVALID_COMPONENT_INDEX)
658   {
659     if( type == Property::VECTOR2
660         || type == Property::VECTOR3
661         || type == Property::VECTOR4 )
662     {
663       type = Property::FLOAT;
664     }
665   }
666   DALI_ASSERT_ALWAYS( type == targetType && "Animation function must match target property type" );
667
668   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
669
670   ExtendDuration( period );
671
672   switch ( targetType )
673   {
674     case Property::BOOLEAN:
675     {
676       AddAnimatorConnector( AnimatorConnector<bool>::New(proxy,
677                                                          target.propertyIndex,
678                                                          target.componentIndex,
679                                                          AnyCast< AnimatorFunctionBool >( func ),
680                                                          alpha,
681                                                          period) );
682       break;
683     }
684
685     case Property::FLOAT:
686     {
687       AddAnimatorConnector( AnimatorConnector<float>::New(proxy,
688                                                           target.propertyIndex,
689                                                           target.componentIndex,
690                                                           AnyCast< AnimatorFunctionFloat >( func ),
691                                                           alpha,
692                                                           period) );
693       break;
694     }
695
696     case Property::INTEGER:
697     {
698       AddAnimatorConnector( AnimatorConnector<int>::New(proxy,
699                                                         target.propertyIndex,
700                                                         target.componentIndex,
701                                                         AnyCast< AnimatorFunctionInteger >( func ),
702                                                         alpha,
703                                                         period) );
704       break;
705     }
706
707     case Property::VECTOR2:
708     {
709       AddAnimatorConnector( AnimatorConnector<Vector2>::New(proxy,
710                                                             target.propertyIndex,
711                                                             target.componentIndex,
712                                                             AnyCast< AnimatorFunctionVector2 >( func ),
713                                                             alpha,
714                                                             period) );
715       break;
716     }
717
718     case Property::VECTOR3:
719     {
720       AddAnimatorConnector( AnimatorConnector<Vector3>::New(proxy,
721                                                             target.propertyIndex,
722                                                             target.componentIndex,
723                                                             AnyCast< AnimatorFunctionVector3 >( func ),
724                                                             alpha,
725                                                             period) );
726       break;
727     }
728
729     case Property::VECTOR4:
730     {
731       AddAnimatorConnector( AnimatorConnector<Vector4>::New(proxy,
732                                                             target.propertyIndex,
733                                                             target.componentIndex,
734                                                             AnyCast< AnimatorFunctionVector4 >( func ),
735                                                             alpha,
736                                                             period) );
737       break;
738     }
739
740     case Property::ROTATION:
741     {
742       AddAnimatorConnector( AnimatorConnector<Quaternion>::New(proxy,
743                                                                target.propertyIndex,
744                                                                target.componentIndex,
745                                                                AnyCast< AnimatorFunctionQuaternion >( func ),
746                                                                alpha,
747                                                                period) );
748       break;
749     }
750
751     default:
752       DALI_ASSERT_ALWAYS(false && "Property type enumeration out of bounds" ); // should never come here
753       break;
754   }
755 }
756
757 bool Animation::HasFinished()
758 {
759   bool hasFinished(false);
760   const int playCount(mAnimation->GetPlayCount());
761
762   // If the play count has been incremented, then another notification is required
763   if (playCount > mNotificationCount)
764   {
765     // Note that only one signal is emitted, if the animation has been played repeatedly
766     mNotificationCount = playCount;
767
768     hasFinished = true;
769   }
770
771   return hasFinished;
772 }
773
774 Dali::Animation::AnimationSignalV2& Animation::FinishedSignal()
775 {
776   return mFinishedSignal;
777 }
778
779 void Animation::EmitSignalFinish()
780 {
781   if ( !mFinishedSignal.Empty() )
782   {
783     Dali::Animation handle( this );
784     mFinishedSignal.Emit( handle );
785   }
786
787   // This callback is used internally, to avoid the overhead of using a signal.
788   if ( mFinishedCallback )
789   {
790     mFinishedCallback( mFinishedCallbackObject );
791   }
792 }
793
794 bool Animation::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
795 {
796   bool connected( true );
797   Animation* animation = dynamic_cast<Animation*>(object);
798
799   if ( Dali::Animation::SIGNAL_FINISHED == signalName )
800   {
801     animation->FinishedSignal().Connect( tracker, functor );
802   }
803   else
804   {
805     // signalName does not match any signal
806     connected = false;
807   }
808
809   return connected;
810 }
811
812 void Animation::SetFinishedCallback( FinishedCallback callback, Object* object )
813 {
814   mFinishedCallback = callback;
815   mFinishedCallbackObject = object;
816 }
817
818 void Animation::AddAnimatorConnector( AnimatorConnectorBase* connector )
819 {
820   DALI_ASSERT_DEBUG( NULL != connector );
821
822   connector->SetParent(*this);
823
824   mConnectors.PushBack( connector );
825 }
826
827 void Animation::MoveBy(Actor& actor, float x, float y, float z)
828 {
829   MoveBy(actor, Vector3(x, y, z), mDefaultAlpha, 0.0f, GetDuration());
830 }
831
832 void Animation::MoveBy(Actor& actor, const Vector3& displacement, AlphaFunction alpha)
833 {
834   MoveBy(actor, displacement, alpha, 0.0f, GetDuration());
835 }
836
837 void Animation::MoveBy(Actor& actor, const Vector3& displacement, AlphaFunction alpha, float delaySeconds, float durationSeconds)
838 {
839   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
840
841   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
842                                                          Dali::Actor::POSITION,
843                                                          Property::INVALID_COMPONENT_INDEX,
844                                                          AnimateByVector3(displacement),
845                                                          alpha,
846                                                          TimePeriod(delaySeconds, durationSeconds) ) );
847 }
848
849 void Animation::MoveTo(Actor& actor, float x, float y, float z)
850 {
851   MoveTo(actor, Vector3(x, y, z), mDefaultAlpha, 0.0f, GetDuration());
852 }
853
854 void Animation::MoveTo(Actor& actor, const Vector3& position, AlphaFunction alpha)
855 {
856   MoveTo(actor, position, alpha, 0.0f, GetDuration());
857 }
858
859 void Animation::MoveTo(Actor& actor, const Vector3& position, AlphaFunction alpha,  float delaySeconds, float durationSeconds)
860 {
861   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
862
863   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
864                                                          Dali::Actor::POSITION,
865                                                          Property::INVALID_COMPONENT_INDEX,
866                                                          AnimateToVector3(position),
867                                                          alpha,
868                                                          TimePeriod(delaySeconds, durationSeconds) ) );
869 }
870
871 void Animation::Move(Actor& actor, AnimatorFunctionVector3 func, AlphaFunction alpha,  float delaySeconds, float durationSeconds)
872 {
873   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
874
875   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
876                                                          Dali::Actor::POSITION,
877                                                          Property::INVALID_COMPONENT_INDEX,
878                                                          func,
879                                                          alpha,
880                                                          TimePeriod(delaySeconds, durationSeconds) ) );
881 }
882
883 void Animation::RotateBy(Actor& actor, Radian angle, const Vector3& axis)
884 {
885   RotateBy(actor, angle, axis, mDefaultAlpha, 0.0f, GetDuration());
886 }
887
888 void Animation::RotateBy(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha)
889 {
890   RotateBy(actor, angle, axis, alpha, 0.0f, GetDuration());
891 }
892
893 void Animation::RotateBy(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha, float delaySeconds, float durationSeconds)
894 {
895   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
896
897   AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
898                                                             Dali::Actor::ROTATION,
899                                                             Property::INVALID_COMPONENT_INDEX,
900                                                             RotateByAngleAxis(angle, axis),
901                                                             alpha,
902                                                             TimePeriod(delaySeconds, durationSeconds) ) );
903 }
904
905 void Animation::RotateTo(Actor& actor, Radian angle, const Vector3& axis)
906 {
907   Vector4 normalizedAxis(axis.x, axis.y, axis.z, 0.0f);
908   normalizedAxis.Normalize();
909
910   Quaternion orientation(Quaternion::FromAxisAngle(normalizedAxis, angle));
911
912   RotateTo(actor, orientation, mDefaultAlpha, 0.0f, GetDuration());
913 }
914
915 void Animation::RotateTo(Actor& actor, const Quaternion& orientation)
916 {
917   RotateTo(actor, orientation, mDefaultAlpha, 0.0f, GetDuration());
918 }
919
920 void Animation::RotateTo(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha)
921 {
922   Vector4 normalizedAxis(axis.x, axis.y, axis.z, 0.0f);
923   normalizedAxis.Normalize();
924
925   Quaternion orientation(Quaternion::FromAxisAngle(normalizedAxis, angle));
926
927   RotateTo(actor, orientation, alpha, 0.0f, GetDuration());
928 }
929
930 void Animation::RotateTo(Actor& actor, const Quaternion& orientation, AlphaFunction alpha)
931 {
932   RotateTo(actor, orientation, alpha, 0.0f, GetDuration());
933 }
934
935 void Animation::RotateTo(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha, float delaySeconds, float durationSeconds)
936 {
937   Vector4 normalizedAxis(axis.x, axis.y, axis.z, 0.0f);
938   normalizedAxis.Normalize();
939
940   Quaternion orientation(Quaternion::FromAxisAngle(normalizedAxis, angle));
941
942   RotateTo(actor, orientation, alpha, delaySeconds, durationSeconds);
943 }
944
945 void Animation::RotateTo(Actor& actor, const Quaternion& rotation, AlphaFunction alpha, float delaySeconds, float durationSeconds)
946 {
947   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
948
949   AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
950                                                             Dali::Actor::ROTATION,
951                                                             Property::INVALID_COMPONENT_INDEX,
952                                                             RotateToQuaternion(rotation),
953                                                             alpha,
954                                                             TimePeriod(delaySeconds, durationSeconds) ) );
955 }
956
957 void Animation::Rotate(Actor& actor, AnimatorFunctionQuaternion func, AlphaFunction alpha,  float delaySeconds, float durationSeconds)
958 {
959   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
960
961   AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
962                                                             Dali::Actor::ROTATION,
963                                                             Property::INVALID_COMPONENT_INDEX,
964                                                             func,
965                                                             alpha,
966                                                             TimePeriod(delaySeconds, durationSeconds) ) );
967 }
968
969 void Animation::ScaleBy(Actor& actor, float x, float y, float z)
970 {
971   ScaleBy(actor, Vector3(x, y, z), mDefaultAlpha, 0.0f, GetDuration());
972 }
973
974 void Animation::ScaleBy(Actor& actor, const Vector3& scale, AlphaFunction alpha)
975 {
976   ScaleBy(actor, scale, alpha, 0.0f, GetDuration());
977 }
978
979 void Animation::ScaleBy(Actor& actor, const Vector3& scale, AlphaFunction alpha, float delaySeconds, float durationSeconds)
980 {
981   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
982
983   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
984                                                          Dali::Actor::SCALE,
985                                                          Property::INVALID_COMPONENT_INDEX,
986                                                          AnimateByVector3(scale),
987                                                          alpha,
988                                                          TimePeriod(delaySeconds, durationSeconds) ) );
989 }
990
991 void Animation::ScaleTo(Actor& actor, float x, float y, float z)
992 {
993   ScaleTo(actor, Vector3(x, y, z), mDefaultAlpha, 0.0f, GetDuration());
994 }
995
996 void Animation::ScaleTo(Actor& actor, const Vector3& scale, AlphaFunction alpha)
997 {
998   ScaleTo(actor, scale, alpha, 0.0f, GetDuration());
999 }
1000
1001 void Animation::ScaleTo(Actor& actor, const Vector3& scale, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1002 {
1003   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
1004
1005   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
1006                                                          Dali::Actor::SCALE,
1007                                                          Property::INVALID_COMPONENT_INDEX,
1008                                                          AnimateToVector3(scale),
1009                                                          alpha,
1010                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1011 }
1012
1013 void Animation::Show(Actor& actor, float delaySeconds)
1014 {
1015   ExtendDuration( TimePeriod(delaySeconds, 0) );
1016
1017   AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
1018                                                       Dali::Actor::VISIBLE,
1019                                                       Property::INVALID_COMPONENT_INDEX,
1020                                                       AnimateToBoolean(SHOW_VALUE),
1021                                                       AlphaFunctions::Default,
1022                                                       TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
1023 }
1024
1025 void Animation::Hide(Actor& actor, float delaySeconds)
1026 {
1027   ExtendDuration( TimePeriod(delaySeconds, 0) );
1028
1029   AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
1030                                                       Dali::Actor::VISIBLE,
1031                                                       Property::INVALID_COMPONENT_INDEX,
1032                                                       AnimateToBoolean(HIDE_VALUE),
1033                                                       AlphaFunctions::Default,
1034                                                       TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
1035 }
1036
1037 void Animation::OpacityBy(Actor& actor, float opacity)
1038 {
1039   OpacityBy(actor, opacity, mDefaultAlpha, 0.0f, GetDuration());
1040 }
1041
1042 void Animation::OpacityBy(Actor& actor, float opacity, AlphaFunction alpha)
1043 {
1044   OpacityBy(actor, opacity, alpha, 0.0f, GetDuration());
1045 }
1046
1047 void Animation::OpacityBy(Actor& actor, float opacity, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1048 {
1049   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
1050
1051   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
1052                                                          Dali::Actor::COLOR,
1053                                                          Property::INVALID_COMPONENT_INDEX,
1054                                                          AnimateByOpacity(opacity),
1055                                                          alpha,
1056                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1057 }
1058
1059 void Animation::OpacityTo(Actor& actor, float opacity)
1060 {
1061   OpacityTo(actor, opacity, mDefaultAlpha, 0.0f, GetDuration());
1062 }
1063
1064 void Animation::OpacityTo(Actor& actor, float opacity, AlphaFunction alpha)
1065 {
1066   OpacityTo(actor, opacity, alpha, 0.0f, GetDuration());
1067 }
1068
1069 void Animation::OpacityTo(Actor& actor, float opacity, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1070 {
1071   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
1072
1073   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
1074                                                          Dali::Actor::COLOR,
1075                                                          Property::INVALID_COMPONENT_INDEX,
1076                                                          AnimateToOpacity(opacity),
1077                                                          alpha,
1078                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1079 }
1080
1081 void Animation::ColorBy(Actor& actor, const Vector4& color)
1082 {
1083   ColorBy(actor, color, mDefaultAlpha, 0.0f, GetDuration());
1084 }
1085
1086 void Animation::ColorBy(Actor& actor, const Vector4& color, AlphaFunction alpha)
1087 {
1088   ColorBy(actor, color, alpha, 0.0f, GetDuration());
1089 }
1090
1091 void Animation::ColorBy(Actor& actor, const Vector4& color, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1092 {
1093   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
1094
1095   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
1096                                                          Dali::Actor::COLOR,
1097                                                          Property::INVALID_COMPONENT_INDEX,
1098                                                          AnimateByVector4(color),
1099                                                          alpha,
1100                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1101 }
1102
1103 void Animation::ColorTo(Actor& actor, const Vector4& color)
1104 {
1105   ColorTo(actor, color, mDefaultAlpha, 0.0f, GetDuration());
1106 }
1107
1108 void Animation::ColorTo(Actor& actor, const Vector4& color, AlphaFunction alpha)
1109 {
1110   ColorTo(actor, color, alpha, 0.0f, GetDuration());
1111 }
1112
1113 void Animation::ColorTo(Actor& actor, const Vector4& color, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1114 {
1115   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
1116
1117   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
1118                                                          Dali::Actor::COLOR,
1119                                                          Property::INVALID_COMPONENT_INDEX,
1120                                                          AnimateToVector4(color),
1121                                                          alpha,
1122                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1123 }
1124
1125 void Animation::Resize(Actor& actor, float width, float height)
1126 {
1127   Resize(actor, width, height, mDefaultAlpha, 0.0f, GetDuration());
1128 }
1129
1130 void Animation::Resize(Actor& actor, float width, float height, AlphaFunction alpha)
1131 {
1132   Resize(actor, width, height, alpha, 0.0f, GetDuration());
1133 }
1134
1135 void Animation::Resize(Actor& actor, float width, float height, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1136 {
1137   Vector3 targetSize( width, height, min(width, height) );
1138
1139   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
1140
1141   // notify the actor impl that its size is being animated
1142   actor.OnSizeAnimation( *this, targetSize );
1143
1144   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
1145                                                          Dali::Actor::SIZE,
1146                                                          Property::INVALID_COMPONENT_INDEX,
1147                                                          AnimateToVector3(targetSize),
1148                                                          alpha,
1149                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1150 }
1151
1152 void Animation::Resize(Actor& actor, const Vector3& size)
1153 {
1154   Resize(actor, size, mDefaultAlpha, 0.0f, GetDuration());
1155 }
1156
1157 void Animation::Resize(Actor& actor, const Vector3& size, AlphaFunction alpha)
1158 {
1159   Resize(actor, size, alpha, 0.0f, GetDuration());
1160 }
1161
1162 void Animation::Resize(Actor& actor, const Vector3& size, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1163 {
1164   ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
1165
1166   // notify the actor impl that its size is being animated
1167   actor.OnSizeAnimation( *this, size );
1168
1169   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
1170                                                          Dali::Actor::SIZE,
1171                                                          Property::INVALID_COMPONENT_INDEX,
1172                                                          AnimateToVector3(size),
1173                                                          alpha,
1174                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1175 }
1176
1177 bool Animation::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
1178 {
1179   bool done = false;
1180   Animation* animation = dynamic_cast<Animation*>(object);
1181
1182   if( animation )
1183   {
1184     if(Dali::Animation::ACTION_PLAY == actionName)
1185     {
1186       if(attributes.size() > 0)
1187       {
1188         animation->SetDuration(attributes[0].Get<float>());
1189       }
1190
1191       animation->Play();
1192       done = true;
1193     }
1194     else if(Dali::Animation::ACTION_STOP == actionName)
1195     {
1196       animation->Stop();
1197       done = true;
1198     }
1199     else if(Dali::Animation::ACTION_PAUSE == actionName)
1200     {
1201       animation->Pause();
1202       done = true;
1203     }
1204   }
1205
1206   return done;
1207 }
1208
1209 float Animation::GetCurrentProgress()
1210 {
1211   if( mAnimation )
1212   {
1213     return mAnimation->GetCurrentProgress();
1214   }
1215
1216   return 0.0f;
1217 }
1218
1219 void Animation::SetCurrentProgress(float progress)
1220 {
1221   if( mAnimation && progress >= 0.0f && progress <= 1.0f )
1222   {
1223     // mAnimation is being used in a separate thread; queue a message to set the current progress
1224     SetCurrentProgressMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, progress );
1225   }
1226 }
1227
1228 void Animation::ExtendDuration( const TimePeriod& timePeriod )
1229 {
1230   float duration = timePeriod.delaySeconds + timePeriod.durationSeconds;
1231
1232   if( duration > mDurationSeconds )
1233   {
1234     SetDuration( duration );
1235   }
1236 }
1237
1238 void Animation::SetSpeedFactor( float factor )
1239 {
1240   if( mAnimation )
1241   {
1242     mSpeedFactor = factor;
1243     SetSpeedFactorMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, factor );
1244   }
1245 }
1246
1247 float Animation::GetSpeedFactor() const
1248 {
1249   return mSpeedFactor;
1250 }
1251
1252
1253
1254 } // namespace Internal
1255
1256 } // namespace Dali