Merge remote-tracking branch 'origin/tizen' into new_text
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / animation-impl.cpp
index cdb116b..7a04d21 100644 (file)
@@ -1,18 +1,19 @@
-//
-// Copyright (c) 2014 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.0 (the License);
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://floralicense.org/license/
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an AS IS BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
 // CLASS HEADER
 #include <dali/internal/event/animation/animation-impl.h>
@@ -33,8 +34,6 @@
 #include <dali/internal/event/effects/shader-effect-impl.h>
 #include <dali/internal/event/common/thread-local-storage.h>
 
-using namespace std;
-
 using Dali::Internal::SceneGraph::UpdateManager;
 using Dali::Internal::SceneGraph::AnimatorBase;
 using Dali::Internal::SceneGraph::Shader;
@@ -64,35 +63,29 @@ TypeAction action1( mType, Dali::Animation::ACTION_PLAY, &Animation::DoAction );
 TypeAction action2( mType, Dali::Animation::ACTION_STOP, &Animation::DoAction );
 TypeAction action3( mType, Dali::Animation::ACTION_PAUSE, &Animation::DoAction );
 
+const Dali::Animation::EndAction DEFAULT_END_ACTION( Dali::Animation::Bake );
+const Dali::Animation::EndAction DEFAULT_DISCONNECT_ACTION( Dali::Animation::BakeFinal );
+const Dali::Animation::Interpolation DEFAULT_INTERPOLATION( Dali::Animation::Linear );
+
 } // anon namespace
 
 
 AnimationPtr Animation::New(float durationSeconds)
 {
-  return New(durationSeconds, Dali::Animation::Bake, Dali::Animation::Bake, Dali::AlphaFunctions::Linear);
-}
-
-AnimationPtr Animation::New(float durationSeconds, EndAction endAction, EndAction destroyAction)
-{
-  return New(durationSeconds, endAction, destroyAction, Dali::AlphaFunctions::Linear);
-}
-
-AnimationPtr Animation::New(float durationSeconds, EndAction endAction, EndAction destroyAction, AlphaFunction alpha)
-{
   ThreadLocalStorage& tls = ThreadLocalStorage::Get();
   UpdateManager& updateManager = tls.GetUpdateManager();
 
   AnimationPlaylist& playlist = Stage::GetCurrent()->GetAnimationPlaylist();
 
-  AnimationPtr progress = new Animation( updateManager, playlist, durationSeconds, endAction, destroyAction, alpha );
+  AnimationPtr animation = new Animation( updateManager, playlist, durationSeconds, DEFAULT_END_ACTION, DEFAULT_DISCONNECT_ACTION, Dali::AlphaFunctions::Linear );
 
   // Second-phase construction
-  progress->Initialize();
+  animation->Initialize();
 
-  return progress;
+  return animation;
 }
 
-Animation::Animation( UpdateManager& updateManager, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction destroyAction, AlphaFunction defaultAlpha )
+Animation::Animation( UpdateManager& updateManager, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction disconnectAction, AlphaFunction defaultAlpha )
 : mUpdateManager( updateManager ),
   mPlaylist( playlist ),
   mAnimation( NULL ),
@@ -100,9 +93,11 @@ Animation::Animation( UpdateManager& updateManager, AnimationPlaylist& playlist,
   mFinishedCallback( NULL ),
   mFinishedCallbackObject( NULL ),
   mDurationSeconds( durationSeconds ),
+  mSpeedFactor(1.0f),
   mIsLooping( false ),
+  mPlayRange( Vector2(0.0f,1.0f)),
   mEndAction( endAction ),
-  mDestroyAction( destroyAction ),
+  mDisconnectAction( disconnectAction ),
   mDefaultAlpha( defaultAlpha )
 {
 }
@@ -136,7 +131,7 @@ void Animation::CreateSceneObject()
   DALI_ASSERT_DEBUG( mAnimation == NULL );
 
   // Create a new animation, temporarily owned
-  SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mIsLooping, mEndAction, mDestroyAction );
+  SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mIsLooping, mEndAction, mDisconnectAction );
 
   // Keep a const pointer to the animation.
   mAnimation = animation;
@@ -200,19 +195,19 @@ Dali::Animation::EndAction Animation::GetEndAction() const
   return mEndAction;
 }
 
-void Animation::SetDestroyAction(EndAction action)
+void Animation::SetDisconnectAction(EndAction action)
 {
   // Cache for public getters
-  mDestroyAction = action;
+  mDisconnectAction = action;
 
   // mAnimation is being used in a separate thread; queue a message to set the value
-  SetDestroyActionMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, action );
+  SetDisconnectActionMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, action );
 }
 
-Dali::Animation::EndAction Animation::GetDestroyAction() const
+Dali::Animation::EndAction Animation::GetDisconnectAction() const
 {
   // This is not animatable; the cached value is up-to-date.
-  return mDestroyAction;
+  return mDisconnectAction;
 }
 
 void Animation::Play()
