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