Refactoring of path constraints + LinearConstrainer 51/38051/17
authorFerran Sole <ferran.sole@samsung.com>
Thu, 9 Apr 2015 15:53:23 +0000 (16:53 +0100)
committerFerran Sole <ferran.sole@samsung.com>
Tue, 12 May 2015 15:57:01 +0000 (08:57 -0700)
- Renamed to PathConstrainer ( an object who applies constraints ).
- Added a base class (Constrainer) who is responsible for observing constrained objects
  and remove the constraints created when it is destroyed.
- Removed range property. Range is now specified in the 'apply' method.
- Added new properties "points" and "control-points" to specify the path.
- Added option to wrap source property value inside a given domain.
- Added LinearConstrainer object to constraint properties given a linear map

Change-Id: Iea89384808505881057c1d75d8e1929b14ecd3d3

19 files changed:
automated-tests/src/dali/CMakeLists.txt
automated-tests/src/dali/utc-Dali-Constrainer.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Path.cpp
dali/internal/event/animation/constrainer.cpp [new file with mode: 0644]
dali/internal/event/animation/constrainer.h [new file with mode: 0644]
dali/internal/event/animation/linear-constrainer-impl.cpp [new file with mode: 0644]
dali/internal/event/animation/linear-constrainer-impl.h [new file with mode: 0644]
dali/internal/event/animation/path-constrainer-impl.cpp [new file with mode: 0644]
dali/internal/event/animation/path-constrainer-impl.h [moved from dali/internal/event/animation/path-constraint-impl.h with 56% similarity]
dali/internal/event/animation/path-constraint-impl.cpp [deleted file]
dali/internal/event/animation/path-impl.cpp
dali/internal/file.list
dali/public-api/animation/linear-constrainer.cpp [new file with mode: 0644]
dali/public-api/animation/linear-constrainer.h [new file with mode: 0644]
dali/public-api/animation/path-constrainer.cpp [new file with mode: 0644]
dali/public-api/animation/path-constrainer.h [moved from dali/public-api/animation/path-constraint.h with 56% similarity]
dali/public-api/animation/path-constraint.cpp [deleted file]
dali/public-api/dali-core.h
dali/public-api/file.list