@@ -224,6 +219,18 @@ void Animation::Play()
   PlayAnimationMessage( mUpdateManager.GetEventToUpdate(), *mAnimation );
 }
 
+void Animation::PlayFrom( float progress )
+{
+  if( progress >= mPlayRange.x && progress <= mPlayRange.y )
+  {
+    // Update the current playlist
+    mPlaylist.OnPlay( *this );
+
+    // mAnimation is being used in a separate thread; queue a Play message
+    PlayAnimationFromMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, progress );
+  }
+}
+
 void Animation::Pause()
 {
   // mAnimation is being used in a separate thread; queue a Pause message
@@ -273,12 +280,15 @@ void Animation::AnimateBy(Property& target, Property::Value& relativeValue, Alph
 {
   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
 
+  ExtendDuration( period );
+
   switch ( relativeValue.GetType() )
   {
     case Property::BOOLEAN:
     {
       AddAnimatorConnector( AnimatorConnector<bool>::New( proxy,
                                                           target.propertyIndex,
+                                                          target.componentIndex,
                                                           AnimateByBoolean(relativeValue.Get<bool>()),
                                                           alpha,
                                                           period ) );
@@ -289,16 +299,29 @@ void Animation::AnimateBy(Property& target, Property::Value& relativeValue, Alph
     {
       AddAnimatorConnector( AnimatorConnector<float>::New( proxy,
                                                            target.propertyIndex,
+                                                           target.componentIndex,
                                                            AnimateByFloat(relativeValue.Get<float>()),
                                                            alpha,
                                                            period ) );
       break;
     }
 
+    case Property::INTEGER:
+    {
+      AddAnimatorConnector( AnimatorConnector<int>::New( proxy,
+                                                         target.propertyIndex,
+                                                         target.componentIndex,
+                                                         AnimateByInteger(relativeValue.Get<int>()),
+                                                         alpha,
+                                                         period ) );
+      break;
+    }
+
     case Property::VECTOR2:
     {
       AddAnimatorConnector( AnimatorConnector<Vector2>::New( proxy,
                                                              target.propertyIndex,
+                                                             target.componentIndex,
                                                              AnimateByVector2(relativeValue.Get<Vector2>()),
                                                              alpha,
                                                              period ) );
@@ -309,6 +332,7 @@ void Animation::AnimateBy(Property& target, Property::Value& relativeValue, Alph
     {
       AddAnimatorConnector( AnimatorConnector<Vector3>::New( proxy,
                                                              target.propertyIndex,
+                                                             target.componentIndex,
                                                              AnimateByVector3(relativeValue.Get<Vector3>()),
                                                              alpha,
                                                              period ) );
@@ -319,6 +343,7 @@ void Animation::AnimateBy(Property& target, Property::Value& relativeValue, Alph
     {
       AddAnimatorConnector( AnimatorConnector<Vector4>::New( proxy,
                                                              target.propertyIndex,
+                                                             target.componentIndex,
                                                              AnimateByVector4(relativeValue.Get<Vector4>()),
                                                              alpha,
                                                              period ) );
@@ -331,6 +356,7 @@ void Animation::AnimateBy(Property& target, Property::Value& relativeValue, Alph
 
       AddAnimatorConnector( AnimatorConnector<Quaternion>::New( proxy,
                                                                 target.propertyIndex,
+                                                                target.componentIndex,
                                                                 RotateByAngleAxis(angleAxis.angle, angleAxis.axis),
                                                                 alpha,
                                                                 period ) );
@@ -362,12 +388,24 @@ void Animation::AnimateTo(Property& target, Property::Value& destinationValue, A
 {
   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
 
-  AnimateTo( proxy, target.propertyIndex, destinationValue, alpha, period );
+  AnimateTo( proxy, target.propertyIndex, target.componentIndex, destinationValue, alpha, period );
 }
 
-void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPropertyIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
+void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
 {
-  DALI_ASSERT_ALWAYS( targetObject.GetPropertyType(targetPropertyIndex) == destinationValue.GetType() && "DestinationValue does not match Target Property type" );
+  Property::Type type = targetObject.GetPropertyType(targetPropertyIndex);
+  if(componentIndex != Property::INVALID_COMPONENT_INDEX)
+  {
+    if( type == Property::VECTOR2
+        || type == Property::VECTOR3
+        || type == Property::VECTOR4 )
+    {
+      type = Property::FLOAT;
+    }
+  }
+  DALI_ASSERT_ALWAYS( type == destinationValue.GetType() && "DestinationValue does not match Target Property type" );
+
+  ExtendDuration( period );
 
   switch (destinationValue.GetType())
   {
@@ -375,6 +413,7 @@ void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPrope
     {
       AddAnimatorConnector( AnimatorConnector<bool>::New(targetObject,
                                                          targetPropertyIndex,
+                                                         componentIndex,
                                                          AnimateToBoolean(destinationValue.Get<bool>()),
                                                          alpha,
                                                          period) );
@@ -385,16 +424,29 @@ void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPrope
     {
       AddAnimatorConnector( AnimatorConnector<float>::New(targetObject,
                                                           targetPropertyIndex,
+                                                          componentIndex,
                                                           AnimateToFloat(destinationValue.Get<float>()),
                                                           alpha,
                                                           period) );
       break;
     }
 
+    case Property::INTEGER:
+    {
+      AddAnimatorConnector( AnimatorConnector<int>::New(targetObject,
+                                                        targetPropertyIndex,
+                                                        componentIndex,
+                                                        AnimateToInteger(destinationValue.Get<int>()),
+                                                        alpha,
+                                                        period) );
+      break;
+    }
+
     case Property::VECTOR2:
     {
       AddAnimatorConnector( AnimatorConnector<Vector2>::New(targetObject,
                                                             targetPropertyIndex,
+                                                            componentIndex,
                                                             AnimateToVector2(destinationValue.Get<Vector2>()),
                                                             alpha,
                                                             period) );
@@ -410,12 +462,13 @@ void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPrope
         if ( maybeActor )
         {
           // Notify the actor that its size is being animated
-          maybeActor->OnSizeAnimation( *this, destinationValue.Get<Vector3>() );
+          maybeActor->NotifySizeAnimation( *this, destinationValue.Get<Vector3>() );
         }
       }
 
       AddAnimatorConnector( AnimatorConnector<Vector3>::New(targetObject,
                                                             targetPropertyIndex,
+                                                            componentIndex,
                                                             AnimateToVector3(destinationValue.Get<Vector3>()),
                                                             alpha,
                                                             period) );
@@ -426,6 +479,7 @@ void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPrope
     {
       AddAnimatorConnector( AnimatorConnector<Vector4>::New(targetObject,
                                                             targetPropertyIndex,
+                                                            componentIndex,
                                                             AnimateToVector4(destinationValue.Get<Vector4>()),
                                                             alpha,
                                                             period) );
@@ -436,6 +490,7 @@ void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPrope
     {
       AddAnimatorConnector( AnimatorConnector<Quaternion>::New(targetObject,
                                                                targetPropertyIndex,
+                                                               componentIndex,
                                                                RotateToQuaternion(destinationValue.Get<Quaternion>()),
                                                                alpha,
                                                                period) );
@@ -450,23 +505,45 @@ void Animation::AnimateTo(ProxyObject& targetObject, Property::Index targetPrope
 
 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames)
 {
-  AnimateBetween(target, keyFrames, mDefaultAlpha, mDurationSeconds);
+  AnimateBetween(target, keyFrames, mDefaultAlpha, mDurationSeconds, DEFAULT_INTERPOLATION );
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation )
+{
+  AnimateBetween(target, keyFrames, mDefaultAlpha, mDurationSeconds, interpolation );
 }
 
 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period)
 {
-  AnimateBetween(target, keyFrames, mDefaultAlpha, period);
+  AnimateBetween(target, keyFrames, mDefaultAlpha, period, DEFAULT_INTERPOLATION);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
+{
+  AnimateBetween(target, keyFrames, mDefaultAlpha, period, interpolation);
 }
 
 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha)
 {
-  AnimateBetween(target, keyFrames, alpha, mDurationSeconds);
+  AnimateBetween(target, keyFrames, alpha, mDurationSeconds, DEFAULT_INTERPOLATION);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
+{
+  AnimateBetween(target, keyFrames, alpha, mDurationSeconds, interpolation);
 }
 
 void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
 {
+  AnimateBetween(target, keyFrames, alpha, period, DEFAULT_INTERPOLATION);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation)
+{
   ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
 
+  ExtendDuration( period );
+
   switch(keyFrames.GetType())
   {
     case Dali::Property::BOOLEAN:
@@ -476,11 +553,13 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       KeyFrameBooleanPtr kfCopy = KeyFrameBoolean::Clone(*kf);
       AddAnimatorConnector( AnimatorConnector<bool>::New( proxy,
                                                           target.propertyIndex,
+                                                          target.componentIndex,
                                                           KeyFrameBooleanFunctor(kfCopy),
                                                           alpha,
                                                           period ) );
       break;
     }
+
     case Dali::Property::FLOAT:
     {
       const KeyFrameNumber* kf;
@@ -488,12 +567,27 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       KeyFrameNumberPtr kfCopy = KeyFrameNumber::Clone(*kf);
       AddAnimatorConnector( AnimatorConnector<float>::New( proxy,
                                                            target.propertyIndex,
-                                                           KeyFrameNumberFunctor(kfCopy),
+                                                           target.componentIndex,
+                                                           KeyFrameNumberFunctor(kfCopy,interpolation),
                                                            alpha,
                                                            period ) );
       break;
     }
 
+    case Dali::Property::INTEGER:
+    {
+      const KeyFrameInteger* kf;
+      GetSpecialization(keyFrames, kf);
+      KeyFrameIntegerPtr kfCopy = KeyFrameInteger::Clone(*kf);
+      AddAnimatorConnector( AnimatorConnector<int>::New( proxy,
+                                                         target.propertyIndex,
+                                                         target.componentIndex,
+                                                         KeyFrameIntegerFunctor(kfCopy,interpolation),
+                                                         alpha,
+                                                         period ) );
+      break;
+    }
+
     case Dali::Property::VECTOR2:
     {
       const KeyFrameVector2* kf;
@@ -501,7 +595,8 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       KeyFrameVector2Ptr kfCopy = KeyFrameVector2::Clone(*kf);
       AddAnimatorConnector( AnimatorConnector<Vector2>::New( proxy,
                                                              target.propertyIndex,
-                                                             KeyFrameVector2Functor(kfCopy),
+                                                             target.componentIndex,
+                                                             KeyFrameVector2Functor(kfCopy,interpolation),
                                                              alpha,
                                                              period ) );
       break;
@@ -514,7 +609,8 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       KeyFrameVector3Ptr kfCopy = KeyFrameVector3::Clone(*kf);
       AddAnimatorConnector( AnimatorConnector<Vector3>::New( proxy,
                                                              target.propertyIndex,
-                                                             KeyFrameVector3Functor(kfCopy),
+                                                             target.componentIndex,
+                                                             KeyFrameVector3Functor(kfCopy,interpolation),
                                                              alpha,
                                                              period ) );
       break;
@@ -527,7 +623,8 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       KeyFrameVector4Ptr kfCopy = KeyFrameVector4::Clone(*kf);
       AddAnimatorConnector( AnimatorConnector<Vector4>::New( proxy,
                                                              target.propertyIndex,
-                                                             KeyFrameVector4Functor(kfCopy),
+                                                             target.componentIndex,
+                                                             KeyFrameVector4Functor(kfCopy,interpolation),
                                                              alpha,
                                                              period ) );
       break;
@@ -540,6 +637,7 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
       KeyFrameQuaternionPtr kfCopy = KeyFrameQuaternion::Clone(*kf);
       AddAnimatorConnector( AnimatorConnector<Quaternion>::New( proxy,
                                                                 target.propertyIndex,
+                                                                target.componentIndex,
                                                                 KeyFrameQuaternionFunctor(kfCopy),
                                                                 alpha,
                                                                 period ) );
@@ -551,95 +649,6 @@ void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Alph
   }
 }
 
-void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func )
-{
-  Animate( target, targetType, func, mDefaultAlpha, mDurationSeconds );
-}
-
-void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func, AlphaFunction& alpha )
-{
-  Animate( target, targetType, func, alpha, mDurationSeconds );
-}
-
-void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func, TimePeriod period )
-{
-  Animate( target, targetType, func, mDefaultAlpha, period );
-}
-
-void Animation::Animate( Property& target, Property::Type targetType, AnyFunction& func, AlphaFunction& alpha, TimePeriod period )
-{
-  DALI_ASSERT_ALWAYS( target.object.GetPropertyType(target.propertyIndex) == targetType && "Animation function must match target property type" );
-
-  ProxyObject& proxy = dynamic_cast<ProxyObject&>( GetImplementation(target.object) );
-
-  switch ( targetType )
-  {
-    case Property::BOOLEAN:
-    {
-      AddAnimatorConnector( AnimatorConnector<bool>::New(proxy,
-                                                         target.propertyIndex,
-                                                         boost::any_cast< AnimatorFunctionBool >( func ),
-                                                         alpha,
-                                                         period) );
-      break;
-    }
-
-    case Property::FLOAT:
-    {
-      AddAnimatorConnector( AnimatorConnector<float>::New(proxy,
-                                                          target.propertyIndex,
-                                                          boost::any_cast< AnimatorFunctionFloat >( func ),
-                                                          alpha,
-                                                          period) );
-      break;
-    }
-
-    case Property::VECTOR2:
-    {
-      AddAnimatorConnector( AnimatorConnector<Vector2>::New(proxy,
-                                                            target.propertyIndex,
-                                                            boost::any_cast< AnimatorFunctionVector2 >( func ),
-                                                            alpha,
-                                                            period) );
-      break;
-    }
-
-    case Property::VECTOR3:
-    {
-      AddAnimatorConnector( AnimatorConnector<Vector3>::New(proxy,
-                                                            target.propertyIndex,
-                                                            boost::any_cast< AnimatorFunctionVector3 >( func ),
-                                                            alpha,
-                                                            period) );
-      break;
-    }
-
-    case Property::VECTOR4:
-    {
-      AddAnimatorConnector( AnimatorConnector<Vector4>::New(proxy,
-                                                            target.propertyIndex,
-                                                            boost::any_cast< AnimatorFunctionVector4 >( func ),
-                                                            alpha,
-                                                            period) );
-      break;
-    }
-
-    case Property::ROTATION:
-    {
-      AddAnimatorConnector( AnimatorConnector<Quaternion>::New(proxy,
-                                                               target.propertyIndex,
-                                                               boost::any_cast< AnimatorFunctionQuaternion >( func ),
-                                                               alpha,
-                                                               period) );
-      break;
-    }
-
-    default:
-      DALI_ASSERT_ALWAYS(false && "Property type enumeration out of bounds" ); // should never come here
-      break;
-  }
-}
-
 bool Animation::HasFinished()
 {
   bool hasFinished(false);
@@ -710,6 +719,48 @@ void Animation::AddAnimatorConnector( AnimatorConnectorBase* connector )
   mConnectors.PushBack( connector );
 }
 
+void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward )
+{
+  Animate( actor, path, forward, mDefaultAlpha, TimePeriod(0.0f,GetDuration()) );
+}
+
+void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha )
+{
+  Animate( actor, path, forward, alpha, TimePeriod(0.0f,GetDuration()) );
+}
+
+void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period )
+{
+  Animate( actor, path, forward, mDefaultAlpha, period );
+}
+
+void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
+{
+  ExtendDuration( period );
+
+  PathPtr pathCopy = Path::Clone(path);
+
+  //Position animation
+  AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
+                                                         Dali::Actor::POSITION,
+                                                         Property::INVALID_COMPONENT_INDEX,
+                                                         PathPositionFunctor( pathCopy ),
+                                                         alpha,
+                                                         period ) );
+
+  //If forward is zero, PathRotationFunctor will always return the unit quaternion
+  if( forward != Vector3::ZERO )
+  {
+    //Rotation animation
+    AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
+                                                              Dali::Actor::ROTATION,
+                                                              Property::INVALID_COMPONENT_INDEX,
+                                                              PathRotationFunctor( pathCopy, forward ),
+                                                              alpha,
+                                                              period ) );
+  }
+}
+
 void Animation::MoveBy(Actor& actor, float x, float y, float z)
 {
   MoveBy(actor, Vector3(x, y, z), mDefaultAlpha, 0.0f, GetDuration());
@@ -722,8 +773,11 @@ void Animation::MoveBy(Actor& actor, const Vector3& displacement, AlphaFunction
 
 void Animation::MoveBy(Actor& actor, const Vector3& displacement, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
+
   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
                                                          Dali::Actor::POSITION,
+                                                         Property::INVALID_COMPONENT_INDEX,
                                                          AnimateByVector3(displacement),
                                                          alpha,
                                                          TimePeriod(delaySeconds, durationSeconds) ) );
@@ -741,18 +795,12 @@ void Animation::MoveTo(Actor& actor, const Vector3& position, AlphaFunction alph
 
 void Animation::MoveTo(Actor& actor, const Vector3& position, AlphaFunction alpha,  float delaySeconds, float durationSeconds)
 {
-  AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
-                                                         Dali::Actor::POSITION,
-                                                         AnimateToVector3(position),
-                                                         alpha,
-                                                         TimePeriod(delaySeconds, durationSeconds) ) );
-}
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
 
-void Animation::Move(Actor& actor, AnimatorFunctionVector3 func, AlphaFunction alpha,  float delaySeconds, float durationSeconds)
-{
   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
                                                          Dali::Actor::POSITION,
-                                                         func,
+                                                         Property::INVALID_COMPONENT_INDEX,
+                                                         AnimateToVector3(position),
                                                          alpha,
                                                          TimePeriod(delaySeconds, durationSeconds) ) );
 }
@@ -769,8 +817,11 @@ void Animation::RotateBy(Actor& actor, Radian angle, const Vector3& axis, AlphaF
 
 void Animation::RotateBy(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
+
   AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
                                                             Dali::Actor::ROTATION,
+                                                            Property::INVALID_COMPONENT_INDEX,
                                                             RotateByAngleAxis(angle, axis),
                                                             alpha,
                                                             TimePeriod(delaySeconds, durationSeconds) ) );
@@ -818,18 +869,12 @@ void Animation::RotateTo(Actor& actor, Radian angle, const Vector3& axis, AlphaF
 
 void Animation::RotateTo(Actor& actor, const Quaternion& rotation, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
-  AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
-                                                            Dali::Actor::ROTATION,
-                                                            RotateToQuaternion(rotation),
-                                                            alpha,
-                                                            TimePeriod(delaySeconds, durationSeconds) ) );
-}
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
 
-void Animation::Rotate(Actor& actor, AnimatorFunctionQuaternion func, AlphaFunction alpha,  float delaySeconds, float durationSeconds)
-{
   AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
                                                             Dali::Actor::ROTATION,
-                                                            func,
+                                                            Property::INVALID_COMPONENT_INDEX,
+                                                            RotateToQuaternion(rotation),
                                                             alpha,
                                                             TimePeriod(delaySeconds, durationSeconds) ) );
 }
@@ -846,8 +891,11 @@ void Animation::ScaleBy(Actor& actor, const Vector3& scale, AlphaFunction alpha)
 
 void Animation::ScaleBy(Actor& actor, const Vector3& scale, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
+
   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
                                                          Dali::Actor::SCALE,
+                                                         Property::INVALID_COMPONENT_INDEX,
                                                          AnimateByVector3(scale),
                                                          alpha,
                                                          TimePeriod(delaySeconds, durationSeconds) ) );
@@ -865,8 +913,11 @@ void Animation::ScaleTo(Actor& actor, const Vector3& scale, AlphaFunction alpha)
 
 void Animation::ScaleTo(Actor& actor, const Vector3& scale, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
+
   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
                                                          Dali::Actor::SCALE,
+                                                         Property::INVALID_COMPONENT_INDEX,
                                                          AnimateToVector3(scale),
                                                          alpha,
                                                          TimePeriod(delaySeconds, durationSeconds) ) );
@@ -874,8 +925,11 @@ void Animation::ScaleTo(Actor& actor, const Vector3& scale, AlphaFunction alpha,
 
 void Animation::Show(Actor& actor, float delaySeconds)
 {
+  ExtendDuration( TimePeriod(delaySeconds, 0) );
+
   AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
                                                       Dali::Actor::VISIBLE,
+                                                      Property::INVALID_COMPONENT_INDEX,
                                                       AnimateToBoolean(SHOW_VALUE),
                                                       AlphaFunctions::Default,
                                                       TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
@@ -883,8 +937,11 @@ void Animation::Show(Actor& actor, float delaySeconds)
 
 void Animation::Hide(Actor& actor, float delaySeconds)
 {
+  ExtendDuration( TimePeriod(delaySeconds, 0) );
+
   AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
                                                       Dali::Actor::VISIBLE,
+                                                      Property::INVALID_COMPONENT_INDEX,
                                                       AnimateToBoolean(HIDE_VALUE),
                                                       AlphaFunctions::Default,
                                                       TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
@@ -902,8 +959,11 @@ void Animation::OpacityBy(Actor& actor, float opacity, AlphaFunction alpha)
 
 void Animation::OpacityBy(Actor& actor, float opacity, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
+
   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
                                                          Dali::Actor::COLOR,
+                                                         Property::INVALID_COMPONENT_INDEX,
                                                          AnimateByOpacity(opacity),
                                                          alpha,
                                                          TimePeriod(delaySeconds, durationSeconds) ) );
@@ -921,8 +981,11 @@ void Animation::OpacityTo(Actor& actor, float opacity, AlphaFunction alpha)
 
 void Animation::OpacityTo(Actor& actor, float opacity, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
+
   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
                                                          Dali::Actor::COLOR,
+                                                         Property::INVALID_COMPONENT_INDEX,
                                                          AnimateToOpacity(opacity),
                                                          alpha,
                                                          TimePeriod(delaySeconds, durationSeconds) ) );
@@ -940,8 +1003,11 @@ void Animation::ColorBy(Actor& actor, const Vector4& color, AlphaFunction alpha)
 
 void Animation::ColorBy(Actor& actor, const Vector4& color, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
+
   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
                                                          Dali::Actor::COLOR,
+                                                         Property::INVALID_COMPONENT_INDEX,
                                                          AnimateByVector4(color),
                                                          alpha,
                                                          TimePeriod(delaySeconds, durationSeconds) ) );
@@ -959,8 +1025,11 @@ void Animation::ColorTo(Actor& actor, const Vector4& color, AlphaFunction alpha)
 
 void Animation::ColorTo(Actor& actor, const Vector4& color, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
+
   AddAnimatorConnector( AnimatorConnector<Vector4>::New( actor,
                                                          Dali::Actor::COLOR,
+                                                         Property::INVALID_COMPONENT_INDEX,
                                                          AnimateToVector4(color),
                                                          alpha,
                                                          TimePeriod(delaySeconds, durationSeconds) ) );
@@ -978,13 +1047,16 @@ void Animation::Resize(Actor& actor, float width, float height, AlphaFunction al
 
 void Animation::Resize(Actor& actor, float width, float height, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
-  Vector3 targetSize( width, height, min(width, height) );
+  Vector3 targetSize( width, height, std::min(width, height) );
+
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
 
-  // notify the actor impl that its size is being animated
-  actor.OnSizeAnimation( *this, targetSize );
+  // Notify the actor impl that its size is being animated
+  actor.NotifySizeAnimation( *this, targetSize );
 
   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
                                                          Dali::Actor::SIZE,
+                                                         Property::INVALID_COMPONENT_INDEX,
                                                          AnimateToVector3(targetSize),
                                                          alpha,
                                                          TimePeriod(delaySeconds, durationSeconds) ) );
@@ -1002,182 +1074,120 @@ void Animation::Resize(Actor& actor, const Vector3& size, AlphaFunction alpha)
 
 void Animation::Resize(Actor& actor, const Vector3& size, AlphaFunction alpha, float delaySeconds, float durationSeconds)
 {
-  // notify the actor impl that its size is being animated
-  actor.OnSizeAnimation( *this, size );
+  ExtendDuration( TimePeriod(delaySeconds, durationSeconds) );
+
+  // Notify the actor impl that its size is being animated
+  actor.NotifySizeAnimation( *this, size );
 
   AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
                                                          Dali::Actor::SIZE,
+                                                         Property::INVALID_COMPONENT_INDEX,
                                                          AnimateToVector3(size),
                                                          alpha,
                                                          TimePeriod(delaySeconds, durationSeconds) ) );
 }
 
