Commit 6d70b1443557e5f588ff932459aac0eff2053f05

Authored by Ferran Sole
1 parent 59f4f735

Added path animation demo

Change-Id: I4a723457a7cfaca87a20f771aa64f187ea160453
com.samsung.dali-demo.xml
... ... @@ -79,4 +79,7 @@
79 79 <ui-application appid="animated-shapes.example" exec="/usr/apps/com.samsung.dali-demo/bin/animated-shapes.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
80 80 <label>Animated shapes</label>
81 81 </ui-application>
  82 + <ui-application appid="path-animation.example" exec="/usr/apps/com.samsung.dali-demo/bin/path-animation.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
  83 + <label>Path Animation</label>
  84 + </ui-application>
82 85 </manifest>
... ...
demo/dali-demo.cpp
... ... @@ -43,6 +43,7 @@ int main(int argc, char **argv)
43 43 demo.AddExample(Example("image-scaling-irregular-grid.example", "Image Scaling Modes"));
44 44 demo.AddExample(Example("text-view.example", "Text View"));
45 45 demo.AddExample(Example("animated-shapes.example", "Animated Shapes"));
  46 + demo.AddExample(Example("path-animation.example", "Path Animation"));
46 47 app.MainLoop();
47 48  
48 49 return 0;
... ...
examples/path-animation/path-animation.cpp 0 → 100644
  1 +/*
  2 + * Copyright (c) 2014 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 +/**
  19 + * This example shows how to use path animations in DALi
  20 + */
  21 +
  22 +// EXTERNAL INCLUDES
  23 +#include <dali-toolkit/dali-toolkit.h>
  24 +
  25 +// INTERNAL INCLUDES
  26 +#include "shared/view.h"
  27 +
  28 +using namespace Dali;
  29 +using namespace Dali::Toolkit;
  30 +
  31 +
  32 +namespace
  33 +{
  34 +const char* BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-default.png" );
  35 +const char* ACTOR_IMAGE( DALI_IMAGE_DIR "dali-logo.png" );
  36 +const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
  37 +const char* APPLICATION_TITLE( "Path Example" );
  38 +}; //Unnamed namespace
  39 +
  40 +/**
  41 + * @brief The main class of the demo.
  42 + */
  43 +class PathController : public ConnectionTracker
  44 +{
  45 +public:
  46 +
  47 + PathController( Application& application )
  48 + : mApplication( application )
  49 + {
  50 + // Connect to the Application's Init signal
  51 + mApplication.InitSignal().Connect( this, &PathController::Create );
  52 + }
  53 +
  54 + ~PathController()
  55 + {
  56 + // Nothing to do here.
  57 + }
  58 +
  59 + /**
  60 + * One-time setup in response to Application InitSignal.
  61 + */
  62 + void Create( Application& application )
  63 + {
  64 + // Get a handle to the stage:
  65 + Stage stage = Stage::GetCurrent();
  66 +
  67 + // Connect to input event signals:
  68 + stage.KeyEventSignal().Connect(this, &PathController::OnKeyEvent);
  69 +
  70 + // Create a default view with a default tool bar:
  71 + Toolkit::View view; ///< The View instance.
  72 + Toolkit::ToolBar toolBar; ///< The View's Toolbar.
  73 + mContentLayer = DemoHelper::CreateView( mApplication,
  74 + view,
  75 + toolBar,
  76 + BACKGROUND_IMAGE,
  77 + TOOLBAR_IMAGE,
  78 + "" );
  79 +
  80 + mContentLayer.TouchedSignal().Connect(this, &PathController::OnTouchLayer);
  81 +
  82 + //Title
  83 + TextView title = TextView::New();
  84 + toolBar.AddControl( title, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Alignment::HorizontalCenter );
  85 + Font font = Font::New();
  86 + title.SetText( APPLICATION_TITLE );
  87 + title.SetSize( font.MeasureText( APPLICATION_TITLE ) );
  88 + title.SetStyleToCurrentText(DemoHelper::GetDefaultTextStyle());
  89 +
  90 + //Path
  91 + mPath = Dali::Path::New();
  92 + mPath.AddPoint( Vector3( 10.0f, stage.GetSize().y*0.5f, 0.0f ));
  93 + mPath.AddPoint( Vector3( stage.GetSize().x*0.5f, stage.GetSize().y*0.3f, 0.0f ));
  94 + mPath.GenerateControlPoints(0.25f);
  95 + DrawPath( 200u );
  96 +
  97 + //Actor
  98 + ImageAttributes attributes;
  99 + Image img = ResourceImage::New(ACTOR_IMAGE, attributes );
  100 + mActor = ImageActor::New( img );
  101 + mActor.SetPosition( Vector3( 10.0f, stage.GetSize().y*0.5f, 0.0f ) );
  102 + mActor.SetAnchorPoint( AnchorPoint::CENTER );
  103 + mActor.SetSize( 100, 50, 1 );
  104 + stage.Add( mActor );
  105 +
  106 + mForward = Vector3::XAXIS;
  107 + CreateAnimation();
  108 +
  109 + Dali::TextActor forwardLabel = TextActor::New("Forward Vector");
  110 + forwardLabel.SetPosition( 10.0f, stage.GetSize().y - 60.0f, 0.0f );
  111 + forwardLabel.SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
  112 + forwardLabel.SetAnchorPoint( AnchorPoint::CENTER_LEFT);
  113 + mContentLayer.Add( forwardLabel );
  114 +
  115 + //TextInput
  116 + Dali::Layer textInputLayer = Dali::Layer::New();
  117 + textInputLayer.SetSize( 400.0f, 30.0f, 0.0 );
  118 + textInputLayer.SetPosition( 0.0f, stage.GetSize().y - 30.0f, 0.0f );
  119 + textInputLayer.SetAnchorPoint( AnchorPoint::TOP_LEFT);
  120 + textInputLayer.SetParentOrigin( ParentOrigin::TOP_LEFT);
  121 + stage.Add( textInputLayer );
  122 + Dali::TextActor label = TextActor::New("X:");
  123 + label.SetPosition( 10.0f, 0.0f, 0.0f );
  124 + label.SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
  125 + label.SetAnchorPoint( AnchorPoint::CENTER_LEFT);
  126 + textInputLayer.Add( label );
  127 + TextStyle style;
  128 + style.SetTextColor( Vector4( 0.0f, 0.0f ,0.0f, 1.0f ));
  129 + mTextInput[0] = TextInput::New();
  130 + mTextInput[0].SetInitialText("1.0");
  131 + mTextInput[0].SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
  132 + mTextInput[0].SetAnchorPoint( AnchorPoint::CENTER_LEFT);
  133 + mTextInput[0].SetParentOrigin( ParentOrigin::CENTER_RIGHT);
  134 + mTextInput[0].SetPosition( 10.0f, 0.0f, 0.0f );
  135 + mTextInput[0].SetSize( 70.0f, 0.0f, 0.0f );
  136 + mTextInput[0].SetTextAlignment(Alignment::HorizontalCenter );
  137 + mTextInput[0].SetMaxCharacterLength( 5 );
  138 + mTextInput[0].SetNumberOfLinesLimit(1);
  139 + mTextInput[0].ApplyStyleToAll( style );
  140 + mTextInput[0].SetProperty( mTextInput[0].GetPropertyIndex("cursor-color"), Vector4(0.0f,0.0f,0.0f,1.0f) );
  141 + mTextInput[0].SetBackgroundColor( Vector4(0.8f,1.0f,0.8f, 0.4f));
  142 + mTextInput[0].InputFinishedSignal().Connect(this, &PathController::OnTextInputEnd);
  143 + mTextInput[0].SetEditOnTouch();
  144 + label.Add( mTextInput[0]);
  145 + label = TextActor::New("Y:");
  146 + label.SetPosition( 160.0f,0.0f, 0.0f );
  147 + label.SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
  148 + label.SetAnchorPoint( AnchorPoint::CENTER_LEFT);
  149 + textInputLayer.Add( label );
  150 + mTextInput[1] = TextInput::New();
  151 + mTextInput[1].SetInitialText("0.0");
  152 + mTextInput[1].SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
  153 + mTextInput[1].SetAnchorPoint( AnchorPoint::CENTER_LEFT);
  154 + mTextInput[1].SetParentOrigin( ParentOrigin::CENTER_RIGHT);
  155 + mTextInput[1].SetPosition( 10.0f, 0.0f, 0.0f );
  156 + mTextInput[1].SetSize( 70.0f, 0.0f, 0.0f );
  157 + mTextInput[1].SetTextAlignment(Alignment::HorizontalCenter );
  158 + mTextInput[1].SetMaxCharacterLength( 5 );
  159 + mTextInput[1].SetNumberOfLinesLimit(1);
  160 + mTextInput[1].ApplyStyleToAll( style );
  161 + mTextInput[1].SetProperty( mTextInput[1].GetPropertyIndex("cursor-color"), Vector4(0.0f,0.0f,0.0f,1.0f) );
  162 + mTextInput[1].SetBackgroundColor( Vector4(0.8f,1.0f,0.8f, 0.4f));
  163 + mTextInput[1].InputFinishedSignal().Connect(this, &PathController::OnTextInputEnd);
  164 + label.Add( mTextInput[1]);
  165 + label = TextActor::New("Z:");
  166 + label.SetPosition( 310.0f, 0.0f, 0.0f );
  167 + label.SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
  168 + label.SetAnchorPoint( AnchorPoint::CENTER_LEFT);
  169 + textInputLayer.Add( label );
  170 + mTextInput[2] = TextInput::New();
  171 + mTextInput[2].SetInitialText("0.0");
  172 + mTextInput[2].SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
  173 + mTextInput[2].SetAnchorPoint( AnchorPoint::CENTER_LEFT);
  174 + mTextInput[2].SetParentOrigin( ParentOrigin::CENTER_RIGHT);
  175 + mTextInput[2].SetPosition( 10.0f, 0.0f, 0.0f );
  176 + mTextInput[2].SetSize( 70.0f, 0.0f, 0.0f );
  177 + mTextInput[2].SetTextAlignment(Alignment::HorizontalCenter );
  178 + mTextInput[2].SetMaxCharacterLength( 5 );
  179 + mTextInput[2].SetNumberOfLinesLimit(1);
  180 + mTextInput[2].ApplyStyleToAll( style );
  181 + mTextInput[2].SetProperty( mTextInput[2].GetPropertyIndex("cursor-color"), Vector4(0.0f,0.0f,0.0f,1.0f) );
  182 + mTextInput[2].SetBackgroundColor( Vector4(0.8f,1.0f,0.8f, 0.4f));
  183 + mTextInput[2].InputFinishedSignal().Connect(this, &PathController::OnTextInputEnd);
  184 + label.Add( mTextInput[2]);
  185 + }
  186 +
  187 + /**
  188 + * Create an actor representing a control point of the curve
  189 + * @param[in] name Name of the actor
  190 + * @param[in] size Size of the containing actor
  191 + * @param[in] imageSize Size of the imageActor
  192 + * @param[in] color Color of the imageActor
  193 + */
  194 + Actor CreateControlPoint(const std::string& name, const Vector3& size, const Vector3& imageSize, const Vector4& color )
  195 + {
  196 + Actor actor = Actor::New();
  197 + actor.SetParentOrigin( ParentOrigin::TOP_LEFT);
  198 + actor.SetAnchorPoint( AnchorPoint::CENTER );
  199 + actor.SetSize( size );
  200 + actor.SetName( name );
  201 + actor.TouchedSignal().Connect(this, &PathController::OnTouchPoint);
  202 +
  203 + ImageActor imageActor = Toolkit::CreateSolidColorActor(color);
  204 + imageActor.SetColor(Vector4(1.0f,0.0f,0.0f,1.0f));
  205 + imageActor.SetParentOrigin( ParentOrigin::CENTER);
  206 + imageActor.SetAnchorPoint( AnchorPoint::CENTER );
  207 + imageActor.SetSize( imageSize );
  208 + actor.Add(imageActor );
  209 +
  210 + return actor;
  211 + }
  212 +
  213 + /**
  214 + * Draws the path and the control points for the path
  215 + * @param[in] resolution Number of segments for the path.
  216 + */
  217 + void DrawPath( unsigned int resolution )
  218 + {
  219 + Stage stage = Dali::Stage::GetCurrent();
  220 +
  221 + //Create path mesh actor
  222 + Dali::MeshData meshData = MeshFactory::NewPath( mPath, resolution );
  223 + Dali::Material material = Material::New("LineMaterial");
  224 + material.SetDiffuseColor( Vector4(0.0f,0.0f,0.0f,1.0f));
  225 + meshData.SetMaterial(material);
  226 + Dali::Mesh mesh = Dali::Mesh::New( meshData );
  227 + if( mMeshPath )
  228 + {
  229 + stage.Remove( mMeshPath );
  230 + }
  231 + mMeshPath = Dali::MeshActor::New( mesh );
  232 + mMeshPath.SetAnchorPoint( AnchorPoint::TOP_LEFT );
  233 + mMeshPath.SetParentOrigin( ParentOrigin::TOP_LEFT );
  234 + stage.Add( mMeshPath );
  235 +
  236 +
  237 + ////Create mesh connecting interpolation points and control points
  238 + std::vector<Dali::MeshData::Vertex> vVertex;
  239 + std::vector<unsigned short> vIndex;
  240 + size_t pointCount = mPath.GetPointCount();
  241 + size_t controlPointIndex = 0;
  242 + for( size_t i(0); i<pointCount; ++i )
  243 + {
  244 + vVertex.push_back( MeshData::Vertex(mPath.GetPoint(i),Vector2::ZERO, Vector3::ZERO ) );
  245 + if( i<pointCount-1)
  246 + {
  247 + vVertex.push_back( MeshData::Vertex(mPath.GetControlPoint(controlPointIndex),Vector2::ZERO, Vector3::ZERO ));
  248 + vVertex.push_back( MeshData::Vertex(mPath.GetControlPoint(controlPointIndex+1),Vector2::ZERO, Vector3::ZERO ));
  249 + }
  250 + controlPointIndex += 2;
  251 + }
  252 +
  253 + size_t segmentCount = 2*(pointCount-2)+2;
  254 + unsigned short index=0;
  255 + for( size_t i(0); i<segmentCount; ++i, ++index )
  256 + {
  257 + vIndex.push_back(index);
  258 + vIndex.push_back(index+1);
  259 +
  260 + if( ~i & 1 )
  261 + {
  262 + index++;
  263 + }
  264 + }
  265 +
  266 + meshData.SetLineData( vVertex, vIndex, material );
  267 + meshData.SetMaterial(material);
  268 + mesh = Dali::Mesh::New( meshData );
  269 + if( mMeshHandlers )
  270 + {
  271 + stage.Remove( mMeshHandlers );
  272 + }
  273 + mMeshHandlers = Dali::MeshActor::New( mesh );
  274 + mMeshHandlers.SetAnchorPoint( AnchorPoint::TOP_LEFT );
  275 + mMeshHandlers.SetParentOrigin( ParentOrigin::TOP_LEFT );
  276 + stage.Add( mMeshHandlers );
  277 +
  278 +
  279 + //Create actors representing interpolation points
  280 + for( size_t i(0); i<pointCount; ++i )
  281 + {
  282 + if( !mKnot[i] )
  283 + {
  284 + std::string name( "Knot");
  285 + name.push_back(i);
  286 + mKnot[i] = CreateControlPoint( name, Vector3(150.0f,150.0f,0.0f), Vector3(20.0f,20.0f,0.0f), Vector4(0.0f,0.0f,0.0f,1.0f) );
  287 + mContentLayer.Add(mKnot[i] );
  288 + }
  289 +
  290 + mKnot[i].SetPosition( mPath.GetPoint(i) );
  291 + }
  292 +
  293 + //Create actors representing control points
  294 + size_t controlPointCount=2*(pointCount-1);
  295 + for( size_t i(0); i<controlPointCount; ++i )
  296 + {
  297 + if( !mControlPoint[i])
  298 + {
  299 + std::string name( "ControlPoint");
  300 + name.push_back(i);
  301 + mControlPoint[i] = CreateControlPoint( name, Vector3(150.0f,150.0f,0.0f), Vector3(20.0f,20.0f,0.0f), Vector4(1.0f,0.0f,0.0f,1.0f) );
  302 + mContentLayer.Add(mControlPoint[i] );
  303 + }
  304 +
  305 + mControlPoint[i].SetPosition( mPath.GetControlPoint(i) );
  306 + }
  307 + }
  308 +
  309 + bool OnTouchPoint(Actor actor, const TouchEvent& event)
  310 + {
  311 + if(event.GetPointCount()>0)
  312 + {
  313 + const TouchPoint& point = event.GetPoint(0);
  314 +
  315 + if(point.state==TouchPoint::Down)
  316 + {
  317 + // Start dragging
  318 + mDragActor = actor;
  319 + }
  320 + }
  321 + return false;
  322 + }
  323 +
  324 + bool OnTouchLayer(Actor actor, const TouchEvent& event)
  325 + {
  326 + if(event.GetPointCount()>0)
  327 + {
  328 + const TouchPoint& point = event.GetPoint(0);
  329 +
  330 + if(point.state==TouchPoint::Up)
  331 + {
  332 + //Stop dragging
  333 + mDragActor.Reset();
  334 + }
  335 + else if(!mDragActor && point.state==TouchPoint::Down && mPath.GetPointCount()<10 )
  336 + {
  337 + // Add new point
  338 + const TouchPoint& point = event.GetPoint(0);
  339 + Vector3 newPoint = Vector3(point.screen.x, point.screen.y, 0.0f);
  340 +
  341 + size_t pointCount = mPath.GetPointCount();
  342 + Vector3 lastPoint = mPath.GetPoint( pointCount-1);
  343 + mPath.AddPoint( newPoint );
  344 +
  345 + Vector3 displacement = (newPoint-lastPoint)/8;
  346 +
  347 + mPath.AddControlPoint( lastPoint + displacement );
  348 + mPath.AddControlPoint( newPoint - displacement);
  349 +
  350 + DrawPath( 200u );
  351 + CreateAnimation();
  352 + }
  353 + else
  354 + {
  355 + if( mDragActor )
  356 + {
  357 + const TouchPoint& point = event.GetPoint(0);
  358 + Vector3 newPosition = Vector3(point.screen.x, point.screen.y, 0.0f);
  359 +
  360 + std::string actorName(mDragActor.GetName());
  361 +
  362 + if( actorName.compare(0, 4, "Knot") == 0)
  363 + {
  364 + int index = actorName[4];
  365 + mPath.GetPoint(index) = newPosition;
  366 + }
  367 + else
  368 + {
  369 + int index = actorName[12];
  370 + mPath.GetControlPoint(index) = newPosition;
  371 + }
  372 +
  373 + DrawPath( 200u );
  374 + CreateAnimation();
  375 + }
  376 + }
  377 + }
  378 + return false;
  379 + }
  380 +
  381 + /**
  382 + * Main key event handler.
  383 + * Quit on escape key.
  384 + */
  385 + void OnKeyEvent(const KeyEvent& event)
  386 + {
  387 + if( event.state == KeyEvent::Down )
  388 + {
  389 + if( IsKey( event, Dali::DALI_KEY_ESCAPE ) ||
  390 + IsKey( event, Dali::DALI_KEY_BACK ) )
  391 + {
  392 + mApplication.Quit();
  393 + }
  394 + }
  395 + }
  396 +
  397 + /**
  398 + * Callback called when user end to input text in any of the TextInput
  399 + * @param[in] textInput The text input that has generated the signal
  400 + */
  401 + void OnTextInputEnd( TextInput textInput)
  402 + {
  403 + mForward.x = (float)atof( mTextInput[0].GetText().c_str() );
  404 + mForward.y = (float)atof( mTextInput[1].GetText().c_str() );
  405 + mForward.z = (float)atof( mTextInput[2].GetText().c_str() );
  406 + CreateAnimation();
  407 + }
  408 +
  409 + /**
  410 + * Create the path animation.
  411 + */
  412 + void CreateAnimation()
  413 + {
  414 + if( !mAnimation )
  415 + {
  416 + mAnimation = Animation::New( 2.0f );
  417 + }
  418 + else
  419 + {
  420 + mAnimation.Pause();
  421 + mAnimation.Clear();
  422 + mActor.SetRotation( Quaternion() );
  423 + }
  424 +
  425 + mAnimation.Animate( mActor, mPath, mForward );
  426 + mAnimation.SetLooping( true );
  427 + mAnimation.Play();
  428 + }
  429 +
  430 +private:
  431 + Application& mApplication;
  432 +
  433 + Layer mContentLayer; ///< The content layer
  434 +
  435 + Path mPath; ///< The path used in the animation
  436 + ImageActor mActor; ///< Actor being animated
  437 + Vector3 mForward; ///< Current forward vector
  438 + Animation mAnimation; ///< Path animation
  439 +
  440 + MeshActor mMeshPath; ///< Mesh actor for the path
  441 + MeshActor mMeshHandlers; ///< Mesh actor for the segments connecting points and control points
  442 + Actor mKnot[10]; ///< ImageActors for the interpolation points
  443 + Actor mControlPoint[18]; ///< ImageActors for the control points
  444 +
  445 + Actor mDragActor; ///< Reference to the actor currently being dragged
  446 + TextInput mTextInput[3]; ///< Text input to specify forward vector of the path animation
  447 +};
  448 +
  449 +void RunTest( Application& application )
  450 +{
  451 + PathController test( application );
  452 +
  453 + application.MainLoop();
  454 +}
  455 +
  456 +/** Entry point for Linux & Tizen applications */
  457 +int main( int argc, char **argv )
  458 +{
  459 + Application application = Application::New( &argc, &argv );
  460 +
  461 + RunTest( application );
  462 +
  463 + return 0;
  464 +}
... ...