/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 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.
// INTERNAL INCLUDES
#include <dali/internal/event/common/property-helper.h>
+#include <dali/public-api/object/property-array.h>
+#include <dali/public-api/object/type-registry.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::CONTROL_POINTS )
+DALI_PROPERTY( "controlPoints", ARRAY, true, false, false, Dali::Path::Property::CONTROL_POINTS )
DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
/**
const Dali::Matrix BezierBasis = Dali::Matrix( BezierBasisCoeff );
+Dali::BaseHandle Create()
+{
+ return Dali::Path::New();
+}
+
+Dali::TypeRegistration mType( typeid(Dali::Path), typeid(Dali::Handle), Create );
+
+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()
void Path::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
{
- indices.reserve( DEFAULT_PROPERTY_COUNT );
+ indices.Reserve( DEFAULT_PROPERTY_COUNT );
for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
{
- indices.push_back( i );
+ indices.PushBack( i );
}
}
Property::Value Path::GetDefaultProperty( Property::Index index ) const
{
- Property::Value value;
if( index == Dali::Path::Property::POINTS )
{
- Property::Array propertyArray;
- value = Property::Value(propertyArray);
- size_t pointCount( mPoint.Size() );
- for( size_t i( 0 ); i != pointCount; ++i )
+ Property::Value value( Property::ARRAY );
+ Property::Array* array = value.GetArray();
+ Property::Array::SizeType pointCount = mPoint.Count();
+
+ if( array )
{
- value.AppendItem( mPoint[i] );
+ array->Reserve( pointCount );
+ for( Property::Array::SizeType i = 0; i < pointCount; ++i )
+ {
+ array->PushBack( mPoint[i] );
+ }
}
+ return value;
}
else if( index == Dali::Path::Property::CONTROL_POINTS )
{
- Property::Array propertyArray;
- value = Property::Value(propertyArray);
- size_t controlpointCount( mControlPoint.Size() );
- for( size_t i( 0 ); i != controlpointCount; ++i )
+ Property::Value value( Property::ARRAY );
+ Property::Array* array = value.GetArray();
+ Property::Array::SizeType controlpointCount = mControlPoint.Count();
+
+ 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();
+}
+
+Property::Value Path::GetDefaultPropertyCurrentValue( Property::Index index ) const
+{
+ return GetDefaultProperty( index ); // Event-side only properties
}
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::CONTROL_POINTS )
- {
- 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 );
+ }
}
}
}
//Find segment and local progress
unsigned int numSegs = GetNumberOfSegments();
- if( t <= 0.0f )
+ if( t <= 0.0f || numSegs == 0 )
{
segment = 0;
tLocal = 0.0f;
{
segment = t * numSegs;
float segLength = 1.0f / numSegs;
- float segStart = (float)segment * segLength;
+ float segStart = static_cast<float>( segment ) * segLength;
tLocal = (t - segStart) * 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)
+ if( !SampleAt(t, position, tangent) )
{
- 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();
+ 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 );
+ unsigned int 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) )
+ {
+ unsigned int 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) )
+ {
+ unsigned int 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 )
return mPoint.Size();
}
+void Path::ClearPoints()
+{
+ mPoint.Clear();
+}
+
+void Path::ClearControlPoints()
+{
+ mControlPoint.Clear();
+}
+
} // Internal
} // Dali