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