Changes after TouchedSignal changes
[platform/core/uifw/dali-demo.git] / examples / bezier-curve / bezier-curve-example.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
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"
22
23 #include <sstream>
24
25 using namespace Dali;
26 using namespace Dali::Toolkit;
27 using namespace std;
28
29 namespace
30 {
31
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);
45
46 const char* CURVE_VERTEX_SHADER = DALI_COMPOSE_SHADER
47   (
48     attribute mediump vec2 aPosition;
49     uniform mediump mat4 uMvpMatrix;
50     uniform vec3 uSize;
51     void main()
52     {
53       gl_Position = uMvpMatrix * vec4(aPosition*uSize.xy, 0.0, 1.0);
54     }
55    );
56
57 const char* CURVE_FRAGMENT_SHADER = DALI_COMPOSE_SHADER
58   (
59     uniform lowp vec4 uColor;
60     void main()
61     {
62       gl_FragColor = vec4(0.0,0.0,0.0,1.0);
63     }
64    );
65
66
67 inline float Clamp(float v, float min, float max)
68 {
69   if(v<min) return min;
70   if(v>max) return max;
71   return v;
72 }
73
74 struct HandlePositionConstraint
75 {
76   HandlePositionConstraint( float minRelX, float maxRelX, float minRelY, float maxRelY )
77   : minRelX(minRelX), maxRelX(maxRelX), minRelY(minRelY), maxRelY(maxRelY)
78   {
79   }
80
81   void operator()( Vector3& current, const PropertyInputContainer& inputs )
82   {
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 );
86   }
87
88   float minRelX;
89   float maxRelX;
90   float minRelY;
91   float maxRelY;
92 };
93
94 void AnimatingPositionConstraint( Vector3& current, const PropertyInputContainer& inputs )
95 {
96   float positionFactor( inputs[0]->GetFloat() ); // -1 - 2
97   Vector3 size( inputs[1]->GetVector3() );
98
99   current.x = size.x * (positionFactor-0.5f); // size * (-1.5 - 1.5)
100 }
101
102 } //unnamed namespace
103
104
105
106 class BezierCurveExample : public ConnectionTracker
107 {
108 public:
109
110   BezierCurveExample( Application& application )
111   : mApplication( application ),
112     mControlPoint1(),
113     mControlPoint2(),
114     mControlLine1(),
115     mControlLine2(),
116     mAnimIcon1(),
117     mAnimIcon2(),
118     mDragActor(),
119     mCurve(),
120     mCoefficientLabel(),
121     mContentLayer(),
122     mGrid(),
123     mTimer(),
124     mDragAnimation(),
125     mBezierAnimation(),
126     mCurveVertices(),
127     mLine1Vertices(),
128     mLine2Vertices(),
129     mRelativeDragPoint(),
130     mLastControlPointPosition1(),
131     mLastControlPointPosition2(),
132     mPositionFactorIndex(),
133     mDuration( 2.0f ),
134     mControlPoint1Id( 0.0f ),
135     mControlPoint2Id( 0.0f ),
136     mControlPointScale( 0.5f ),
137     mControlPointZoomScale( mControlPointScale * 2.0 ),
138     mGoingRight( true )
139   {
140     // Connect to the Application's Init signal
141     mApplication.InitSignal().Connect( this, &BezierCurveExample::Create );
142   }
143
144   ~BezierCurveExample()
145   {
146     // Nothing to do here;
147   }
148
149   // The Init signal is received once (only) during the Application lifetime
150   void Create( Application& application )
151   {
152     Window window = mApplication.GetWindow();
153     window.KeyEventSignal().Connect( this, &BezierCurveExample::OnKeyEvent );
154
155     CreateBackground(window);
156
157     mControlPointScale = 0.5f;
158     mControlPointZoomScale = mControlPointScale * 2.0f;
159
160     mContentLayer = Layer::New();
161     mContentLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
162     mContentLayer.TouchedSignal().Connect(this, &BezierCurveExample::OnTouchLayer);
163     mContentLayer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
164     window.Add( mContentLayer );
165
166     // 6 rows: title, grid, coords, play, anim1, anim2
167     TableView contentLayout = TableView::New(5, 1);
168     contentLayout.SetProperty( Dali::Actor::Property::NAME,"contentLayout");
169     contentLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
170     contentLayout.SetCellPadding( Size( 30, 30 ) );
171     contentLayout.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::TOP_CENTER);
172     contentLayout.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_CENTER);
173     mContentLayer.Add( contentLayout );
174
175     // Create a TextLabel for the application title.
176     Toolkit::TextLabel label = Toolkit::TextLabel::New( APPLICATION_TITLE );
177     label.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
178     label.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
179     label.SetProperty( Toolkit::TextLabel::Property::TEXT_COLOR, Color::BLACK );
180     contentLayout.Add( label );
181     contentLayout.SetFitHeight(0);
182
183     mGrid = Control::New();
184
185     mGrid.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH );
186     mGrid.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
187
188     mGrid.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
189     mGrid.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::CENTER);
190     mGrid.SetBackgroundColor(GRID_BACKGROUND_COLOR);
191
192     contentLayout.Add( mGrid );
193     contentLayout.SetCellAlignment(1, HorizontalAlignment::CENTER, VerticalAlignment::CENTER );
194     CreateCubic(mGrid);
195     CreateControlPoints( mGrid ); // Control points constrained to double height of grid
196     CreateAxisLabels( mGrid );
197
198     mCoefficientLabel = TextLabel::New();
199     mCoefficientLabel.SetProperty( TextLabel::Property::ENABLE_MARKUP, true );
200     mCoefficientLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
201     mCoefficientLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
202     mCoefficientLabel.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
203
204     contentLayout.Add( mCoefficientLabel );
205     SetLabel( Vector2(0,0), Vector2(1,1));
206     contentLayout.SetCellAlignment(2, HorizontalAlignment::CENTER, VerticalAlignment::CENTER );
207     contentLayout.SetFitHeight(2);
208
209     // Setup Play button and 2 icons to show off current anim and linear anim
210
211     PushButton play = PushButton::New();
212     play.SetProperty( Dali::Actor::Property::NAME,"Play");
213     play.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
214     play.SetProperty( Button::Property::LABEL, "Play");
215     play.ClickedSignal().Connect( this, &BezierCurveExample::OnPlayClicked );
216
217     contentLayout.Add( play );
218     contentLayout.SetCellAlignment(3, HorizontalAlignment::CENTER, VerticalAlignment::CENTER );
219     contentLayout.SetFitHeight(3);
220
221     auto animContainer = Control::New();
222     animContainer.SetProperty( Dali::Actor::Property::NAME,"AnimationContainer");
223     animContainer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
224     animContainer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
225
226     auto animRail = Control::New();
227     animRail.SetProperty( Control::Property::BACKGROUND, Property::Map()
228                           .Add( Visual::Property::TYPE, Visual::IMAGE )
229                           .Add( ImageVisual::Property::URL, ANIMATION_BACKGROUND ) );
230     animRail.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
231     animRail.SetProperty( Actor::Property::SIZE_MODE_FACTOR, Vector3( 0.666f, 0.2f, 1.0f ) );
232     animRail.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
233     animContainer.Add( animRail );
234
235     contentLayout.Add( animContainer );
236     contentLayout.SetFixedHeight(4, 150 );
237
238     mAnimIcon1 = ImageView::New( CIRCLE1_IMAGE );
239     mAnimIcon1.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
240     mAnimIcon1.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
241
242     // Would like some means of setting and animating position as a percentage of
243     // parent size without using constraints, but this will have to suffice for the moment.
244     mPositionFactorIndex = mAnimIcon1.RegisterProperty( "positionFactor", ANIM_LEFT_FACTOR); // range: 0-1 (+/- 1)
245     Constraint constraint = Constraint::New<Vector3>( mAnimIcon1, Actor::Property::POSITION, AnimatingPositionConstraint );
246     constraint.AddSource( Source( mAnimIcon1, mPositionFactorIndex ) );
247     constraint.AddSource( Source( animContainer, Actor::Property::SIZE ) );
248     constraint.Apply();
249
250     animContainer.Add( mAnimIcon1 );
251
252     // First UpdateCurve needs to run after size negotiation and after images have loaded
253     mGrid.OnRelayoutSignal().Connect( this, &BezierCurveExample::InitialUpdateCurve );
254
255     auto controlPoint1 = Control::DownCast( mControlPoint1 );
256     if( controlPoint1 )
257     {
258       controlPoint1.ResourceReadySignal().Connect( this, &BezierCurveExample::ControlPointReady );
259     }
260
261     auto controlPoint2 = Control::DownCast( mControlPoint2 );
262     if( controlPoint2 )
263     {
264       controlPoint2.ResourceReadySignal().Connect( this, &BezierCurveExample::ControlPointReady );
265     }
266   }
267
268   void ControlPointReady( Control control )
269   {
270     UpdateCurve();
271   }
272
273   void InitialUpdateCurve(Actor actor)
274   {
275     UpdateCurve();
276   }
277
278   void CreateBackground( Window window )
279   {
280     Toolkit::Control background = Dali::Toolkit::Control::New();
281     background.SetProperty( Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::CENTER );
282     background.SetProperty( Actor::Property::PARENT_ORIGIN, Dali::ParentOrigin::CENTER );
283     background.SetResizePolicy( Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS );
284
285     Property::Map map;
286     map.Insert( Visual::Property::TYPE,  Visual::COLOR );
287     map.Insert( ColorVisual::Property::MIX_COLOR, Vector4( 253/255.0f, 245/255.0f, 230/255.0f, 1.0f ) );
288     background.SetProperty( Dali::Toolkit::Control::Property::BACKGROUND, map );
289     window.Add( background );
290   }
291
292   void CreateCubic(Actor parent)
293   {
294     // Create a mesh to draw the cubic as a single line
295     mCurve = Actor::New();
296     mCurve.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
297     mCurve.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
298
299     Shader shader = Shader::New( CURVE_VERTEX_SHADER, CURVE_FRAGMENT_SHADER );
300
301     Property::Map curveVertexFormat;
302     curveVertexFormat["aPosition"] = Property::VECTOR2;
303     mCurveVertices = VertexBuffer::New( curveVertexFormat );
304     Vector2 vertexData[2] = { Vector2(-0.5f, 0.5f), Vector2( 0.5f, -0.5f ) };
305     mCurveVertices.SetData( vertexData, 2 );
306
307     Geometry geometry = Geometry::New();
308     geometry.AddVertexBuffer( mCurveVertices );
309     geometry.SetType( Geometry::LINE_STRIP );
310
311     Renderer renderer = Renderer::New( geometry, shader );
312     mCurve.AddRenderer( renderer );
313     parent.Add(mCurve);
314   }
315
316   Actor CreateControlPoint( Actor parent, const char* url, Vector3 position)
317   {
318     Actor actor = ImageView::New( url );
319     actor.SetProperty( Actor::Property::SCALE, mControlPointScale);
320     actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
321     // Curve and line drawing works off current value (i.e. last update frame's value). Need to animate to ensure
322     // initial position is baked to both frames before initially drawing the curve.
323     auto positionAnimation = Animation::New( 0.01f );
324     positionAnimation.AnimateTo( Property( actor, Actor::Property::POSITION ), position, AlphaFunction::EASE_IN_OUT );
325     positionAnimation.Play();
326     positionAnimation.FinishedSignal().Connect( this, &BezierCurveExample::OnAnimationFinished );
327
328     // Set up constraints for drag/drop
329     Constraint constraint = Constraint::New<Vector3>( actor, Actor::Property::POSITION, HandlePositionConstraint( -0.5, 0.5, -1, 1));
330     constraint.AddSource( Source( parent, Actor::Property::SIZE ) );
331     constraint.Apply();
332
333     actor.TouchedSignal().Connect(this, &BezierCurveExample::OnTouchControlPoint);
334     return actor;
335   }
336
337   Actor CreateControlLine( VertexBuffer vertexBuffer )
338   {
339     Actor line = Actor::New();
340     line.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
341     line.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
342
343     Shader shader = Shader::New( CURVE_VERTEX_SHADER, CURVE_FRAGMENT_SHADER );
344     Geometry geometry = Geometry::New();
345     geometry.AddVertexBuffer( vertexBuffer );
346     geometry.SetType( Geometry::LINE_STRIP );
347
348     Renderer renderer = Renderer::New( geometry, shader );
349     line.AddRenderer( renderer );
350     return line;
351   }
352
353   void CreateControlPoints( Actor parent )
354   {
355     mControlPoint1 = CreateControlPoint( parent,
356                                          CIRCLE1_IMAGE,
357                                          CONTROL_POINT1_ORIGIN );
358     mControlPoint1Id = mControlPoint1.GetProperty< int >( Actor::Property::ID );
359
360     mControlPoint2 = CreateControlPoint( parent,
361                                          CIRCLE2_IMAGE,
362                                          CONTROL_POINT2_ORIGIN );
363     mControlPoint2Id = mControlPoint2.GetProperty< int >( Actor::Property::ID );
364
365     Property::Map lineVertexFormat;
366     lineVertexFormat["aPosition"] = Property::VECTOR2;
367     mLine1Vertices = VertexBuffer::New( lineVertexFormat );
368     mLine2Vertices = VertexBuffer::New( lineVertexFormat );
369
370     mControlLine1 = CreateControlLine( mLine1Vertices );
371     mControlLine2 = CreateControlLine( mLine2Vertices );
372
373     parent.Add( mControlLine1 );
374     parent.Add( mControlLine2 );
375     parent.Add( mControlPoint1 );
376     parent.Add( mControlPoint2 );
377   }
378
379   void CreateAxisLabels( Actor parent )
380   {
381     TextLabel progressionLabel = TextLabel::New( "Progression" );
382     progressionLabel.SetProperty( TextLabel::Property::POINT_SIZE, AXIS_LABEL_POINT_SIZE );
383     progressionLabel.SetProperty( Actor::Property::ORIENTATION, Quaternion( Radian( Degree(-90.0f) ), Vector3::ZAXIS ) );
384     progressionLabel.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_LEFT );
385     progressionLabel.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_LEFT );
386     CreateLine( progressionLabel, ParentOrigin::BOTTOM_LEFT );
387
388     TextLabel timeLabel = TextLabel::New( "Time" );
389     timeLabel.SetProperty( TextLabel::Property::POINT_SIZE, AXIS_LABEL_POINT_SIZE );
390     timeLabel.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
391     timeLabel.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_LEFT );
392     CreateLine( timeLabel, ParentOrigin::TOP_LEFT );
393
394     parent.Add( progressionLabel );
395     parent.Add( timeLabel );
396   }
397
398   void CreateLine( Actor parent, const Vector3& parentOrigin )
399   {
400     Control control = Control::New();
401     control.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
402     control.SetProperty( Actor::Property::PARENT_ORIGIN, parentOrigin );
403     control.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
404     control.SetProperty( Actor::Property::SIZE_HEIGHT, AXIS_LINE_SIZE );
405     control.SetBackgroundColor( Color::BLACK );
406     parent.Add( control );
407   }
408
409   void SetLabel( Vector2 pos1, Vector2 pos2 )
410   {
411     std::ostringstream oss;
412     oss.setf(std::ios::fixed, std::ios::floatfield);
413     oss.precision(2);
414     oss << "( <color value='#971586'>" << pos1.x << ", " << pos1.y << ", </color>";
415     oss << "<color value='#e7640d'>" << pos2.x << ", " << pos2.y << "</color>";
416     oss << "<color value='black'> )</color>";
417
418     mCoefficientLabel.SetProperty( TextLabel::Property::TEXT, oss.str() );
419   }
420
421   Vector2 AlignToGrid( Vector3 actorPos, Vector3 gridSize )
422   {
423     actorPos /= gridSize; // => -0.5 - 0.5
424     actorPos.x = Clamp( actorPos.x, -0.5f, 0.5f );
425     return Vector2( actorPos.x + 0.5f, 0.5f - actorPos.y );
426   }
427
428   void GetControlPoints(Vector2& pt1, Vector2& pt2)
429   {
430     Vector3 gridSize = mGrid.GetProperty<Vector3>( Actor::Property::SIZE ); // Get target value
431
432     pt1 = AlignToGrid( mControlPoint1.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ), gridSize );
433     pt2 = AlignToGrid( mControlPoint2.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ), gridSize );
434   }
435
436   /**
437    * @param[in] actor The actor to get the position from
438    * @param[out] point The point in the grid in the range -0.5 -> 0.5 in x and y, with y up.
439    * @param[out] position The actor position, floored to the nearest pixel
440    */
441   void GetPoint( Actor actor, Vector2& point, Vector2& position)
442   {
443     auto gridSize = mGrid.GetProperty<Vector3>( Actor::Property::SIZE ); // Get target value
444     auto currentPosition = actor.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ); // Get constrained current value
445
446     position = Vector2( floor( currentPosition.x ), floor( currentPosition.y ) );
447
448     point.x = Clamp( position.x / gridSize.x, -0.5f, 0.5f ) + 0.5f;
449     point.y = 0.5f - position.y / gridSize.y;
450   }
451
452   void UpdateCurve()
453   {
454     Vector2 point1, point2;
455     Vector2 position1, position2;
456     const int NUMBER_OF_SEGMENTS(40);
457
458     GetPoint( mControlPoint1, point1, position1 );
459     GetPoint( mControlPoint2, point2, position2 );
460
461     if( position1 != mLastControlPointPosition1 ||
462         position2 != mLastControlPointPosition2 )
463     {
464       mLastControlPointPosition1 = position1;
465       mLastControlPointPosition2 = position2;
466
467       SetLabel( point1, point2 );
468
469       Path path = Path::New();
470       path.AddPoint(Vector3::ZERO);
471       path.AddPoint(Vector3(1.0f, 1.0f, 1.0f));
472       path.AddControlPoint( Vector3( point1.x, point1.y, 0 ) );
473       path.AddControlPoint( Vector3( point2.x, point2.y, 0 ) );
474
475       Dali::Vector<float> verts;
476
477       verts.Resize(2*(NUMBER_OF_SEGMENTS+1)); // 1 more point than segment
478       for( int i=0; i<=NUMBER_OF_SEGMENTS; ++i)
479       {
480         Vector3 position, tangent;
481         path.Sample( i/float(NUMBER_OF_SEGMENTS), position, tangent );
482         verts[i*2] = position.x-0.5;
483         verts[i*2+1] = 0.5-position.y;
484       }
485       mCurveVertices.SetData(&verts[0], NUMBER_OF_SEGMENTS+1);
486
487       Vector4 line1( -0.5f, 0.5f, point1.x-0.5f, 0.5f-point1.y );
488       mLine1Vertices.SetData( line1.AsFloat(), 2 );
489
490       Vector4 line2( 0.5f, -0.5f, point2.x-0.5f, 0.5f-point2.y );
491       mLine2Vertices.SetData( line2.AsFloat(), 2 );
492     }
493   }
494
495   bool OnTouchControlPoint( Actor controlPoint, const TouchEvent& event )
496   {
497     if( event.GetPointCount() > 0 )
498     {
499       if( event.GetState( 0 ) == PointState::DOWN )
500       {
501         Vector2 screenPoint = event.GetScreenPosition( 0 );
502         mRelativeDragPoint = screenPoint;
503         mRelativeDragPoint -= Vector2(controlPoint.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ));
504         mDragActor = controlPoint;
505         mDragAnimation = Animation::New(0.25f);
506         mDragAnimation.AnimateTo( Property(mDragActor, Actor::Property::SCALE), Vector3( mControlPointZoomScale, mControlPointZoomScale, 1.0f), AlphaFunction::EASE_OUT);
507         mDragAnimation.Play();
508       }
509     }
510     return false; // Don't mark this as consumed - let the layer get the touch
511   }
512
513   bool OnTouchLayer( Actor actor, const TouchEvent& event )
514   {
515     if( event.GetPointCount() > 0 )
516     {
517       if( mDragActor )
518       {
519         Vector3 position( event.GetScreenPosition( 0 ) );
520
521         mDragActor.SetProperty( Actor::Property::POSITION, position - Vector3( mRelativeDragPoint ) );
522
523         if( event.GetState( 0 ) == PointState::UP ) // Stop dragging
524         {
525           mDragAnimation = Animation::New(0.25f);
526           mDragAnimation.AnimateTo( Property( mDragActor, Actor::Property::SCALE ), Vector3( mControlPointScale, mControlPointScale, 1.0f), AlphaFunction::EASE_IN);
527           mDragAnimation.FinishedSignal().Connect( this, &BezierCurveExample::OnAnimationFinished );
528           mDragAnimation.Play();
529           mDragActor.Reset();
530         }
531       }
532       UpdateCurve();
533     }
534     return false;
535   }
536
537   void OnAnimationFinished( Animation& animation )
538   {
539     UpdateCurve();
540   }
541
542   bool OnPlayClicked( Button button )
543   {
544     if( ! mBezierAnimation )
545     {
546       mBezierAnimation = Animation::New( mDuration );
547     }
548     mBezierAnimation.Stop();
549     mBezierAnimation.Clear();
550
551     float positionFactor = ANIM_LEFT_FACTOR;
552     if( mGoingRight )
553     {
554       positionFactor = ANIM_RIGHT_FACTOR;
555       mGoingRight = false;
556     }
557     else
558     {
559       mGoingRight = true;
560     }
561
562     Vector2 pt1, pt2;
563     GetControlPoints(pt1, pt2);
564
565     mBezierAnimation.AnimateTo( Property(mAnimIcon1, mPositionFactorIndex), positionFactor, AlphaFunction( pt1, pt2 ) );
566     mBezierAnimation.Play();
567     return true;
568   }
569
570   /**
571    * Main key event handler
572    */
573   void OnKeyEvent(const KeyEvent& event)
574   {
575
576     if( event.GetState() == KeyEvent::DOWN && (IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ))  )
577     {
578       mApplication.Quit();
579     }
580   }
581
582 private:
583   Application& mApplication;
584   Actor mControlPoint1;
585   Actor mControlPoint2;
586   Actor mControlLine1;
587   Actor mControlLine2;
588   ImageView mAnimIcon1;
589   ImageView mAnimIcon2;
590   Actor mDragActor;
591   Actor mCurve;
592   TextLabel mCoefficientLabel;
593   Layer mContentLayer;
594   Control mGrid;
595   Timer mTimer;
596   Animation mDragAnimation;
597   Animation mBezierAnimation;
598   VertexBuffer mCurveVertices;
599   VertexBuffer mLine1Vertices;
600   VertexBuffer mLine2Vertices;
601   Vector2 mRelativeDragPoint;
602   Vector2 mLastControlPointPosition1;
603   Vector2 mLastControlPointPosition2;
604   Property::Index mPositionFactorIndex;
605   float mDuration;
606   unsigned int mControlPoint1Id;
607   unsigned int mControlPoint2Id;
608   float mControlPointScale;
609   float mControlPointZoomScale;
610   bool mGoingRight;
611 };
612
613
614 int DALI_EXPORT_API main( int argc, char **argv )
615 {
616   Application application = Application::New( &argc, &argv );
617
618   BezierCurveExample test( application );
619   application.MainLoop();
620   return 0;
621 }