-void Animation::ParentOriginTo(Actor& actor, const Vector3& parentOrigin)
-{
-  ParentOriginTo(actor, parentOrigin, mDefaultAlpha, 0.0f, GetDuration());
-}
-
-void Animation::ParentOriginTo(Actor& actor, const Vector3& parentOrigin, AlphaFunction alpha)
-{
-  ParentOriginTo(actor, parentOrigin, alpha, 0.0f, GetDuration());
-}
-
-void Animation::ParentOriginTo(Actor& actor, const Vector3& parentOrigin, AlphaFunction alpha, float delaySeconds, float durationSeconds)
-{
-  AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
-                                                         Dali::Actor::PARENT_ORIGIN,
-                                                         AnimateToVector3(parentOrigin),
-                                                         alpha,
-                                                         TimePeriod(delaySeconds, durationSeconds) ) );
-}
-
-void Animation::AnchorPointTo(Actor& actor, const Vector3& anchorPoint)
-{
-  AnchorPointTo(actor, anchorPoint, mDefaultAlpha, 0.0f, GetDuration());
-}
-
-void Animation::AnchorPointTo(Actor& actor, const Vector3& anchorPoint, AlphaFunction alpha)
+bool Animation::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
 {
-  AnchorPointTo(actor, anchorPoint, alpha, 0.0f, GetDuration());
-}
+  bool done = false;
+  Animation* animation = dynamic_cast<Animation*>(object);
 
