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