Added PathConstraint object. 42/36942/19
authorFerran Sole <ferran.sole@samsung.com>
Tue, 17 Mar 2015 09:28:27 +0000 (09:28 +0000)
committerFerran Sole <ferran.sole@samsung.com>
Tue, 24 Mar 2015 10:44:13 +0000 (10:44 +0000)
PathConstraints allows to constraint properties to a given path.
Vector3 properties will be constrained to the position of the path
and Rotation properties will be constrained to follow the tangent
of the path.

Change-Id: I1f4f8d98094f257bf1a54221d53293cf22bf7eeb

automated-tests/src/dali/utc-Dali-Path.cpp
dali/internal/event/animation/path-constraint-impl.cpp [new file with mode: 0644]
dali/internal/event/animation/path-constraint-impl.h [new file with mode: 0644]
dali/internal/file.list
dali/public-api/animation/path-constraint.cpp [new file with mode: 0644]
dali/public-api/animation/path-constraint.h [new file with mode: 0644]
dali/public-api/dali-core.h
dali/public-api/file.list

index 395aece..4b740fa 100644 (file)
@@ -271,3 +271,219 @@ 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/path-constraint-impl.cpp b/dali/internal/event/animation/path-constraint-impl.cpp
new file mode 100644 (file)
index 0000000..3e0a74b
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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>
+
+// 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, contraint its value to the position of the path
+
+    Dali::Constraint constraint = Dali::Constraint::New<Vector3>( target.propertyIndex,
+                                                                  Source(source.object, source.propertyIndex ),
+                                                                  PathConstraintFunctor( mPath, mRange ) );
+
+    constraint.SetTag( reinterpret_cast<size_t>( this ) );
+    constraint.SetRemoveAction( Dali::Constraint::Discard );
+    target.object.ApplyConstraint(constraint);
+  }
+  else if( propertyType == Dali::Property::ROTATION )
+  {
+    //If property is Rotation, constraint its value to align the forward vector to the tangent of the path
+    Dali::Constraint constraint = Dali::Constraint::New<Quaternion>( target.propertyIndex,
+                                                                     Source(source.object, source.propertyIndex ),
+                                                                     PathConstraintFunctor( mPath, mRange,forward) );
+
+    constraint.SetTag( reinterpret_cast<size_t>( this ) );
+    constraint.SetRemoveAction( Dali::Constraint::Discard );
+    target.object.ApplyConstraint(constraint);
+  }
+
+  //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
diff --git a/dali/internal/event/animation/path-constraint-impl.h b/dali/internal/event/animation/path-constraint-impl.h
new file mode 100644 (file)
index 0000000..abebe16
--- /dev/null
@@ -0,0 +1,260 @@
+#ifndef __DALI_INTERNAL_PATH_CONSTRAINT_H__
+#define __DALI_INTERNAL_PATH_CONSTRAINT_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/path-impl.h>
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/public-api/animation/path-constraint.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef IntrusivePtr<PathConstraint>  PathConstraintPtr;
+typedef Dali::Vector<Object*>         ObjectContainer;
+typedef ObjectContainer::Iterator     ObjectIter;
+
+/**
+ * @brief Constraint functor to constraint properties to paths.
+ *
+ * Vector3 properties will be constrained to the position of the path and
+ * Rotation properties will be constrained to follow the tangent of the path
+ * given a forward vector in object's local space.
+ */
+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
+   */
+
+  PathConstraintFunctor(PathPtr path, const Vector2& range ):mPath(path),mRange(range){}
+
+  /**
+   * @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] forward Vector in object space which will be aligned with the tangent of the path
+   */
+  PathConstraintFunctor(PathPtr path, const Vector2& range,const Vector3& forward ):mPath(path),mForward(forward),mRange(range){}
+
+  /**
+   * @brief Functor operator for Vector3 properties
+   *
+   * @param[in] current Current value of the property
+   * @param[in] property The input property used as the parameter for the path
+   *
+   * @return The position of the path at the given parameter.
+   */
+  Vector3 operator()(const Vector3& current,
+                     const PropertyInput& property)
+  {
+    float t = ( property.GetFloat() - mRange.x ) / (mRange.y-mRange.x);
+    Vector3 position, tangent;
+    mPath->Sample( t, position, tangent );
+    return position;
+  }
+
+  /**
+   * @brief Functor operator for Quaternion properties
+   *
+   * @param[in] current Current value of the property
+   * @param[in] property The input property used as the parameter for the path
+   *
+   * @return The rotation which will align the forward vector and the tangent of the path at the given parameter.
+   */
+  Quaternion operator()( const Quaternion& current,
+                         const PropertyInput& property)
+  {
+    float t = ( property.GetFloat() - mRange.x ) / (mRange.y-mRange.x);
+    Vector3 position, tangent;
+    mPath->Sample( t, position, tangent );
+    return Quaternion( mForward, tangent );
+  }
+
+  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
+};
+
+/**
+ * @brief A PathConstraint used to constraint properties to a path
+ */
+class PathConstraint : public Object, public Object::Observer
+{
+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.
+   */
+  static PathConstraint* New( Path& path, const Vector2& range );
+
+
+
+protected:
+  /**
+   * virtual destructor
+   */
+  virtual ~PathConstraint();
+
+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()
+   */
+  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;
+
+  /**
+   * @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
+   */
+  void Apply( Property source, Property target, const Vector3& forward );
+
+  /**
+   * @copydoc Dali::PathConstraint::Remove
+   */
+  void Remove( Dali::Handle& target );
+
+
+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();
+
+  // Undefined
+  PathConstraint(const PathConstraint&);
+
+  // Undefined
+  PathConstraint& operator=(const PathConstraint& 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
+};
+
+} // Internal
+
+// Get impl of handle
+inline Internal::PathConstraint& GetImplementation(Dali::PathConstraint& pathConstraint)
+{
+  DALI_ASSERT_ALWAYS( pathConstraint && "PathConstraint handle is empty" );
+  Dali::RefObject& object = pathConstraint.GetBaseObject();
+  return static_cast<Internal::PathConstraint&>(object);
+}
+
+inline const Internal::PathConstraint& GetImplementation(const Dali::PathConstraint& pathConstraint)
+{
+  DALI_ASSERT_ALWAYS( pathConstraint && "PathConstraint handle is empty" );
+  const Dali::RefObject& object = pathConstraint.GetBaseObject();
+  return static_cast<const Internal::PathConstraint&>(object);
+}
+
+} // Dali
+
+#endif //__DALI_INTERNAL_KEY_FRAMES_H__
index f00d715..6fb8dac 100644 (file)
@@ -31,6 +31,7 @@ internal_src_files = \
   $(internal_src_dir)/event/animation/constraint-impl.cpp \
   $(internal_src_dir)/event/animation/key-frames-impl.cpp \
   $(internal_src_dir)/event/animation/path-impl.cpp \