-void Animation::AnchorPointTo(Actor& actor, const Vector3& anchorPoint, AlphaFunction alpha, float delaySeconds, float durationSeconds)
-{
-  AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
-                                                         Dali::Actor::ANCHOR_POINT,
-                                                         AnimateToVector3(anchorPoint),
-                                                         alpha,
-                                                         TimePeriod(delaySeconds, durationSeconds) ) );
-}
+  if( animation )
+  {
+    if(Dali::Animation::ACTION_PLAY == actionName)
+    {
+      if(attributes.size() > 0)
+      {
+        animation->SetDuration(attributes[0].Get<float>());
+      }
 
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, float value )
-{
-  AnimateProperty( shaderEffect, name, value, GetDefaultAlphaFunction(), 0, GetDuration() );
-}
+      animation->Play();
+      done = true;
+    }
+    else if(Dali::Animation::ACTION_STOP == actionName)
+    {
+      animation->Stop();
+      done = true;
+    }
+    else if(Dali::Animation::ACTION_PAUSE == actionName)
+    {
+      animation->Pause();
+      done = true;
+    }
+  }
 
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, float value, AlphaFunction alpha )
-{
-  AnimateProperty( shaderEffect, name, value, alpha, 0, GetDuration() );
+  return done;
 }
 
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, float value, AlphaFunction alpha, float delaySeconds, float durationSeconds )
+void Animation::SetCurrentProgress(float progress)
 {
-  Property::Value propertyValue( value );
-
-  // Register the property if it does not exist
-  Property::Index index = shaderEffect.GetPropertyIndex( name );
-  if ( Property::INVALID_INDEX == index )
+  if( mAnimation && progress >= mPlayRange.x && progress <= mPlayRange.y )
   {
-    index = shaderEffect.RegisterProperty( name, propertyValue );
+    // mAnimation is being used in a separate thread; queue a message to set the current progress
+    SetCurrentProgressMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, progress );
   }
