/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
// CLASS HEADER
#include <dali/internal/event/animation/path-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-array.h>
+#include <dali/public-api/object/type-registry.h>
#include <dali/internal/event/common/property-helper.h>
namespace Dali
// Name Type writable animatable constraint-input enum for index-checking
DALI_PROPERTY_TABLE_BEGIN
-DALI_PROPERTY( "points", ARRAY, true, false, false, Dali::Path::Property::Points )
-DALI_PROPERTY( "control-points", ARRAY, true, false, false, Dali::Path::Property::ControlPoints )
-DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX )
+DALI_PROPERTY( "points", ARRAY, true, false, false, Dali::Path::Property::POINTS )
+DALI_PROPERTY( "controlPoints", ARRAY, true, false, false, Dali::Path::Property::CONTROL_POINTS )
+DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX, PathDefaultProperties )
/**
* These coefficient arise from the cubic polynomial equations for
const Dali::Matrix BezierBasis = Dali::Matrix( BezierBasisCoeff );
+Dali::BaseHandle Create()
+{
+ return Dali::Path::New();
+}
+
+TypeRegistration mType( typeid(Dali::Path), typeid(Dali::Handle), Create, PathDefaultProperties );
+
+inline bool PathIsComplete(const Dali::Vector<Vector3>& point, const Dali::Vector<Vector3>& controlPoint)
+{
+ return ( point.Size() > 1 && controlPoint.Size() == (point.Size()-1)*2 );
+}
+
} //Unnamed namespace
Path* Path::New()
}
Path::Path()
-: Object()
+: Object( nullptr ) // we don't have our own scene object
{
}
-Path::~Path()
-{
-}
+Path::~Path() = default;
Path* Path::Clone(const Path& path)
{
return clone;
}
-unsigned int Path::GetDefaultPropertyCount() const
-{
- return DEFAULT_PROPERTY_COUNT;
-}
-
-void Path::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
-{
- indices.reserve( DEFAULT_PROPERTY_COUNT );
-
- for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
- {
- indices.push_back( i );
- }
-}
-
-const char* Path::GetDefaultPropertyName(Property::Index index) const
+Property::Value Path::GetDefaultProperty( Property::Index index ) const
{
- if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+ if( index == Dali::Path::Property::POINTS )
{
- return DEFAULT_PROPERTY_DETAILS[index].name;
- }
-
- // index out of range
- return NULL;
-}
+ Property::Value value( Property::ARRAY );
+ Property::Array* array = value.GetArray();
+ Property::Array::SizeType pointCount = mPoint.Count();
-Property::Index Path::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
+ if( array )
{
- index = i;
- break;
+ array->Reserve( pointCount );
+ for( Property::Array::SizeType i = 0; i < pointCount; ++i )
+ {
+ array->PushBack( mPoint[i] );
+ }
}
+ return value;
}
- return index;
-}
-
-Property::Type Path::GetDefaultPropertyType(Property::Index index) const
-{
- if( index < DEFAULT_PROPERTY_COUNT )
+ else if( index == Dali::Path::Property::CONTROL_POINTS )
{
- return DEFAULT_PROPERTY_DETAILS[index].type;
- }
+ Property::Value value( Property::ARRAY );
+ Property::Array* array = value.GetArray();
+ Property::Array::SizeType controlpointCount = mControlPoint.Count();
- // index out of range
- return Property::NONE;
-}
-
-Property::Value Path::GetDefaultProperty( Property::Index index ) const
-{
- Property::Value value;
- if( index == Dali::Path::Property::Points )
- {
- size_t pointCount( mPoint.Size() );
- for( size_t i( 0 ); i != pointCount; ++i )
- {
- value.AppendItem( mPoint[i] );
- }
- }
- else if( index == Dali::Path::Property::ControlPoints )
- {
- size_t controlpointCount( mControlPoint.Size() );
- for( size_t i( 0 ); i != controlpointCount; ++i )
+ if( array )
{
- value.AppendItem( mControlPoint[i] );
+ array->Reserve( controlpointCount );
+ for( Property::Array::SizeType i = 0; i < controlpointCount; ++i )
+ {
+ array->PushBack( mControlPoint[i] );
+ }
}
+ return value;
}
- return value;
+ return Property::Value();
}
void Path::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
{
- if( index == Dali::Path::Property::Points )
+ const Property::Array* array = propertyValue.GetArray();
+ if( array )
{
- Property::Array propertyArray;
- propertyValue.Get(propertyArray);
-
- size_t propertyArrayCount = propertyArray.size();
- mPoint.Resize( propertyArrayCount );
- for( size_t i(0); i!=propertyArrayCount; ++i )
+ Property::Array::SizeType propertyArrayCount = array->Count();
+ if( index == Dali::Path::Property::POINTS )
{
- propertyArray[i].Get( mPoint[i]);
+ mPoint.Reserve( propertyArrayCount );
+ for( Property::Array::SizeType i = 0; i < propertyArrayCount; ++i )
+ {
+ Vector3 point;
+ array->GetElementAt( i ).Get( point );
+ mPoint.PushBack( point );
+ }
}
- }
- else if( index == Dali::Path::Property::ControlPoints )
- {
- Property::Array propertyArray;
- propertyValue.Get(propertyArray);
-
- size_t propertyArrayCount = propertyArray.size();
- mControlPoint.Resize( propertyArrayCount );
- for( size_t i(0); i!=propertyArrayCount; ++i )
+ else if( index == Dali::Path::Property::CONTROL_POINTS )
{
- propertyArray[i].Get( mControlPoint[i]);
+ mControlPoint.Reserve( propertyArrayCount );
+ for( Property::Array::SizeType i = 0; i < propertyArrayCount; ++i )
+ {
+ Vector3 point;
+ array->GetElementAt( i ).Get( point );
+ mControlPoint.PushBack( point );
+ }
}
}
}
-bool Path::IsDefaultPropertyWritable(Property::Index index) const
-{
- if( index < DEFAULT_PROPERTY_COUNT )
- {
- return DEFAULT_PROPERTY_DETAILS[index].writable;
- }
-
- return false;
-}
-
-bool Path::IsDefaultPropertyAnimatable(Property::Index index) const
-{
- if( index < DEFAULT_PROPERTY_COUNT )
- {
- return DEFAULT_PROPERTY_DETAILS[index].animatable;
- }
-
- return false;
-}
-
-bool Path::IsDefaultPropertyAConstraintInput( Property::Index index ) const
-{
- if( index < DEFAULT_PROPERTY_COUNT )
- {
- return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
- }
-
- return false;
-}
-
void Path::AddPoint(const Vector3& point )
{
mPoint.PushBack( point );
mControlPoint.PushBack( point );
}
-unsigned int Path::GetNumberOfSegments() const
+uint32_t Path::GetNumberOfSegments() const
{
- return (mPoint.Size()>1)?mPoint.Size()-1:0;
+ return static_cast<uint32_t>( (mPoint.Size()>1) ? mPoint.Size()-1 : 0 );
}
void Path::GenerateControlPoints( float curvature )
{
- unsigned int numSegments = GetNumberOfSegments();
+ uint32_t numSegments = GetNumberOfSegments();
DALI_ASSERT_ALWAYS( numSegments > 0 && "Need at least 1 segment to generate control points" ); // need at least 1 segment
mControlPoint.Resize( numSegments * 2);
//Generate two control points for each segment
- for( unsigned int i(0); i<numSegments; ++i )
+ for( uint32_t i(0); i<numSegments; ++i )
{
//Segment end-points
Vector3 p1 = mPoint[i];
}
}
-void Path::FindSegmentAndProgress( float t, unsigned int& segment, float& tLocal ) const
+void Path::FindSegmentAndProgress( float t, uint32_t& segment, float& tLocal ) const
{
//Find segment and local progress
- unsigned int numSegs = GetNumberOfSegments();
+ uint32_t numSegs = GetNumberOfSegments();
- if( t <= 0.0f )
+ if( t <= 0.0f || numSegs == 0 )
{
segment = 0;
tLocal = 0.0f;
}
else
{
- segment = t * numSegs;
- float segLength = 1.0f / numSegs;
- float segStart = (float)segment * segLength;
- tLocal = (t - segStart) * numSegs;
+ segment = static_cast<uint32_t>( t * static_cast<float>( numSegs ) );
+ float segLength = 1.0f / static_cast<float>( numSegs );
+ float segStart = static_cast<float>( segment ) * segLength;
+ tLocal = (t - segStart) * static_cast<float>( numSegs );
}
}
void Path::Sample( float t, Vector3& position, Vector3& tangent ) const
{
- DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
-
- unsigned int segment;
- float tLocal;
- FindSegmentAndProgress( t, segment, tLocal );
-
- //Get points and control points in the segment
- const Vector3& controlPoint0 = mControlPoint[2*segment];
- const Vector3& controlPoint1 = mControlPoint[2*segment+1];
- const Vector3& point0 = mPoint[segment];
- const Vector3& point1 = mPoint[segment+1];
-
- if(tLocal < Math::MACHINE_EPSILON_1)
- {
- position = point0;
- tangent = ( controlPoint0 - point0 ) * 3.0f;
- tangent.Normalize();
- }
- else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
+ if( !SampleAt(t, position, tangent) )
{
- position = point1;
- tangent = ( point1 - controlPoint1 ) * 3.0f;
- tangent.Normalize();
+ DALI_ASSERT_ALWAYS(!"Spline not fully initialized" );
}
- else
+}
+
+bool Path::SampleAt( float t, Vector3& position, Vector3& tangent ) const
+{
+ bool done = false;
+
+ if( PathIsComplete(mPoint, mControlPoint) )
{
- const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
- const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
+ uint32_t segment;
+ float tLocal;
+ FindSegmentAndProgress( t, segment, tLocal );
- //X
- Vector4 cVect( point0.x, controlPoint0.x, controlPoint1.x, point1.x);
+ //Get points and control points in the segment
+ const Vector3& controlPoint0 = mControlPoint[2*segment];
+ const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+ const Vector3& point0 = mPoint[segment];
+ const Vector3& point1 = mPoint[segment+1];
- Vector4 A = BezierBasis * cVect;
- position.x = sVect.Dot4(A);
- tangent.x = sVectDerivative.Dot(Vector3(A));
+ if(tLocal < Math::MACHINE_EPSILON_1)
+ {
+ position = point0;
+ tangent = ( controlPoint0 - point0 ) * 3.0f;
+ tangent.Normalize();
+ }
+ else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
+ {
+ position = point1;
+ tangent = ( point1 - controlPoint1 ) * 3.0f;
+ tangent.Normalize();
+ }
+ else
+ {
+ const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
+ const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
- //Y
- cVect.x = point0.y;
- cVect.y = controlPoint0.y;
- cVect.z = controlPoint1.y;
- cVect.w = point1.y;
+ //X
+ Vector4 cVect( point0.x, controlPoint0.x, controlPoint1.x, point1.x);
- A = BezierBasis * cVect;
- position.y = sVect.Dot4(A);
- tangent.y = sVectDerivative.Dot(Vector3(A));
+ Vector4 A = BezierBasis * cVect;
+ position.x = sVect.Dot4(A);
+ tangent.x = sVectDerivative.Dot(Vector3(A));
- //Z
- cVect.x = point0.z;
- cVect.y = controlPoint0.z;
- cVect.z = controlPoint1.z;
- cVect.w = point1.z;
+ //Y
+ cVect.x = point0.y;
+ cVect.y = controlPoint0.y;
+ cVect.z = controlPoint1.y;
+ cVect.w = point1.y;
- A = BezierBasis * cVect;
- position.z = sVect.Dot4(A);
- tangent.z = sVectDerivative.Dot(Vector3(A));
+ A = BezierBasis * cVect;
+ position.y = sVect.Dot4(A);
+ tangent.y = sVectDerivative.Dot(Vector3(A));
- tangent.Normalize();
+ //Z
+ cVect.x = point0.z;
+ cVect.y = controlPoint0.z;
+ cVect.z = controlPoint1.z;
+ cVect.w = point1.z;
+
+ A = BezierBasis * cVect;
+ position.z = sVect.Dot4(A);
+ tangent.z = sVectDerivative.Dot(Vector3(A));
+
+ tangent.Normalize();
+ }
+
+ done = true;
}
+
+ return done;
}
-Vector3 Path::SamplePosition( float t ) const
+bool Path::SamplePosition( float t, Vector3& position ) const
{
- DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
+ bool done = false;
- unsigned int segment;
- float tLocal;
- FindSegmentAndProgress( t, segment, tLocal );
+ if( PathIsComplete(mPoint, mControlPoint) )
+ {
+ uint32_t segment;
+ float tLocal;
+ FindSegmentAndProgress( t, segment, tLocal );
- const Vector3& controlPoint0 = mControlPoint[2*segment];
- const Vector3& controlPoint1 = mControlPoint[2*segment+1];
- const Vector3& point0 = mPoint[segment];
- const Vector3& point1 = mPoint[segment+1];
+ const Vector3& controlPoint0 = mControlPoint[2*segment];
+ const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+ const Vector3& point0 = mPoint[segment];
+ const Vector3& point1 = mPoint[segment+1];
- Vector3 position;
- if(tLocal < Math::MACHINE_EPSILON_1)
- {
- position = point0;
- }
- else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
- {
- position = point1;
- }
- else
- {
- const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
-
- //X
- Vector4 cVect( point0.x, controlPoint0.x, controlPoint1.x, point1.x);
- position.x = sVect.Dot4(BezierBasis * cVect);
-
- //Y
- cVect.x = point0.y;
- cVect.y = controlPoint0.y;
- cVect.z = controlPoint1.y;
- cVect.w = point1.y;
- position.y = sVect.Dot4(BezierBasis * cVect);
-
- //Z
- cVect.x = point0.z;
- cVect.y = controlPoint0.z;
- cVect.z = controlPoint1.z;
- cVect.w = point1.z;
- position.z = sVect.Dot4(BezierBasis * cVect);
+ if(tLocal < Math::MACHINE_EPSILON_1)
+ {
+ position = point0;
+ }
+ else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
+ {
+ position = point1;
+ }
+ else
+ {
+ const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
+
+ //X
+ Vector4 cVect( point0.x, controlPoint0.x, controlPoint1.x, point1.x);
+ position.x = sVect.Dot4(BezierBasis * cVect);
+
+ //Y
+ cVect.x = point0.y;
+ cVect.y = controlPoint0.y;
+ cVect.z = controlPoint1.y;
+ cVect.w = point1.y;
+ position.y = sVect.Dot4(BezierBasis * cVect);
+
+ //Z
+ cVect.x = point0.z;
+ cVect.y = controlPoint0.z;
+ cVect.z = controlPoint1.z;
+ cVect.w = point1.z;
+ position.z = sVect.Dot4(BezierBasis * cVect);
+ }
+
+ done = true;
}
- return position;
+ return done;
}
-Vector3 Path::SampleTangent( float t ) const
+bool Path::SampleTangent( float t, Vector3& tangent ) const
{
- DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
+ bool done = false;
- unsigned int segment;
- float tLocal;
- FindSegmentAndProgress( t, segment, tLocal );
+ if( PathIsComplete(mPoint, mControlPoint) )
+ {
+ uint32_t segment;
+ float tLocal;
+ FindSegmentAndProgress( t, segment, tLocal );
- const Vector3& controlPoint0 = mControlPoint[2*segment];
- const Vector3& controlPoint1 = mControlPoint[2*segment+1];
- const Vector3& point0 = mPoint[segment];
- const Vector3& point1 = mPoint[segment+1];
+ const Vector3& controlPoint0 = mControlPoint[2*segment];
+ const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+ const Vector3& point0 = mPoint[segment];
+ const Vector3& point1 = mPoint[segment+1];
- Vector3 tangent;
- if(tLocal < Math::MACHINE_EPSILON_1)
- {
- tangent = ( controlPoint0 - point0 ) * 3.0f;
- }
- else if( (1.0f - tLocal) < Math::MACHINE_EPSILON_1)
- {
- tangent = ( point1 - controlPoint1 ) * 3.0f;
- }
- else
- {
- const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
-
- //X
- Vector4 cVect( point0.x, controlPoint0.x, controlPoint1.x, point1.x);
- tangent.x = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
-
- //Y
- cVect.x = point0.y;
- cVect.y = controlPoint0.y;
- cVect.z = controlPoint1.y;
- cVect.w = point1.y;
- tangent.y = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
-
- //Z
- cVect.x = point0.z;
- cVect.y = controlPoint0.z;
- cVect.z = controlPoint1.z;
- cVect.w = point1.z;
- tangent.z = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+ if(tLocal < Math::MACHINE_EPSILON_1)
+ {
+ tangent = ( controlPoint0 - point0 ) * 3.0f;
+ }
+ else if( (1.0f - tLocal) < Math::MACHINE_EPSILON_1)
+ {
+ tangent = ( point1 - controlPoint1 ) * 3.0f;
+ }
+ else
+ {
+ const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
+
+ //X
+ Vector4 cVect( point0.x, controlPoint0.x, controlPoint1.x, point1.x);
+ tangent.x = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+
+ //Y
+ cVect.x = point0.y;
+ cVect.y = controlPoint0.y;
+ cVect.z = controlPoint1.y;
+ cVect.w = point1.y;
+ tangent.y = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+
+ //Z
+ cVect.x = point0.z;
+ cVect.y = controlPoint0.z;
+ cVect.z = controlPoint1.z;
+ cVect.w = point1.z;
+ tangent.z = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+ }
+
+ tangent.Normalize();
+ done = true;
}
- tangent.Normalize();
- return tangent;
+ return done;
}
-Vector3& Path::GetPoint( size_t index )
+Vector3& Path::GetPoint( uint32_t index )
{
DALI_ASSERT_ALWAYS( index < mPoint.Size() && "Path: Point index out of bounds" );
return mPoint[index];
}
-Vector3& Path::GetControlPoint( size_t index )
+Vector3& Path::GetControlPoint( uint32_t index )
{
DALI_ASSERT_ALWAYS( index < mControlPoint.Size() && "Path: Control Point index out of bounds" );
return mControlPoint[index];
}
-size_t Path::GetPointCount() const
+uint32_t Path::GetPointCount() const
{
- return mPoint.Size();
+ return static_cast<uint32_t>( mPoint.Size() );
}
-} // Internal
-} // Dali
+void Path::ClearPoints()
+{
+ mPoint.Clear();
+}
+void Path::ClearControlPoints()
+{
+ mControlPoint.Clear();
+}
+} // Internal
+} // Dali