2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <dali/dali.h>
19 #include <dali-toolkit/dali-toolkit.h>
20 #include <dali-toolkit/devel-api/controls/table-view/table-view.h>
21 #include "shared/view.h"
26 using namespace Dali::Toolkit;
32 const Vector4 GRID_BACKGROUND_COLOR(0.85f, 0.85f, 0.85f, 1.0f);
33 const Vector4 CONTROL_POINT1_COLOR(Color::MAGENTA);
34 const Vector4 CONTROL_POINT2_COLOR(0.0, 0.9, 0.9, 1.0);
35 const Vector3 CONTROL_POINT1_ORIGIN(-100, 200, 0);
36 const Vector3 CONTROL_POINT2_ORIGIN( 100, -200, 0);
37 const char* const CIRCLE1_IMAGE( DEMO_IMAGE_DIR "circle1.png" );
38 const char* const CIRCLE2_IMAGE( DEMO_IMAGE_DIR "circle2.png" );
39 const char* const ANIMATION_BACKGROUND( DEMO_IMAGE_DIR "slider-skin.9.png" );
40 const char* APPLICATION_TITLE("Bezier curve animation");
41 const float ANIM_LEFT_FACTOR(0.2f);
42 const float ANIM_RIGHT_FACTOR(0.8f);
43 const int AXIS_LABEL_POINT_SIZE(7);
44 const float AXIS_LINE_SIZE(1.0f);
46 const char* CURVE_VERTEX_SHADER = DALI_COMPOSE_SHADER
48 attribute mediump vec2 aPosition;
49 uniform mediump mat4 uMvpMatrix;
53 gl_Position = uMvpMatrix * vec4(aPosition*uSize.xy, 0.0, 1.0);
57 const char* CURVE_FRAGMENT_SHADER = DALI_COMPOSE_SHADER
59 uniform lowp vec4 uColor;
62 gl_FragColor = vec4(0.0,0.0,0.0,1.0);
67 inline float Clamp(float v, float min, float max)
74 struct HandlePositionConstraint
76 HandlePositionConstraint( float minRelX, float maxRelX, float minRelY, float maxRelY )
77 : minRelX(minRelX), maxRelX(maxRelX), minRelY(minRelY), maxRelY(maxRelY)
81 void operator()( Vector3& current, const PropertyInputContainer& inputs )
83 Vector3 size( inputs[0]->GetVector3() );
84 current.x = Clamp(current.x, minRelX*size.x, maxRelX*size.x );
85 current.y = Clamp(current.y, minRelY*size.y, maxRelY*size.y );
94 void AnimatingPositionConstraint( Vector3& current, const PropertyInputContainer& inputs )
96 float positionFactor( inputs[0]->GetFloat() ); // -1 - 2
97 Vector3 size( inputs[1]->GetVector3() );
99 current.x = size.x * (positionFactor-0.5f); // size * (-1.5 - 1.5)
102 } //unnamed namespace
106 class BezierCurveExample : public ConnectionTracker
110 BezierCurveExample( Application& application )
111 : mApplication( application ),
129 mRelativeDragPoint(),
130 mLastControlPointPosition1(),
131 mLastControlPointPosition2(),
132 mPositionFactorIndex(),
134 mControlPoint1Id( 0.0f ),
135 mControlPoint2Id( 0.0f ),
136 mControlPointScale( 0.5f ),
137 mControlPointZoomScale( mControlPointScale * 2.0 ),
140 // Connect to the Application's Init signal
141 mApplication.InitSignal().Connect( this, &BezierCurveExample::Create );
144 ~BezierCurveExample()
146 // Nothing to do here;
149 // The Init signal is received once (only) during the Application lifetime
150 void Create( Application& application )
152 // Hide the indicator bar
153 application.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
155 Stage stage = Stage::GetCurrent();
156 stage.KeyEventSignal().Connect( this, &BezierCurveExample::OnKeyEvent );
158 CreateBackground(stage);
160 mControlPointScale = 0.5f;
161 mControlPointZoomScale = mControlPointScale * 2.0f;
163 mContentLayer = Layer::New();
164 mContentLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
165 mContentLayer.TouchSignal().Connect(this, &BezierCurveExample::OnTouchLayer);
166 mContentLayer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
167 stage.Add( mContentLayer );
169 // 6 rows: title, grid, coords, play, anim1, anim2
170 TableView contentLayout = TableView::New(5, 1);
171 contentLayout.SetProperty( Dali::Actor::Property::NAME,"contentLayout");
172 contentLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
173 contentLayout.SetCellPadding( Size( 30, 30 ) );
174 contentLayout.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::TOP_CENTER);
175 contentLayout.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_CENTER);
176 mContentLayer.Add( contentLayout );
178 // Create a TextLabel for the application title.
179 Toolkit::TextLabel label = Toolkit::TextLabel::New( APPLICATION_TITLE );
180 label.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
181 label.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
182 label.SetProperty( Toolkit::TextLabel::Property::TEXT_COLOR, Color::BLACK );
183 contentLayout.Add( label );
184 contentLayout.SetFitHeight(0);
186 mGrid = Control::New();
188 mGrid.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH );
189 mGrid.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
191 mGrid.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
192 mGrid.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::CENTER);
193 mGrid.SetBackgroundColor(GRID_BACKGROUND_COLOR);
195 contentLayout.Add( mGrid );
196 contentLayout.SetCellAlignment(1, HorizontalAlignment::CENTER, VerticalAlignment::CENTER );
198 CreateControlPoints( mGrid ); // Control points constrained to double height of grid
199 CreateAxisLabels( mGrid );
201 mCoefficientLabel = TextLabel::New();
202 mCoefficientLabel.SetProperty( TextLabel::Property::ENABLE_MARKUP, true );
203 mCoefficientLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
204 mCoefficientLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
205 mCoefficientLabel.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
207 contentLayout.Add( mCoefficientLabel );
208 SetLabel( Vector2(0,0), Vector2(1,1));
209 contentLayout.SetCellAlignment(2, HorizontalAlignment::CENTER, VerticalAlignment::CENTER );
210 contentLayout.SetFitHeight(2);
212 // Setup Play button and 2 icons to show off current anim and linear anim
214 PushButton play = PushButton::New();
215 play.SetProperty( Dali::Actor::Property::NAME,"Play");
216 play.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
217 play.SetProperty( Button::Property::LABEL, "Play");
218 play.ClickedSignal().Connect( this, &BezierCurveExample::OnPlayClicked );
220 contentLayout.Add( play );
221 contentLayout.SetCellAlignment(3, HorizontalAlignment::CENTER, VerticalAlignment::CENTER );
222 contentLayout.SetFitHeight(3);
224 auto animContainer = Control::New();
225 animContainer.SetProperty( Dali::Actor::Property::NAME,"AnimationContainer");
226 animContainer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
227 animContainer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
229 auto animRail = Control::New();
230 animRail.SetProperty( Control::Property::BACKGROUND, Property::Map()
231 .Add( Visual::Property::TYPE, Visual::IMAGE )
232 .Add( ImageVisual::Property::URL, ANIMATION_BACKGROUND ) );
233 animRail.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
234 animRail.SetProperty( Actor::Property::SIZE_MODE_FACTOR, Vector3( 0.666f, 0.2f, 1.0f ) );
235 animRail.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
236 animContainer.Add( animRail );
238 contentLayout.Add( animContainer );
239 contentLayout.SetFixedHeight(4, 150 );
241 mAnimIcon1 = ImageView::New( CIRCLE1_IMAGE );
242 mAnimIcon1.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
243 mAnimIcon1.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
245 // Would like some means of setting and animating position as a percentage of
246 // parent size without using constraints, but this will have to suffice for the moment.
247 mPositionFactorIndex = mAnimIcon1.RegisterProperty( "positionFactor", ANIM_LEFT_FACTOR); // range: 0-1 (+/- 1)
248 Constraint constraint = Constraint::New<Vector3>( mAnimIcon1, Actor::Property::POSITION, AnimatingPositionConstraint );
249 constraint.AddSource( Source( mAnimIcon1, mPositionFactorIndex ) );
250 constraint.AddSource( Source( animContainer, Actor::Property::SIZE ) );
253 animContainer.Add( mAnimIcon1 );
255 // First UpdateCurve needs to run after size negotiation and after images have loaded
256 mGrid.OnRelayoutSignal().Connect( this, &BezierCurveExample::InitialUpdateCurve );
258 auto controlPoint1 = Control::DownCast( mControlPoint1 );
261 controlPoint1.ResourceReadySignal().Connect( this, &BezierCurveExample::ControlPointReady );
264 auto controlPoint2 = Control::DownCast( mControlPoint2 );
267 controlPoint2.ResourceReadySignal().Connect( this, &BezierCurveExample::ControlPointReady );
271 void ControlPointReady( Control control )
276 void InitialUpdateCurve(Actor actor)
281 void CreateBackground( Stage stage )
283 Toolkit::Control background = Dali::Toolkit::Control::New();
284 background.SetProperty( Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::CENTER );
285 background.SetProperty( Actor::Property::PARENT_ORIGIN, Dali::ParentOrigin::CENTER );
286 background.SetResizePolicy( Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS );
289 map.Insert( Visual::Property::TYPE, Visual::COLOR );
290 map.Insert( ColorVisual::Property::MIX_COLOR, Vector4( 253/255.0f, 245/255.0f, 230/255.0f, 1.0f ) );
291 background.SetProperty( Dali::Toolkit::Control::Property::BACKGROUND, map );
292 stage.Add( background );
295 void CreateCubic(Actor parent)
297 // Create a mesh to draw the cubic as a single line
298 mCurve = Actor::New();
299 mCurve.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
300 mCurve.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
302 Shader shader = Shader::New( CURVE_VERTEX_SHADER, CURVE_FRAGMENT_SHADER );
304 Property::Map curveVertexFormat;
305 curveVertexFormat["aPosition"] = Property::VECTOR2;
306 mCurveVertices = PropertyBuffer::New( curveVertexFormat );
307 Vector2 vertexData[2] = { Vector2(-0.5f, 0.5f), Vector2( 0.5f, -0.5f ) };
308 mCurveVertices.SetData( vertexData, 2 );
310 Geometry geometry = Geometry::New();
311 geometry.AddVertexBuffer( mCurveVertices );
312 geometry.SetType( Geometry::LINE_STRIP );
314 Renderer renderer = Renderer::New( geometry, shader );
315 mCurve.AddRenderer( renderer );
319 Actor CreateControlPoint( Actor parent, const char* url, Vector3 position)
321 Actor actor = ImageView::New( url );
322 actor.SetProperty( Actor::Property::SCALE, mControlPointScale);
323 actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
324 // Curve and line drawing works off current value (i.e. last update frame's value). Need to animate to ensure
325 // initial position is baked to both frames before initially drawing the curve.
326 auto positionAnimation = Animation::New( 0.01f );
327 positionAnimation.AnimateTo( Property( actor, Actor::Property::POSITION ), position, AlphaFunction::EASE_IN_OUT );
328 positionAnimation.Play();
329 positionAnimation.FinishedSignal().Connect( this, &BezierCurveExample::OnAnimationFinished );
331 // Set up constraints for drag/drop
332 Constraint constraint = Constraint::New<Vector3>( actor, Actor::Property::POSITION, HandlePositionConstraint( -0.5, 0.5, -1, 1));
333 constraint.AddSource( Source( parent, Actor::Property::SIZE ) );
336 actor.TouchSignal().Connect(this, &BezierCurveExample::OnTouchControlPoint);
340 Actor CreateControlLine( PropertyBuffer vertexBuffer )
342 Actor line = Actor::New();
343 line.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
344 line.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
346 Shader shader = Shader::New( CURVE_VERTEX_SHADER, CURVE_FRAGMENT_SHADER );
347 Geometry geometry = Geometry::New();
348 geometry.AddVertexBuffer( vertexBuffer );
349 geometry.SetType( Geometry::LINE_STRIP );
351 Renderer renderer = Renderer::New( geometry, shader );
352 line.AddRenderer( renderer );
356 void CreateControlPoints( Actor parent )
358 mControlPoint1 = CreateControlPoint( parent,
360 CONTROL_POINT1_ORIGIN );
361 mControlPoint1Id = mControlPoint1.GetProperty< int >( Actor::Property::ID );
363 mControlPoint2 = CreateControlPoint( parent,
365 CONTROL_POINT2_ORIGIN );
366 mControlPoint2Id = mControlPoint2.GetProperty< int >( Actor::Property::ID );
368 Property::Map lineVertexFormat;
369 lineVertexFormat["aPosition"] = Property::VECTOR2;
370 mLine1Vertices = PropertyBuffer::New( lineVertexFormat );
371 mLine2Vertices = PropertyBuffer::New( lineVertexFormat );
373 mControlLine1 = CreateControlLine( mLine1Vertices );
374 mControlLine2 = CreateControlLine( mLine2Vertices );
376 parent.Add( mControlLine1 );
377 parent.Add( mControlLine2 );
378 parent.Add( mControlPoint1 );
379 parent.Add( mControlPoint2 );
382 void CreateAxisLabels( Actor parent )
384 TextLabel progressionLabel = TextLabel::New( "Progression" );
385 progressionLabel.SetProperty( TextLabel::Property::POINT_SIZE, AXIS_LABEL_POINT_SIZE );
386 progressionLabel.SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( Degree(-90.0f) ), Vector3::ZAXIS ) );
387 progressionLabel.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_LEFT );
388 progressionLabel.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_LEFT );
389 CreateLine( progressionLabel, ParentOrigin::BOTTOM_LEFT );
391 TextLabel timeLabel = TextLabel::New( "Time" );
392 timeLabel.SetProperty( TextLabel::Property::POINT_SIZE, AXIS_LABEL_POINT_SIZE );
393 timeLabel.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
394 timeLabel.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_LEFT );
395 CreateLine( timeLabel, ParentOrigin::TOP_LEFT );
397 parent.Add( progressionLabel );
398 parent.Add( timeLabel );
401 void CreateLine( Actor parent, const Vector3& parentOrigin )
403 Control control = Control::New();
404 control.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
405 control.SetProperty( Actor::Property::PARENT_ORIGIN, parentOrigin );
406 control.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
407 control.SetProperty( Actor::Property::SIZE_HEIGHT, AXIS_LINE_SIZE );
408 control.SetBackgroundColor( Color::BLACK );
409 parent.Add( control );
412 void SetLabel( Vector2 pos1, Vector2 pos2 )
414 std::ostringstream oss;
415 oss.setf(std::ios::fixed, std::ios::floatfield);
417 oss << "( <color value='#971586'>" << pos1.x << ", " << pos1.y << ", </color>";
418 oss << "<color value='#e7640d'>" << pos2.x << ", " << pos2.y << "</color>";
419 oss << "<color value='black'> )</color>";
421 mCoefficientLabel.SetProperty( TextLabel::Property::TEXT, oss.str() );
424 Vector2 AlignToGrid( Vector3 actorPos, Vector3 gridSize )
426 actorPos /= gridSize; // => -0.5 - 0.5
427 actorPos.x = Clamp( actorPos.x, -0.5f, 0.5f );
428 return Vector2( actorPos.x + 0.5f, 0.5f - actorPos.y );
431 void GetControlPoints(Vector2& pt1, Vector2& pt2)
433 Vector3 gridSize = mGrid.GetProperty<Vector3>( Actor::Property::SIZE ); // Get target value
435 pt1 = AlignToGrid( mControlPoint1.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ), gridSize );
436 pt2 = AlignToGrid( mControlPoint2.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ), gridSize );
440 * @param[in] actor The actor to get the position from
441 * @param[out] point The point in the grid in the range -0.5 -> 0.5 in x and y, with y up.
442 * @param[out] position The actor position, floored to the nearest pixel
444 void GetPoint( Actor actor, Vector2& point, Vector2& position)
446 auto gridSize = mGrid.GetProperty<Vector3>( Actor::Property::SIZE ); // Get target value
447 auto currentPosition = actor.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ); // Get constrained current value
449 position = Vector2( floor( currentPosition.x ), floor( currentPosition.y ) );
451 point.x = Clamp( position.x / gridSize.x, -0.5f, 0.5f ) + 0.5f;
452 point.y = 0.5f - position.y / gridSize.y;
457 Vector2 point1, point2;
458 Vector2 position1, position2;
459 const int NUMBER_OF_SEGMENTS(40);
461 GetPoint( mControlPoint1, point1, position1 );
462 GetPoint( mControlPoint2, point2, position2 );
464 if( position1 != mLastControlPointPosition1 ||
465 position2 != mLastControlPointPosition2 )
467 mLastControlPointPosition1 = position1;
468 mLastControlPointPosition2 = position2;
470 SetLabel( point1, point2 );
472 Path path = Path::New();
473 path.AddPoint(Vector3::ZERO);
474 path.AddPoint(Vector3(1.0f, 1.0f, 1.0f));
475 path.AddControlPoint( Vector3( point1.x, point1.y, 0 ) );
476 path.AddControlPoint( Vector3( point2.x, point2.y, 0 ) );
478 Dali::Vector<float> verts;
480 verts.Resize(2*(NUMBER_OF_SEGMENTS+1)); // 1 more point than segment
481 for( int i=0; i<=NUMBER_OF_SEGMENTS; ++i)
483 Vector3 position, tangent;
484 path.Sample( i/float(NUMBER_OF_SEGMENTS), position, tangent );
485 verts[i*2] = position.x-0.5;
486 verts[i*2+1] = 0.5-position.y;
488 mCurveVertices.SetData(&verts[0], NUMBER_OF_SEGMENTS+1);
490 Vector4 line1( -0.5f, 0.5f, point1.x-0.5f, 0.5f-point1.y );
491 mLine1Vertices.SetData( line1.AsFloat(), 2 );
493 Vector4 line2( 0.5f, -0.5f, point2.x-0.5f, 0.5f-point2.y );
494 mLine2Vertices.SetData( line2.AsFloat(), 2 );
498 bool OnTouchControlPoint( Actor controlPoint, const TouchData& event )
500 if( event.GetPointCount() > 0 )
502 if( event.GetState( 0 ) == PointState::DOWN )
504 Vector2 screenPoint = event.GetScreenPosition( 0 );
505 mRelativeDragPoint = screenPoint;
506 mRelativeDragPoint -= Vector2(controlPoint.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ));
507 mDragActor = controlPoint;
508 mDragAnimation = Animation::New(0.25f);
509 mDragAnimation.AnimateTo( Property(mDragActor, Actor::Property::SCALE), Vector3( mControlPointZoomScale, mControlPointZoomScale, 1.0f), AlphaFunction::EASE_OUT);
510 mDragAnimation.Play();
513 return false; // Don't mark this as consumed - let the layer get the touch
516 bool OnTouchLayer( Actor actor, const TouchData& event )
518 if( event.GetPointCount() > 0 )
522 Vector3 position( event.GetScreenPosition( 0 ) );
524 mDragActor.SetProperty( Actor::Property::POSITION, position - Vector3( mRelativeDragPoint ) );
526 if( event.GetState( 0 ) == PointState::UP ) // Stop dragging
528 mDragAnimation = Animation::New(0.25f);
529 mDragAnimation.AnimateTo( Property( mDragActor, Actor::Property::SCALE ), Vector3( mControlPointScale, mControlPointScale, 1.0f), AlphaFunction::EASE_IN);
530 mDragAnimation.FinishedSignal().Connect( this, &BezierCurveExample::OnAnimationFinished );
531 mDragAnimation.Play();
540 void OnAnimationFinished( Animation& animation )
545 bool OnPlayClicked( Button button )
547 if( ! mBezierAnimation )
549 mBezierAnimation = Animation::New( mDuration );
551 mBezierAnimation.Stop();
552 mBezierAnimation.Clear();
554 float positionFactor = ANIM_LEFT_FACTOR;
557 positionFactor = ANIM_RIGHT_FACTOR;
566 GetControlPoints(pt1, pt2);
568 mBezierAnimation.AnimateTo( Property(mAnimIcon1, mPositionFactorIndex), positionFactor, AlphaFunction( pt1, pt2 ) );
569 mBezierAnimation.Play();
574 * Main key event handler
576 void OnKeyEvent(const KeyEvent& event)
579 if( event.state == KeyEvent::Down && (IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK )) )
586 Application& mApplication;
587 Actor mControlPoint1;
588 Actor mControlPoint2;
591 ImageView mAnimIcon1;
592 ImageView mAnimIcon2;
595 TextLabel mCoefficientLabel;
599 Animation mDragAnimation;
600 Animation mBezierAnimation;
601 PropertyBuffer mCurveVertices;
602 PropertyBuffer mLine1Vertices;
603 PropertyBuffer mLine2Vertices;
604 Vector2 mRelativeDragPoint;
605 Vector2 mLastControlPointPosition1;
606 Vector2 mLastControlPointPosition2;
607 Property::Index mPositionFactorIndex;
609 unsigned int mControlPoint1Id;
610 unsigned int mControlPoint2Id;
611 float mControlPointScale;
612 float mControlPointZoomScale;
617 int DALI_EXPORT_API main( int argc, char **argv )
619 Application application = Application::New( &argc, &argv );
621 BezierCurveExample test( application );
622 application.MainLoop();