-
-  AnimateTo( shaderEffect, index, propertyValue, alpha, TimePeriod(delaySeconds, durationSeconds) );
 }
 
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector2 value )
+float Animation::GetCurrentProgress()
 {
-  AnimateProperty( shaderEffect, name, value, GetDefaultAlphaFunction(), 0, GetDuration());
-}
-
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector2 value, AlphaFunction alpha )
-{
-  AnimateProperty( shaderEffect, name, value, alpha, 0, GetDuration() );
-}
-
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector2 value, AlphaFunction alpha, float delaySeconds, float durationSeconds )
-{
-  Property::Value propertyValue( value );
-
-  // Register the property if it does not exist
-  Property::Index index = shaderEffect.GetPropertyIndex( name );
-  if ( Property::INVALID_INDEX == index )
+  if( mAnimation )
   {
-    index = shaderEffect.RegisterProperty( name, propertyValue );
+    return mAnimation->GetCurrentProgress();
   }
 
-  AnimateTo( shaderEffect, index, propertyValue, alpha, TimePeriod(delaySeconds, durationSeconds) );
+  return 0.0f;
 }
 
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector3 value )
+void Animation::ExtendDuration( const TimePeriod& timePeriod )
 {
-  AnimateProperty( shaderEffect, name, value, GetDefaultAlphaFunction(), 0, GetDuration() );
-}
+  float duration = timePeriod.delaySeconds + timePeriod.durationSeconds;
 
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector3 value, AlphaFunction alpha )
-{
-  AnimateProperty( shaderEffect, name, value, alpha, 0, GetDuration() );
+  if( duration > mDurationSeconds )
+  {
+    SetDuration( duration );
+  }
 }
 
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector3 value, AlphaFunction alpha, float delaySeconds, float durationSeconds )
+void Animation::SetSpeedFactor( float factor )
 {
-  Property::Value propertyValue( value );
-
-  // Register the property if it does not exist
-  Property::Index index = shaderEffect.GetPropertyIndex( name );
-  if ( Property::INVALID_INDEX == index )
+  if( mAnimation )
   {
-    index = shaderEffect.RegisterProperty( name, propertyValue );
+    mSpeedFactor = factor;
+    SetSpeedFactorMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, factor );
   }
