Added api to animate an actor (position and orientation) through a path 74/30174/20
authorFerran Sole <ferran.sole@samsung.com>
Wed, 12 Nov 2014 11:41:57 +0000 (11:41 +0000)
committerFerran Sole <ferran.sole@samsung.com>
Thu, 27 Nov 2014 15:18:18 +0000 (15:18 +0000)
[Problem]  N/A
[Cause]    N/A
[Solution] N/A

Change-Id: Ibcf6a98cd073c145b3b873822aecde73afb31e39

17 files changed:
automated-tests/src/dali/CMakeLists.txt
automated-tests/src/dali/utc-Dali-Animation.cpp
automated-tests/src/dali/utc-Dali-Path.cpp [new file with mode: 0644]
dali/internal/event/animation/animation-impl.cpp
dali/internal/event/animation/animation-impl.h
dali/internal/event/animation/path-impl.cpp [new file with mode: 0644]
dali/internal/event/animation/path-impl.h [new file with mode: 0644]
dali/internal/file.list
dali/internal/update/animation/scene-graph-animator.h
dali/public-api/animation/animation.cpp
dali/public-api/animation/animation.h
dali/public-api/animation/path.cpp [new file with mode: 0644]
dali/public-api/animation/path.h [new file with mode: 0644]
dali/public-api/dali-core.h
dali/public-api/file.list
dali/public-api/math/quaternion.cpp
dali/public-api/math/quaternion.h

index 85a0bcf..fe83dbe 100644 (file)
@@ -41,6 +41,7 @@ SET(TC_SOURCES
         utc-Dali-MeshActor.cpp
         utc-Dali-PanGesture.cpp
         utc-Dali-PanGestureDetector.cpp
+        utc-Dali-Path.cpp
         utc-Dali-PinchGesture.cpp
         utc-Dali-PinchGestureDetector.cpp
         utc-Dali-Pixel.cpp
index 8304b60..69b2a56 100644 (file)
@@ -9440,3 +9440,81 @@ int UtcDaliAnimationExtendDuration(void)
   END_TEST;
 }
 
