From bacd9c91a90df553245c03d475491432acf4f367 Mon Sep 17 00:00:00 2001 From: Ferran Sole Date: Tue, 17 Mar 2015 09:28:27 +0000 Subject: [PATCH] Added PathConstraint object. 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 | 216 +++++++++++++++++ .../event/animation/path-constraint-impl.cpp | 261 +++++++++++++++++++++ .../event/animation/path-constraint-impl.h | 260 ++++++++++++++++++++ dali/internal/file.list | 1 + dali/public-api/animation/path-constraint.cpp | 74 ++++++ dali/public-api/animation/path-constraint.h | 130 ++++++++++ dali/public-api/dali-core.h | 1 + dali/public-api/file.list | 2 + 8 files changed, 945 insertions(+) create mode 100644 dali/internal/event/animation/path-constraint-impl.cpp create mode 100644 dali/internal/event/animation/path-constraint-impl.h create mode 100644 dali/public-api/animation/path-constraint.cpp create mode 100644 dali/public-api/animation/path-constraint.h diff --git a/automated-tests/src/dali/utc-Dali-Path.cpp b/automated-tests/src/dali/utc-Dali-Path.cpp index 395aece..4b740fa 100644 --- a/automated-tests/src/dali/utc-Dali-Path.cpp +++ b/automated-tests/src/dali/utc-Dali-Path.cpp @@ -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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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 index 0000000..3e0a74b --- /dev/null +++ b/dali/internal/event/animation/path-constraint-impl.cpp @@ -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 + +// INTERNAL INCLUDES +#include +#include + +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( 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( target.propertyIndex, + Source(source.object, source.propertyIndex ), + PathConstraintFunctor( mPath, mRange ) ); + + constraint.SetTag( reinterpret_cast( 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( target.propertyIndex, + Source(source.object, source.propertyIndex ), + PathConstraintFunctor( mPath, mRange,forward) ); + + constraint.SetTag( reinterpret_cast( 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( 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( 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( 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 index 0000000..abebe16 --- /dev/null +++ b/dali/internal/event/animation/path-constraint-impl.h @@ -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 +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +typedef IntrusivePtr PathConstraintPtr; +typedef Dali::Vector 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(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(object); +} + +} // Dali + +#endif //__DALI_INTERNAL_KEY_FRAMES_H__ diff --git a/dali/internal/file.list b/dali/internal/file.list index f00d715..6fb8dac 100644 --- a/dali/internal/file.list +++ b/dali/internal/file.list @@ -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 index 0000000..b03b482 --- /dev/null +++ b/dali/public-api/animation/path-constraint.cpp @@ -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 + +// INTERNAL INCLUDES +#include +#include + +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(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 index 0000000..0daa5b0 --- /dev/null +++ b/dali/public-api/animation/path-constraint.h @@ -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 +#include +#include + +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__ diff --git a/dali/public-api/dali-core.h b/dali/public-api/dali-core.h index e1578bc..3d2b35e 100644 --- a/dali/public-api/dali-core.h +++ b/dali/public-api/dali-core.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include diff --git a/dali/public-api/file.list b/dali/public-api/file.list index b31bee7..e8fb24f 100644 --- a/dali/public-api/file.list +++ b/dali/public-api/file.list @@ -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 = \ -- 2.7.4