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