2 * Copyright (c) 2022 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-toolkit/dali-toolkit.h>
19 #include <dali-toolkit/devel-api/controls/table-view/table-view.h>
20 #include <dali/dali.h>
21 #include "generated/bezier-curve-frag.h"
22 #include "generated/bezier-curve-vert.h"
23 #include "shared/view.h"
28 using namespace Dali::Toolkit;
33 const Vector4 GRID_BACKGROUND_COLOR(0.85f, 0.85f, 0.85f, 1.0f);
34 const Vector4 CONTROL_POINT1_COLOR(Color::MAGENTA);
35 const Vector4 CONTROL_POINT2_COLOR(0.0, 0.9, 0.9, 1.0);
36 const Vector3 CONTROL_POINT1_ORIGIN(-100, 200, 0);
37 const Vector3 CONTROL_POINT2_ORIGIN(100, -200, 0);
38 const char* const CIRCLE1_IMAGE(DEMO_IMAGE_DIR "circle1.png");
39 const char* const CIRCLE2_IMAGE(DEMO_IMAGE_DIR "circle2.png");
40 const char* const ANIMATION_BACKGROUND(DEMO_IMAGE_DIR "slider-skin.9.png");
41 const char* APPLICATION_TITLE("Bezier curve animation");
42 const float ANIM_LEFT_FACTOR(0.2f);
43 const float ANIM_RIGHT_FACTOR(0.8f);
44 const int AXIS_LABEL_POINT_SIZE(7);
45 const float AXIS_LINE_SIZE(1.0f);
47 inline float Clamp(float v, float min, float max)
49 if(v < min) return min;
50 if(v > max) return max;
54 struct HandlePositionConstraint
56 void operator()(Vector3& current, const PropertyInputContainer& inputs)
58 Vector3 size(inputs[0]->GetVector3());
59 current.x = Clamp(current.x, minRelX * size.x, maxRelX * size.x);
60 current.y = Clamp(current.y, minRelY * size.y, maxRelY * size.y);
69 void AnimatingPositionConstraint(Vector3& current, const PropertyInputContainer& inputs)
71 float positionFactor(inputs[0]->GetFloat()); // -1 - 2
72 Vector3 size(inputs[1]->GetVector3());
74 current.x = size.x * (positionFactor - 0.5f); // size * (-1.5 - 1.5)
79 class BezierCurveExample : public ConnectionTracker
82 BezierCurveExample(Application& application)
83 : mApplication(application),
101 mRelativeDragPoint(),
102 mLastControlPointPosition1(),
103 mLastControlPointPosition2(),
104 mPositionFactorIndex(),
106 mControlPoint1Id(0.0f),
107 mControlPoint2Id(0.0f),
108 mControlPointScale(0.5f),
109 mControlPointZoomScale(mControlPointScale * 2.0),
112 // Connect to the Application's Init signal
113 mApplication.InitSignal().Connect(this, &BezierCurveExample::Create);
116 ~BezierCurveExample()
118 // Nothing to do here;
121 // The Init signal is received once (only) during the Application lifetime
122 void Create(Application& application)
124 Window window = mApplication.GetWindow();
125 window.KeyEventSignal().Connect(this, &BezierCurveExample::OnKeyEvent);
126 const Vector2 windowSize = window.GetSize();
127 const bool orientationPortrait = windowSize.width < windowSize.height;
129 unsigned int tableViewRows = 5;
130 unsigned int tableViewColumns = 1;
131 unsigned int rowPositionAdder = 1;
132 TableView::CellPosition gridPosition{1,0};
134 // Change layout if we're in landscape mode
135 if(!orientationPortrait)
138 tableViewColumns = 2;
139 rowPositionAdder = 0;
140 gridPosition = {0,1,4,1};
143 CreateBackground(window);
145 mControlPointScale = 0.5f;
146 mControlPointZoomScale = mControlPointScale * 2.0f;
148 mContentLayer = Layer::New();
149 mContentLayer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
150 mContentLayer.TouchedSignal().Connect(this, &BezierCurveExample::OnTouchLayer);
151 mContentLayer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
152 window.Add(mContentLayer);
154 TableView contentLayout = TableView::New(tableViewRows, tableViewColumns);
155 contentLayout.SetProperty(Dali::Actor::Property::NAME, "contentLayout");
156 contentLayout.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
157 contentLayout.SetCellPadding(Size(30, 30));
158 contentLayout.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER);
159 contentLayout.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
160 mContentLayer.Add(contentLayout);
162 // Create a TextLabel for the application title.
163 Toolkit::TextLabel label = Toolkit::TextLabel::New(APPLICATION_TITLE);
164 label.SetProperty(Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER");
165 label.SetProperty(Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER");
166 label.SetProperty(Toolkit::TextLabel::Property::TEXT_COLOR, Color::BLACK);
167 contentLayout.Add(label);
168 contentLayout.SetFitHeight(0);
170 mGrid = Control::New();
172 mGrid.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH);
173 mGrid.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT);
175 mGrid.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
176 mGrid.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
177 mGrid.SetBackgroundColor(GRID_BACKGROUND_COLOR);
179 contentLayout.AddChild(mGrid, gridPosition);
180 contentLayout.SetCellAlignment(1, HorizontalAlignment::CENTER, VerticalAlignment::CENTER);
182 CreateControlPoints(mGrid); // Control points constrained to double height of grid
183 CreateAxisLabels(mGrid);
185 mCoefficientLabel = TextLabel::New();
186 mCoefficientLabel.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
187 mCoefficientLabel.SetProperty(Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER");
188 mCoefficientLabel.SetProperty(Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER");
189 mCoefficientLabel.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
191 contentLayout.Add(mCoefficientLabel);
192 SetLabel(Vector2(0, 0), Vector2(1, 1));
193 contentLayout.SetCellAlignment(1 + rowPositionAdder, HorizontalAlignment::CENTER, VerticalAlignment::CENTER);
194 contentLayout.SetFitHeight(2);
196 // Setup Play button and 2 icons to show off current anim and linear anim
198 PushButton play = PushButton::New();
199 play.SetProperty(Dali::Actor::Property::NAME, "Play");
200 play.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
201 play.SetProperty(Button::Property::LABEL, "Play");
202 play.ClickedSignal().Connect(this, &BezierCurveExample::OnPlayClicked);
204 contentLayout.Add(play);
205 contentLayout.SetCellAlignment(2 + rowPositionAdder, HorizontalAlignment::CENTER, VerticalAlignment::CENTER);
206 contentLayout.SetFitHeight(2 + rowPositionAdder);
208 auto animContainer = Control::New();
209 animContainer.SetProperty(Dali::Actor::Property::NAME, "AnimationContainer");
210 animContainer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
211 animContainer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
213 auto animRail = Control::New();
214 animRail.SetProperty(Control::Property::BACKGROUND, Property::Map().Add(Visual::Property::TYPE, Visual::IMAGE).Add(ImageVisual::Property::URL, ANIMATION_BACKGROUND));
215 animRail.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS);
216 animRail.SetProperty(Actor::Property::SIZE_MODE_FACTOR, Vector3(0.666f, 0.2f, 1.0f));
217 animRail.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
218 animContainer.Add(animRail);
220 contentLayout.Add(animContainer);
221 contentLayout.SetFixedHeight(3 + rowPositionAdder, 150);
223 mAnimIcon1 = ImageView::New(CIRCLE1_IMAGE);
224 mAnimIcon1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
225 mAnimIcon1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
227 // Would like some means of setting and animating position as a percentage of
228 // parent size without using constraints, but this will have to suffice for the moment.
229 mPositionFactorIndex = mAnimIcon1.RegisterProperty("positionFactor", ANIM_LEFT_FACTOR); // range: 0-1 (+/- 1)
230 Constraint constraint = Constraint::New<Vector3>(mAnimIcon1, Actor::Property::POSITION, AnimatingPositionConstraint);
231 constraint.AddSource(Source(mAnimIcon1, mPositionFactorIndex));
232 constraint.AddSource(Source(animContainer, Actor::Property::SIZE));
235 animContainer.Add(mAnimIcon1);
237 // First UpdateCurve needs to run after size negotiation and after images have loaded
238 mGrid.OnRelayoutSignal().Connect(this, &BezierCurveExample::InitialUpdateCurve);
240 auto controlPoint1 = Control::DownCast(mControlPoint1);
243 controlPoint1.ResourceReadySignal().Connect(this, &BezierCurveExample::ControlPointReady);
246 auto controlPoint2 = Control::DownCast(mControlPoint2);
249 controlPoint2.ResourceReadySignal().Connect(this, &BezierCurveExample::ControlPointReady);
253 void ControlPointReady(Control control)
258 void InitialUpdateCurve(Actor actor)
263 void CreateBackground(Window window)
265 Toolkit::Control background = Dali::Toolkit::Control::New();
266 background.SetProperty(Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::CENTER);
267 background.SetProperty(Actor::Property::PARENT_ORIGIN, Dali::ParentOrigin::CENTER);
268 background.SetResizePolicy(Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS);
271 map.Insert(Visual::Property::TYPE, Visual::COLOR);
272 map.Insert(ColorVisual::Property::MIX_COLOR, Vector4(253 / 255.0f, 245 / 255.0f, 230 / 255.0f, 1.0f));
273 background.SetProperty(Dali::Toolkit::Control::Property::BACKGROUND, map);
274 window.Add(background);
277 void CreateCubic(Actor parent)
279 // Create a mesh to draw the cubic as a single line
280 mCurve = Actor::New();
281 mCurve.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
282 mCurve.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
284 Shader shader = Shader::New(SHADER_BEZIER_CURVE_VERT, SHADER_BEZIER_CURVE_FRAG);
286 Property::Map curveVertexFormat;
287 curveVertexFormat["aPosition"] = Property::VECTOR2;
288 mCurveVertices = VertexBuffer::New(curveVertexFormat);
289 Vector2 vertexData[2] = {Vector2(-0.5f, 0.5f), Vector2(0.5f, -0.5f)};
290 mCurveVertices.SetData(vertexData, 2);
292 Geometry geometry = Geometry::New();
293 geometry.AddVertexBuffer(mCurveVertices);
294 geometry.SetType(Geometry::LINE_STRIP);
296 Renderer renderer = Renderer::New(geometry, shader);
297 mCurve.AddRenderer(renderer);
301 Actor CreateControlPoint(Actor parent, const char* url, Vector3 position)
303 Actor actor = ImageView::New(url);
304 actor.SetProperty(Actor::Property::SCALE, mControlPointScale);
305 actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
306 // Curve and line drawing works off current value (i.e. last update frame's value). Need to animate to ensure
307 // initial position is baked to both frames before initially drawing the curve.
308 auto positionAnimation = Animation::New(0.01f);
309 positionAnimation.AnimateTo(Property(actor, Actor::Property::POSITION), position, AlphaFunction::EASE_IN_OUT);
310 positionAnimation.Play();
311 positionAnimation.FinishedSignal().Connect(this, &BezierCurveExample::OnAnimationFinished);
313 // Set up constraints for drag/drop
314 Constraint constraint = Constraint::New<Vector3>(actor, Actor::Property::POSITION, HandlePositionConstraint{-0.5, 0.5, -1, 1});
315 constraint.AddSource(Source(parent, Actor::Property::SIZE));
318 actor.TouchedSignal().Connect(this, &BezierCurveExample::OnTouchControlPoint);
322 Actor CreateControlLine(VertexBuffer vertexBuffer)
324 Actor line = Actor::New();
325 line.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
326 line.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
328 Shader shader = Shader::New(SHADER_BEZIER_CURVE_VERT, SHADER_BEZIER_CURVE_FRAG);
329 Geometry geometry = Geometry::New();
330 geometry.AddVertexBuffer(vertexBuffer);
331 geometry.SetType(Geometry::LINE_STRIP);
333 Renderer renderer = Renderer::New(geometry, shader);
334 line.AddRenderer(renderer);
338 void CreateControlPoints(Actor parent)
340 mControlPoint1 = CreateControlPoint(parent,
342 CONTROL_POINT1_ORIGIN);
343 mControlPoint1Id = mControlPoint1.GetProperty<int>(Actor::Property::ID);
345 mControlPoint2 = CreateControlPoint(parent,
347 CONTROL_POINT2_ORIGIN);
348 mControlPoint2Id = mControlPoint2.GetProperty<int>(Actor::Property::ID);
350 Property::Map lineVertexFormat;
351 lineVertexFormat["aPosition"] = Property::VECTOR2;
352 mLine1Vertices = VertexBuffer::New(lineVertexFormat);
353 mLine2Vertices = VertexBuffer::New(lineVertexFormat);
355 mControlLine1 = CreateControlLine(mLine1Vertices);
356 mControlLine2 = CreateControlLine(mLine2Vertices);
358 parent.Add(mControlLine1);
359 parent.Add(mControlLine2);
360 parent.Add(mControlPoint1);
361 parent.Add(mControlPoint2);
364 void CreateAxisLabels(Actor parent)
366 TextLabel progressionLabel = TextLabel::New("Progression");
367 progressionLabel.SetProperty(TextLabel::Property::POINT_SIZE, AXIS_LABEL_POINT_SIZE);
368 progressionLabel.SetProperty(Actor::Property::ORIENTATION, Quaternion(Radian(Degree(-90.0f)), Vector3::ZAXIS));
369 progressionLabel.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_LEFT);
370 progressionLabel.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_LEFT);
371 CreateLine(progressionLabel, ParentOrigin::BOTTOM_LEFT);
373 TextLabel timeLabel = TextLabel::New("Time");
374 timeLabel.SetProperty(TextLabel::Property::POINT_SIZE, AXIS_LABEL_POINT_SIZE);
375 timeLabel.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
376 timeLabel.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_LEFT);
377 CreateLine(timeLabel, ParentOrigin::TOP_LEFT);
379 parent.Add(progressionLabel);
380 parent.Add(timeLabel);
383 void CreateLine(Actor parent, const Vector3& parentOrigin)
385 Control control = Control::New();
386 control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
387 control.SetProperty(Actor::Property::PARENT_ORIGIN, parentOrigin);
388 control.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH);
389 control.SetProperty(Actor::Property::SIZE_HEIGHT, AXIS_LINE_SIZE);
390 control.SetBackgroundColor(Color::BLACK);
394 void SetLabel(Vector2 pos1, Vector2 pos2)
396 std::ostringstream oss;
397 oss.setf(std::ios::fixed, std::ios::floatfield);
399 oss << "( <color value='#971586'>" << pos1.x << ", " << pos1.y << ", </color>";
400 oss << "<color value='#e7640d'>" << pos2.x << ", " << pos2.y << "</color>";
401 oss << "<color value='black'> )</color>";
403 mCoefficientLabel.SetProperty(TextLabel::Property::TEXT, oss.str());
406 Vector2 AlignToGrid(Vector3 actorPos, Vector3 gridSize)
408 actorPos /= gridSize; // => -0.5 - 0.5
409 actorPos.x = Clamp(actorPos.x, -0.5f, 0.5f);
410 return Vector2(actorPos.x + 0.5f, 0.5f - actorPos.y);
413 void GetControlPoints(Vector2& pt1, Vector2& pt2)
415 Vector3 gridSize = mGrid.GetProperty<Vector3>(Actor::Property::SIZE); // Get target value
417 pt1 = AlignToGrid(mControlPoint1.GetCurrentProperty<Vector3>(Actor::Property::POSITION), gridSize);
418 pt2 = AlignToGrid(mControlPoint2.GetCurrentProperty<Vector3>(Actor::Property::POSITION), gridSize);
422 * @param[in] actor The actor to get the position from
423 * @param[out] point The point in the grid in the range -0.5 -> 0.5 in x and y, with y up.
424 * @param[out] position The actor position, floored to the nearest pixel
426 void GetPoint(Actor actor, Vector2& point, Vector2& position)
428 auto gridSize = mGrid.GetProperty<Vector3>(Actor::Property::SIZE); // Get target value
429 auto currentPosition = actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION); // Get constrained current value
431 position = Vector2(floor(currentPosition.x), floor(currentPosition.y));
433 point.x = Clamp(position.x / gridSize.x, -0.5f, 0.5f) + 0.5f;
434 point.y = 0.5f - position.y / gridSize.y;
439 Vector2 point1, point2;
440 Vector2 position1, position2;
441 const int NUMBER_OF_SEGMENTS(40);
443 GetPoint(mControlPoint1, point1, position1);
444 GetPoint(mControlPoint2, point2, position2);
446 if(position1 != mLastControlPointPosition1 ||
447 position2 != mLastControlPointPosition2)
449 mLastControlPointPosition1 = position1;
450 mLastControlPointPosition2 = position2;
452 SetLabel(point1, point2);
454 Path path = Path::New();
455 path.AddPoint(Vector3::ZERO);
456 path.AddPoint(Vector3(1.0f, 1.0f, 1.0f));
457 path.AddControlPoint(Vector3(point1.x, point1.y, 0));
458 path.AddControlPoint(Vector3(point2.x, point2.y, 0));
460 Dali::Vector<float> verts;
462 verts.Resize(2 * (NUMBER_OF_SEGMENTS + 1)); // 1 more point than segment
463 for(int i = 0; i <= NUMBER_OF_SEGMENTS; ++i)
465 Vector3 position, tangent;
466 path.Sample(i / float(NUMBER_OF_SEGMENTS), position, tangent);
467 verts[i * 2] = position.x - 0.5;
468 verts[i * 2 + 1] = 0.5 - position.y;
470 mCurveVertices.SetData(&verts[0], NUMBER_OF_SEGMENTS + 1);
472 Vector4 line1(-0.5f, 0.5f, point1.x - 0.5f, 0.5f - point1.y);
473 mLine1Vertices.SetData(line1.AsFloat(), 2);
475 Vector4 line2(0.5f, -0.5f, point2.x - 0.5f, 0.5f - point2.y);
476 mLine2Vertices.SetData(line2.AsFloat(), 2);
480 bool OnTouchControlPoint(Actor controlPoint, const TouchEvent& event)
482 if(event.GetPointCount() > 0)
484 if(event.GetState(0) == PointState::DOWN)
486 Vector2 screenPoint = event.GetScreenPosition(0);
487 mRelativeDragPoint = screenPoint;
488 mRelativeDragPoint -= Vector2(controlPoint.GetCurrentProperty<Vector3>(Actor::Property::POSITION));
489 mDragActor = controlPoint;
490 mDragAnimation = Animation::New(0.25f);
491 mDragAnimation.AnimateTo(Property(mDragActor, Actor::Property::SCALE), Vector3(mControlPointZoomScale, mControlPointZoomScale, 1.0f), AlphaFunction::EASE_OUT);
492 mDragAnimation.Play();
495 return false; // Don't mark this as consumed - let the layer get the touch
498 bool OnTouchLayer(Actor actor, const TouchEvent& event)
500 if(event.GetPointCount() > 0)
504 Vector3 position(event.GetScreenPosition(0));
506 mDragActor.SetProperty(Actor::Property::POSITION, position - Vector3(mRelativeDragPoint));
508 if(event.GetState(0) == PointState::UP) // Stop dragging
510 mDragAnimation = Animation::New(0.25f);
511 mDragAnimation.AnimateTo(Property(mDragActor, Actor::Property::SCALE), Vector3(mControlPointScale, mControlPointScale, 1.0f), AlphaFunction::EASE_IN);
512 mDragAnimation.FinishedSignal().Connect(this, &BezierCurveExample::OnAnimationFinished);
513 mDragAnimation.Play();
522 void OnAnimationFinished(Animation& animation)
527 bool OnPlayClicked(Button button)
529 if(!mBezierAnimation)
531 mBezierAnimation = Animation::New(mDuration);
533 mBezierAnimation.Stop();
534 mBezierAnimation.Clear();
536 float positionFactor = ANIM_LEFT_FACTOR;
539 positionFactor = ANIM_RIGHT_FACTOR;
548 GetControlPoints(pt1, pt2);
550 mBezierAnimation.AnimateTo(Property(mAnimIcon1, mPositionFactorIndex), positionFactor, AlphaFunction(pt1, pt2));
551 mBezierAnimation.Play();
556 * Main key event handler
558 void OnKeyEvent(const KeyEvent& event)
560 if(event.GetState() == KeyEvent::DOWN && (IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK)))
567 Application& mApplication;
568 Actor mControlPoint1;
569 Actor mControlPoint2;
572 ImageView mAnimIcon1;
573 ImageView mAnimIcon2;
576 TextLabel mCoefficientLabel;
580 Animation mDragAnimation;
581 Animation mBezierAnimation;
582 VertexBuffer mCurveVertices;
583 VertexBuffer mLine1Vertices;
584 VertexBuffer mLine2Vertices;
585 Vector2 mRelativeDragPoint;
586 Vector2 mLastControlPointPosition1;
587 Vector2 mLastControlPointPosition2;
588 Property::Index mPositionFactorIndex;
590 unsigned int mControlPoint1Id;
591 unsigned int mControlPoint2Id;
592 float mControlPointScale;
593 float mControlPointZoomScale;
597 int DALI_EXPORT_API main(int argc, char** argv)
599 Application application = Application::New(&argc, &argv);
601 BezierCurveExample test(application);
602 application.MainLoop();