index 3608c93..d7a819e 100644 (file)
@@ -16,6 +16,7 @@ SET(TC_SOURCES
         utc-Dali-BaseHandle.cpp
         utc-Dali-BufferImage.cpp
         utc-Dali-CameraActor.cpp
+        utc-Dali-Constrainer.cpp
         utc-Dali-Context.cpp
         utc-Dali-ConnectionTracker.cpp
         utc-Dali-CustomActor.cpp
diff --git a/automated-tests/src/dali/utc-Dali-Constrainer.cpp b/automated-tests/src/dali/utc-Dali-Constrainer.cpp
new file mode 100644 (file)
index 0000000..8e9a47e
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * 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
+{
+
+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) );
+}
+
+static void SetupPathConstrainer( Dali::PathConstrainer& PathConstrainer)
+{
+  PathConstrainer.SetProperty( Dali::PathConstrainer::Property::FORWARD, Vector3(1.0f,0.0f,0.0f) );
+
+  Dali::Property::Array points;
+  points.resize(3);
+  points[0] = Vector3( 30.0,  80.0, 0.0);
+  points[1] = Vector3( 70.0, 120.0, 0.0);
+  points[2] = Vector3(100.0, 100.0, 0.0);
+  PathConstrainer.SetProperty( Dali::PathConstrainer::Property::POINTS, points );
+
+  points.resize(4);
+  points[0] = Vector3( 39.0,  90.0, 0.0);
+  points[1] = Vector3( 56.0, 119.0, 0.0);
+  points[2] = Vector3( 78.0, 120.0, 0.0);
+  points[3] = Vector3( 93.0, 104.0, 0.0);
+  PathConstrainer.SetProperty( Dali::PathConstrainer::Property::CONTROL_POINTS, points );
+}
+
+static void SetupLinearConstrainerUniformProgress( Dali::LinearConstrainer& linearConstrainer)
+{
+  Dali::Property::Array points;
+  points.resize(3);
+  points[0] = 0.0f;
+  points[1] = 1.0f;
+  points[2] = 0.0f;
+  linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::VALUE, points );
+}
+
+static void SetupLinearConstrainerNonUniformProgress( Dali::LinearConstrainer& linearConstrainer)
+{
+  Dali::Property::Array points;
+  points.resize(3);
+  points[0] = 0.0f;
+  points[1] = 1.0f;
+  points[2] = 0.0f;
+  linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::VALUE, points );
+
+  points[0] = 0.0f;
+  points[1] = 0.25f;
+  points[2] = 1.0f;
+  linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::PROGRESS, points );
+}
+
+} // anonymous namespace
+
+//PathConstrainer test cases
+int UtcPathConstrainerApply(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+
+  Dali::Stage::GetCurrent().Add(actor);
+
+  //Create a Path
+  Dali::Path path = Dali::Path::New();
+  SetupPath(path);
+
+  //Create a PathConstrainer
+  Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New();
+  SetupPathConstrainer( pathConstrainer );
+
+  //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 0.0f, 1.0f );
+  pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range );
+
+  //Create an animation to animate the custom property
+  float durationSeconds(1.0f);
+  Dali::Animation animation = Dali::Animation::New(durationSeconds);
+  animation.AnimateTo(Dali::Property(actor,index),1.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 20% progress */);
+
+  Vector3 position, tangent;
+  path.Sample(0.2f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 40% progress */);
+  path.Sample(0.4f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+  path.Sample(0.6f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
+  path.Sample(0.8f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 100% progress */);
+  path.Sample(1.0f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* beyond the animation duration*/);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcPathConstrainerApplyRange(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  //Create a Path
+  Dali::Path path = Dali::Path::New();
+  SetupPath(path);
+
+  //Create a PathConstrainer
+  Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New();
+  SetupPathConstrainer( pathConstrainer );
+
+  //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 100.0f, 300.0f );
+  pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range );
+
+
+  //Create an animation to animate the custom property
+  float durationSeconds(1.0f);
+  Dali::Animation animation = Dali::Animation::New(durationSeconds);
+  animation.AnimateTo(Dali::Property(actor,index),400.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+
+  Vector3 position, tangent;
+  float tValue;
+  actor.GetProperty(index).Get(tValue);
+  float currentCursor =  ( tValue - range.x ) / (range.y-range.x);
+  path.Sample(currentCursor, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  actor.GetProperty(index).Get(tValue);
+  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
+  path.Sample(currentCursor, position, tangent );
+  path.Sample(0.5, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  actor.GetProperty(index).Get(tValue);
+  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
+  path.Sample(currentCursor, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
+  actor.GetProperty(index).Get(tValue);
+  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
+  path.Sample(currentCursor, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
+  actor.GetProperty(index).Get(tValue);
+  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
+  path.Sample(currentCursor, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcPathConstrainerDestroy(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  {
+    //Create a Path
+    Dali::Path path = Dali::Path::New();
+    SetupPath(path);
+
+    //Create a PathConstrainer
+    Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New();
+    SetupPathConstrainer( pathConstrainer );
+
+    //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t"
+    Vector2 range( 0.0f, 1.0f );
+    pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range );
+
+    //Test that the constraint is correctly applied
+    actor.SetProperty(index,0.5f);
+    application.SendNotification();
+    application.Render(static_cast<unsigned int>(1.0f));
+
+    Vector3 position, tangent;
+    path.Sample(0.5f, position, tangent );
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  }
+
+  //PathConstrainer has been destroyed. Constraint in the actor should have been removed
+  actor.SetProperty(index,0.75f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcPathConstrainerRemove(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  //Create a Path
+  Dali::Path path = Dali::Path::New();
+  SetupPath(path);
+
+  //Create a PathConstrainer
+  Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New();
+  SetupPathConstrainer( pathConstrainer );
+
+  //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 0.0f, 1.0f );
+  pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range );
+
+  //Test that the constraint is correctly applied
+  actor.SetProperty(index,0.5f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  Vector3 position, tangent;
+  path.Sample(0.5f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  //Remove constraint
+  pathConstrainer.Remove( actor );
+  actor.SetProperty(index,0.75f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  END_TEST;
+}
+
+//LinearConstrainer test cases
+int UtcLinearConstrainerApply(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+
+  Dali::Stage::GetCurrent().Add(actor);
+
+
+  //Create a LinearConstrainer without specifying progress for values
+  Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New();
+  SetupLinearConstrainerUniformProgress( linearConstrainer );
+
+  //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 0.0f, 1.0f );
+  linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+  //Create an animation to animate the custom property
+  float durationSeconds(1.0f);
+  Dali::Animation animation = Dali::Animation::New(durationSeconds);
+  animation.AnimateTo(Dali::Property(actor,index),1.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  //Setup a LinearConstrainer specifying the progress for each value
+  linearConstrainer.Remove(actor);
+  SetupLinearConstrainerNonUniformProgress( linearConstrainer );
+  linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+  actor.SetProperty(index,0.0f);
+  animation.Play();
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 2.0f/3.0f, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f/3.0f, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcLinearConstrainerApplyRange(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 100.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  //Create a LinearConstrainer
+  Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New();
+  SetupLinearConstrainerUniformProgress( linearConstrainer );
+
+  //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 100.0f, 300.0f );
+  linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+
+  //Create an animation to animate the custom property
+  float durationSeconds(1.0f);
+  Dali::Animation animation = Dali::Animation::New(durationSeconds);
+  animation.AnimateTo(Dali::Property(actor,index),300.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcLinearConstrainerDestroy(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  {
+    //Create a LinearConstrainer
+    Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New();
+    SetupLinearConstrainerUniformProgress( linearConstrainer );
+
+    //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t"
+    Vector2 range( 0.0f, 1.0f );
+    linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+    //Test that the constraint is correctly applied
+    actor.SetProperty(index,0.5f);
+    application.SendNotification();
+    application.Render(static_cast<unsigned int>(1.0f));
+
+    DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  }
+
+  //LinearConstrainer has been destroyed. Constraint in the actor should have been removed
+  actor.SetProperty(index,0.75f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcLinearConstrainerRemove(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  //Create a LinearConstrainer
+  Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New();
+  SetupLinearConstrainerUniformProgress( linearConstrainer );
+
+  //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 0.0f, 1.0f );
+  linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+  //Test that the constraint is correctly applied
+  actor.SetProperty(index,0.5f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  //Remove constraint
+  linearConstrainer.Remove( actor );
+  actor.SetProperty(index,0.75f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  END_TEST;
+}
index 4b740fa..4a41766 100644 (file)
@@ -272,218 +272,3 @@ int UtcDaliPathSample01(void)
   END_TEST;
 }
 
-//PathConstraint test cases
-int UtcPathConstraintApply(void)
-{
-  TestApplication application;
-
-  Dali::Actor actor = Dali::Actor::New();
-
-  // Register a float property
-  Property::Index index = actor.RegisterProperty( "t", 0.0f );
-
-  Dali::Stage::GetCurrent().Add(actor);
-
-
-  Dali::Path path = Dali::Path::New();
-  SetupPath(path);
-
-  //Create a PathConstraint
-  Dali::PathConstraint pathConstraint = Dali::PathConstraint::New( path, Vector2(0.0f,1.0f) );
-
-  //Apply the path constraint to the actor position. The source property for the constraint will be the custom property "t"
-  pathConstraint.Apply( Property(actor, index), Property(actor,Dali::Actor::Property::POSITION) );
-
-  //Create an animation to animate the custom property
-  float durationSeconds(1.0f);
-  Dali::Animation animation = Dali::Animation::New(durationSeconds);
-  animation.AnimateTo(Dali::Property(actor,index),1.0f);
-  animation.Play();
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 20% progress */);
-
-  Vector3 position, tangent;
-  path.Sample(0.2f, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 40% progress */);
-  path.Sample(0.4f, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
-  path.Sample(0.6f, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
-  path.Sample(0.8f, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 100% progress */);
-  path.Sample(1.0f, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* beyond the animation duration*/);
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  END_TEST;
-}
-
-int UtcPathConstraintApplyRange(void)
-{
-  TestApplication application;
-
-  Dali::Actor actor = Dali::Actor::New();
-
-  // Register a float property
-  Property::Index index = actor.RegisterProperty( "t", 0.0f );
-  Dali::Stage::GetCurrent().Add(actor);
-
-
-  Dali::Path path = Dali::Path::New();
-  SetupPath(path);
-
-  //Create a PathConstraint
-  Vector2 range( 100.0f, 300.0f );
-  Dali::PathConstraint pathConstraint = Dali::PathConstraint::New( path, range );
-
-  //Apply the path constraint to the actor position. The source property for the constraint will be the custom property "t"
-  pathConstraint.Apply( Property(actor,index), Property(actor,Dali::Actor::Property::POSITION) );
-
-
-  //Create an animation to animate the custom property
-  float durationSeconds(1.0f);
-  Dali::Animation animation = Dali::Animation::New(durationSeconds);
-  animation.AnimateTo(Dali::Property(actor,index),400.0f);
-  animation.Play();
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
-
-
-  Vector3 position, tangent;
-  float tValue;
-  actor.GetProperty(index).Get(tValue);
-  float currentCursor =  ( tValue - range.x ) / (range.y-range.x);
-  path.Sample(currentCursor, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
-  actor.GetProperty(index).Get(tValue);
-  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
-  path.Sample(currentCursor, position, tangent );
-  path.Sample(0.5, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
-  actor.GetProperty(index).Get(tValue);
-  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
-  path.Sample(currentCursor, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
-  actor.GetProperty(index).Get(tValue);
-  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
-  path.Sample(currentCursor, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
-  actor.GetProperty(index).Get(tValue);
-  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
-  path.Sample(currentCursor, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  END_TEST;
-}
-
-int UtcPathConstraintDestroy(void)
-{
-  TestApplication application;
-
-  Dali::Actor actor = Dali::Actor::New();
-
-  // Register a float property
-  Property::Index index = actor.RegisterProperty( "t", 0.0f );
-  Dali::Stage::GetCurrent().Add(actor);
-
-
-  Dali::Path path = Dali::Path::New();
-  SetupPath(path);
-
-  {
-    //Create a PathConstraint
-    Vector2 range( 0.0f, 1.0f );
-    Dali::PathConstraint pathConstraint = Dali::PathConstraint::New( path, range );
-
-    //Apply the path constraint to the actor position. The source property for the constraint will be the custom property "t"
-    pathConstraint.Apply( Property(actor,index), Property(actor,Dali::Actor::Property::POSITION) );
-
-    //Test that the constraint is correctly applied
-    actor.SetProperty(index,0.5f);
-    application.SendNotification();
-    application.Render(static_cast<unsigned int>(1.0f));
-
-    Vector3 position, tangent;
-    path.Sample(0.5f, position, tangent );
-    DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  }
-
-  //PathConstraint has been destroyed. Constraint in the actor should have been removed
-  actor.SetProperty(index,0.75f);
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(1.0f));
-
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
-
-  END_TEST;
-}
-
-int UtcPathConstraintRemove(void)
-{
-  TestApplication application;
-
-  Dali::Actor actor = Dali::Actor::New();
-
-  // Register a float property
-  Property::Index index = actor.RegisterProperty( "t", 0.0f );
-  Dali::Stage::GetCurrent().Add(actor);
-
-  Dali::Path path = Dali::Path::New();
-  SetupPath(path);
-
-  //Create a PathConstraint
-  Vector2 range( 0.0f, 1.0f );
-  Dali::PathConstraint pathConstraint = Dali::PathConstraint::New( path, range );
-
-  //Apply the path constraint to the actor position. The source property for the constraint will be the custom property "t"
-  pathConstraint.Apply( Property(actor,index), Property(actor,Dali::Actor::Property::POSITION) );
-
-  //Test that the constraint is correctly applied
-  actor.SetProperty(index,0.5f);
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(1.0f));
-
-  Vector3 position, tangent;
-  path.Sample(0.5f, position, tangent );
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
-
-  //Remove constraint
-  pathConstraint.Remove( actor );
-  actor.SetProperty(index,0.75f);
-  application.SendNotification();
-  application.Render(static_cast<unsigned int>(1.0f));
-
-  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
-
-  END_TEST;
-}
diff --git a/dali/internal/event/animation/constrainer.cpp b/dali/internal/event/animation/constrainer.cpp
new file mode 100644 (file)
index 0000000..7e4f6a2
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015 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/constrainer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/constraint-source-impl.h>
+#include <dali/public-api/animation/constraint.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+Constrainer::Constrainer()
+:Object()
+{
+}
+
+Constrainer::~Constrainer()
+{
+  //Remove all the constraints created by the object
+  size_t tag = reinterpret_cast<size_t>( this );
+  const ObjectIter end = mObservedObjects.End();
+  for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
+  {
+    //Remove Constrainer from the observers list of the object
+    (*iter)->RemoveObserver( *this );
+
+    //Remove constraints
+    (*iter)->RemoveConstraints( tag );
+  }
+}
+
+void Constrainer::ObjectDestroyed( Object& object )
+{
+  //Remove object from the list of observed
+  const ObjectIter end = mObservedObjects.End();
+  for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
+  {
+    if( *iter == &object )
+    {
+      mObservedObjects.Erase(iter);
+      return;
+    }
+  }
+}
+
+void Constrainer::Remove( Dali::Handle& target )
+{
+  size_t tag = reinterpret_cast<size_t>( this );
+  Object& object = GetImplementation(target);
+  const ObjectIter end = mObservedObjects.End();
+  for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
+  {
+    if( *iter == &object )
+    {
+      //Stop observing the object
+      (*iter)->RemoveObserver( *this );
+
+      //Remove constraints created in the object
+      target.RemoveConstraints( tag );
+
+      //Remove object from the vector of observed objects
+      mObservedObjects.Erase(iter);
+    }
+  }
+}
+
+void Constrainer::Observe( Dali::Handle& handle )
+{
+  Object& object = GetImplementation(handle);
+
+  //Add the object to the list of observed objects if it is not in it already
+  const ObjectIter end = mObservedObjects.End();
+  ObjectIter iter = mObservedObjects.Begin();
+  for(; iter != end; ++iter )
+  {
+    if( *iter == &object )
+    {
+      break;
+    }
+  }
+
+  if( iter == end )
+  {
+    //Start observing the object
+    object.AddObserver( *this );
+
+    //Add object in the observed objects vector
+    mObservedObjects.PushBack( &object );
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
diff --git a/dali/internal/event/animation/constrainer.h b/dali/internal/event/animation/constrainer.h
new file mode 100644 (file)
index 0000000..3b56212
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef __DALI_INTERNAL_CONSTRAINER_H__
+#define __DALI_INTERNAL_CONSTRAINER_H__
+
+/*
+ * Copyright (c) 2015 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/internal/event/common/object-impl.h>
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef Dali::Vector<Object*>         ObjectContainer;
+typedef ObjectContainer::Iterator     ObjectIter;
+
+/**
+ * An abstract base class for constrainers.
+ * Constrainer base class is responsible or observing constrained objects and remove all the constraints created
+ * when it is destroyed
+ */
+class Constrainer : public Object, public Object::Observer
+{
+public:
+
+  /**
+   * Constructor.
+   */
+  Constrainer();
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~Constrainer();
+
+public: // Object methods
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const{return 0;}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const{}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName( Property::Index index ) const{return 0;}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex( const std::string& name ) const{return  Property::INVALID_INDEX;}
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable( Property::Index index ) const{return false;}
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable( Property::Index index ) const{return false;}
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const{return false;}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType( Property::Index index ) const{return Property::NONE;}
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ){}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const{return Property::Value();}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const{return 0;}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const{return 0;}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const{return 0;}
+
+public: // Object::Observer methods
+
+  /**
+   * @copydoc Object::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectAdded( Object& object ){}
+
+  /**
+   * @copydoc Object::Observer::SceneObjectRemoved()
+   */
+  virtual void SceneObjectRemoved( Object& object ){}
+
+  /**
+   * @copydoc Object::Observer::ObjectDestroyed()
+   */
+  virtual void ObjectDestroyed( Object& object );
+
+public:
+
+  /**
+   * @brief Applies the constraint to the target property
+
+   * @param[in] target Property to be constrained
+   * @param[in] source Property used as parameter for the path
+   * @param[in] range The range of values in the source property which will be mapped to [0,1]
+   * @param[in] wrap Wrapping domain. Source property will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
+   */
+  virtual void Apply( Property target, Property source, const Vector2& range, const Vector2& wrap) = 0;
+
+  /**
+   * @brief Removes the constraint in the target object
+   *
+   * @param[in] target A handle to an object constrained by the Constrainer
+   */
+  void Remove( Dali::Handle& target );
+
+protected:
+
+  /**
+   * @brief Adds an object to the list of observed objects
+   *
+   * @param[in] handle A handle to the object to be observed
+   */
+  void Observe( Dali::Handle& handle );
+
+private:
+
+  ObjectContainer   mObservedObjects;   ///< The list of object which have been constrained by the Constrainer
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CONSTRAINER_H__
diff --git a/dali/internal/event/animation/linear-constrainer-impl.cpp b/dali/internal/event/animation/linear-constrainer-impl.cpp
new file mode 100644 (file)
index 0000000..3a793b7
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2015 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/linear-constrainer-impl.h>
+
+//EXTRENAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/public-api/animation/constraint.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Properties
+//              Name            Type   writable animatable constraint-input  enum for index-checking
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "value",        ARRAY,     true,    false,       false,        Dali::LinearConstrainer::Property::VALUE )
+DALI_PROPERTY( "progress",     ARRAY,     true,    false,       false,        Dali::LinearConstrainer::Property::PROGRESS )
+DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
+
+} //Unnamed namespace
+
+LinearConstrainer* LinearConstrainer::New()
+{
+  return new LinearConstrainer();
+}
+
+LinearConstrainer::LinearConstrainer()
+: Constrainer()
+{
+}
+
+LinearConstrainer::~LinearConstrainer()
+{
+}
+
+unsigned int LinearConstrainer::GetDefaultPropertyCount() const
+{
+  return DEFAULT_PROPERTY_COUNT;
+}
+
+void LinearConstrainer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.reserve( DEFAULT_PROPERTY_COUNT );
+
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    indices.push_back( i );
+  }
+}
+
+const char* LinearConstrainer::GetDefaultPropertyName(Property::Index index) const
+{
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].name;
+  }
+
+  // index out of range
+  return NULL;
+}
+
+Property::Index LinearConstrainer::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+    if( 0 == strcmp( name.c_str(), property->name ) )
+    {
+      index = i;
+      break;
+    }
+  }
+  return index;
+}
+
+Property::Type LinearConstrainer::GetDefaultPropertyType(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].type;
+  }
+
+  // index out of range
+  return Property::NONE;
+}
+
+Property::Value LinearConstrainer::GetDefaultProperty( Property::Index index ) const
+{
+  Property::Value value;
+  if( index == Dali::LinearConstrainer::Property::VALUE )
+  {
+    Property::Array propertyArray;
+    value = Property::Value(propertyArray);
+    size_t count( mValue.Size() );
+    for( size_t i( 0 ); i != count; ++i )
+    {
+      value.AppendItem( mValue[i] );
+    }
+  }
+  else if( index == Dali::LinearConstrainer::Property::PROGRESS )
+  {
+    Property::Array propertyArray;
+    value = Property::Value(propertyArray);
+    size_t count( mValue.Size() );
+    for( size_t i( 0 ); i != count; ++i )
+    {
+      value.AppendItem( mProgress[i] );
+    }
+  }
+
+  return value;
+}
+
+void LinearConstrainer::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
+{
+  if( index == Dali::LinearConstrainer::Property::VALUE  )
+  {
+    Property::Array propertyArray;
+    propertyValue.Get(propertyArray);
+
+    size_t propertyArrayCount = propertyArray.size();
+    mValue.Resize( propertyArrayCount );
+    for( size_t i(0); i!=propertyArrayCount; ++i )
+    {
+      propertyArray[i].Get( mValue[i]);
+    }
+  }
+  else if( index == Dali::LinearConstrainer::Property::PROGRESS  )
+  {
+    Property::Array propertyArray;
+    propertyValue.Get(propertyArray);
+
+    size_t propertyArrayCount = propertyArray.size();
+    mProgress.Resize( propertyArrayCount );
+    for( size_t i(0); i!=propertyArrayCount; ++i )
+    {
+      propertyArray[i].Get( mProgress[i]);
+    }
+  }
+}
+
+bool LinearConstrainer::IsDefaultPropertyWritable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].writable;
+  }
+
+  return false;
+}
+
+bool LinearConstrainer::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].animatable;
+  }
+
+  return false;
+}
+
+bool LinearConstrainer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
+  }
+
+  return false;
+}
+
+void LinearConstrainer::Apply( Property target, Property source, const Vector2& range, const Vector2& wrap)
+{
+  Dali::Constraint constraint = Dali::Constraint::New<float>( target.object, target.propertyIndex, LinearConstraintFunctor( mValue, mProgress, range, wrap ) );
+  constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) );
+
+  constraint.SetTag( reinterpret_cast<size_t>( this ) );
+  constraint.SetRemoveAction( Dali::Constraint::Discard );
+  constraint.Apply();
+
+
+  //Start observing the object
+  Observe( target.object );
+}
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/event/animation/linear-constrainer-impl.h b/dali/internal/event/animation/linear-constrainer-impl.h
new file mode 100644 (file)
index 0000000..73b1706
--- /dev/null
@@ -0,0 +1,253 @@
+#ifndef __DALI_INTERNAL_LINEAR_CONSTRAINER_H__
+#define __DALI_INTERNAL_LINEAR_CONSTRAINER_H__
+
+/*
+ * Copyright (c) 2015 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/internal/event/animation/constrainer.h>
+#include <dali/public-api/animation/linear-constrainer.h>
+#include <dali/public-api/math/math-utils.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef IntrusivePtr<LinearConstrainer> LinearConstrainerPtr;
+
+/**
+ * @brief Constraint functor to constraint properties given a linear map.
+ */
+struct LinearConstraintFunctor
+{
+  /**
+   * @brief Constructor.
+   *
+   * @param[in] value The list of values for the linear map (f(x) of the linear map)
+   * @param[in] progress Progress for each of the values normalized to [0,1] ( x of the linear map)
+   * @param[in] range The range of values in the input property which will be mapped to [0,1]
+   * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
+   *
+   * @note If progress is an empty vector, the values will be assumed to be equally spaced in the x-axis
+   */
+  LinearConstraintFunctor( Dali::Vector<float>& value, Dali::Vector<float>& progress, const Vector2& range, const Vector2& wrap )
+  :mValue(value),
+   mProgress(progress),
+   mRange(range),
+   mWrap(wrap)
+  {}
+
+  /**
+   * @brief Functor operator for float properties
+   *
+   * @param[in,out] position Current value of the property
+   * @param[in]     inputs Contains the input property used as the parameter for the path
+   *
+   * @return The value of the linear map at the given parameter.
+   */
+  void operator()( float& value,
+                   const PropertyInputContainer& inputs)
+  {
+    size_t valueCount(  mValue.Size() );
+    if( valueCount == 0 )
+    {
+      //No values.
+    }
+    else if(valueCount == 1 )
+    {
+      value = mValue[0];
+    }
+    else
+    {
+      float inputWrapped = inputs[0]->GetFloat();
+      if( inputWrapped < mWrap.x || inputWrapped > mWrap.y )
+      {
+        inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y);
+      }
+
+      float t = (( inputWrapped - mRange.x ) / ( mRange.y-mRange.x ));
+
+      //Find min and max values and local t between them
+      size_t min(0);
+      size_t max(0);
+      float tLocal(0.0f);
+      if( mProgress.Size() < valueCount )
+      {
+        float step = 1.0f / (valueCount-1.0f);
+        min = static_cast<int>(t/step);
+        max = min+1;
+        if( min < 0)
+        {
+          min = 0;
+          max = 1;
+        }
+        else if( min >= valueCount-1)
+        {
+          min = max = valueCount-1;
+        }
+
+        tLocal =(t - min*step) / step;
+      }
+      else
+      {
+        while( t >= mProgress[min] && min < valueCount-1 )
+        {
+          min++;
+        }
+
+        min--;
+        max = min+1;
+
+        if( min >= valueCount-1)
+        {
+          min = max = valueCount-1;
+          tLocal = 0.0f;
+        }
+        else
+        {
+          tLocal =(t - mProgress[min]) / ( mProgress[max]-mProgress[min]);
+        }
+      }
+
+      //Linear interpolation
+      value = (mValue[max]-mValue[min])*tLocal + mValue[min];
+    }
+  }
+
+
+  Dali::Vector<float> mValue;     ///< values for the linear map
+  Dali::Vector<float> mProgress;  ///< Progress for each of the values normalized to [0,1]
+  Vector2             mRange;     ///< The range of values in the input property which will be mapped to 0..1
+  Vector2             mWrap;      ///< Wrapping domain. Input property will be wrapped in this domain before being mapped to [0,1]
+};
+
+/**
+ * @brief A LinearConstrainer used to constraint properties given a linear map
+ */
+class LinearConstrainer : public Constrainer
+{
+public:
+
+  /**
+   * Create a new LinearConstrainer
+   * @return A smart-pointer to the newly allocated LinearConstrainer.
+   */
+  static LinearConstrainer* New();
+
+protected:
+
+  /**
+   * virtual destructor
+   */
+  virtual ~LinearConstrainer();
+
+private:
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+   /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+public:
+
+  /**
+   * @copydoc Dali::PathConstrainer::Apply
+   */
+  void Apply( Property target, Property source, const Vector2& range, const Vector2& wrap );
+
+private:
+
+  //Constructor
+  LinearConstrainer();
+
+  // Undefined
+  LinearConstrainer(const LinearConstrainer&);
+
+  // Undefined
+  LinearConstrainer& operator=(const LinearConstrainer& rhs);
+
+  Dali::Vector<float> mValue;     ///< values for the linear map
+  Dali::Vector<float> mProgress;  ///< Progress for each of the values normalized to [0,1]
+};
+
+} // Internal
+
+// Get impl of handle
+inline Internal::LinearConstrainer& GetImplementation(Dali::LinearConstrainer& linearConstrainer)
+{
+  DALI_ASSERT_ALWAYS( linearConstrainer && "LinearConstrainer handle is empty" );
+  Dali::RefObject& object = linearConstrainer.GetBaseObject();
+  return static_cast<Internal::LinearConstrainer&>(object);
+}
+
+inline const Internal::LinearConstrainer& GetImplementation(const Dali::LinearConstrainer& linearConstrainer)
+{
+  DALI_ASSERT_ALWAYS( linearConstrainer && "LinearConstrainer handle is empty" );
+  const Dali::RefObject& object = linearConstrainer.GetBaseObject();
+  return static_cast<const Internal::LinearConstrainer&>(object);
+}
+
+} // Dali
+
+#endif //__DALI_INTERNAL_PATH_CONSTRAINER_H__
diff --git a/dali/internal/event/animation/path-constrainer-impl.cpp b/dali/internal/event/animation/path-constrainer-impl.cpp
new file mode 100644 (file)
index 0000000..17dea0f
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2015 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-constrainer-impl.h>
+
+//EXTRENAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/public-api/animation/constraint.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Properties
+//              Name             Type   writable animatable constraint-input  enum for index-checking
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "forward",       VECTOR3,   true,    false,       false,        Dali::PathConstrainer::Property::FORWARD )
+DALI_PROPERTY( "points",         ARRAY,    true,    false,       false,        Dali::PathConstrainer::Property::POINTS )
+DALI_PROPERTY( "control-points", ARRAY,    true,    false,       false,        Dali::PathConstrainer::Property::CONTROL_POINTS )
+DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
+
+} //Unnamed namespace
+
+PathConstrainer* PathConstrainer::New()
+{
+  return new PathConstrainer();
+}
+
+PathConstrainer::PathConstrainer()
+: Constrainer(),
+  mPath( Path::New() )
+{
+}
+
+PathConstrainer::~PathConstrainer()
+{
+}
+
+unsigned int PathConstrainer::GetDefaultPropertyCount() const
+{
+  return DEFAULT_PROPERTY_COUNT;
+}
+
+void PathConstrainer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.reserve( DEFAULT_PROPERTY_COUNT );
+
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    indices.push_back( i );
+  }
+}
+
+const char* PathConstrainer::GetDefaultPropertyName(Property::Index index) const
+{
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].name;
+  }
+
+  // index out of range
+  return NULL;
+}
+
+Property::Index PathConstrainer::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+    if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
+    {
+      index = i;
+      break;
+    }
+  }
+  return index;
+}
+
+Property::Type PathConstrainer::GetDefaultPropertyType(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].type;
+  }
+
+  // index out of range
+  return Property::NONE;
+}
+
+Property::Value PathConstrainer::GetDefaultProperty( Property::Index index ) const
+{
+  Property::Value value;
+  if( index == Dali::PathConstrainer::Property::FORWARD )
+  {
+    value = Property::Value( mForward );
+  }
+  else if( index == Dali::PathConstrainer::Property::POINTS )
+  {
+    Property::Array propertyArray;
+    value = Property::Value(propertyArray);
+    const Dali::Vector<Vector3>& point = mPath->GetPoints();
+    size_t pointCount( point.Size() );
+    for( size_t i( 0 ); i != pointCount; ++i )
+    {
+      value.AppendItem( point[i] );
+    }
+  }
+  else if( index == Dali::PathConstrainer::Property::CONTROL_POINTS )
+  {
+    Property::Array propertyArray;
+    value = Property::Value(propertyArray);
+    const Dali::Vector<Vector3>& point = mPath->GetControlPoints();
+    size_t pointCount( point.Size() );
+    for( size_t i( 0 ); i != pointCount; ++i )
+    {
+      value.AppendItem( point[i] );
+    }
+  }
+
+  return value;
+}
+
+void PathConstrainer::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
+{
+  if( index == Dali::PathConstrainer::Property::FORWARD )
+  {
+    propertyValue.Get(mForward);
+  }
+  else if( index == Dali::PathConstrainer::Property::POINTS  )
+  {
+    Property::Array propertyArray;
+    propertyValue.Get(propertyArray);
+
+    size_t propertyArrayCount = propertyArray.size();
+    Dali::Vector<Vector3> point;
+    point.Resize( propertyArrayCount );
+    for( size_t i(0); i!=propertyArrayCount; ++i )
+    {
+      propertyArray[i].Get( point[i]);
+    }
+    mPath->SetPoints( point );
+  }
+  else if( index == Dali::PathConstrainer::Property::CONTROL_POINTS )
+  {
+    Property::Array propertyArray;
+    propertyValue.Get(propertyArray);
+
+    size_t propertyArrayCount = propertyArray.size();
+    Dali::Vector<Vector3> point;
+    point.Resize( propertyArrayCount );
+    for( size_t i(0); i!=propertyArrayCount; ++i )
+    {
+      propertyArray[i].Get( point[i]);
+    }
+    mPath->SetControlPoints( point );
+  }
+}
+
+bool PathConstrainer::IsDefaultPropertyWritable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].writable;
+  }
+
+  return false;
+}
+
+bool PathConstrainer::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].animatable;
+  }
+
+  return false;
+}
+
+bool PathConstrainer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
+  }
+
+  return false;
+}
+
+void PathConstrainer::Apply( Property target, Property source, const Vector2& range, const Vector2& wrap)
+{
+  Dali::Property::Type propertyType = target.object.GetPropertyType( target.propertyIndex);
+  if( propertyType == Dali::Property::VECTOR3)
+  {
+    // If property type is Vector3, constrain its value to the position of the path
+    Dali::Constraint constraint = Dali::Constraint::New<Vector3>( target.object, target.propertyIndex, PathConstraintFunctor( mPath, range, wrap ) );
+    constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) );
+
+    constraint.SetTag( reinterpret_cast<size_t>( this ) );
+    constraint.SetRemoveAction( Dali::Constraint::Discard );
+    constraint.Apply();
+  }
+  else if( propertyType == Dali::Property::ROTATION )
+  {
+    // If property type is Rotation, constrain its value to align the forward vector to the tangent of the path
+    Dali::Constraint constraint = Dali::Constraint::New<Quaternion>( target.object, target.propertyIndex, PathConstraintFunctor( mPath, range, mForward, wrap) );
+    constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) );
+
+    constraint.SetTag( reinterpret_cast<size_t>( this ) );
+    constraint.SetRemoveAction( Dali::Constraint::Discard );
+    constraint.Apply();
+  }
+
+  //Start observing the object
+  Observe( target.object );
+}
+
+} // Internal
+
+} // Dali
@@ -1,5 +1,5 @@
-#ifndef __DALI_INTERNAL_PATH_CONSTRAINT_H__
-#define __DALI_INTERNAL_PATH_CONSTRAINT_H__
+#ifndef __DALI_INTERNAL_PATH_CONSTRAINER_H__
+#define __DALI_INTERNAL_PATH_CONSTRAINER_H__
 
 /*
  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
  */
 
 // INTERNAL INCLUDES
