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