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