+#include <dali/internal/event/animation/constrainer.h>
+#include <dali/public-api/animation/path-constrainer.h>
+#include <dali/public-api/math/math-utils.h>
 #include <dali/internal/event/animation/path-impl.h>
-#include <dali/internal/event/common/object-impl.h>
-#include <dali/public-api/animation/path-constraint.h>
 
 namespace Dali
 {
@@ -29,9 +30,7 @@ namespace Dali
 namespace Internal
 {
 
-typedef IntrusivePtr<PathConstraint>  PathConstraintPtr;
-typedef Dali::Vector<Object*>         ObjectContainer;
-typedef ObjectContainer::Iterator     ObjectIter;
+typedef IntrusivePtr<PathConstrainer> PathConstrainerPtr;
 
 /**
  * @brief Constraint functor to constraint properties to paths.
@@ -46,10 +45,10 @@ struct PathConstraintFunctor
    * @brief Constructor.
    *
    * @param[in] path The path used in the constraint
-   * @param[in] range The range of values in the input property which will be mapped to 0..1
+   * @param[in] range The range of values in the input property which will be mapped to [0,1]
+   * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
    */
-
-  PathConstraintFunctor(PathPtr path, const Vector2& range ):mPath(path),mRange(range){}
+  PathConstraintFunctor(PathPtr path, const Vector2& range, const Vector2& wrap ):mPath(path),mRange(range),mWrap(wrap){}
 
   /**
    * @brief Constructor.
@@ -57,8 +56,9 @@ struct PathConstraintFunctor
    * @param[in] path The path used in the constraint
    * @param[in] range The range of values in the input property which will be mapped to 0..1
    * @param[in] forward Vector in object space which will be aligned with the tangent of the path
+   * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
    */
-  PathConstraintFunctor(PathPtr path, const Vector2& range,const Vector3& forward ):mPath(path),mForward(forward),mRange(range){}
+  PathConstraintFunctor(PathPtr path, const Vector2& range,const Vector3& forward, const Vector2& wrap ):mPath(path),mForward(forward),mRange(range),mWrap(wrap){}
 
   /**
    * @brief Functor operator for Vector3 properties
@@ -71,7 +71,14 @@ struct PathConstraintFunctor
   void operator()( Vector3& position,
                    const PropertyInputContainer& inputs)
   {
-    float t = ( inputs[0]->GetFloat() - mRange.x ) / ( mRange.y-mRange.x );
+    float inputWrapped = inputs[0]->GetFloat();
+    if( inputWrapped < mWrap.x || inputWrapped > mWrap.y )
+    {
+      inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y);
+    }
+
+    float t = ( inputWrapped - mRange.x ) / ( mRange.y-mRange.x );
+
     Vector3 tangent;
     mPath->Sample( t, position, tangent );
   }
@@ -87,7 +94,14 @@ struct PathConstraintFunctor
   void operator()( Quaternion& current,
                    const PropertyInputContainer& inputs)
   {
-    float t = ( inputs[0]->GetFloat() - mRange.x ) / (mRange.y-mRange.x);
+    float inputWrapped = inputs[0]->GetFloat();
+    if( inputWrapped < mWrap.x || inputWrapped > mWrap.y )
+    {
+      inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y);
+    }
+
+    float t = ( inputWrapped - mRange.x ) / ( mRange.y-mRange.x );
+
     Vector3 position, tangent;
     mPath->Sample( t, position, tangent );
     current = Quaternion( mForward, tangent );
@@ -96,46 +110,30 @@ struct PathConstraintFunctor
   PathPtr     mPath;      ///< The path used
   Vector3     mForward;   ///< Vector in object space which will be aligned with the tangent of the path
   Vector2     mRange;     ///< The range of values in the input property which will be mapped to 0..1
+  Vector2     mWrap;      ///< Wrapping domain. Input property will be wrapped in this domain before being mapped to [0,1]
 };
 
 /**
- * @brief A PathConstraint used to constraint properties to a path
+ * @brief A PathConstrainer used to constraint properties to a path
  */
-class PathConstraint : public Object, public Object::Observer
+class PathConstrainer : public Constrainer
 {
 public:
 
   /**
-   * Create a new PathConstraint
-   * @param[in] path The path used in the constraint
-   * @param[in] range The range of values in the input property which will be mapped to 0..1
-   * @return A smart-pointer to the newly allocated PathConstraint.
+   * Create a new PathConstrainer
+   * @return A smart-pointer to the newly allocated PathConstrainer.
    */
-  static PathConstraint* New( Path& path, const Vector2& range );
-
-
+  static PathConstrainer* New();
 
 protected:
+
   /**
    * virtual destructor
    */
-  virtual ~PathConstraint();
+  virtual ~PathConstrainer();
 
 private:
-  /**
-   * @copydoc Dali::Internal::Object::Observer::SceneObjectAdded()
-   */
-  virtual void SceneObjectAdded(Object& object){}
-
-  /**
-   * @copydoc Dali::Internal::Object::Observer::SceneObjectAdded()
-   */
-  virtual void SceneObjectRemoved(Object& object){}
-
-  /**
-   * @copydoc Dali::Internal::Object::Observer::ObjectDestroyed()
-   */
-  virtual void ObjectDestroyed(Object& object);
 
   /**
    * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
@@ -187,73 +185,45 @@ private:
    */
   virtual Property::Value GetDefaultProperty( Property::Index index ) const;
 
-  /**
-   * @copydoc Dali::Internal::Object::GetSceneObject()
-   */
-  virtual const SceneGraph::PropertyOwner* GetSceneObject() const{ return NULL; }
-
-  /**
-   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
-   */
-  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const{ return NULL; }
-
-  /**
-   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
-   */
-  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const{ return NULL; }
-
 public:
 
   /**
-   * @copydoc Dali::PathConstraint::Apply
+   * @copydoc Dali::PathConstrainer::Apply
    */
-  void Apply( Property source, Property target, const Vector3& forward );
-
-  /**
-   * @copydoc Dali::PathConstraint::Remove
-   */
-  void Remove( Dali::Handle& target );
-
+  void Apply( Property target, Property source, const Vector2& range, const Vector2& wrap );
 
 private:
-  /**
-   * Constructor
-   * @param[in] path The path used in the constraint
-   * @param[in] range The range of values in the input property which will be mapped to 0..1
-   */
-  PathConstraint( Path& path, const Vector2& range );
 
-  // Undefined
-  PathConstraint();
+  //Constructor
+  PathConstrainer();
 
   // Undefined
-  PathConstraint(const PathConstraint&);
+  PathConstrainer(const PathConstrainer&);
 
   // Undefined
-  PathConstraint& operator=(const PathConstraint& rhs);
+  PathConstrainer& operator=(const PathConstrainer& rhs);
 
-  PathPtr           mPath;              ///< The path used to constrain objects
-  ObjectContainer   mObservedObjects;   ///< The list of object which have been constrained by the PathConstraint
-  Vector2           mRange;             ///< The range of values in the input property which will be mapped to 0..1
+  PathPtr mPath;    ///< The path used in the constraints
+  Vector3 mForward; ///< Vector in object space which will be aligned with the tangent of the path
 };
 
 } // Internal
 
 // Get impl of handle
-inline Internal::PathConstraint& GetImplementation(Dali::PathConstraint& pathConstraint)
+inline Internal::PathConstrainer& GetImplementation(Dali::PathConstrainer& pathConstrainer)
 {
-  DALI_ASSERT_ALWAYS( pathConstraint && "PathConstraint handle is empty" );
-  Dali::RefObject& object = pathConstraint.GetBaseObject();
-  return static_cast<Internal::PathConstraint&>(object);
+  DALI_ASSERT_ALWAYS( pathConstrainer && "PathConstrainer handle is empty" );
+  Dali::RefObject& object = pathConstrainer.GetBaseObject();
+  return static_cast<Internal::PathConstrainer&>(object);
 }
 
-inline const Internal::PathConstraint& GetImplementation(const Dali::PathConstraint& pathConstraint)
+inline const Internal::PathConstrainer& GetImplementation(const Dali::PathConstrainer& pathConstrainer)
 {
-  DALI_ASSERT_ALWAYS( pathConstraint && "PathConstraint handle is empty" );
-  const Dali::RefObject& object = pathConstraint.GetBaseObject();
-  return static_cast<const Internal::PathConstraint&>(object);
+  DALI_ASSERT_ALWAYS( pathConstrainer && "PathConstrainer handle is empty" );
+  const Dali::RefObject& object = pathConstrainer.GetBaseObject();
+  return static_cast<const Internal::PathConstrainer&>(object);
 }
 
 } // Dali
 
