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