License conversion from Flora to Apache 2.0
[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::Pause()
229 {
230   // mAnimation is being used in a separate thread; queue a Pause message
231   PauseAnimationMessage( mUpdateManager.GetEventToUpdate(), *mAnimation );
232 }
233
234 void Animation::Stop()
235 {
236   // mAnimation is being used in a separate thread; queue a Stop message
237   StopAnimationMessage( mUpdateManager, *mAnimation );
238 }
239
240 void Animation::Clear()
241 {
242   DALI_ASSERT_DEBUG(mAnimation);
243
244   // Remove all the connectors
245   mConnectors.Clear();
246
247   // Replace the old scene-object with a new one
248   DestroySceneObject();
249   CreateSceneObject();
250
251   // Reset the notification count, since the new scene-object has never been played
252   mNotificationCount = 0;
253
254   // Update the current playlist
255   mPlaylist.OnClear( *this );
256 }
257
258 void Animation::AnimateBy(Property& target, Property::Value& relativeValue)
259 {
260   AnimateBy(target, relativeValue, AlphaFunctions::Default, mDurationSeconds);
261 }
262
263 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha)
264 {
265   AnimateBy(target, relativeValue, alpha, mDurationSeconds);
266 }
267
268 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, TimePeriod period)
269 {
270   AnimateBy(target, relativeValue, AlphaFunctions::Default, period);
271 }
272
273 void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period)
274 {
275   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
276
277   switch ( relativeValue.GetType() )
278   {
279     case Property::BOOLEAN:
280     {
281       AddAnimatorConnector( AnimatorConnector<bool>::New( proxy,
282                                                           target.propertyIndex,
283                                                           target.componentIndex,
284                                                           AnimateByBoolean(relativeValue.Get<bool>()),
285                                                           alpha,
286                                                           period ) );
287       break;
288     }
289
290     case Property::FLOAT:
291     {
292       AddAnimatorConnector( AnimatorConnector<float>::New( proxy,
293                                                            target.propertyIndex,
294                                                            target.componentIndex,
295                                                            AnimateByFloat(relativeValue.Get<float>()),
296                                                            alpha,
297                                                            period ) );
298       break;
299     }
300
301     case Property::VECTOR2:
302     {
303       AddAnimatorConnector( AnimatorConnector<Vector2>::New( proxy,
304                                                              target.propertyIndex,
305                                                              target.componentIndex,
306                                                              AnimateByVector2(relativeValue.Get<Vector2>()),
307                                                              alpha,
308                                                              period ) );
309       break;
310     }
311
312     case Property::VECTOR3:
313     {
314       AddAnimatorConnector( AnimatorConnector<Vector3>::New( proxy,
315                                                              target.propertyIndex,
316                                                              target.componentIndex,
317                                                              AnimateByVector3(relativeValue.Get<Vector3>()),
318                                                              alpha,
319                                                              period ) );
320       break;
321     }
322
323     case Property::VECTOR4:
324     {
325       AddAnimatorConnector( AnimatorConnector<Vector4>::New( proxy,
326                                                              target.propertyIndex,
327                                                              target.componentIndex,
328                                                              AnimateByVector4(relativeValue.Get<Vector4>()),
329                                                              alpha,
330                                                              period ) );
331       break;
332     }
333
334     case Property::ROTATION:
335     {
336       AngleAxis angleAxis = relativeValue.Get<AngleAxis>();
337
338       AddAnimatorConnector( AnimatorConnector<Quaternion>::New( proxy,
339                                                                 target.propertyIndex,
340                                                                 target.componentIndex,
341                                                                 RotateByAngleAxis(angleAxis.angle, angleAxis.axis),
342                                                                 alpha,
343                                                                 period ) );
344       break;
345     }
346
347     default:
348       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here
349       break;
350   }
351 }
352
353 void Animation::AnimateTo(Property& target, Property::Value& destinationValue)
354 {
355   AnimateTo(target, destinationValue, AlphaFunctions::Default, mDurationSeconds);
356 }
357
358 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha)
359 {
360   AnimateTo(target, destinationValue, alpha, mDurationSeconds);
361 }
362
363 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, TimePeriod period)
364 {
365   AnimateTo(target, destinationValue, AlphaFunctions::Default, period);
366 }
367
368 void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
369 {
370   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
371
372   AnimateTo( proxy, target.propertyIndex, target.componentIndex, destinationValue, alpha, period );
373 }
374
375 void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
376 {
377   Property::Type type = targetObject.GetPropertyType(targetPropertyIndex);
378   if(componentIndex != Property::INVALID_COMPONENT_INDEX)
379   {
380     if( type == Property::VECTOR2
381         || type == Property::VECTOR3
382         || type == Property::VECTOR4 )
383     {
384       type = Property::FLOAT;
385     }
386   }
387   DALI_ASSERT_ALWAYS( type == destinationValue.GetType() && "DestinationValue does not match Target Property type" );
388
389   switch (destinationValue.GetType())
390   {
391     case Property::BOOLEAN:
392     {
393       AddAnimatorConnector( AnimatorConnector<bool>::New(targetObject,
394                                                          targetPropertyIndex,
395                                                          componentIndex,
396                                                          AnimateToBoolean(destinationValue.Get<bool>()),
397                                                          alpha,
398                                                          period) );
399       break;
400     }
401
402     case Property::FLOAT:
403     {
404       AddAnimatorConnector( AnimatorConnector<float>::New(targetObject,
405                                                           targetPropertyIndex,
406                                                           componentIndex,
407                                                           AnimateToFloat(destinationValue.Get<float>()),
408                                                           alpha,
409                                                           period) );
410       break;
411     }
412
413     case Property::VECTOR2:
414     {
415       AddAnimatorConnector( AnimatorConnector<Vector2>::New(targetObject,
416                                                             targetPropertyIndex,
417                                                             componentIndex,
418                                                             AnimateToVector2(destinationValue.Get<Vector2>()),
419                                                             alpha,
420                                                             period) );
421       break;
422     }
423
424     case Property::VECTOR3:
425     {
426       if ( Dali::Actor::SIZE == targetPropertyIndex )
427       {
428         // Test whether this is actually an Actor
429         Actor* maybeActor = dynamic_cast<Actor*>( &targetObject );
430         if ( maybeActor )
431         {
432           // Notify the actor that its size is being animated
433           maybeActor->OnSizeAnimation( *this, destinationValue.Get<Vector3>() );
434         }
435       }
436
437       AddAnimatorConnector( AnimatorConnector<Vector3>::New(targetObject,
438                                                             targetPropertyIndex,
439                                                             componentIndex,
440                                                             AnimateToVector3(destinationValue.Get<Vector3>()),
441                                                             alpha,
442                                                             period) );
443       break;
444     }
445
446     case Property::VECTOR4:
447     {
448       AddAnimatorConnector( AnimatorConnector<Vector4>::New(targetObject,
449                                                             targetPropertyIndex,
450                                                             componentIndex,
451                                                             AnimateToVector4(destinationValue.Get<Vector4>()),
452                                                             alpha,
453                                                             period) );
454       break;
455     }
456
457     case Property::ROTATION:
458     {
459       AddAnimatorConnector( AnimatorConnector<Quaternion>::New(targetObject,
460                                                                targetPropertyIndex,
461                                                                componentIndex,
462                                                                RotateToQuaternion(destinationValue.Get<Quaternion>()),
463                                                                alpha,
464                                                                period) );
465       break;
466     }
467
468     default:
469       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here
470       break;
471   }
472 }
473
474 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames)
475 {
476   AnimateBetween(target, keyFrames, mDefaultAlpha, mDurationSeconds);
477 }
478
479 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period)
480 {
481   AnimateBetween(target, keyFrames, mDefaultAlpha, period);
482 }
483
484 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha)
485 {
486   AnimateBetween(target, keyFrames, alpha, mDurationSeconds);
487 }
488
489 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
490 {
491   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
492
493   switch(keyFrames.GetType())
494   {
495     case Dali::Property::BOOLEAN:
496     {
497       const KeyFrameBoolean* kf;
498       GetSpecialization(keyFrames, kf);
499       KeyFrameBooleanPtr kfCopy = KeyFrameBoolean::Clone(*kf);
500       AddAnimatorConnector( AnimatorConnector<bool>::New( proxy,
501                                                           target.propertyIndex,
502                                                           target.componentIndex,
503                                                           KeyFrameBooleanFunctor(kfCopy),
504                                                           alpha,
505                                                           period ) );
506       break;
507     }
508     case Dali::Property::FLOAT:
509     {
510       const KeyFrameNumber* kf;
511       GetSpecialization(keyFrames, kf);
512       KeyFrameNumberPtr kfCopy = KeyFrameNumber::Clone(*kf);
513       AddAnimatorConnector( AnimatorConnector<float>::New( proxy,
514                                                            target.propertyIndex,
515                                                            target.componentIndex,
516                                                            KeyFrameNumberFunctor(kfCopy),
517                                                            alpha,
518                                                            period ) );
519       break;
520     }
521
522     case Dali::Property::VECTOR2:
523     {
524       const KeyFrameVector2* kf;
525       GetSpecialization(keyFrames, kf);
526       KeyFrameVector2Ptr kfCopy = KeyFrameVector2::Clone(*kf);
527       AddAnimatorConnector( AnimatorConnector<Vector2>::New( proxy,
528                                                              target.propertyIndex,
529                                                              target.componentIndex,
530                                                              KeyFrameVector2Functor(kfCopy),
531                                                              alpha,
532                                                              period ) );
533       break;
534     }
535
536     case Dali::Property::VECTOR3:
537     {
538       const KeyFrameVector3* kf;
539       GetSpecialization(keyFrames, kf);
540       KeyFrameVector3Ptr kfCopy = KeyFrameVector3::Clone(*kf);
541       AddAnimatorConnector( AnimatorConnector<Vector3>::New( proxy,
542                                                              target.propertyIndex,
543                                                              target.componentIndex,
544                                                              KeyFrameVector3Functor(kfCopy),
545                                                              alpha,
546                                                              period ) );
547       break;
548     }
549
550     case Dali::Property::VECTOR4:
551     {
552       const KeyFrameVector4* kf;
553       GetSpecialization(keyFrames, kf);
554       KeyFrameVector4Ptr kfCopy = KeyFrameVector4::Clone(*kf);
555       AddAnimatorConnector( AnimatorConnector<Vector4>::New( proxy,
556                                                              target.propertyIndex,
557                                                              target.componentIndex,
558                                                              KeyFrameVector4Functor(kfCopy),
559                                                              alpha,
560                                                              period ) );
561       break;
562     }
563
564     case Dali::Property::ROTATION:
565     {
566       const KeyFrameQuaternion* kf;
567       GetSpecialization(keyFrames, kf);
568       KeyFrameQuaternionPtr kfCopy = KeyFrameQuaternion::Clone(*kf);
569       AddAnimatorConnector( AnimatorConnector<Quaternion>::New( proxy,
570                                                                 target.propertyIndex,
571                                                                 target.componentIndex,
572                                                                 KeyFrameQuaternionFunctor(kfCopy),
573                                                                 alpha,
574                                                                 period ) );
575       break;
576     }
577
578     default: // not all property types are animateable
579       break;
580   }
581 }
582
583 void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func )
584 {
585   Animate( target, targetType, func, mDefaultAlpha, mDurationSeconds );
586 }
587
588 void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func, AlphaFunction& alpha )
589 {
590   Animate( target, targetType, func, alpha, mDurationSeconds );
591 }
592
593 void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func, TimePeriod period )
594 {
595   Animate( target, targetType, func, mDefaultAlpha, period );
596 }
597
598 void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func, AlphaFunction& alpha, TimePeriod period )
599 {
600   Property::Type type = target.object.GetPropertyType(target.propertyIndex);
601   if(target.componentIndex != Property::INVALID_COMPONENT_INDEX)
602   {
603     if( type == Property::VECTOR2
604         || type == Property::VECTOR3
605         || type == Property::VECTOR4 )
606     {
607       type = Property::FLOAT;
608     }
609   }
610   DALI_ASSERT_ALWAYS( type == targetType && "Animation function must match target property type" );
611
612   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
613
614   switch ( targetType )
615   {
616     case Property::BOOLEAN:
617     {
618       AddAnimatorConnector( AnimatorConnector<bool>::New(proxy,
619                                                          target.propertyIndex,
620                                                          target.componentIndex,
621                                                          AnyCast< AnimatorFunctionBool >( func ),
622                                                          alpha,
623                                                          period) );
624       break;
625     }
626
627     case Property::FLOAT:
628     {
629       AddAnimatorConnector( AnimatorConnector<float>::New(proxy,
630                                                           target.propertyIndex,
631                                                           target.componentIndex,
632                                                           AnyCast< AnimatorFunctionFloat >( func ),
633                                                           alpha,
634                                                           period) );
635       break;
636     }
637
638     case Property::VECTOR2:
639     {
640       AddAnimatorConnector( AnimatorConnector<Vector2>::New(proxy,
641                                                             target.propertyIndex,
642                                                             target.componentIndex,
643                                                             AnyCast< AnimatorFunctionVector2 >( func ),
644                                                             alpha,
645                                                             period) );
646       break;
647     }
648
649     case Property::VECTOR3:
650     {
651       AddAnimatorConnector( AnimatorConnector<Vector3>::New(proxy,
652                                                             target.propertyIndex,
653                                                             target.componentIndex,
654                                                             AnyCast< AnimatorFunctionVector3 >( func ),
655                                                             alpha,
656                                                             period) );
657       break;
658     }
659
660     case Property::VECTOR4:
661     {
662       AddAnimatorConnector( AnimatorConnector<Vector4>::New(proxy,
663                                                             target.propertyIndex,
664                                                             target.componentIndex,
665                                                             AnyCast< AnimatorFunctionVector4 >( func ),
666                                                             alpha,
667                                                             period) );
668       break;
669     }
670
671     case Property::ROTATION:
672     {
673       AddAnimatorConnector( AnimatorConnector<Quaternion>::New(proxy,
674                                                                target.propertyIndex,
675                                                                target.componentIndex,
676                                                                AnyCast< AnimatorFunctionQuaternion >( func ),
677                                                                alpha,
678                                                                period) );
679       break;
680     }
681
682     default:
683       DALI_ASSERT_ALWAYS(false && "Property type enumeration out of bounds" ); // should never come here
684       break;
685   }
686 }
687
688 bool Animation::HasFinished()
689 {
690   bool hasFinished(false);
691   const int playCount(mAnimation->GetPlayCount());
692
693   // If the play count has been incremented, then another notification is required
694   if (playCount > mNotificationCount)
695   {
696     // Note that only one signal is emitted, if the animation has been played repeatedly
697     mNotificationCount = playCount;
698
699     hasFinished = true;
700   }
701
702   return hasFinished;
703 }
704
705 Dali::Animation::AnimationSignalV2& Animation::FinishedSignal()
706 {
707   return mFinishedSignal;
708 }
709
710 void Animation::EmitSignalFinish()
711 {
712   if ( !mFinishedSignal.Empty() )
713   {
714     Dali::Animation handle( this );
715     mFinishedSignal.Emit( handle );
716   }
717
718   // This callback is used internally, to avoid the overhead of using a signal.
719   if ( mFinishedCallback )
720   {
721     mFinishedCallback( mFinishedCallbackObject );
722   }
723 }
724
725 bool Animation::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
726 {
727   bool connected( true );
728   Animation* animation = dynamic_cast<Animation*>(object);
729
730   if ( Dali::Animation::SIGNAL_FINISHED == signalName )
731   {
732     animation->FinishedSignal().Connect( tracker, functor );
733   }
734   else
735   {
736     // signalName does not match any signal
737     connected = false;
738   }
739
740   return connected;
741 }
742
743 void Animation::SetFinishedCallback( FinishedCallback callback, Object* object )
744 {
745   mFinishedCallback = callback;
746   mFinishedCallbackObject = object;
747 }
748
749 void Animation::AddAnimatorConnector( AnimatorConnectorBase* connector )
750 {
751   DALI_ASSERT_DEBUG( NULL != connector );
752
753   connector->SetParent(*this);
754
755   mConnectors.PushBack( connector );
756 }
757
758 void Animation::MoveBy(Actor& actor, float x, float y, float z)
759 {
760   MoveBy(actor, Vector3(x, y, z), mDefaultAlpha, 0.0f, GetDuration());
761 }
762
763 void Animation::MoveBy(Actor& actor, const Vector3& displacement, AlphaFunction alpha)
764 {
765   MoveBy(actor, displacement, alpha, 0.0f, GetDuration());
766 }
767
768 void Animation::MoveBy(Actor& actor, const Vector3& displacement, AlphaFunction alpha, float delaySeconds, float durationSeconds)
769 {
770   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
771                                                          Dali::Actor::POSITION,
772                                                          Property::INVALID_COMPONENT_INDEX,
773                                                          AnimateByVector3(displacement),
774                                                          alpha,
775                                                          TimePeriod(delaySeconds, durationSeconds) ) );
776 }
777
778 void Animation::MoveTo(Actor& actor, float x, float y, float z)
779 {
780   MoveTo(actor, Vector3(x, y, z), mDefaultAlpha, 0.0f, GetDuration());
781 }
782
783 void Animation::MoveTo(Actor& actor, const Vector3& position, AlphaFunction alpha)
784 {
785   MoveTo(actor, position, alpha, 0.0f, GetDuration());
786 }
787
788 void Animation::MoveTo(Actor& actor, const Vector3& position, AlphaFunction alpha,  float delaySeconds, float durationSeconds)
789 {
790   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
791                                                          Dali::Actor::POSITION,
792                                                          Property::INVALID_COMPONENT_INDEX,
793                                                          AnimateToVector3(position),
794                                                          alpha,
795                                                          TimePeriod(delaySeconds, durationSeconds) ) );
796 }
797
798 void Animation::Move(Actor& actor, AnimatorFunctionVector3 func, AlphaFunction alpha,  float delaySeconds, float durationSeconds)
799 {
800   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
801                                                          Dali::Actor::POSITION,
802                                                          Property::INVALID_COMPONENT_INDEX,
803                                                          func,
804                                                          alpha,
805                                                          TimePeriod(delaySeconds, durationSeconds) ) );
806 }
807
808 void Animation::RotateBy(Actor& actor, Radian angle, const Vector3& axis)
809 {
810   RotateBy(actor, angle, axis, mDefaultAlpha, 0.0f, GetDuration());
811 }
812
813 void Animation::RotateBy(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha)
814 {
815   RotateBy(actor, angle, axis, alpha, 0.0f, GetDuration());
816 }
817
818 void Animation::RotateBy(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha, float delaySeconds, float durationSeconds)
819 {
820   AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
821                                                             Dali::Actor::ROTATION,
822                                                             Property::INVALID_COMPONENT_INDEX,
823                                                             RotateByAngleAxis(angle, axis),
824                                                             alpha,
825                                                             TimePeriod(delaySeconds, durationSeconds) ) );
826 }
827
828 void Animation::RotateTo(Actor& actor, Radian angle, const Vector3& axis)
829 {
830   Vector4 normalizedAxis(axis.x, axis.y, axis.z, 0.0f);
831   normalizedAxis.Normalize();
832
833   Quaternion orientation(Quaternion::FromAxisAngle(normalizedAxis, angle));
834
835   RotateTo(actor, orientation, mDefaultAlpha, 0.0f, GetDuration());
836 }
837
838 void Animation::RotateTo(Actor& actor, const Quaternion& orientation)
839 {
840   RotateTo(actor, orientation, mDefaultAlpha, 0.0f, GetDuration());
841 }
842
843 void Animation::RotateTo(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha)
844 {
845   Vector4 normalizedAxis(axis.x, axis.y, axis.z, 0.0f);
846   normalizedAxis.Normalize();
847
848   Quaternion orientation(Quaternion::FromAxisAngle(normalizedAxis, angle));
849
850   RotateTo(actor, orientation, alpha, 0.0f, GetDuration());
851 }
852
853 void Animation::RotateTo(Actor& actor, const Quaternion& orientation, AlphaFunction alpha)
854 {
855   RotateTo(actor, orientation, alpha, 0.0f, GetDuration());
856 }
857
858 void Animation::RotateTo(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha, float delaySeconds, float durationSeconds)
859 {
860   Vector4 normalizedAxis(axis.x, axis.y, axis.z, 0.0f);
861   normalizedAxis.Normalize();
862
863   Quaternion orientation(Quaternion::FromAxisAngle(normalizedAxis, angle));
864
865   RotateTo(actor, orientation, alpha, delaySeconds, durationSeconds);
866 }
867
868 void Animation::RotateTo(Actor& actor, const Quaternion& rotation, AlphaFunction alpha, float delaySeconds, float durationSeconds)
869 {
870   AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
871                                                             Dali::Actor::ROTATION,
872                                                             Property::INVALID_COMPONENT_INDEX,
873                                                             RotateToQuaternion(rotation),
874                                                             alpha,
875                                                             TimePeriod(delaySeconds, durationSeconds) ) );
876 }
877
878 void Animation::Rotate(Actor& actor, AnimatorFunctionQuaternion func, AlphaFunction alpha,  float delaySeconds, float durationSeconds)
879 {
880   AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
881                                                             Dali::Actor::ROTATION,
882                                                             Property::INVALID_COMPONENT_INDEX,
883                                                             func,
884                                                             alpha,
885                                                             TimePeriod(delaySeconds, durationSeconds) ) );
886 }
887
888 void Animation::ScaleBy(Actor& actor, float x, float y, float z)
889 {
890   ScaleBy(actor, Vector3(x, y, z), mDefaultAlpha, 0.0f, GetDuration());
891 }
892
893 void Animation::ScaleBy(Actor& actor, const Vector3& scale, AlphaFunction alpha)
894 {
895   ScaleBy(actor, scale, alpha, 0.0f, GetDuration());
896 }
897
898 void Animation::ScaleBy(Actor& actor, const Vector3& scale, AlphaFunction alpha, float delaySeconds, float durationSeconds)
899 {
900   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
901                                                          Dali::Actor::SCALE,
902                                                          Property::INVALID_COMPONENT_INDEX,
903                                                          AnimateByVector3(scale),
904                                                          alpha,
905                                                          TimePeriod(delaySeconds, durationSeconds) ) );
906 }
907
908 void Animation::ScaleTo(Actor& actor, float x, float y, float z)
909 {
910   ScaleTo(actor, Vector3(x, y, z), mDefaultAlpha, 0.0f, GetDuration());
911 }
912
913 void Animation::ScaleTo(Actor& actor, const Vector3& scale, AlphaFunction alpha)
914 {
915   ScaleTo(actor, scale, alpha, 0.0f, GetDuration());
916 }
917
918 void Animation::ScaleTo(Actor& actor, const Vector3& scale, AlphaFunction alpha, float delaySeconds, float durationSeconds)
919 {
920   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
921                                                          Dali::Actor::SCALE,
922                                                          Property::INVALID_COMPONENT_INDEX,
923                                                          AnimateToVector3(scale),
924                                                          alpha,
925                                                          TimePeriod(delaySeconds, durationSeconds) ) );
926 }
927
928 void Animation::Show(Actor& actor, float delaySeconds)
929 {
930   AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
931                                                       Dali::Actor::VISIBLE,
932                                                       Property::INVALID_COMPONENT_INDEX,
933                                                       AnimateToBoolean(SHOW_VALUE),
934                                                       AlphaFunctions::Default,
935                                                       TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
936 }
937
938 void Animation::Hide(Actor& actor, float delaySeconds)
939 {
940   AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
941                                                       Dali::Actor::VISIBLE,
942                                                       Property::INVALID_COMPONENT_INDEX,
943                                                       AnimateToBoolean(HIDE_VALUE),
944                                                       AlphaFunctions::Default,
945                                                       TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
946 }
947
948 void Animation::OpacityBy(Actor& actor, float opacity)
949 {
950   OpacityBy(actor, opacity, mDefaultAlpha, 0.0f, GetDuration());
951 }
952
953 void Animation::OpacityBy(Actor& actor, float opacity, AlphaFunction alpha)
954 {
955   OpacityBy(actor, opacity, alpha, 0.0f, GetDuration());
956 }
957
958 void Animation::OpacityBy(Actor& actor, float opacity, AlphaFunction alpha, float delaySeconds, float durationSeconds)
959 {
960   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
961                                                          Dali::Actor::COLOR,
962                                                          Property::INVALID_COMPONENT_INDEX,
963                                                          AnimateByOpacity(opacity),
964                                                          alpha,
965                                                          TimePeriod(delaySeconds, durationSeconds) ) );
966 }
967
968 void Animation::OpacityTo(Actor& actor, float opacity)
969 {
970   OpacityTo(actor, opacity, mDefaultAlpha, 0.0f, GetDuration());
971 }
972
973 void Animation::OpacityTo(Actor& actor, float opacity, AlphaFunction alpha)
974 {
975   OpacityTo(actor, opacity, alpha, 0.0f, GetDuration());
976 }
977
978 void Animation::OpacityTo(Actor& actor, float opacity, AlphaFunction alpha, float delaySeconds, float durationSeconds)
979 {
980   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
981                                                          Dali::Actor::COLOR,
982                                                          Property::INVALID_COMPONENT_INDEX,
983                                                          AnimateToOpacity(opacity),
984                                                          alpha,
985                                                          TimePeriod(delaySeconds, durationSeconds) ) );
986 }
987
988 void Animation::ColorBy(Actor& actor, const Vector4& color)
989 {
990   ColorBy(actor, color, mDefaultAlpha, 0.0f, GetDuration());
991 }
992
993 void Animation::ColorBy(Actor& actor, const Vector4& color, AlphaFunction alpha)
994 {
995   ColorBy(actor, color, alpha, 0.0f, GetDuration());
996 }
997
998 void Animation::ColorBy(Actor& actor, const Vector4& color, AlphaFunction alpha, float delaySeconds, float durationSeconds)
999 {
1000   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
1001                                                          Dali::Actor::COLOR,
1002                                                          Property::INVALID_COMPONENT_INDEX,
1003                                                          AnimateByVector4(color),
1004                                                          alpha,
1005                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1006 }
1007
1008 void Animation::ColorTo(Actor& actor, const Vector4& color)
1009 {
1010   ColorTo(actor, color, mDefaultAlpha, 0.0f, GetDuration());
1011 }
1012
1013 void Animation::ColorTo(Actor& actor, const Vector4& color, AlphaFunction alpha)
1014 {
1015   ColorTo(actor, color, alpha, 0.0f, GetDuration());
1016 }
1017
1018 void Animation::ColorTo(Actor& actor, const Vector4& color, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1019 {
1020   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
1021                                                          Dali::Actor::COLOR,
1022                                                          Property::INVALID_COMPONENT_INDEX,
1023                                                          AnimateToVector4(color),
1024                                                          alpha,
1025                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1026 }
1027
1028 void Animation::Resize(Actor& actor, float width, float height)
1029 {
1030   Resize(actor, width, height, mDefaultAlpha, 0.0f, GetDuration());
1031 }
1032
1033 void Animation::Resize(Actor& actor, float width, float height, AlphaFunction alpha)
1034 {
1035   Resize(actor, width, height, alpha, 0.0f, GetDuration());
1036 }
1037
1038 void Animation::Resize(Actor& actor, float width, float height, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1039 {
1040   Vector3 targetSize( width, height, min(width, height) );
1041
1042   // notify the actor impl that its size is being animated
1043   actor.OnSizeAnimation( *this, targetSize );
1044
1045   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
1046                                                          Dali::Actor::SIZE,
1047                                                          Property::INVALID_COMPONENT_INDEX,
1048                                                          AnimateToVector3(targetSize),
1049                                                          alpha,
1050                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1051 }
1052
1053 void Animation::Resize(Actor& actor, const Vector3& size)
1054 {
1055   Resize(actor, size, mDefaultAlpha, 0.0f, GetDuration());
1056 }
1057
1058 void Animation::Resize(Actor& actor, const Vector3& size, AlphaFunction alpha)
1059 {
1060   Resize(actor, size, alpha, 0.0f, GetDuration());
1061 }
1062
1063 void Animation::Resize(Actor& actor, const Vector3& size, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1064 {
1065   // notify the actor impl that its size is being animated
1066   actor.OnSizeAnimation( *this, size );
1067
1068   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
1069                                                          Dali::Actor::SIZE,
1070                                                          Property::INVALID_COMPONENT_INDEX,
1071                                                          AnimateToVector3(size),
1072                                                          alpha,
1073                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1074 }
1075
1076 void Animation::ParentOriginTo(Actor& actor, const Vector3& parentOrigin)
1077 {
1078   ParentOriginTo(actor, parentOrigin, mDefaultAlpha, 0.0f, GetDuration());
1079 }
1080
1081 void Animation::ParentOriginTo(Actor& actor, const Vector3& parentOrigin, AlphaFunction alpha)
1082 {
1083   ParentOriginTo(actor, parentOrigin, alpha, 0.0f, GetDuration());
1084 }
1085
1086 void Animation::ParentOriginTo(Actor& actor, const Vector3& parentOrigin, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1087 {
1088   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
1089                                                          Dali::Actor::PARENT_ORIGIN,
1090                                                          Property::INVALID_COMPONENT_INDEX,
1091                                                          AnimateToVector3(parentOrigin),
1092                                                          alpha,
1093                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1094 }
1095
1096 void Animation::AnchorPointTo(Actor& actor, const Vector3& anchorPoint)
1097 {
1098   AnchorPointTo(actor, anchorPoint, mDefaultAlpha, 0.0f, GetDuration());
1099 }
1100
1101 void Animation::AnchorPointTo(Actor& actor, const Vector3& anchorPoint, AlphaFunction alpha)
1102 {
1103   AnchorPointTo(actor, anchorPoint, alpha, 0.0f, GetDuration());
1104 }
1105
1106 void Animation::AnchorPointTo(Actor& actor, const Vector3& anchorPoint, AlphaFunction alpha, float delaySeconds, float durationSeconds)
1107 {
1108   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
1109                                                          Dali::Actor::ANCHOR_POINT,
1110                                                          Property::INVALID_COMPONENT_INDEX,
1111                                                          AnimateToVector3(anchorPoint),
1112                                                          alpha,
1113                                                          TimePeriod(delaySeconds, durationSeconds) ) );
1114 }
1115
1116 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, float value )
1117 {
1118   AnimateProperty( shaderEffect, name, value, GetDefaultAlphaFunction(), 0, GetDuration() );
1119 }
1120
1121 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, float value, AlphaFunction alpha )
1122 {
1123   AnimateProperty( shaderEffect, name, value, alpha, 0, GetDuration() );
1124 }
1125
1126 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, float value, AlphaFunction alpha, float delaySeconds, float durationSeconds )
1127 {
1128   Property::Value propertyValue( value );
1129
1130   // Register the property if it does not exist
1131   Property::Index index = shaderEffect.GetPropertyIndex( name );
1132   if ( Property::INVALID_INDEX == index )
1133   {
1134     index = shaderEffect.RegisterProperty( name, propertyValue );
1135   }
1136
1137   AnimateTo( shaderEffect, index, Property::INVALID_COMPONENT_INDEX, propertyValue, alpha, TimePeriod(delaySeconds, durationSeconds) );
1138 }
1139
1140 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector2 value )
1141 {
1142   AnimateProperty( shaderEffect, name, value, GetDefaultAlphaFunction(), 0, GetDuration());
1143 }
1144
1145 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector2 value, AlphaFunction alpha )
1146 {
1147   AnimateProperty( shaderEffect, name, value, alpha, 0, GetDuration() );
1148 }
1149
1150 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector2 value, AlphaFunction alpha, float delaySeconds, float durationSeconds )
1151 {
1152   Property::Value propertyValue( value );
1153
1154   // Register the property if it does not exist
1155   Property::Index index = shaderEffect.GetPropertyIndex( name );
1156   if ( Property::INVALID_INDEX == index )
1157   {
1158     index = shaderEffect.RegisterProperty( name, propertyValue );
1159   }
1160
1161   AnimateTo( shaderEffect, index, Property::INVALID_COMPONENT_INDEX, propertyValue, alpha, TimePeriod(delaySeconds, durationSeconds) );
1162 }
1163
1164 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector3 value )
1165 {
1166   AnimateProperty( shaderEffect, name, value, GetDefaultAlphaFunction(), 0, GetDuration() );
1167 }
1168
1169 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector3 value, AlphaFunction alpha )
1170 {
1171   AnimateProperty( shaderEffect, name, value, alpha, 0, GetDuration() );
1172 }
1173
1174 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector3 value, AlphaFunction alpha, float delaySeconds, float durationSeconds )
1175 {
1176   Property::Value propertyValue( value );
1177
1178   // Register the property if it does not exist
1179   Property::Index index = shaderEffect.GetPropertyIndex( name );
1180   if ( Property::INVALID_INDEX == index )
1181   {
1182     index = shaderEffect.RegisterProperty( name, propertyValue );
1183   }
1184
1185   AnimateTo( shaderEffect, index, Property::INVALID_COMPONENT_INDEX, propertyValue, alpha, TimePeriod(delaySeconds, durationSeconds) );
1186 }
1187
1188 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector4 value )
1189 {
1190   AnimateProperty( shaderEffect, name, value, GetDefaultAlphaFunction(), 0, GetDuration() );
1191 }
1192
1193 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector4 value, AlphaFunction alpha )
1194 {
1195   AnimateProperty( shaderEffect, name, value, alpha, 0, GetDuration() );
1196 }
1197
1198 void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector4 value, AlphaFunction alpha, float delaySeconds, float durationSeconds )
1199 {
1200   Property::Value propertyValue( value );
1201
1202   // Register the property if it does not exist
1203   Property::Index index = shaderEffect.GetPropertyIndex( name );
1204   if ( Property::INVALID_INDEX == index )
1205   {
1206     index = shaderEffect.RegisterProperty( name, propertyValue );
1207   }
1208
1209   AnimateTo( shaderEffect, index, Property::INVALID_COMPONENT_INDEX, propertyValue, alpha, TimePeriod(delaySeconds, durationSeconds) );
1210 }
1211
1212 bool Animation::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
1213 {
1214   bool done = false;
1215   Animation* animation = dynamic_cast<Animation*>(object);
1216
1217   if( animation )
1218   {
1219     if(Dali::Animation::ACTION_PLAY == actionName)
1220     {
1221       if(attributes.size() > 0)
1222       {
1223         animation->SetDuration(attributes[0].Get<float>());
1224       }
1225
1226       animation->Play();
1227       done = true;
1228     }
1229     else if(Dali::Animation::ACTION_STOP == actionName)
1230     {
1231       animation->Stop();
1232       done = true;
1233     }
1234     else if(Dali::Animation::ACTION_PAUSE == actionName)
1235     {
1236       animation->Pause();
1237       done = true;
1238     }
1239   }
1240
1241   return done;
1242 }
1243
1244 } // namespace Internal
1245
1246 } // namespace Dali