-
-  AnimateTo( shaderEffect, index, propertyValue, alpha, TimePeriod(delaySeconds, durationSeconds) );
 }
 
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector4 value )
+float Animation::GetSpeedFactor() const
 {
-  AnimateProperty( shaderEffect, name, value, GetDefaultAlphaFunction(), 0, GetDuration() );
+  return mSpeedFactor;
 }
 
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector4 value, AlphaFunction alpha )
+void Animation::SetPlayRange( const Vector2& range)
 {
-  AnimateProperty( shaderEffect, name, value, alpha, 0, GetDuration() );
-}
+  //Make sure the range specified is between 0.0 and 1.0
+  if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
+  {
+    Vector2 orderedRange( range );
+    //If the range is not in order swap values
+    if( range.x > range.y )
+    {
+      orderedRange = Vector2(range.y, range.x);
+    }
 
-void Animation::AnimateProperty( Internal::ShaderEffect& shaderEffect, const std::string& name, Vector4 value, AlphaFunction alpha, float delaySeconds, float durationSeconds )
-{
-  Property::Value propertyValue( value );
+    // Cache for public getters
+    mPlayRange = orderedRange;
 
-  // Register the property if it does not exist
-  Property::Index index = shaderEffect.GetPropertyIndex( name );
-  if ( Property::INVALID_INDEX == index )
-  {
-    index = shaderEffect.RegisterProperty( name, propertyValue );
+    // mAnimation is being used in a separate thread; queue a message to set play range
+    SetPlayRangeMessage( mUpdateManager.GetEventToUpdate(), *mAnimation, orderedRange );
   }
-
-  AnimateTo( shaderEffect, index, propertyValue, alpha, TimePeriod(delaySeconds, durationSeconds) );
 }
 
-bool Animation::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
+Vector2 Animation::GetPlayRange() const
 {
-  bool done = false;
-  Animation* animation = dynamic_cast<Animation*>(object);
-
-  if( animation )
-  {
-    if(Dali::Animation::ACTION_PLAY == actionName)
-    {
-      if(attributes.size() > 0)
-      {
-        animation->SetDuration(attributes[0].Get<float>());
-      }
-
-      animation->Play();
-      done = true;
-    }
-    else if(Dali::Animation::ACTION_STOP == actionName)
-    {
-      animation->Stop();
-      done = true;
-    }
-    else if(Dali::Animation::ACTION_PAUSE == actionName)
-    {
-      animation->Pause();
-      done = true;
-    }
-  }
-
-  return done;
+  return mPlayRange;
 }
 
+
 } // namespace Internal
 
 } // namespace Dali