+  $(internal_src_dir)/event/animation/path-constraint-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/path-constraint.cpp b/dali/public-api/animation/path-constraint.cpp
new file mode 100644 (file)
index 0000000..b03b482
--- /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-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
diff --git a/dali/public-api/animation/path-constraint.h b/dali/public-api/animation/path-constraint.h
new file mode 100644 (file)
index 0000000..0daa5b0
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef __DALI_PATH_CONSTRAINT_H__
+#define __DALI_PATH_CONSTRAINT_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/public-api/animation/path.h>
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class PathConstraint;
+}
+/**
+ * @brief
+ *
+ * PathConstraint 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
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the PathConstraint class.
+   */
+  struct Property
+  {
+    enum
+    {
+      RANGE   =  DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "range" type Vector2
+    };
+  };
+
+  /**
+   * @brief Create an initialized PathConstraint handle.
+   *
+   * @return a handle to a newly allocated Dali resource.
+   */
+  static PathConstraint New( Dali::Path path, const Vector2& range );
+
+  /**
+   * @brief Downcast an Object handle to PathConstraint handle.
+   *
+   * If handle points to a PathConstraint 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
+   */
+  static PathConstraint DownCast( BaseHandle handle );
+
+  /**
+   * @brief Create an uninitialized PathConstraint handle.
+   *
+   * This can be initialized with PathConstraint::New(). Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   */
+  PathConstraint();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~PathConstraint();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @param [in] handle A reference to the copied handle
+   */
+  PathConstraint(const PathConstraint& 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
+   */
+  PathConstraint& operator=(const PathConstraint& 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)
+   */
+  void Apply( Dali::Property source, Dali::Property target, const Vector3& forward = Vector3() );
+
+  /**
+   * @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 );
+
+public: // Not intended for application developers
+  /**
+   * @brief This constructor is used by Dali::New() methods.
+   *
+   * @param[in] path A pointer to an internal path resource
+   */
+  explicit DALI_INTERNAL PathConstraint(Internal::PathConstraint* path);
+};
+
+} // namespace Dali
+
+#endif // __DALI_KEY_FRAMES_H__
index e1578bc..3d2b35e 100644 (file)
@@ -42,6 +42,7 @@
 #include <dali/public-api/animation/constraints.h>
 #include <dali/public-api/animation/key-frames.h>
 #include <dali/public-api/animation/path.h>
+#include <dali/public-api/animation/path-constraint.h>
 #include <dali/public-api/animation/time-period.h>
 
 #include <dali/public-api/common/compile-time-assert.h>
index b31bee7..e8fb24f 100644 (file)
@@ -18,6 +18,7 @@ public_api_src_files = \
   $(public_api_src_dir)/animation/constraint-source.cpp \
   $(public_api_src_dir)/animation/key-frames.cpp \
   $(public_api_src_dir)/animation/path.cpp \
+  $(public_api_src_dir)/animation/path-constraint.cpp \
   $(public_api_src_dir)/animation/time-period.cpp \
   $(public_api_src_dir)/common/constants.cpp \
   $(public_api_src_dir)/common/dali-common.cpp \
@@ -145,6 +146,7 @@ public_api_core_animation_header_files = \
   $(public_api_src_dir)/animation/constraint-source.h \
   $(public_api_src_dir)/animation/key-frames.h \
   $(public_api_src_dir)/animation/path.h \
+  $(public_api_src_dir)/animation/path-constraint.h \
   $(public_api_src_dir)/animation/time-period.h
 
 public_api_core_common_header_files = \