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
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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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__
$(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 \
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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__
#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>
$(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 \
$(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 = \