2 * Copyright (c) 2014 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.
19 * This example shows how to use path animations in DALi
23 #include <dali-toolkit/dali-toolkit.h>
24 #include <dali/devel-api/actors/mesh-actor.h>
25 #include <dali/devel-api/geometry/mesh.h>
26 #include <dali/devel-api/geometry/mesh-factory.h>
27 #include <dali-toolkit/devel-api/controls/slider/slider.h>
32 #include "shared/view.h"
35 using namespace Dali::Toolkit;
40 const char* BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-default.png" );
41 const char* ACTOR_IMAGE( DALI_IMAGE_DIR "dali-logo.png" );
42 const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
43 const char* APPLICATION_TITLE( "Path Animation Example" );
44 }; //Unnamed namespace
47 * @brief The main class of the demo.
49 class PathController : public ConnectionTracker
53 PathController( Application& application )
54 : mApplication( application )
56 // Connect to the Application's Init signal
57 mApplication.InitSignal().Connect( this, &PathController::Create );
62 // Nothing to do here.
66 * Create a control composed of a label and an slider
67 * @param[in] label The text to be displayed ny the label
68 * @param[in] size The size of the slider
69 * @param[in] callback Pointer to the callback function to be called when user moves the slider
71 Actor CreateVectorComponentControl( const std::string& label, const Vector3& size, bool(PathController::*callback)(Dali::Toolkit::Slider,float) )
73 TextLabel text = TextLabel::New(label);
74 text.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH );
75 text.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
76 text.SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
78 Slider slider = Slider::New();
79 slider.SetAnchorPoint( AnchorPoint::CENTER_LEFT);
80 slider.SetParentOrigin( ParentOrigin::CENTER_RIGHT);
81 slider.SetProperty(Slider::Property::LOWER_BOUND, -1.0f );
82 slider.SetProperty(Slider::Property::UPPER_BOUND, 1.0f );
84 Property::Array marks;
86 for(unsigned short i(0); i<21; ++i )
88 marks.PushBack( mark );
92 slider.SetProperty(Slider::Property::MARKS, marks);
93 slider.SetProperty(Slider::Property::SNAP_TO_MARKS, true );
95 slider.SetScale( 0.5f );
96 slider.ValueChangedSignal().Connect(this,callback);
102 * Crate all the GUI controls
104 void CreateControls()
106 Stage stage = Stage::GetCurrent();
109 Dali::Layer controlsLayer = Dali::Layer::New();
110 controlsLayer.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
111 controlsLayer.SetSizeModeFactor( Vector3( 1.0f, 0.3f, 1.0f ) );
112 controlsLayer.SetPosition( 0.0f, stage.GetSize().y*0.8f, 0.0f );
113 controlsLayer.SetAnchorPoint( AnchorPoint::TOP_LEFT);
114 controlsLayer.SetParentOrigin( ParentOrigin::TOP_LEFT);
115 controlsLayer.TouchedSignal().Connect(this, &PathController::OnTouchGuiLayer);
116 stage.Add( controlsLayer );
118 Vector3 textInputSize( stage.GetSize().x, stage.GetSize().y*0.04f, 0.0f );
119 Actor control0 = CreateVectorComponentControl("x:", textInputSize, &PathController::OnSliderXValueChange );
120 control0.SetY( stage.GetSize().y*0.05f );
121 control0.SetAnchorPoint(AnchorPoint::TOP_LEFT);
122 controlsLayer.Add( control0 );
124 Actor control1 = CreateVectorComponentControl("y:", textInputSize, &PathController::OnSliderYValueChange );
125 control1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
126 control1.SetParentOrigin( ParentOrigin::BOTTOM_LEFT );
127 control1.SetPosition(0.0f,stage.GetSize().y*0.01,0.0f);
128 control0.Add( control1 );
130 Actor control2 =CreateVectorComponentControl("z:", textInputSize, &PathController::OnSliderZValueChange );
131 control2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
132 control2.SetParentOrigin( ParentOrigin::BOTTOM_LEFT );
133 control2.SetPosition(0.0f,stage.GetSize().y*0.01,0.0f);
134 control1.Add( control2 );
138 * Draws the path and the control points for the path
139 * @param[in] resolution Number of segments for the path.
141 void DrawPath( unsigned int resolution )
143 //Create path mesh actor
144 Dali::MeshData meshData = MeshFactory::NewPath( mPath, resolution );
145 Dali::Material material = Material::New("LineMaterial");
146 material.SetDiffuseColor( Vector4(0.0f,0.0f,0.0f,1.0f));
147 meshData.SetMaterial(material);
148 Dali::Mesh mesh = Dali::Mesh::New( meshData );
151 mContentLayer.Remove( mMeshPath );
153 mMeshPath = Dali::MeshActor::New( mesh );
154 mMeshPath.SetAnchorPoint( AnchorPoint::TOP_LEFT );
155 mMeshPath.SetParentOrigin( ParentOrigin::TOP_LEFT );
156 mContentLayer.Add( mMeshPath );
159 ////Create mesh connecting interpolation points and control points
160 std::vector<Dali::MeshData::Vertex> vVertex;
161 std::vector<unsigned short> vIndex;
162 size_t pointCount = mPath.GetPointCount();
163 size_t controlPointIndex = 0;
164 for( size_t i(0); i<pointCount; ++i )
166 vVertex.push_back( MeshData::Vertex(mPath.GetPoint(i),Vector2::ZERO, Vector3::ZERO ) );
169 vVertex.push_back( MeshData::Vertex(mPath.GetControlPoint(controlPointIndex),Vector2::ZERO, Vector3::ZERO ));
170 vVertex.push_back( MeshData::Vertex(mPath.GetControlPoint(controlPointIndex+1),Vector2::ZERO, Vector3::ZERO ));
172 controlPointIndex += 2;
175 size_t segmentCount = 2*(pointCount-2)+2;
176 unsigned short index=0;
177 for( size_t i(0); i<segmentCount; ++i, ++index )
179 vIndex.push_back(index);
180 vIndex.push_back(index+1);
188 meshData.SetLineData( vVertex, vIndex, material );
189 meshData.SetMaterial(material);
190 mesh = Dali::Mesh::New( meshData );
193 mContentLayer.Remove( mMeshHandlers );
195 mMeshHandlers = Dali::MeshActor::New( mesh );
196 mMeshHandlers.SetAnchorPoint( AnchorPoint::TOP_LEFT );
197 mMeshHandlers.SetParentOrigin( ParentOrigin::TOP_LEFT );
198 mContentLayer.Add( mMeshHandlers );
201 //Create actors representing interpolation points
203 for( size_t i(0); i<pointCount; ++i )
205 if( !mControlPoint[index] )
207 mControlPoint[index] = Toolkit::CreateSolidColorActor(Vector4(1.0f,1.0f,1.0f,1.0f));
208 mControlPoint[index].SetParentOrigin( ParentOrigin::TOP_LEFT);
209 mControlPoint[index].SetAnchorPoint( AnchorPoint::CENTER );
210 mControlPoint[index].SetSize( 20.0f, 20.0f );
211 mContentLayer.Add(mControlPoint[index]);
214 std::string name( "Knot");
216 mControlPoint[index].SetName( name );
217 mControlPoint[index].SetPosition( mPath.GetPoint(i) );
218 mControlPoint[index].SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
222 //Create actors representing control points
223 size_t controlPointCount=2*(pointCount-1);
224 for( size_t i(0); i<controlPointCount; ++i )
226 if( !mControlPoint[index])
228 mControlPoint[index] = Toolkit::CreateSolidColorActor(Vector4(1.0f,1.0f,1.0f,1.0f));
229 mControlPoint[index].SetParentOrigin( ParentOrigin::TOP_LEFT);
230 mControlPoint[index].SetAnchorPoint( AnchorPoint::CENTER );
231 mControlPoint[index].SetSize( 20.0f, 20.0f );
232 mContentLayer.Add(mControlPoint[index]);
234 std::string name( "ControlPoint");
236 mControlPoint[index].SetName( name );
237 mControlPoint[index].SetPosition( mPath.GetControlPoint(i) );
238 mControlPoint[index].SetColor( Vector4(1.0f,0.0f,0.0f,1.0f));
244 * Create the path animation.
246 void CreateAnimation()
250 mAnimation = Animation::New( 2.0f );
256 mActor.SetOrientation( Quaternion() );
259 mAnimation.Animate( mActor, mPath, mForward );
260 mAnimation.SetLooping( true );
265 * Get closest control point.void
266 * @param[in] point Point from where the distance is computed
267 * @return The closest actor if the distance is beyond 0.5cm or an uninitialized actor otherwise
269 Actor GetClosestActor(const Vector3& point)
271 size_t pointCount = mPath.GetPointCount();
272 size_t controlPointCount = 3*pointCount - 2;
274 float minDistance = 1.0/0.0;
276 for( size_t i(0); i<controlPointCount; ++i )
278 Vector3 v = mControlPoint[i].GetCurrentPosition() - point;
279 float distance = v.LengthSquared();
280 if( distance < minDistance )
282 result = mControlPoint[i];
283 minDistance = distance;
287 Vector2 dpi = Dali::Stage::GetCurrent().GetDpi();
288 float distanceTreshold = 0.2f * dpi.x * 0.2f * dpi.x;
290 if( minDistance < distanceTreshold )
301 * Callback called when the background layer is touched
303 bool OnTouchLayer(Actor actor, const TouchEvent& event)
305 if(event.GetPointCount()>0)
307 const TouchPoint& point = event.GetPoint(0);
309 if(point.state==TouchPoint::Up)
314 else if(point.state==TouchPoint::Down)
316 Vector3 touchPoint = Vector3(event.GetPoint(0).screen.x, event.GetPoint(0).screen.y, 0.0f);
319 mDragActor = GetClosestActor( touchPoint );
320 if( !mDragActor && mPath.GetPointCount() < 10 )
323 Vector3 lastPoint = mPath.GetPoint( mPath.GetPointCount()-1);
324 mPath.AddPoint( touchPoint );
325 Vector3 displacement = (touchPoint-lastPoint)/8;
326 mPath.AddControlPoint( lastPoint + displacement );
327 mPath.AddControlPoint( touchPoint - displacement);
334 else if( mDragActor && point.state==TouchPoint::Motion )
336 Vector3 touchPoint = Vector3(event.GetPoint(0).screen.x, event.GetPoint(0).screen.y, 0.0f);
337 std::string actorName(mDragActor.GetName());
338 if( actorName.compare(0, 4, "Knot") == 0)
340 int index = actorName[4];
341 mPath.GetPoint(index) = touchPoint;
345 int index = actorName[12];
346 mPath.GetControlPoint(index) = touchPoint;
357 bool OnTouchGuiLayer(Actor actor, const TouchEvent& event)
363 * Callback called when user changes slider X
364 * @param[in] slider The slider that has generated the signal
365 * @param[in] value The new value
367 bool OnSliderXValueChange( Slider s, float value)
369 if( fabs( value ) - Math::MACHINE_EPSILON_1000 < 0.0f )
383 * Callback called when user changes slider Y
384 * @param[in] slider The slider that has generated the signal
385 * @param[in] value The new value
387 bool OnSliderYValueChange( Slider s, float value)
389 if( fabs( value ) - Math::MACHINE_EPSILON_1000 < 0.0f )
402 * Callback called when user changes slider Z
403 * @param[in] slider The slider that has generated the signal
404 * @param[in] value The new value
406 bool OnSliderZValueChange( Slider s, float value)
408 if( fabs( value ) - Math::MACHINE_EPSILON_1000 < 0.0f )
422 * Main key event handler.
423 * Quit on escape key.
425 void OnKeyEvent(const KeyEvent& event)
427 if( event.state == KeyEvent::Down )
429 if( IsKey( event, Dali::DALI_KEY_ESCAPE ) ||
430 IsKey( event, Dali::DALI_KEY_BACK ) )
438 * One-time setup in response to Application InitSignal.
440 void Create( Application& application )
442 // Get a handle to the stage:
443 Stage stage = Stage::GetCurrent();
445 // Connect to input event signals:
446 stage.KeyEventSignal().Connect(this, &PathController::OnKeyEvent);
448 // Create a default view with a default tool bar:
449 Toolkit::Control view; ///< The View instance.
450 Toolkit::ToolBar toolBar; ///< The View's Toolbar.
451 mContentLayer = DemoHelper::CreateView( mApplication,
457 mContentLayer.SetDrawMode( DrawMode::OVERLAY );
459 mContentLayer.TouchedSignal().Connect(this, &PathController::OnTouchLayer);
462 TextLabel title = DemoHelper::CreateToolBarLabel( APPLICATION_TITLE );
463 toolBar.AddControl( title, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Alignment::HorizontalCenter );
466 mPath = Dali::Path::New();
467 mPath.AddPoint( Vector3( 10.0f, stage.GetSize().y*0.5f, 0.0f ));
468 mPath.AddPoint( Vector3( stage.GetSize().x*0.5f, stage.GetSize().y*0.5f, 0.0f ));
469 mPath.GenerateControlPoints(0.25f);
473 Image img = ResourceImage::New(ACTOR_IMAGE);
474 mActor = ImageActor::New( img );
475 mActor.SetAnchorPoint( AnchorPoint::CENTER );
476 mActor.SetSize( 100, 50, 1 );
477 mContentLayer.Add( mActor );
484 Application& mApplication;
486 Layer mContentLayer; ///< The content layer
488 Path mPath; ///< The path used in the animation
489 ImageActor mActor; ///< Actor being animated
490 Vector3 mForward; ///< Current forward vector
491 Animation mAnimation; ///< Path animation
493 MeshActor mMeshPath; ///< Mesh actor for the path
494 MeshActor mMeshHandlers; ///< Mesh actor for the handlers of the path
496 Actor mControlPoint[28]; ///< ImageActors represeting control points of the path
498 Actor mDragActor; ///< Reference to the actor currently being dragged
502 void RunTest( Application& application )
504 PathController test( application );
506 application.MainLoop();
509 /** Entry point for Linux & Tizen applications */
510 int main( int argc, char **argv )
512 Application application = Application::New( &argc, &argv, DALI_DEMO_THEME_PATH );
514 RunTest( application );