-#endif //__DALI_INTERNAL_KEY_FRAMES_H__
+#endif //__DALI_INTERNAL_PATH_CONSTRAINER_H__
diff --git a/dali/internal/event/animation/path-constraint-impl.cpp b/dali/internal/event/animation/path-constraint-impl.cpp
deleted file mode 100644 (file)
index cb4c9df..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 2015 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-constraint-impl.h>
-
-// EXTERNAL INCLUDES
-#include <cstring> // for strcmp
-
-// INTERNAL INCLUDES
-#include <dali/internal/event/common/property-helper.h>
-#include <dali/public-api/animation/constraint.h>
-
-namespace Dali
-{
-
-namespace Internal
-{
-
-namespace
-{
-
-// Properties
-
-//              Name         Type   writable animatable constraint-input  enum for index-checking
-DALI_PROPERTY_TABLE_BEGIN
-DALI_PROPERTY( "range",     VECTOR2,   true,    false,        false,        Dali::PathConstraint::Property::RANGE )
-DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
-
-
-} //Unnamed namespace
-
-PathConstraint* PathConstraint::New( Path& path, const Vector2& range)
-{
-  return new PathConstraint( path, range);
-}
-
-PathConstraint::PathConstraint( Path& path, const Vector2& range)
-: Object(),
-  mPath( Path::Clone(path)),
-  mRange(range)
-{
-}
-
-PathConstraint::~PathConstraint()
-{
-  //Remove constraints created by this PathConstraint
-  size_t tag = reinterpret_cast<size_t>( this );
-  const ObjectIter end = mObservedObjects.End();
-  for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
-  {
-    //Remove PathConstraint from the observers list of the object
-    (*iter)->RemoveObserver( *this );
-
-    //Remove constraints created by this PathConstraint in the object
-    (*iter)->RemoveConstraints( tag );
-  }
-}
-
-void PathConstraint::ObjectDestroyed(Object& object)
-{
-  //Remove object from the list of observed
-  const ObjectIter end = mObservedObjects.End();
-  for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
-  {
-    if( *iter == &object )
-    {
-      mObservedObjects.Erase(iter);
-      return;
-    }
-  }
-}
-
-unsigned int PathConstraint::GetDefaultPropertyCount() const
-{
-  return DEFAULT_PROPERTY_COUNT;
-}
-
-void PathConstraint::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
-{
-  indices.reserve( DEFAULT_PROPERTY_COUNT );
-
-  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
-  {
-    indices.push_back( i );
-  }
-}
-
-const char* PathConstraint::GetDefaultPropertyName(Property::Index index) const
-{
-  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
-  {
-    return DEFAULT_PROPERTY_DETAILS[index].name;
-  }
-
-  // index out of range
-  return NULL;
-}
-
-Property::Index PathConstraint::GetDefaultPropertyIndex(const std::string& name) const
-{
-  Property::Index index = Property::INVALID_INDEX;
-
-  // Look for name in default properties
-  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
-  {
-    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
-    if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
-    {
-      index = i;
-      break;
-    }
-  }
-  return index;
-}
-
-Property::Type PathConstraint::GetDefaultPropertyType(Property::Index index) const
-{
-  if( index < DEFAULT_PROPERTY_COUNT )
-  {
-    return DEFAULT_PROPERTY_DETAILS[index].type;
-  }
-
-  // index out of range
-  return Property::NONE;
-}
-
-Property::Value PathConstraint::GetDefaultProperty( Property::Index index ) const
-{
-  if( index == Dali::PathConstraint::Property::RANGE )
-  {
-    return Property::Value( mRange );
-  }
-
-  return Property::Value();
-}
-
-void PathConstraint::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
-{
-  if( index == Dali::PathConstraint::Property::RANGE )
-  {
-    propertyValue.Get(mRange);
-  }
-}
-
-bool PathConstraint::IsDefaultPropertyWritable(Property::Index index) const
-{
-  if( index < DEFAULT_PROPERTY_COUNT )
-  {
-    return DEFAULT_PROPERTY_DETAILS[index].writable;
-  }
-
-  return false;
-}
-
-bool PathConstraint::IsDefaultPropertyAnimatable(Property::Index index) const
-{
-  if( index < DEFAULT_PROPERTY_COUNT )
-  {
-    return DEFAULT_PROPERTY_DETAILS[index].animatable;
-  }
-
-  return false;
-}
-
-bool PathConstraint::IsDefaultPropertyAConstraintInput( Property::Index index ) const
-{
-  if( index < DEFAULT_PROPERTY_COUNT )
-  {
-    return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
-  }
-
-  return false;
-}
-
-void PathConstraint::Apply( Property source, Property target, const Vector3& forward)
-{
-
-  Dali::Property::Type propertyType = target.object.GetPropertyType( target.propertyIndex);
-
-
-  if( propertyType == Dali::Property::VECTOR3)
-  {
-    // If property is Vector3, constrain its value to the position of the path
-    Dali::Constraint constraint = Dali::Constraint::New<Vector3>( target.object, target.propertyIndex, PathConstraintFunctor( mPath, mRange ) );
-    constraint.AddSource( Source(source.object, source.propertyIndex ) );
-
-    constraint.SetTag( reinterpret_cast<size_t>( this ) );
-    constraint.SetRemoveAction( Dali::Constraint::Discard );
-    constraint.Apply();
-  }
-  else if( propertyType == Dali::Property::ROTATION )
-  {
-    // If property is Rotation, constrain its value to align the forward vector to the tangent of the path
-    Dali::Constraint constraint = Dali::Constraint::New<Quaternion>( target.object, target.propertyIndex, PathConstraintFunctor( mPath, mRange,forward) );
-    constraint.AddSource( Source(source.object, source.propertyIndex ) );
-
-    constraint.SetTag( reinterpret_cast<size_t>( this ) );
-    constraint.SetRemoveAction( Dali::Constraint::Discard );
-    constraint.Apply();
-  }
-
-  //Add the object to the list of observed objects if it is not there already
-  Object& object = dynamic_cast<Object&>( GetImplementation(target.object) );
-  const ObjectIter end = mObservedObjects.End();
-  ObjectIter iter = mObservedObjects.Begin();
-  for(; iter != end; ++iter )
-  {
-    if( *iter == &object )
-    {
-      break;
-    }
-  }
-
-  if( iter == end )
-  {
-    //Start observing the object
-    object.AddObserver( *this );
-
-    //Add object in the observed objects vector
-    mObservedObjects.PushBack( &object );
-  }
-}
-
-void PathConstraint::Remove( Dali::Handle& target )
-{
-  Object& object = dynamic_cast<Object&>( GetImplementation(target) );
-  const ObjectIter end = mObservedObjects.End();
-  for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
-  {
-    if( *iter == &object )
-    {
-      //Stop observing the object
-      (*iter)->RemoveObserver( *this );
-
-      //Remove constraints created by PathConstraint in the object
-      size_t tag = reinterpret_cast<size_t>( this );
-      target.RemoveConstraints( tag );
-
-      //Remove object from the vector of observed objects
-      mObservedObjects.Erase(iter);
-    }
-  }
-}
-
-} // Internal
-} // Dali
index 4ca4c8e..b599b33 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 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.
@@ -144,6 +144,8 @@ Property::Value Path::GetDefaultProperty( Property::Index index ) const
   Property::Value value;
   if( index == Dali::Path::Property::POINTS )
   {
+    Property::Array propertyArray;
+    value = Property::Value(propertyArray);
     size_t pointCount( mPoint.Size() );
     for( size_t i( 0 ); i != pointCount; ++i )
     {
@@ -152,6 +154,8 @@ Property::Value Path::GetDefaultProperty( Property::Index index ) const
   }
   else if( index == Dali::Path::Property::CONTROL_POINTS )
   {
+    Property::Array propertyArray;
+    value = Property::Value(propertyArray);
     size_t controlpointCount( mControlPoint.Size() );
     for( size_t i( 0 ); i != controlpointCount; ++i )
     {
index 7cd159f..46f58f3 100644 (file)
@@ -24,10 +24,12 @@ internal_src_files = \
   $(internal_src_dir)/event/actors/renderable-actor-impl.cpp \
   $(internal_src_dir)/event/animation/animation-impl.cpp \
   $(internal_src_dir)/event/animation/animation-playlist.cpp \
+  $(internal_src_dir)/event/animation/constrainer.cpp \
   $(internal_src_dir)/event/animation/constraint-base.cpp \
   $(internal_src_dir)/event/animation/key-frames-impl.cpp \
+  $(internal_src_dir)/event/animation/linear-constrainer-impl.cpp \
   $(internal_src_dir)/event/animation/path-impl.cpp \
-  $(internal_src_dir)/event/animation/path-constraint-impl.cpp \
+  $(internal_src_dir)/event/animation/path-constrainer-impl.cpp \
   $(internal_src_dir)/event/common/demangler.cpp \
   $(internal_src_dir)/event/common/event-thread-services.cpp \
   $(internal_src_dir)/event/common/notification-manager.cpp \
diff --git a/dali/public-api/animation/linear-constrainer.cpp b/dali/public-api/animation/linear-constrainer.cpp
new file mode 100644 (file)
index 0000000..8d81f9e
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 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/linear-constrainer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/linear-constrainer-impl.h>
+
+
+namespace Dali
+{
+
+LinearConstrainer LinearConstrainer::New()
+{
+  Internal::LinearConstrainer* internal = Internal::LinearConstrainer::New();
+  return LinearConstrainer(internal);
+}
+
+LinearConstrainer LinearConstrainer::DownCast( BaseHandle handle )
+{
+  return LinearConstrainer( dynamic_cast<Dali::Internal::LinearConstrainer*>(handle.GetObjectPtr()) );
+}
+
+LinearConstrainer::LinearConstrainer()
+{
+}
+
+LinearConstrainer::~LinearConstrainer()
+{
+}
+
+LinearConstrainer::LinearConstrainer(const LinearConstrainer& handle)
+:Handle(handle)
+{
+}
+
+LinearConstrainer::LinearConstrainer(Internal::LinearConstrainer* internal)
+: Handle(internal)
+{
+}
+
+LinearConstrainer& LinearConstrainer::operator=(const LinearConstrainer& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void LinearConstrainer::Apply( Dali::Property target, Dali::Property source, const Vector2& range, const Vector2& wrap )
+{
+  GetImplementation(*this).Apply( target, source, range, wrap );
+}
+
+void LinearConstrainer::Remove( Dali::Handle& target )
+{
+  GetImplementation(*this).Remove( target );
+}
+
+
+} // Dali
diff --git a/dali/public-api/animation/linear-constrainer.h b/dali/public-api/animation/linear-constrainer.h
new file mode 100644 (file)
index 0000000..917a4eb
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef __DALI_LINEAR_CONSTRAINER_H__
+#define __DALI_LINEAR_CONSTRAINER_H__
+
+/*
+ * Copyright (c) 2015 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.
+ *
+ */
+
+//EXTERNAL INCLUDES
+#include <cfloat> //For FLT_MAX
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+  class LinearConstrainer;
+}
+/**
+ * @brief
+ *
+ * LinearConstrainer applies constraints to objects given a linear map.
+ * A linear map is defined by a set of value-progress pairs.
+ * Progress must be normalized between [0,1]. If no progress is defined, the values
+ * are considered to be equally spaced along the x axis.
+ */
+class DALI_IMPORT_API LinearConstrainer : public Handle
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the LinearConstrainer class.
+   */
+  struct Property
+  {
+    enum
+    {
+      VALUE     = DEFAULT_OBJECT_PROPERTY_START_INDEX,  ///< name "value" type Array of float
+      PROGRESS,                                         ///< name "progress" type Array of float
+    };
+  };
+
+  /**
+   * @brief Create an initialized LinearConstrainer handle.
+   *
+   * @return a handle to a newly allocated Dali resource.
+   */
+  static LinearConstrainer New();
+
+  /**
+   * @brief Downcast an Object handle to LinearConstrainer handle.
+   *
+   * If handle points to a LinearConstrainer object the downcast produces
+   * valid handle. If not the returned handle is left uninitialized.
+   * @param[in] handle to An object
+   * @return handle to a LinearConstrainer object or an uninitialized handle
+   */
+  static LinearConstrainer DownCast( BaseHandle handle );
+
+  /**
+   * @brief Create an uninitialized LinearConstrainer handle.
+   *
+   * This can be initialized with PathConstrainer::New(). Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   */
+  LinearConstrainer();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~LinearConstrainer();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @param [in] handle A reference to the copied handle
+   */
+  LinearConstrainer(const LinearConstrainer& 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
+   */
+  LinearConstrainer& operator=(const LinearConstrainer& rhs);
+
+  /**
+   * @brief Applies the linear constraint to the target property
+   *
+   * @param[in] target Property to be constrained
+   * @param[in] source Property used as parameter for the path
+   * @param[in] range The range of values in the source property which will be mapped to [0,1]
+   * @param[in] wrap Wrapping domain. Source property will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
+   */
+  void Apply( Dali::Property target, Dali::Property source, const Vector2& range, const Vector2& wrap = Vector2(-FLT_MAX, FLT_MAX) );
+
+  /**
+   * @brief Removes the linear constraint in the target object
+   *
+   * @param[in] target A handle to an object constrained by the LinearConstrainer
+   */
+  void Remove( Dali::Handle& target );
+
+public: // Not intended for application developers
+  /**
+   * @brief This constructor is used by Dali::New() methods.
+   *
+   * @param[in] pathConstrainer A pointer to an internal PathConstrainer resource
+   */
+  explicit DALI_INTERNAL LinearConstrainer(Internal::LinearConstrainer* pathConstrainer);
+};
+
+} // namespace Dali
+
+#endif // __DALI_LINEAR_CONSTRAINER_H__
diff --git a/dali/public-api/animation/path-constrainer.cpp b/dali/public-api/animation/path-constrainer.cpp
new file mode 100644 (file)
index 0000000..194d5da
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 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-constrainer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/path-constrainer-impl.h>
+#include <dali/internal/event/animation/path-impl.h>
+
+namespace Dali
+{
+
+PathConstrainer PathConstrainer::New()
+{
+  Internal::PathConstrainer* internal = Internal::PathConstrainer::New();
+  return PathConstrainer(internal);
+}
+
+PathConstrainer PathConstrainer::DownCast( BaseHandle handle )
+{
+  return PathConstrainer( dynamic_cast<Dali::Internal::PathConstrainer*>(handle.GetObjectPtr()) );
+}
+
+PathConstrainer::PathConstrainer()
+{
+}
+
+PathConstrainer::~PathConstrainer()
+{
+}
+
+PathConstrainer::PathConstrainer(const PathConstrainer& handle)
+:Handle(handle)
+{
+}
+
+PathConstrainer::PathConstrainer(Internal::PathConstrainer* internal)
+: Handle(internal)
+{
+}
+
+PathConstrainer& PathConstrainer::operator=(const PathConstrainer& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void PathConstrainer::Apply( Dali::Property target, Dali::Property source, const Vector2& range, const Vector2& wrap )
+{
+  GetImplementation(*this).Apply( target, source, range, wrap );
+}
+
+void PathConstrainer::Remove( Dali::Handle& target )
+{
+  GetImplementation(*this).Remove( target );
+}
+
+
+} // Dali
similarity index 56%
rename from dali/public-api/animation/path-constraint.h
rename to dali/public-api/animation/path-constrainer.h
index 0daa5b0..6790a25 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __DALI_PATH_CONSTRAINT_H__
-#define __DALI_PATH_CONSTRAINT_H__
+#ifndef __DALI_PATH_CONSTRAINER_H__
+#define __DALI_PATH_CONSTRAINER_H__
 
 /*
  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
@@ -18,6 +18,9 @@
  *
  */
 
+//EXTERNAL INCLUDES
+#include <cfloat> //For FLT_MAX
+
 // INTERNAL INCLUDES
 #include <dali/public-api/animation/path.h>
 #include <dali/public-api/object/handle.h>
@@ -28,69 +31,71 @@ namespace Dali
 
 namespace Internal DALI_INTERNAL
 {
-class PathConstraint;
+  class PathConstrainer;
 }
 /**
  * @brief
  *
- * PathConstraint applies constraints to objects to follow a path.
+ * PathConstrainer applies constraints to objects to follow a path.
  * A Vector3 property will be constrained to the position of the path and a Rotation property will be constrained to follow
  * the tangent of the path given a forward vector in object's local space.
  *
  */
-class DALI_IMPORT_API PathConstraint : public Handle
+class DALI_IMPORT_API PathConstrainer : public Handle
 {
 public:
 
   /**
-   * @brief An enumeration of properties belonging to the PathConstraint class.
+   * @brief An enumeration of properties belonging to the PathConstrainer class.
    */
   struct Property
   {
     enum
     {
-      RANGE   =  DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "range" type Vector2
+      FORWARD   =  DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "forward" type Vector3
+      POINTS,                                           ///< name "points" type Array of Vector3
+      CONTROL_POINTS                                    ///< name "control-points" type Array of Vector3
     };
   };
 
   /**
-   * @brief Create an initialized PathConstraint handle.
+   * @brief Create an initialized PathConstrainer handle.
    *
    * @return a handle to a newly allocated Dali resource.
    */
-  static PathConstraint New( Dali::Path path, const Vector2& range );
+  static PathConstrainer New();
 
   /**
-   * @brief Downcast an Object handle to PathConstraint handle.
+   * @brief Downcast an Object handle to PathConstrainer handle.
    *
-   * If handle points to a PathConstraint object the downcast produces
+   * If handle points to a PathConstrainer object the downcast produces
    * valid handle. If not the returned handle is left uninitialized.
    * @param[in] handle to An object
-   * @return handle to a PathConstraint object or an uninitialized handle
+   * @return handle to a PathConstrainer object or an uninitialized handle
    */
-  static PathConstraint DownCast( BaseHandle handle );
+  static PathConstrainer DownCast( BaseHandle handle );
 
   /**
-   * @brief Create an uninitialized PathConstraint handle.
+   * @brief Create an uninitialized PathConstrainer handle.
    *
-   * This can be initialized with PathConstraint::New(). Calling member
+   * This can be initialized with PathConstrainer::New(). Calling member
    * functions with an uninitialized Dali::Object is not allowed.
    */
-  PathConstraint();
+  PathConstrainer();
 
   /**
    * @brief Destructor
    *
    * This is non-virtual since derived Handle types must not contain data or virtual methods.
    */
-  ~PathConstraint();
+  ~PathConstrainer();
 
   /**
    * @brief This copy constructor is required for (smart) pointer semantics.
    *
    * @param [in] handle A reference to the copied handle
    */
-  PathConstraint(const PathConstraint& handle);
+  PathConstrainer(const PathConstrainer& handle);
 
   /**
    * @brief This assignment operator is required for (smart) pointer semantics.
@@ -98,33 +103,34 @@ public:
    * @param [in] rhs  A reference to the copied handle
    * @return A reference to this
    */
-  PathConstraint& operator=(const PathConstraint& rhs);
+  PathConstrainer& operator=(const PathConstrainer& rhs);
 
   /**
    * @brief Applies the path constraint to the target property
    *
-   * @param[in] source Property used as parameter for the path
    * @param[in] target Property to be constrained
-   * @param[in] forward Vector in object's local space which will be aligned to the tangent of the path (only needed for Rotation properties)
+   * @param[in] source Property used as parameter for the path
+   * @param[in] range The range of values in the source property which will be mapped to [0,1]
+   * @param[in] wrap Wrapping domain. Source property will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
    */
-  void Apply( Dali::Property source, Dali::Property target, const Vector3& forward = Vector3() );
+  void Apply( Dali::Property target, Dali::Property source, const Vector2& range, const Vector2& wrap = Vector2(-FLT_MAX, FLT_MAX) );
 
   /**
    * @brief Removes the path constraint in the target object
    *
-   * @param[in] target A handle to an object constrained by the PathConstraint
-  */
-  void Remove( Dali::Handle target );
+   * @param[in] target A handle to an object constrained by the PathConstrainer
+   */
+  void Remove( Dali::Handle& target );
 
 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
+   * @param[in] pathConstrainer A pointer to an internal PathConstrainer resource
    */
-  explicit DALI_INTERNAL PathConstraint(Internal::PathConstraint* path);
+  explicit DALI_INTERNAL PathConstrainer(Internal::PathConstrainer* pathConstrainer);
 };
 
 } // namespace Dali
 
-#endif // __DALI_KEY_FRAMES_H__
+#endif // __DALI_PATH_CONSTRAINER_H__
diff --git a/dali/public-api/animation/path-constraint.cpp b/dali/public-api/animation/path-constraint.cpp
deleted file mode 100644 (file)
index b03b482..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2015 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-constraint.h>
-
-// INTERNAL INCLUDES
-#include <dali/internal/event/animation/path-constraint-impl.h>
-#include <dali/internal/event/animation/path-impl.h>
-
-namespace Dali
-{
-
-PathConstraint PathConstraint::New( Dali::Path path, const Vector2& range )
-{
-  Internal::PathConstraint* internal = Internal::PathConstraint::New(GetImplementation(path), range);
-  return PathConstraint(internal);
-}
-
-PathConstraint PathConstraint::DownCast( BaseHandle handle )
-{
-  return PathConstraint( dynamic_cast<Dali::Internal::PathConstraint*>(handle.GetObjectPtr()) );
-}
-
-PathConstraint::PathConstraint()
-{
-}
-
-PathConstraint::~PathConstraint()
-{
-}
-
-PathConstraint::PathConstraint(const PathConstraint& handle)
-:Handle(handle)
-{
-}
-
-PathConstraint::PathConstraint(Internal::PathConstraint* internal)
-: Handle(internal)
-{
-}
-
-PathConstraint& PathConstraint::operator=(const PathConstraint& rhs)
-{
-  BaseHandle::operator=(rhs);
-  return *this;
-}
-
-void PathConstraint::Apply( Dali::Property source, Dali::Property target, const Vector3& forward )
-{
-  GetImplementation(*this).Apply( source, target, forward );
-}
-
-void PathConstraint::Remove( Dali::Handle target )
-{
-  GetImplementation(*this).Remove( target );
-}
-
-
-} // Dali
index ebcd2f5..3e1bcde 100644 (file)
@@ -37,8 +37,9 @@
 #include <dali/public-api/animation/constraint.h>
 #include <dali/public-api/animation/constraints.h>
 #include <dali/public-api/animation/key-frames.h>
+#include <dali/public-api/animation/linear-constrainer.h>
 #include <dali/public-api/animation/path.h>
-#include <dali/public-api/animation/path-constraint.h>
+#include <dali/public-api/animation/path-constrainer.h>
 #include <dali/public-api/animation/time-period.h>
 
 #include <dali/public-api/common/compile-time-assert.h>
index ee482d5..c4b4359 100644 (file)
@@ -15,8 +15,9 @@ public_api_src_files = \
   $(public_api_src_dir)/animation/constraint.cpp \
   $(public_api_src_dir)/animation/constraint-source.cpp \
   $(public_api_src_dir)/animation/key-frames.cpp \
+  $(public_api_src_dir)/animation/linear-constrainer.cpp \
   $(public_api_src_dir)/animation/path.cpp \
-  $(public_api_src_dir)/animation/path-constraint.cpp \
+  $(public_api_src_dir)/animation/path-constrainer.cpp \
   $(public_api_src_dir)/animation/time-period.cpp \
   $(public_api_src_dir)/common/constants.cpp \
   $(public_api_src_dir)/common/dali-common.cpp \
@@ -128,8 +129,9 @@ public_api_core_animation_header_files = \
   $(public_api_src_dir)/animation/constraints.h \
   $(public_api_src_dir)/animation/constraint-source.h \
   $(public_api_src_dir)/animation/key-frames.h \
+  $(public_api_src_dir)/animation/linear-constrainer.h \
   $(public_api_src_dir)/animation/path.h \
-  $(public_api_src_dir)/animation/path-constraint.h \
+  $(public_api_src_dir)/animation/path-constrainer.h \
   $(public_api_src_dir)/animation/time-period.h
 
 public_api_core_common_header_files = \