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