+int UtcDaliAnimationPath(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  //Build the path
+  Vector3 position0( 30.0,  80.0,  0.0);
+  Vector3 position1( 70.0,  120.0, 0.0);
+  Vector3 position2( 100.0, 100.0, 0.0);
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(position0);
+  path.AddPoint(position1);
+  path.AddPoint(position2);
+
+  //Control points for first segment
+  path.AddControlPoint( Vector3( 39.0,  90.0, 0.0) );
+  path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) );
+
+  //Control points for second segment
+  path.AddControlPoint(Vector3( 78.0, 120.0, 0.0));
+  path.AddControlPoint(Vector3( 93.0, 104.0, 0.0));
+
+  // Build the animation
+  float durationSeconds( 1.0f );
+  Animation animation = Animation::New(durationSeconds);
+  animation.Animate(actor, path, Vector3::XAXIS, AlphaFunctions::Linear, TimePeriod(0.0f, 1.0f ));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  Vector3 position, tangent;
+  Quaternion rotation;
+  path.Sample( 0.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentRotation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  path.Sample( 0.25f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentRotation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  path.Sample( 0.5f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentRotation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  path.Sample( 0.75f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentRotation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  path.Sample( 1.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentRotation(), rotation, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Path.cpp b/automated-tests/src/dali/utc-Dali-Path.cpp
new file mode 100644 (file)
index 0000000..2dbb9ee
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * 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.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+using namespace Dali::Internal;
+
+namespace
+{
+// Knots fed into Allegro, which generates control points
+static void SetupPath( Dali::Path& path)
+{
+  path.AddPoint(Vector3( 30.0,  80.0, 0.0));
+  path.AddPoint(Vector3( 70.0, 120.0, 0.0));
+  path.AddPoint(Vector3(100.0, 100.0, 0.0));
+
+  //Control points for first segment
+  path.AddControlPoint( Vector3( 39.0,  90.0, 0.0) );
+  path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) );
+
+  //Control points for second segment
+  path.AddControlPoint(Vector3( 78.0, 120.0, 0.0) );
+  path.AddControlPoint(Vector3( 93.0, 104.0, 0.0) );
+}
+
+} // anonymous namespace
+
+int utcDaliPathGetPoint(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(Vector3( 50.0,  50.0, 0.0));
+  path.AddPoint(Vector3(120.0,  70.0, 0.0));
+  path.AddPoint(Vector3(190.0, 250.0, 0.0));
+  path.AddPoint(Vector3(260.0, 260.0, 0.0));
+  path.AddPoint(Vector3(330.0, 220.0, 0.0));
+  path.AddPoint(Vector3(400.0,  50.0, 0.0));
+
+  DALI_TEST_EQUALS(path.GetPoint(0), Vector3( 50.0,  50.0, 0.0), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetPoint(1), Vector3(120.0,  70.0, 0.0), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetPoint(2), Vector3(190.0, 250.0, 0.0), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetPoint(3), Vector3(260.0, 260.0, 0.0), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetPoint(4), Vector3(330.0, 220.0, 0.0), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetPoint(5), Vector3(400.0,  50.0, 0.0), TEST_LOCATION);
+  END_TEST;
+}
+
+int utcDaliPathGetPoint02(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(Vector3( 50.0,  50.0, 0.0f));
+
+  try
+  {
+    path.GetPoint(1);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    tet_printf("Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str());
+    DALI_TEST_ASSERT(e, "index < mPoint.Size()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int utcDaliPathGetPoint03(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+
+  try
+  {
+    path.GetPoint(0);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    tet_printf("Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str());
+    DALI_TEST_ASSERT(e, "index < mPoint.Size()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int utcDaliPathGetControlPoints(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  path.AddControlPoint( Vector3(0.0f, 0.0f, 0.0) );
+  path.AddControlPoint( Vector3(108.0f, 57.0f, 0.0) );
+
+  DALI_TEST_EQUALS(path.GetControlPoint(0), Vector3(0.0f, 0.0f, 0.0f), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(1), Vector3(108.0f, 57.0f, 0.0f), TEST_LOCATION);
+  END_TEST;
+}
+
+int utcDaliPathGetControlPoints01(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  path.AddControlPoint(Vector3(0.0f, 0.0f, 0.0) );
+  path.AddControlPoint(Vector3(108.0f, 57.0f, 0.0) );
+
+  try
+  {
+    path.GetControlPoint(5);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    tet_printf("Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str());
+    DALI_TEST_ASSERT(e, "index < mControlPoint.Size()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int utcDaliPathGetControlPoints02(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  try
+  {
+    path.GetControlPoint(0);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    tet_printf("Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str());
+    DALI_TEST_ASSERT(e, "index < mControlPoint.Size()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int utcDaliPathGenerateControlPoints01(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+
+  path.AddPoint(Vector3( 50.0,  50.0, 0.0));
+  path.AddPoint(Vector3(120.0,  70.0, 0.0));
+  path.AddPoint(Vector3(190.0, 250.0, 0.0));
+  path.AddPoint(Vector3(260.0, 260.0, 0.0));
+  path.AddPoint(Vector3(330.0, 220.0, 0.0));
+  path.AddPoint(Vector3(400.0,  50.0, 0.0));
+
+  path.GenerateControlPoints(0.25);
+
+  DALI_TEST_EQUALS(path.GetControlPoint(0), Vector3( 68.0,  55.0, 0.0), 1.0, TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(1), Vector3(107.0,  58.0, 0.0), 1.0, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(path.GetControlPoint(2), Vector3(156.0, 102.0, 0.0), 1.0, TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(3), Vector3(152.0, 220.0, 0.0), 1.0, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(path.GetControlPoint(4), Vector3(204.0, 261.0, 0.0), 1.0, TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(5), Vector3(243.0, 263.0, 0.0), 1.0, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(path.GetControlPoint(6), Vector3(280.0, 256.0, 0.0), 1.0, TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(7), Vector3(317.0, 235.0, 0.0), 1.0, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(path.GetControlPoint(8), Vector3(360.0, 185.0, 0.0), 1.0, TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(9), Vector3(383.0,  93.0, 0.0), 1.0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int utcDaliPathGenerateControlPoints02(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  try
+  {
+    path.GenerateControlPoints(0.25);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    tet_printf("Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str());
+    DALI_TEST_ASSERT(e, "numSegments > 0", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int utcDaliPathGenerateControlPoints03(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(Vector3(400.0,  50.0, 0.0f));
+  try
+  {
+    path.GenerateControlPoints(0.25);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    tet_printf("Assertion %s failed at %s\n", e.mCondition.c_str(), e.mLocation.c_str());
+    DALI_TEST_ASSERT(e, "numSegments > 0", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliPathSample01(void)
+{
+  TestApplication application;
+  Dali::Path path = Dali::Path::New();
+  SetupPath(path);
+
+  //t = 0
+  Vector3 position, tangent;
+  path.Sample(0.0f, position, tangent );
+  DALI_TEST_EQUALS(position.x, 30.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 80.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.6f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.7f, 0.1f, TEST_LOCATION);
+
+  //t = 0.25
+  path.Sample(0.25f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  48.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 102.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.6f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.7f, 0.1f, TEST_LOCATION);
+
+  // t = 0.5
+  path.Sample(0.5f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  70.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 120.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  1.0f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.0f, 0.1f, TEST_LOCATION);
+
+
+  //t = 0.75
+  path.Sample(0.75f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  85.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 112.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.7f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  -0.6f, 0.1f, TEST_LOCATION);
+
+  // t = 1
+  path.Sample(1.0f, position, tangent );
+  DALI_TEST_EQUALS(position.x, 100.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 100.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.8f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  -0.4f, 0.1f, TEST_LOCATION);
+
+  END_TEST;
+}
index 2af1a77..dad1f27 100644 (file)
@@ -698,6 +698,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());
index 1985998..7d10295 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali/public-api/object/base-object.h>
 #include <dali/internal/event/animation/animator-connector-base.h>
 #include <dali/internal/event/animation/key-frames-impl.h>
+#include <dali/internal/event/animation/path-impl.h>
 
 namespace Dali
 {
@@ -71,56 +72,47 @@ public:
   static AnimationPtr New(float durationSeconds);
 
   /**
-   * Set the duration of an animation.
-   * @pre durationSeconds must be greater than zero.
-   * @param[in] seconds The duration in seconds.
+   * @copydoc Dali::Animation::SetDuration()
    */
   void SetDuration(float seconds);
 
   /**
-   * Retrieve the duration of an animation.
-   * @return The duration in seconds.
+   * @copydoc Dali::Animation::GetDuration()
    */
   float GetDuration() const;
 
   /**
-   * Set whether the animation will loop.
-   * @param[in] looping True if the animation will loop.
+   * @copydoc Dali::Animation::SetLooping()
    */
   void SetLooping(bool looping);
 
   /**
-   * Query whether the animation will loop.
-   * @return True if the animation will loop.
+   * @copydoc Dali::Animation::IsLooping()
    */
   bool IsLooping() const;
 
   /**
-   * Set the end action of the animation.
-   * @param[in] action The end action.
+   * @copydoc Dali::Animation::SetEndAction()
    */
   void SetEndAction(EndAction action);
 
   /**
-   * Returns the end action of the animation.
+   * @copydoc Dali::Animation::GetEndAction()
    */
   EndAction GetEndAction() const;
 
   /**
-   * Set the disconnect action of the animation.
-   * @param[in] action The disconnect action.
+   * @copydoc Dali::Animation::SetDisconnectAction()
    */
   void SetDisconnectAction(EndAction action);
 
   /**
-   * Returns the disconnect action of the animation.
+   * @copydoc Dali::Animation::GetDisconnectAction()
    */
   EndAction GetDisconnectAction() const;
 
   /**
-   * Set the default alpha function for an animation.
-   * This is applied to individual property animations, if no further alpha functions are supplied.
-   * @param[in] alpha The default alpha function.
+   * @copydoc Dali::Animation::SetDefaultAlphaFunction()
    */
   void SetDefaultAlphaFunction(AlphaFunction alpha)
   {
@@ -128,8 +120,7 @@ public:
   }
 
   /**
-   * Retrieve the default alpha function for an animation.
-   * @return The default alpha function.
+   * @copydoc Dali::Animation::GetDefaultAlphaFunction()
    */
   AlphaFunction GetDefaultAlphaFunction() const
   {
@@ -137,29 +128,27 @@ public:
   }
 
   /**
-   * (Re)start the animation.
+   * @copydoc Dali::Animation::Play()
    */
   void Play();
 
   /**
-   * (Re)start the animation from a given point.
-   * @param[in] progress The progress between [0,1] from where the animation should start
+   * @copydoc Dali::Animation::PlayFrom()
    */
   void PlayFrom( float progress );
 
   /**
-   * Pause the animation.
+   * @copydoc Dali::Animation::Pause()
    */
   void Pause();
 
   /**
-   * Stop the animation.
+   * @copydoc Dali::Animation::Stop()
    */
   void Stop();
 
   /**
-   * Clear the animation.
-   * This disconnects any objects that were being animated, effectively stopping the animation.
+   * @copydoc Dali::Animation::Clear()
    */
   void Clear();
 
@@ -258,466 +247,250 @@ public:
    */
   void AnimateTo(ProxyObject& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period);
 
-
   /**
-   * Animate a property between the keyframe time / value pairs.
-   * It uses the current duration of the animation to run the key
-   * frame animator. Note, If the animation duration is subsequently
-   * changed, this does not change to match.
-   *
-   * @param[in] target The target object + property to animate
-   * @param[in] keyFrames The set of time / value pairs between which to animate.
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames)
    */
   void AnimateBetween(Property target, const KeyFrames& keyFrames);
 
   /**
-   * Animate a property between the keyframe time / value pairs.
-   * @param[in] target The target object + property to animate
-   * @param[in] keyFrames The set of time / value pairs between which to animate.
-   * @param[in] period The effect will occur duing this time period.
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period)
    */
   void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period);
 
   /**
-   * Animate a property between the keyframe time / value pairs.
-   * @param[in] target The target object + property to animate
-   * @param[in] keyFrames The set of time / value pairs between which to animate.
-   * @param[in] alpha The alpha function to apply to the overall progress.
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha)
    */
   void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha);
 
   /**
-   * Animate a property between the keyframe time / value pairs.
-   * @param[in] target The target object + property to animate
-   * @param[in] keyFrames The set of time / value pairs between which to animate.
-   * @param[in] alpha The alpha function to apply to the overall progress.
-   * @param[in] period The effect will occur duing this time period.
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
    */
   void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period);
 
-  // Action-specific convenience functions
+  // Actor-specific convenience functions
+
+  /**
+   * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward )
+   */
+  void Animate( Actor& actor, const Path& path, const Vector3& forward );
+
+  /**
+   * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha )
+   */
+  void Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha );
+
+  /**
+   * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period )
+   */
+  void Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period );
+
+  /**
+   * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
+   */
+  void Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period);
 
   /**
-   * Translate an actor.
-   * The default alpha function will be used.
-   * The translation will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] x Translation in the X-direction.
-   * @param [in] y Translation in the Y-direction.
-   * @param [in] z Translation in the Z-direction.
+   * @copydoc Dali::Animation::MoveBy(Actor actor, float x, float y, float z)
    */
   void MoveBy(Actor& actor, float x, float y, float z);
 
   /**
-   * Translate an actor. This overload allows the alpha function to be customized.
-   * The translation will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] translation The translation.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::MoveBy(Actor actor, Vector3 displacement, AlphaFunction alpha)
    */
   void MoveBy(Actor& actor, const Vector3& translation, AlphaFunction alpha);
 
   /**
-   * Translate an actor. This overload allows the translation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be greater than zero.
-   * @param [in] actor The actor to animate.
-   * @param [in] translation The translation.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the translation.
+   * @copydoc Dali::Animation::MoveBy(Actor actor, Vector3 displacement, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void MoveBy(Actor& actor, const Vector3& translation, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Translate an actor to a target position.
-   * The default alpha function will be used.
-   * The translation will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] x Translation in the X-direction.
-   * @param [in] y Translation in the Y-direction.
-   * @param [in] z Translation in the Z-direction.
+   * @copydoc Dali::Animation::MoveTo(Actor actor, float x, float y, float z)
    */
   void MoveTo(Actor& actor, float x, float y, float z);
 
   /**
-   * Translate an actor to a target position. This overload allows the alpha function to be customized.
-   * The translation will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] translation The translation.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::MoveTo(Actor actor, Vector3 position, AlphaFunction alpha)
    */
   void MoveTo(Actor& actor, const Vector3& translation, AlphaFunction alpha);
 
   /**
-   * Translate an actor to a target position. This overload allows the translation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be greater than zero.
-   * @param [in] actor The actor to animate.
-   * @param [in] translation The translation.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the translation.
+   * @copydoc Dali::Animation::MoveTo(Actor actor, Vector3 position, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void MoveTo(Actor& actor, const Vector3& translation, AlphaFunction alpha,  float delaySeconds, float durationSeconds);
 
   /**
-   * Rotate an actor around an arbitrary axis.
-   * The default alpha function will be used.
-   * The rotation will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] angle The angle in radians.
-   * @param [in] axis The axis of rotation.
+   * @copydoc Dali::Animation::RotateBy(Actor actor, Radian angle, Vector3 axis)
    */
   void RotateBy(Actor& actor, Radian angle, const Vector3& axis);
 
   /**
-   * Rotate an actor around an arbitrary axis. This overload allows the alpha function to be customized.
-   * The rotation will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] angle The angle in radians.
-   * @param [in] axis The axis of rotation.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::RotateBy(Actor actor, Radian angle, Vector3 axis, AlphaFunction alpha)()
    */
   void RotateBy(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha);
 
   /**
-   * Rotate an actor around an arbitrary axis. This overload allows the rotation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be zero or greater; zero is useful when animating boolean values.
-   * @param [in] actor The actor to animate.
-   * @param [in] angle The angle in radians.
-   * @param [in] axis The axis of rotation.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the rotation.
+   * @copydoc Dali::Animation::RotateBy(Actor actor, Radian angle, Vector3 axis, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void RotateBy(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Rotate an actor to a target orientation.
-   * The default alpha function will be used.
-   * The rotation will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] angle The target rotation angle in radians.
-   * @param [in] axis The target axis of rotation.
+   * @copydoc Dali::Animation::RotateTo(Actor actor, Radian angle, Vector3 axis)
    */
   void RotateTo(Actor& actor, Radian angle, const Vector3& axis);
 
   /**
-   * Rotate an actor to a target orientation.
-   * The default alpha function will be used.
-   * The rotation will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] orientation The target orientation.
+   * @copydoc Dali::Animation::RotateTo(Actor actor, Quaternion orientation)
    */
   void RotateTo(Actor& actor, const Quaternion& orientation);
 
   /**
-   * Rotate an actor to a target orientation. This overload allows the alpha function to be customized.
-   * The rotation will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] angle The target rotation angle in radians.
-   * @param [in] axis The target axis of rotation.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::RotateTo(Actor actor, Radian angle, Vector3 axis, AlphaFunction alpha)
    */
   void RotateTo(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha);
 
   /**
-   * Rotate an actor to a target orientation. This overload allows the alpha function to be customized.
-   * The rotation will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] orientation The target orientation.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::RotateTo(Actor actor, Quaternion orientation, AlphaFunction alpha)
    */
   void RotateTo(Actor& actor, const Quaternion& orientation, AlphaFunction alpha);
 
   /**
-   * Rotate an actor to a target orientation. This overload allows the rotation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be greater than zero.
-   * @param [in] actor The actor to animate.
-   * @param [in] orientation The target orientation.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the rotation.
+   * @copydoc Dali::Animation::RotateTo(Actor actor, Quaternion orientation, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void RotateTo(Actor& actor, const Quaternion& orientation, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Rotate an actor to a target orientation. This overload allows the rotation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be greater than zero.
-   * @param [in] actor The actor to animate.
-   * @param [in] angle The target rotation angle in radians.
-   * @param [in] axis The target axis of rotation.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the rotation.
+   * @copydoc Dali::Animation::RotateTo(Actor actor, Radian angle, Vector3 axis, AlphaFunction alpha, float delaySeconds, float durationSeconds)()
    */
   void RotateTo(Actor& actor, Radian angle, const Vector3& axis, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Scale an actor.
-   * The default alpha function will be used.
-   * The scaling will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] x Scale factor in the X-direction.
-   * @param [in] y Scale factor in the Y-direction.
-   * @param [in] z Scale factor in the Z-direction.
+   * @copydoc Dali::Animation::ScaleBy(Actor actor, float x, float y, float z)()
    */
   void ScaleBy(Actor& actor, float x, float y, float z);
 
   /**
-   * Scale an actor. This overload allows the alpha function to be customized.
-   * The scaling will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] scale The scale factor.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::ScaleBy(Actor actor, Vector3 scale, AlphaFunction alpha)
    */
   void ScaleBy(Actor& actor, const Vector3& scale, AlphaFunction alpha);
 
   /**
-   * Scale an actor. This overload allows the translation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be greater than zero.
-   * @param [in] actor The actor to animate.
-   * @param [in] scale The scale factor.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the translation.
+   * @copydoc Dali::Animation::ScaleBy(Actor actor, Vector3 scale, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void ScaleBy(Actor& actor, const Vector3& scale, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Scale an actor to a target scale factor.
-   * The default alpha function will be used.
-   * The scaling will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] x Target scale-factor in the X-direction.
-   * @param [in] y Target scale-factor in the Y-direction.
-   * @param [in] z Target scale-factor in the Z-direction.
+   * @copydoc Dali::Animation::ScaleTo(Actor actor, float x, float y, float z)
    */
   void ScaleTo(Actor& actor, float x, float y, float z);
 
   /**
-   * Scale an actor to a target scale factor. This overload allows the alpha function to be customized.
-   * The scaling will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] scale The target scale factor.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::ScaleTo(Actor actor, Vector3 scale, AlphaFunction alpha)
    */
   void ScaleTo(Actor& actor, const Vector3& scale, AlphaFunction alpha);
 
   /**
-   * Scale an actor to a target scale factor. This overload allows the translation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be greater than zero.
-   * @param [in] actor The actor to animate.
-   * @param [in] scale The target scale factor.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the translation.
+   * @copydoc Dali::Animation::ScaleTo(Actor actor, Vector3 scale, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void ScaleTo(Actor& actor, const Vector3& scale, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Show an actor during the animation.
-   * @param [in] actor The actor to animate.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
+   * @copydoc Dali::Animation::Show()
    */
   void Show(Actor& actor, float delaySeconds);
 
   /**
-   * Hide an actor during the animation.
-   * @param [in] actor The actor to animate.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
+   * @copydoc Dali::Animation::Hide()
    */
   void Hide(Actor& actor, float delaySeconds);
 
   /**
-   * Animate the opacity of an actor.
-   * The default alpha function will be used.
-   * The effect will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] opacity The relative change in opacity.
+   * @copydoc Dali::Animation::OpacityBy(Actor actor, float opacity)
    */
   void OpacityBy(Actor& actor, float opacity);
 
   /**
-   * Animate the opacity of an actor. This overload allows the alpha function to be customized.
-   * The effect will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] opacity The relative change in opacity.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::OpacityBy(Actor actor, float opacity, AlphaFunction alpha)
    */
   void OpacityBy(Actor& actor, float opacity, AlphaFunction alpha);
 
   /**
-   * Animate the opacity of an actor. This overload allows the translation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be greater than zero.
-   * @param [in] actor The actor to animate.
-   * @param [in] opacity The relative change in opacity.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the translation.
+   * @copydoc Dali::Animation::OpacityBy(Actor actor, float opacity, AlphaFunction alpha, float delaySeconds, float durationSeconds)()
    */
   void OpacityBy(Actor& actor, float opacity, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Animate an actor to a target opacity.
-   * The default alpha function will be used.
-   * The effect will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] opacity The target opacity.
+   * @copydoc Dali::Animation::OpacityTo(Actor actor, float opacity)
    */
   void OpacityTo(Actor& actor, float opacity);
 
   /**
-   * Animate an actor to a target opacity. This overload allows the alpha function to be customized.
-   * The effect will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] opacity The target opacity.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::OpacityTo(Actor actor, float opacity, AlphaFunction alpha)
    */
   void OpacityTo(Actor& actor, float opacity, AlphaFunction alpha);
 
   /**
-   * Animate an actor to a target opacity. This overload allows the translation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be greater than zero.
-   * @param [in] actor The actor to animate.
-   * @param [in] opacity The target opacity.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the translation.
+   * @copydoc Dali::Animation::OpacityTo(Actor actor, float opacity, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void OpacityTo(Actor& actor, float opacity, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Animate the color of an actor.
-   * The default alpha function will be used.
-   * The effect will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] color The relative change in color.
+   * @copydoc Dali::Animation::ColorBy(Actor actor, Vector4 color)
    */
   void ColorBy(Actor& actor, const Vector4& color);
 
   /**
-   * Animate the color of an actor. This overload allows the alpha function to be customized.
-   * The effect will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] color The relative change in color.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::ColorBy(Actor actor, Vector4 color, AlphaFunction alpha)
    */
   void ColorBy(Actor& actor, const Vector4& color, AlphaFunction alpha);
 
   /**
-   * Animate the color of an actor. This overload allows the translation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be zero or greater; zero is useful when animating boolean values.
-   * @param [in] actor The actor to animate.
-   * @param [in] color The relative change in color.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the translation.
+   * @copydoc Dali::Animation::ColorBy(Actor actor, Vector4 color, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void ColorBy(Actor& actor, const Vector4& color, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Animate an actor to a target color.
-   * The default alpha function will be used.
-   * The effect will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] color The target color.
+   * @copydoc Dali::Animation::ColorTo(Actor actor, Vector4 color)
    */
   void ColorTo(Actor& actor, const Vector4& color);
 
   /**
-   * Animate an actor to a target color. This overload allows the alpha function to be customized.
-   * The effect will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] color The target color.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::ColorTo(Actor actor, Vector4 color, AlphaFunction alpha)
    */
   void ColorTo(Actor& actor, const Vector4& color, AlphaFunction alpha);
 
   /**
-   * Animate an actor to a target color. This overload allows the translation start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be zero or greater; zero is useful when animating boolean values.
-   * @param [in] actor The actor to animate.
-   * @param [in] color The target color.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the translation.
+   * @copydoc Dali::Animation::ColorTo(Actor actor, Vector4 color, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void ColorTo(Actor& actor, const Vector4& color, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Resize an actor.
-   * The default alpha function will be used.
-   * The resizing will start & end when the animation begins & ends.
-   * The depth defaults to the minimum of width & height.
-   * @param [in] actor The actor to animate.
-   * @param [in] width The target width.
-   * @param [in] height The target height.
+   * @copydoc Dali::Animation::Resize(Actor actor, float width, float height)
    */
   void Resize(Actor& actor, float width, float height);
 
   /**
-   * Resize an actor. This overload allows the alpha function to be customized.
-   * The resizing will start & end when the animation begins & ends.
-   * The depth defaults to the minimum of width & height.
-   * @param [in] actor The actor to animate.
-   * @param [in] width The target width.
-   * @param [in] height The target height.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::Resize(Actor actor, float width, float height, AlphaFunction alpha)
    */
   void Resize(Actor& actor, float width, float height, AlphaFunction alpha);
 
   /**
-   * Resize an actor. This overload allows the resizing start & end time to be customized.
-   * The depth defaults to the minimum of width & height.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be greater than zero.
-   * @param [in] actor The actor to animate.
-   * @param [in] width The target width.
-   * @param [in] height The target height.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the translation.
+   * @copydoc Dali::Animation::Resize(Actor actor, float width, float height, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void Resize(Actor& actor, float width, float height, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
   /**
-   * Resize an actor.
-   * The default alpha function will be used.
-   * The resizing will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] size The target size.
+   * @copydoc Dali::Animation::Resize(Actor actor, Vector3 size)
    */
   void Resize(Actor& actor, const Vector3& size);
 
   /**
-   * Resize an actor. This overload allows the alpha function to be customized.
-   * The resizing will start & end when the animation begins & ends.
-   * @param [in] actor The actor to animate.
-   * @param [in] size The target size.
-   * @param [in] alpha The alpha function to apply.
+   * @copydoc Dali::Animation::Resize(Actor actor, Vector3 size, AlphaFunction alpha)
    */
   void Resize(Actor& actor, const Vector3& size, AlphaFunction alpha);
 
   /**
-   * Resize an actor. This overload allows the resizing start & end time to be customized.
-   * @pre delaySeconds must be zero or greater.
-   * @pre durationSeconds must be greater than zero.
-   * @param [in] actor The actor to animate.
-   * @param [in] size The target size.
-   * @param [in] alpha The alpha function to apply.
-   * @param [in] delaySeconds The initial delay from the start of the animation.
-   * @param [in] durationSeconds The duration of the translation.
+   * @copydoc Dali::Animation::Resize(Actor actor, Vector3 size, AlphaFunction alpha, float delaySeconds, float durationSeconds)
    */
   void Resize(Actor& actor, const Vector3& size, AlphaFunction alpha, float delaySeconds, float durationSeconds);
 
diff --git a/dali/internal/event/animation/path-impl.cpp b/dali/internal/event/animation/path-impl.cpp
new file mode 100644 (file)
index 0000000..94477f2
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ * 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/path-impl.h>
+
+namespace
+{
+/**
+ * These coefficient arise from the cubic polynomial equations for
+ * a bezier curve.
+ *
+ * A bezier curve is defined by a cubic polynomial. Given two end points p0 and p1
+ * and two control points cp0 and cp1, the bezier curve will be defined by a polynomial in the form
+ * f(x) = a3*x^3 + a2*x^2 + a1*x + a0 with this restrictions:
+ * f(0) = p0
+ * f(1) = p1
+ * f'(0) = 3*(cp0 - p0)
+ * f'(1) = 3*(p1-cp1)
+ */
+const float BezierBasisCoeff[] = {  -1.0f,  3.0f, -3.0f, 1.0f,
+                                     3.0f, -6.0f,  3.0f, 0.0f,
+                                    -3.0f,  3.0f,  0.0f, 0.0f,
+                                     1.0f,  0.0f,  0.0f, 0.0f  };
+
+const Dali::Matrix BezierBasis = Dali::Matrix( BezierBasisCoeff );
+
+struct PropertyDetails
+{
+  std::string name;           ///< The name of the property.
+  Dali::Property::Type type;  ///< The property type.
+  bool writable:1;            ///< Whether the property is writable
+  bool animatable:1;          ///< Whether the property is animatable.
+  bool constraintInput:1;     ///< Whether the property can be used as an input to a constraint.
+};
+
+const PropertyDetails DEFAULT_PROPERTY_DETAILS[] =  {{"points", Dali::Property::ARRAY, true, false, false },
+                                                     {"control-points", Dali::Property::ARRAY, true, false, false },
+                                                    };
+
+const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( PropertyDetails );
+
+}//Unnamed namespace
+
+namespace Dali
+{
+const Property::Index Path::POINTS              = 0;
+const Property::Index Path::CONTROL_POINTS      = 1;
+
+namespace Internal
+{
+
+Path* Path::New()
+{
+  return new Path();
+}
+
+Path::Path()
+:ProxyObject()
+{
+}
+
+Path::~Path()
+{
+}
+
+Path* Path::Clone(const Path& path)
+{
+  Path* clone = new Path();
+  clone->SetPoints( path.GetPoints() );
+  clone->SetControlPoints( path.GetControlPoints() );
+
+  return clone;
+}
+
+unsigned int Path::GetDefaultPropertyCount() const
+{
+  return DEFAULT_PROPERTY_COUNT;
+}
+
+void Path::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.reserve( DEFAULT_PROPERTY_COUNT );
+
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    indices.push_back( i );
+  }
+}
+
+const std::string& Path::GetDefaultPropertyName(Property::Index index) const
+{
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].name;
+  }
+  else
+  {
+    // index out of range
+    static const std::string INVALID_PROPERTY_NAME;
+    return INVALID_PROPERTY_NAME;
+  }
+}
+
+Property::Index Path::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  for( int i(0); i<DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    if ( name == DEFAULT_PROPERTY_DETAILS[i].name )
+    {
+      index = i;
+      break;
+    }
+  }
+  return index;
+}
+
+Property::Type Path::GetDefaultPropertyType(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].type;
+  }
+  else
+  {
+    // index out of range
+    return Property::NONE;
+  }
+}
+
+Property::Value Path::GetDefaultProperty( Property::Index index ) const
+{
+  Property::Value value;
+  switch ( index )
+  {
+    case Dali::Path::POINTS:
+    {
+      size_t pointCount( mPoint.Size() );
+      for( size_t i(0); i!=pointCount; ++i )
+      {
+        value.AppendItem( mPoint[i] );
+      }
+      break;
+    }
+    case Dali::Path::CONTROL_POINTS:
+    {
+      size_t controlpointCount( mControlPoint.Size() );
+      for( size_t i(0); i!=controlpointCount; ++i )
+      {
+        value.AppendItem( mControlPoint[i] );
+      }
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false && "Path::Property is out of bounds");
+      break;
+    }
+  }
+
+  return value;
+}
+
+void Path::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
+{
+  switch ( index )
+  {
+    case Dali::Path::POINTS:
+    {
+      Property::Array propertyArray;
+      propertyValue.Get(propertyArray);
+
+      size_t propertyArrayCount = propertyArray.size();
+      mPoint.Resize( propertyArrayCount );
+      for( size_t i(0); i!=propertyArrayCount; ++i )
+      {
+        propertyArray[i].Get( mPoint[i]);
+      }
+      break;
+    }
+    case Dali::Path::CONTROL_POINTS:
+    {
+      Property::Array propertyArray;
+      propertyValue.Get(propertyArray);
+
+      size_t propertyArrayCount = propertyArray.size();
+      mControlPoint.Resize( propertyArrayCount );
+      for( size_t i(0); i!=propertyArrayCount; ++i )
+      {
+        propertyArray[i].Get( mControlPoint[i]);
+      }
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false && "Path::Property is out of bounds");
+      break;
+    }
+  }
+}
+
+bool Path::IsDefaultPropertyWritable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].writable;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool Path::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].animatable;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool Path::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+void Path::AddPoint(const Vector3& point )
+{
+  mPoint.PushBack( point );
+}
+
+void Path::AddControlPoint(const Vector3& point )
+{
+  mControlPoint.PushBack( point );
+}
+
+unsigned int Path::GetNumberOfSegments() const
+{
+  return (mPoint.Size()>1)?mPoint.Size()-1:0;
+}
+
+void Path::GenerateControlPoints( float curvature )
+{
+  unsigned int numSegments = GetNumberOfSegments();
+  DALI_ASSERT_ALWAYS( numSegments > 0 && "Need at least 1 segment to generate control points" ); // need at least 1 segment
+
+  mControlPoint.Resize( numSegments * 2);
+
+  //Generate two control points for each segment
+  for( unsigned int i(0); i<numSegments; ++i )
+  {
+    //Segment end-points
+    Vector3 p1 = mPoint[i];
+    Vector3 p2 = mPoint[i+1];
+
+    Vector3 p0;
+    if( i == 0 )
+    {
+      //There's no previous point. We chose a point in the line defined by the two end points  at
+      //a 1/8th of the distance between them.
+      p0 = p1 - (p2 - p1)/8.0f;
+    }
+    else
+    {
+      //Previous point
+      p0 = mPoint[i-1];
+    }
+
+    Vector3 p3;
+    if( i == numSegments - 1)
+    {
+      //There's no next point. We chose a point in the line defined by the two end points  at
+      //a 1/8th of the distance between them.
+      p3 = p2 - (p1 - p2)/8.0f;
+    }
+    else
+    {
+      //Next point
+      p3 = mPoint[i+2];
+    }
+
+    Vector3 p0p1 = p1 - p0;
+    Vector3 p1p2 = p2 - p1;
+    Vector3 p2p3 = p3 - p2;
+
+    float length = p1p2.Length();
+
+    Vector3 tangentOut = ( p0p1*length + p1p2*p0p1.Length() ) * 0.5f;
+    tangentOut.Normalize();
+
+    Vector3 tangentIn = ( p1p2*p2p3.Length() + p2p3*length ) * 0.5f;
+    tangentIn.Normalize();
+
+    //Use curvature to scale the tangents
+    length *= curvature;
+    mControlPoint[2*i] =   p1 + tangentOut*length;
+    mControlPoint[2*i+1] = p2 - tangentIn*length;
+  }
+}
+
+void Path::FindSegmentAndProgress( float t, unsigned int& segment, float& tLocal ) const
+{
+  //Find segment and local progress
+  unsigned int numSegs = GetNumberOfSegments();
+
+  if( t <= 0.0f )
+  {
+    segment = 0;
+    tLocal = 0.0f;
+  }
+  else if( t >= 1.0f )
+  {
+    segment = numSegs-1;
+    tLocal = 1.0f;
+  }
+  else
+  {
+    segment = t * numSegs;
+    float segLength = 1.0f / numSegs;
+    float segStart  = (float)segment * segLength;
+    tLocal = (t - segStart) * numSegs;
+  }
+}
+
+void Path::Sample( float t, Vector3& position, Vector3& tangent ) const
+{
+  DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
+
+  unsigned int segment;
+  float tLocal;
+  FindSegmentAndProgress( t, segment, tLocal );
+
+  //Get points and control points in the segment
+  const Vector3& controlPoint0 = mControlPoint[2*segment];
+  const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+  const Vector3& point0 = mPoint[segment];
+  const Vector3& point1 = mPoint[segment+1];
+
+  if(tLocal < Math::MACHINE_EPSILON_1)
+  {
+    position = point0;
+    tangent = ( controlPoint0 - point0 ) * 3.0f;
+    tangent.Normalize();
+  }
+  else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
+  {
+    position = point1;
+    tangent = ( point1 - controlPoint1 ) * 3.0f;
+    tangent.Normalize();
+  }
+  else
+  {
+    const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
+    const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
+
+    //X
+    Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
+
+    Vector4 A = BezierBasis * cVect;
+    position.x = sVect.Dot4(A);
+    tangent.x  = sVectDerivative.Dot(Vector3(A));
+
+    //Y
+    cVect.x  = point0.y;
+    cVect.y  = controlPoint0.y;
+    cVect.z  = controlPoint1.y;
+    cVect.w  = point1.y;
+
+    A = BezierBasis * cVect;
+    position.y = sVect.Dot4(A);
+    tangent.y  = sVectDerivative.Dot(Vector3(A));
+
+    //Z
+    cVect.x  = point0.z;
+    cVect.y  = controlPoint0.z;
+    cVect.z  = controlPoint1.z;
+    cVect.w  = point1.z;
+
+    A = BezierBasis * cVect;
+    position.z = sVect.Dot4(A);
+    tangent.z  = sVectDerivative.Dot(Vector3(A));
+
+    tangent.Normalize();
+  }
+}
+
+Vector3 Path::SamplePosition( float t ) const
+{
+  DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
+
+  unsigned int segment;
+  float tLocal;
+  FindSegmentAndProgress( t, segment, tLocal );
+
+  const Vector3& controlPoint0 = mControlPoint[2*segment];
+  const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+  const Vector3& point0 = mPoint[segment];
+  const Vector3& point1 = mPoint[segment+1];
+
+  Vector3 position;
+  if(tLocal < Math::MACHINE_EPSILON_1)
+  {
+    position = point0;
+  }
+  else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
+  {
+    position = point1;
+  }
+  else
+  {
+    const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
+
+    //X
+    Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
+    position.x = sVect.Dot4(BezierBasis * cVect);
+
+    //Y
+    cVect.x  = point0.y;
+    cVect.y  = controlPoint0.y;
+    cVect.z  = controlPoint1.y;
+    cVect.w  = point1.y;
+    position.y = sVect.Dot4(BezierBasis * cVect);
+
+    //Z
+    cVect.x  = point0.z;
+    cVect.y  = controlPoint0.z;
+    cVect.z  = controlPoint1.z;
+    cVect.w  = point1.z;
+    position.z = sVect.Dot4(BezierBasis * cVect);
+  }
+
+  return position;
+}
+
+Vector3 Path::SampleTangent( float t ) const
+{
+  DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
+
+  unsigned int segment;
+  float tLocal;
+  FindSegmentAndProgress( t, segment, tLocal );
+
+  const Vector3& controlPoint0 = mControlPoint[2*segment];
+  const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+  const Vector3& point0 = mPoint[segment];
+  const Vector3& point1 = mPoint[segment+1];
+
+  Vector3 tangent;
+  if(tLocal < Math::MACHINE_EPSILON_1)
+  {
+    tangent = ( controlPoint0 - point0 ) * 3.0f;
+  }
+  else if( (1.0f - tLocal) < Math::MACHINE_EPSILON_1)
+  {
+    tangent = ( point1 - controlPoint1 ) * 3.0f;
+  }
+  else
+  {
+    const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
+
+    //X
+    Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
+    tangent.x  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+
+    //Y
+    cVect.x  = point0.y;
+    cVect.y  = controlPoint0.y;
+    cVect.z  = controlPoint1.y;
+    cVect.w  = point1.y;
+    tangent.y  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+
+    //Z
+    cVect.x  = point0.z;
+    cVect.y  = controlPoint0.z;
+    cVect.z  = controlPoint1.z;
+    cVect.w  = point1.z;
+    tangent.z  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+  }
+
+  tangent.Normalize();
+  return tangent;
+}
+
+Vector3& Path::GetPoint( size_t index )
+{
+  DALI_ASSERT_ALWAYS( index < mPoint.Size() && "Path: Point index out of bounds" );
+
+  return mPoint[index];
+}
+
+Vector3& Path::GetControlPoint( size_t index )
+{
+  DALI_ASSERT_ALWAYS( index < mControlPoint.Size() && "Path: Control Point index out of bounds" );
+
+  return mControlPoint[index];
+}
+
+size_t Path::GetPointCount() const
+{
+  return mPoint.Size();
+}
+
+} // Internal
+} // Dali
+
+
diff --git a/dali/internal/event/animation/path-impl.h b/dali/internal/event/animation/path-impl.h
new file mode 100644 (file)
index 0000000..5233747
--- /dev/null
@@ -0,0 +1,288 @@
+#ifndef __DALI_INTERNAL_PATH_H__
+#define __DALI_INTERNAL_PATH_H__
+
+/*
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/path.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/internal/event/common/proxy-object.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+typedef IntrusivePtr<Path> PathPtr;
+
+/**
+ * A 3D path
+ */
+class Path : public ProxyObject
+{
+public:
+
+  /**
+   * Construct a new path
+   */
+  static Path* New();
+
+  /**
+   * Constructor
+   */
+  Path();
+
+
+protected:
+  /**
+   * virtual destructor
+   */
+  virtual ~Path();
+
+private:
+  /**
+   * @copydoc Dali::Internal::ProxyObject::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectAdded(ProxyObject& proxy){}
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectRemoved(ProxyObject& proxy){}
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::Observer::ProxyDestroyed()
+   */
+  virtual void ProxyDestroyed(ProxyObject& proxy){}
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::IsSceneObjectRemovable()
+   */
+  virtual bool IsSceneObjectRemovable() const{ return false;}
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultPropertyName()
+   */
+  virtual const std::string& GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+   /**
+   * @copydoc Dali::Internal::ProxyObject::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::InstallSceneObjectProperty()
+   */
+  virtual void InstallSceneObjectProperty( SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index ){}
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const{ return NULL; }
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const{ return NULL; }
+
+  /**
+   * @copydoc Dali::Internal::ProxyObject::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const{ return NULL; }
+
+public:
+
+  /**
+   * Returns a clone to the given path
+   */
+  static Path* Clone(const Path& path);
+
+  /**
+   * @copydoc Dali::Path::AddPoint
+   */
+  void AddPoint(const Vector3& point );
+
+  /**
+   * @copydoc Dali::Path::AddControlPoint
+   */
+  void AddControlPoint(const Vector3& point );
+
+  /**
+   * @copydoc Dali::Path::GenerateControlPoints
+   */
+  void GenerateControlPoints( float curvature );
+
+  /**
+   * @copydoc Dali::Path::Sample
+   */
+  void Sample( float t, Vector3& position, Vector3& tangent ) const;
+
+  /**
+   * Sample position at point t.
+   *
+   * @param[in] progress  A floating point value between 0.0 and 1.0.
+   * @param[out] position The interpolated position at that progress.
+   */
+  Vector3 SamplePosition( float t ) const;
+
+  /**
+   * @brief Sample tangent at point t.
+   *
+   * @param[in] progress  A floating point value between 0.0 and 1.0.
+   * @param[out] tangent The interpolated tangent at that progress.
+   */
+  Vector3 SampleTangent( float t ) const;
+
+  /**
+   * @copydoc Dali::Path::GetPoint
+   */
+  Vector3& GetPoint( size_t index );
+
+  /**
+   * @copydoc Dali::Path::GetControlPoint
+   */
+  Vector3& GetControlPoint( size_t index );
+
+  /**
+   * @copydoc Dali::Path::GetPointCount
+   */
+  size_t GetPointCount() const;
+
+  /**
+   * @brief Get mPoint property
+   *
+   * @return A const reference to mPoint vector
+   */
+  const Dali::Vector<Vector3>& GetPoints() const{ return mPoint; }
+
+  /*
+   * @brief Set mPoint
+   *
+   * @param[in] p New value for mPoint property
+   */
+  void SetPoints( const Dali::Vector<Vector3>& p ){ mPoint = p; }
+
+  /**
+   * @brief Get mCotrolPoint property
+   *
+   * @return A const reference to mControlPoint vector
+   */
+  const Dali::Vector<Vector3>& GetControlPoints() const{ return mControlPoint; }
+
+  /*
+   * @brief Set mControlPoint property
+   *
+   * @param[in] p New value for mControlPoint property
+   */
+  void SetControlPoints( const Dali::Vector<Vector3>& p ){ mControlPoint = p; }
+
+private:
+
+  /**
+   * Undefined
+   */
+  Path(const Path& p);
+
+  /**
+   * Undefined
+   */
+  Path& operator=(const Path& rhs);
+
+  /**
+   * Helper function to calculate the segment and local progress in that segment
+   * given a progress
+   *
+   * @param[in] t Progress
+   * @param[out] segment Segment for t
+   * @param[out] tLocal Local progress in the segment
+   *
+   */
+  void FindSegmentAndProgress( float t, unsigned int& segment, float& tLocal ) const;
+
+  /**
+   * Helper function to calculate to number of segments in the path
+   */
+  unsigned int GetNumberOfSegments() const;
+
+  Dali::Vector<Vector3> mPoint;            ///< Interpolation points
+  Dali::Vector<Vector3> mControlPoint;     ///< Control points
+};
+
+} // Internal
+
+// Get impl of handle
+inline Internal::Path& GetImplementation(Dali::Path& path)
+{
+  DALI_ASSERT_ALWAYS( path && "Path handle is empty" );
+  Dali::RefObject& object = path.GetBaseObject();
+  return static_cast<Internal::Path&>(object);
+}
+
+inline const Internal::Path& GetImplementation(const Dali::Path& path)
+{
+  DALI_ASSERT_ALWAYS( path && "Path handle is empty" );
+  const Dali::RefObject& object = path.GetBaseObject();
+  return static_cast<const Internal::Path&>(object);
+}
+
+
+} // Dali
+
+#endif //__DALI_INTERNAL_KEY_FRAMES_H__
index 1a02614..709fabd 100644 (file)
@@ -32,6 +32,7 @@ internal_src_files = \
   $(internal_src_dir)/event/animation/animation-playlist.cpp \
   $(internal_src_dir)/event/animation/constraint-impl.cpp \
   $(internal_src_dir)/event/animation/key-frames-impl.cpp \
+  $(internal_src_dir)/event/animation/path-impl.cpp \
   $(internal_src_dir)/event/common/demangler.cpp \
   $(internal_src_dir)/event/common/notification-manager.cpp \
   $(internal_src_dir)/event/common/object-registry-impl.cpp \
index 2d324bb..13c245f 100644 (file)
@@ -24,6 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali/internal/common/owner-container.h>
 #include <dali/internal/event/animation/key-frames-impl.h>
+#include <dali/internal/event/animation/path-impl.h>
 #include <dali/internal/update/nodes/node.h>
 #include <dali/internal/update/common/property-base.h>
 #include <dali/public-api/animation/alpha-functions.h>
@@ -757,7 +758,39 @@ struct KeyFrameQuaternionFunctor
   KeyFrameQuaternionPtr mKeyFrames;
 };
 
+struct PathPositionFunctor
+{
+  PathPositionFunctor( PathPtr path )
+  : mPath(path)
+  {
+  }
+
+  Vector3 operator()(float progress, const Vector3& property)
+  {
+    return mPath->SamplePosition(progress );
+  }
+
+  PathPtr mPath;
+};
 
+struct PathRotationFunctor
+{
+  PathRotationFunctor( PathPtr path, const Vector3& forward )
+  : mPath(path),
+    mForward( forward )
+  {
+    mForward.Normalize();
+  }
+
+  Quaternion operator()(float progress, const Quaternion& property)
+  {
+    Vector3 tangent( mPath->SampleTangent(progress) );
+    return Quaternion( mForward, tangent );
+  }
+
+  PathPtr mPath;
+  Vector3 mForward;
+};
 
 
 } // namespace Internal
index 585a30f..40c1e26 100644 (file)
@@ -216,6 +216,26 @@ void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunct
 
 // Actor specific animations
 
+void Animation::Animate( Actor actor, Path path, const Vector3& forward )
+{
+  GetImplementation(*this).Animate(GetImplementation(actor), GetImplementation( path ), forward );
+}
+
+void Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha )
+{
+  GetImplementation(*this).Animate(GetImplementation(actor), GetImplementation( path ), forward, alpha );
+}
+
+void Animation::Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period )
+{
+  GetImplementation(*this).Animate(GetImplementation(actor), GetImplementation( path ), forward, period);
+}
+
+void Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
+{
+  GetImplementation(*this).Animate(GetImplementation(actor), GetImplementation( path ), forward, alpha, period );
+}
+
 void Animation::MoveBy(Actor actor, float x, float y, float z)
 {
   GetImplementation(*this).MoveBy(GetImplementation(actor), x, y, z);
index e293070..51470f1 100644 (file)
@@ -21,6 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali/public-api/animation/alpha-functions.h>
 #include <dali/public-api/animation/key-frames.h>
+#include <dali/public-api/animation/path.h>
 #include <dali/public-api/animation/time-period.h>
 #include <dali/public-api/object/any.h>
 #include <dali/public-api/object/handle.h>
@@ -461,6 +462,50 @@ public:
   // Actor-specific convenience methods
 
   /**
+   * @brief Animate an actor's position and orientation through a predefined path. The actor will rotate to orient the supplied
+   * forward vector with the path's tangent. If forward is the zero vector then no rotation will happen.
+   *
+   * @param[in] actor The actor to animate
+   * @param[in] path The path. It defines position and orientation
+   * @param[in] forward The vector (in local space coordinate system) that will be oriented with the path's tangent direction
+   */
+  void Animate( Actor actor, Path path, const Vector3& forward );
+
+  /**
+   * @brief Animate an actor's position and orientation through a predefined path. The actor will rotate to orient the supplied
+   * forward vector with the path's tangent. If forward is the zero vector then no rotation will happen.
+   *
+   * @param[in] actor The actor to animate
+   * @param[in] path The path. It defines position and orientation
+   * @param[in] forward The vector (in local space coordinate system) that will be oriented with the path's tangent direction
+   * @param [in] alpha The alpha function to apply.
+   */
+  void Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha );
+
+  /**
+   * @brief Animate an actor's position and orientation through a predefined path. The actor will rotate to orient the supplied
+   * forward vector with the path's tangent. If forward is the zero vector then no rotation will happen.
+   *
+   * @param[in] actor The actor to animate
+   * @param[in] path The path. It defines position and orientation
+   * @param[in] forward The vector (in local space coordinate system) that will be oriented with the path's tangent direction
+   * @param [in] period The effect will occur during this time period.
+   */
+  void Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period );
+
+  /**
+   * @brief Animate an actor's position and orientation through a predefined path. The actor will rotate to orient the supplied
+   * forward vector with the path's tangent. If forward is the zero vector then no rotation will happen.
+   *
+   * @param[in] actor The actor to animate
+   * @param[in] path The path. It defines position and orientation
+   * @param[in] forward The vector (in local space coordinate system) that will be oriented with the path's tangent direction
+   * @param [in] alpha The alpha function to apply.
+   * @param [in] period The effect will occur during this time period.
+   */
+  void Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period);
+
+  /**
    * @brief Move an actor relative to its position.
    *
    * The default alpha function will be used.
diff --git a/dali/public-api/animation/path.cpp b/dali/public-api/animation/path.cpp
new file mode 100644 (file)
index 0000000..e4b4240
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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/public-api/animation/path.h>
+#include <dali/internal/event/animation/path-impl.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+Path Path::New()
+{
+  Internal::Path* internal = Internal::Path::New();
+  return Path(internal);
+}
+
+Path Path::DownCast( BaseHandle handle )
+{
+  return Path( dynamic_cast<Dali::Internal::Path*>(handle.GetObjectPtr()) );
+}
+
+Path::Path()
+{
+}
+
+Path::~Path()
+{
+}
+
+Path::Path(const Path& handle)
+:Handle(handle)
+{
+}
+
+Path::Path(Internal::Path* internal)
+: Handle(internal)
+{
+}
+
+Path& Path::operator=(const Path& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void Path::AddPoint(const Vector3& point )
+{
+  GetImplementation(*this).AddPoint( point );
+}
+
+void Path::AddControlPoint(const Vector3& point )
+{
+  GetImplementation(*this).AddControlPoint( point );
+}
+
+void Path::GenerateControlPoints( float curvature )
+{
+  GetImplementation(*this).GenerateControlPoints( curvature );
+}
+
+
+void Path::Sample( float progress, Vector3& position, Vector3& tangent ) const
+{
+  GetImplementation(*this).Sample( progress, position, tangent );
+}
+
+Vector3& Path::GetPoint( size_t index )
+{
+  return GetImplementation(*this).GetPoint(index);
+}
+
+Vector3& Path::GetControlPoint( size_t index )
+{
+  return GetImplementation(*this).GetControlPoint(index);
+}
+
+size_t Path::GetPointCount() const
+{
+  return GetImplementation(*this).GetPointCount();
+}
+
+} // Dali
diff --git a/dali/public-api/animation/path.h b/dali/public-api/animation/path.h
new file mode 100644 (file)
index 0000000..dad6217
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef __DALI_PATH_H__
+#define __DALI_PATH_H__
+
+/*
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h>
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class Path;
+}
+/**
+ * @brief A 3D parametric curve
+ *
+ * Paths can be used to animate position and orientation of actors using Dali::Animate( Actor, Path, ... )
+ *
+ */
+class DALI_IMPORT_API Path : public Handle
+{
+public:
+
+  static const Property::Index POINTS;               ///< name "points",          type ARRAY of Vector3
+  static const Property::Index CONTROL_POINTS;       ///< name "control-points",  type ARRAY of Vector3
+  /**
+   * @brief Create an initialized Path handle.
+   *
+   * @return a handle to a newly allocated Dali resource.
+   */
+  static Path New();
+
+  /**
+   * @brief Downcast an Object handle to Path handle.
+   *
+   * If handle points to a KeyFrames object the downcast produces
+   * valid handle. If not the returned handle is left uninitialized.
+   * @param[in] handle to An object
+   * @return handle to a Path object or an uninitialized handle
+   */
+  static Path DownCast( BaseHandle handle );
+
+  /**
+   * @brief Create an uninitialized Path handle.
+   *
+   * This can be initialized with Path::New(). Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   */
+  Path();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~Path();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @param [in] handle A reference to the copied handle
+   */
+  Path(const Path& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  Path& operator=(const Path& rhs);
+
+  /**
+   * @brief Add an interpolation point.
+   *
+   * @param[in] point The new interpolation point to be added
+   */
+  void AddPoint(const Vector3& point );
+
+  /**
+   * @brief Add a control point.
+   *
+   * @param[in] point The new control point to be added
+   */
+  void AddControlPoint(const Vector3& point );
+
+  /**
+   * @brief Automatic generation of control points. Generated control points which result in a smooth join between the splines of each segment.
+   *
+   * The generating algorithm is as follows:
+   * For a given knot point K[N], find the vector that bisects K[N-1],[N] and [N],[N+1].
+   * Calculate the tangent vector by taking the normal of this bisector.
+   * The in control point is the length of the preceding segment back along this bisector multiplied by the curvature
+   * The out control point is the length of the succeeding segment forward along this bisector multiplied by the curvature
+   *
+   * @pre There are at least two points in the path ( one segment ).
+   *
+   * @param[in] curvature The curvature of the spline. 0 gives straight lines between the knots,
+   *                      negative values means the spline contains loops, positive values up to
+   *                      0.5 result in a smooth curve, positive values between 0.5 and 1 result
+   *                      in looped curves where the loops are not distinct (i.e. the curve appears
+   *                      to be non-continuous), positive values higher than 1 result in looped curves.
+   */
+  void GenerateControlPoints( float curvature );
+
+  /**
+   * @brief Sample path at a given progress. Calculates position and tangent at that point of the curve
+   *
+   * @param[in]  progress  A floating point value between 0.0 and 1.0.
+   * @param[out] position The interpolated position at that progress.
+   * @param[out] tangent The interpolated tangent at that progress.
+   */
+  void Sample( float progress, Vector3& position, Vector3& tangent ) const;
+
+  /**
+   * @brief Accessor for the interpolation points.
+   *
+   * @param[in] index The index of the interpolation point.
+   * @return A reference to the interpolation point.
+   */
+  Vector3& GetPoint( size_t index );
+
+  /**
+   * @brief Accessor for the control points.
+   *
+   * @param[in] index The index of the control point.
+   * @return A reference to the control point.
+   */
+  Vector3& GetControlPoint( size_t index );
+
+  /**
+   * @brief Get the number of interpolation points in the path
+   *
+   * @return The number of interpolation points in the path
+   */
+  size_t GetPointCount() const;
+
+public: // Not intended for application developers
+  /**
+   * @brief This constructor is used by Dali::New() methods.
+   *
+   * @param[in] Path A pointer to an internal path resource
+   */
+  explicit DALI_INTERNAL Path(Internal::Path* path);
+};
+
+} // namespace Dali
+
+#endif // __DALI_KEY_FRAMES_H__
index 812f52f..2408982 100644 (file)
@@ -44,6 +44,7 @@
 #include <dali/public-api/animation/constraints.h>
 #include <dali/public-api/animation/interpolator-functions.h>
 #include <dali/public-api/animation/key-frames.h>
+#include <dali/public-api/animation/path.h>
 #include <dali/public-api/animation/time-period.h>
 
 #include <dali/public-api/common/compile-time-assert.h>
index b80e6b5..1d4847c 100644 (file)
@@ -20,6 +20,7 @@ public_api_src_files = \
   $(public_api_src_dir)/animation/constraint-source.cpp \
   $(public_api_src_dir)/animation/interpolator-functions.cpp \
   $(public_api_src_dir)/animation/key-frames.cpp \
+  $(public_api_src_dir)/animation/path.cpp \
   $(public_api_src_dir)/animation/time-period.cpp \
   $(public_api_src_dir)/common/constants.cpp \
   $(public_api_src_dir)/common/dali-common.cpp \
@@ -151,6 +152,7 @@ public_api_core_animation_header_files = \
   $(public_api_src_dir)/animation/constraint-source.h \
   $(public_api_src_dir)/animation/interpolator-functions.h \
   $(public_api_src_dir)/animation/key-frames.h \
+  $(public_api_src_dir)/animation/path.h \
   $(public_api_src_dir)/animation/time-period.h
 
 public_api_core_common_header_files = \
index fb5b9ad..167f51a 100644 (file)
@@ -100,6 +100,31 @@ Quaternion::Quaternion( const Vector3& xAxis, const Vector3& yAxis, const Vector
   SetFromAxes( xAxis, yAxis, zAxis );
 }
 
+Quaternion::Quaternion( const Vector3& v0, const Vector3& v1 )
+{
+  float dot = v0.Dot(v1);
+  if( dot > 1.0f - Math::MACHINE_EPSILON_1 )
+  {
+    //Identity quaternion
+    mVector.x = mVector.y = mVector.z = 0.0f;
+    mVector.w = 1.0f;
+  }
+  else if( dot < -1.0f + Math::MACHINE_EPSILON_1)
+  {
+    //180 degree rotation across the Z axis
+    mVector.x = mVector.y = mVector.w = 0.0f;
+    mVector.z = 1.0f;
+  }
+  else
+  {
+    Vector3 w = v0.Cross(v1);
+    mVector.w = 1.0f + dot;
+    mVector.x = w.x;
+    mVector.y = w.y;
+    mVector.z = w.z;
+    Normalize();
+  }
+}
 
 Quaternion Quaternion::FromAxisAngle(const Vector4 &axis, float angle)
 {
index c2d6531..98dbb3c 100644 (file)
@@ -104,6 +104,15 @@ public:
   explicit Quaternion( const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis );
 
   /**
+   * @brief Construct quaternion which describes minimum rotation to align v0 with v1
+   * @pre v0 and v1 should be normalized
+   *
+   * @param[in] v0 First normalized vector
+   * @param[in] v1 Second normalized vector
+   */
+  explicit Quaternion( const Vector3& v0, const Vector3& v1 );
+
+  /**
    * @brief Converts an axis + angle pair rotation to a Quaternion.
    *
    * @param[in] axis