Added path animation demo 34/36134/4
authorFerran Sole <ferran.sole@samsung.com>
Mon, 2 Mar 2015 15:38:27 +0000 (15:38 +0000)
committerFerran Sole <ferran.sole@samsung.com>
Tue, 3 Mar 2015 11:38:48 +0000 (11:38 +0000)
Change-Id: I4a723457a7cfaca87a20f771aa64f187ea160453

com.samsung.dali-demo.xml
demo/dali-demo.cpp
examples/path-animation/path-animation.cpp [new file with mode: 0644]

index aaf6dd5..4292b9c 100644 (file)
@@ -79,4 +79,7 @@
        <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">
                <label>Animated shapes</label>
        </ui-application>
+       <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">
+               <label>Path Animation</label>
+       </ui-application>
 </manifest>
index 281fe63..a2741e8 100644 (file)
@@ -43,6 +43,7 @@ int main(int argc, char **argv)
   demo.AddExample(Example("image-scaling-irregular-grid.example", "Image Scaling Modes"));
   demo.AddExample(Example("text-view.example", "Text View"));
   demo.AddExample(Example("animated-shapes.example", "Animated Shapes"));
+  demo.AddExample(Example("path-animation.example", "Path Animation"));
   app.MainLoop();
 
   return 0;
diff --git a/examples/path-animation/path-animation.cpp b/examples/path-animation/path-animation.cpp
new file mode 100644 (file)
index 0000000..e4b12a3
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This example shows how to use path animations in DALi
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/dali-toolkit.h>
+
+// INTERNAL INCLUDES
+#include "shared/view.h"
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+
+namespace
+{
+const char* BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-default.png" );
+const char* ACTOR_IMAGE( DALI_IMAGE_DIR "dali-logo.png" );
+const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
+const char* APPLICATION_TITLE( "Path Example" );
+}; //Unnamed namespace
+
+/**
+ * @brief The main class of the demo.
+ */
+class PathController : public ConnectionTracker
+{
+public:
+
+  PathController( Application& application )
+  : mApplication( application )
+  {
+    // Connect to the Application's Init signal
+    mApplication.InitSignal().Connect( this, &PathController::Create );
+  }
+
+  ~PathController()
+  {
+    // Nothing to do here.
+  }
+
+  /**
+   * One-time setup in response to Application InitSignal.
+   */
+  void Create( Application& application )
+  {
+    // Get a handle to the stage:
+    Stage stage = Stage::GetCurrent();
+
+    // Connect to input event signals:
+    stage.KeyEventSignal().Connect(this, &PathController::OnKeyEvent);
+
+    // Create a default view with a default tool bar:
+    Toolkit::View view;                ///< The View instance.
+    Toolkit::ToolBar toolBar;          ///< The View's Toolbar.
+    mContentLayer = DemoHelper::CreateView( mApplication,
+                                            view,
+                                            toolBar,
+                                            BACKGROUND_IMAGE,
+                                            TOOLBAR_IMAGE,
+                                            "" );
+
+    mContentLayer.TouchedSignal().Connect(this, &PathController::OnTouchLayer);
+
+    //Title
+    TextView title = TextView::New();
+    toolBar.AddControl( title, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Alignment::HorizontalCenter );
+    Font font = Font::New();
+    title.SetText( APPLICATION_TITLE );
+    title.SetSize( font.MeasureText( APPLICATION_TITLE ) );
+    title.SetStyleToCurrentText(DemoHelper::GetDefaultTextStyle());
+
+    //Path
+    mPath = Dali::Path::New();
+    mPath.AddPoint( Vector3( 10.0f, stage.GetSize().y*0.5f, 0.0f ));
+    mPath.AddPoint( Vector3( stage.GetSize().x*0.5f, stage.GetSize().y*0.3f, 0.0f ));
+    mPath.GenerateControlPoints(0.25f);
+    DrawPath( 200u );
+
+    //Actor
+    ImageAttributes attributes;
+    Image img = ResourceImage::New(ACTOR_IMAGE, attributes );
+    mActor = ImageActor::New( img );
+    mActor.SetPosition( Vector3( 10.0f, stage.GetSize().y*0.5f, 0.0f ) );
+    mActor.SetAnchorPoint( AnchorPoint::CENTER );
+    mActor.SetSize( 100, 50, 1 );
+    stage.Add( mActor );
+
+    mForward = Vector3::XAXIS;
+    CreateAnimation();
+
+    Dali::TextActor forwardLabel = TextActor::New("Forward Vector");
+    forwardLabel.SetPosition( 10.0f, stage.GetSize().y - 60.0f, 0.0f );
+    forwardLabel.SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
+    forwardLabel.SetAnchorPoint( AnchorPoint::CENTER_LEFT);
+    mContentLayer.Add( forwardLabel );
+
+    //TextInput
+    Dali::Layer textInputLayer = Dali::Layer::New();
+    textInputLayer.SetSize( 400.0f, 30.0f, 0.0 );
+    textInputLayer.SetPosition( 0.0f, stage.GetSize().y - 30.0f, 0.0f );
+    textInputLayer.SetAnchorPoint( AnchorPoint::TOP_LEFT);
+    textInputLayer.SetParentOrigin( ParentOrigin::TOP_LEFT);
+    stage.Add( textInputLayer );
+    Dali::TextActor label = TextActor::New("X:");
+    label.SetPosition( 10.0f, 0.0f, 0.0f );
+    label.SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
+    label.SetAnchorPoint( AnchorPoint::CENTER_LEFT);
+    textInputLayer.Add( label );
+    TextStyle style;
+    style.SetTextColor( Vector4( 0.0f, 0.0f ,0.0f, 1.0f ));
+    mTextInput[0] = TextInput::New();
+    mTextInput[0].SetInitialText("1.0");
+    mTextInput[0].SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
+    mTextInput[0].SetAnchorPoint( AnchorPoint::CENTER_LEFT);
+    mTextInput[0].SetParentOrigin( ParentOrigin::CENTER_RIGHT);
+    mTextInput[0].SetPosition( 10.0f, 0.0f, 0.0f );
+    mTextInput[0].SetSize( 70.0f, 0.0f, 0.0f );
+    mTextInput[0].SetTextAlignment(Alignment::HorizontalCenter );
+    mTextInput[0].SetMaxCharacterLength( 5 );
+    mTextInput[0].SetNumberOfLinesLimit(1);
+    mTextInput[0].ApplyStyleToAll( style );
+    mTextInput[0].SetProperty( mTextInput[0].GetPropertyIndex("cursor-color"), Vector4(0.0f,0.0f,0.0f,1.0f) );
+    mTextInput[0].SetBackgroundColor( Vector4(0.8f,1.0f,0.8f, 0.4f));
+    mTextInput[0].InputFinishedSignal().Connect(this, &PathController::OnTextInputEnd);
+    mTextInput[0].SetEditOnTouch();
+    label.Add( mTextInput[0]);
+    label = TextActor::New("Y:");
+    label.SetPosition( 160.0f,0.0f, 0.0f );
+    label.SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
+    label.SetAnchorPoint( AnchorPoint::CENTER_LEFT);
+    textInputLayer.Add( label );
+    mTextInput[1] = TextInput::New();
+    mTextInput[1].SetInitialText("0.0");
+    mTextInput[1].SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
+    mTextInput[1].SetAnchorPoint( AnchorPoint::CENTER_LEFT);
+    mTextInput[1].SetParentOrigin( ParentOrigin::CENTER_RIGHT);
+    mTextInput[1].SetPosition( 10.0f, 0.0f, 0.0f );
+    mTextInput[1].SetSize( 70.0f, 0.0f, 0.0f );
+    mTextInput[1].SetTextAlignment(Alignment::HorizontalCenter );
+    mTextInput[1].SetMaxCharacterLength( 5 );
+    mTextInput[1].SetNumberOfLinesLimit(1);
+    mTextInput[1].ApplyStyleToAll( style );
+    mTextInput[1].SetProperty( mTextInput[1].GetPropertyIndex("cursor-color"), Vector4(0.0f,0.0f,0.0f,1.0f) );
+    mTextInput[1].SetBackgroundColor( Vector4(0.8f,1.0f,0.8f, 0.4f));
+    mTextInput[1].InputFinishedSignal().Connect(this, &PathController::OnTextInputEnd);
+    label.Add( mTextInput[1]);
+    label = TextActor::New("Z:");
+    label.SetPosition( 310.0f, 0.0f, 0.0f );
+    label.SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
+    label.SetAnchorPoint( AnchorPoint::CENTER_LEFT);
+    textInputLayer.Add( label );
+    mTextInput[2] = TextInput::New();
+    mTextInput[2].SetInitialText("0.0");
+    mTextInput[2].SetColor( Vector4(0.0f,0.0f,0.0f,1.0f));
+    mTextInput[2].SetAnchorPoint( AnchorPoint::CENTER_LEFT);
+    mTextInput[2].SetParentOrigin( ParentOrigin::CENTER_RIGHT);
+    mTextInput[2].SetPosition( 10.0f, 0.0f, 0.0f );
+    mTextInput[2].SetSize( 70.0f, 0.0f, 0.0f );
+    mTextInput[2].SetTextAlignment(Alignment::HorizontalCenter );
+    mTextInput[2].SetMaxCharacterLength( 5 );
+    mTextInput[2].SetNumberOfLinesLimit(1);
+    mTextInput[2].ApplyStyleToAll( style );
+    mTextInput[2].SetProperty( mTextInput[2].GetPropertyIndex("cursor-color"), Vector4(0.0f,0.0f,0.0f,1.0f) );
+    mTextInput[2].SetBackgroundColor( Vector4(0.8f,1.0f,0.8f, 0.4f));
+    mTextInput[2].InputFinishedSignal().Connect(this, &PathController::OnTextInputEnd);
+    label.Add( mTextInput[2]);
+  }
+
+  /**
+   * Create an actor representing a control point of the curve
+   * @param[in] name Name of the actor
+   * @param[in] size Size of the containing actor
+   * @param[in] imageSize Size of the imageActor
+   * @param[in] color Color of the imageActor
+   */
+  Actor CreateControlPoint(const std::string& name, const Vector3& size, const Vector3& imageSize, const Vector4& color )
+  {
+    Actor actor = Actor::New();
+    actor.SetParentOrigin( ParentOrigin::TOP_LEFT);
+    actor.SetAnchorPoint( AnchorPoint::CENTER );
+    actor.SetSize( size );
+    actor.SetName( name );
+    actor.TouchedSignal().Connect(this, &PathController::OnTouchPoint);
+
+    ImageActor imageActor = Toolkit::CreateSolidColorActor(color);
+    imageActor.SetColor(Vector4(1.0f,0.0f,0.0f,1.0f));
+    imageActor.SetParentOrigin( ParentOrigin::CENTER);
+    imageActor.SetAnchorPoint( AnchorPoint::CENTER );
+    imageActor.SetSize( imageSize );
+    actor.Add(imageActor );
+
+    return actor;
+  }
+
+  /**
+   * Draws the path and the control points for the path
+   * @param[in] resolution Number of segments for the path.
+   */
+  void DrawPath( unsigned int resolution )
+  {
+    Stage stage = Dali::Stage::GetCurrent();
+
+    //Create path mesh actor
+    Dali::MeshData meshData = MeshFactory::NewPath( mPath, resolution );
+    Dali::Material material = Material::New("LineMaterial");
+    material.SetDiffuseColor( Vector4(0.0f,0.0f,0.0f,1.0f));
+    meshData.SetMaterial(material);
+    Dali::Mesh mesh = Dali::Mesh::New( meshData );
+    if( mMeshPath )
+    {
+      stage.Remove( mMeshPath );
+    }
+    mMeshPath = Dali::MeshActor::New( mesh );
+    mMeshPath.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+    mMeshPath.SetParentOrigin( ParentOrigin::TOP_LEFT );
+    stage.Add( mMeshPath );
+
+
+    ////Create mesh connecting interpolation points and control points
+    std::vector<Dali::MeshData::Vertex> vVertex;
+    std::vector<unsigned short> vIndex;
+    size_t pointCount = mPath.GetPointCount();
+    size_t controlPointIndex = 0;
+    for( size_t i(0); i<pointCount; ++i )
+    {
+      vVertex.push_back( MeshData::Vertex(mPath.GetPoint(i),Vector2::ZERO, Vector3::ZERO ) );
+      if( i<pointCount-1)
+      {
+        vVertex.push_back( MeshData::Vertex(mPath.GetControlPoint(controlPointIndex),Vector2::ZERO, Vector3::ZERO ));
+        vVertex.push_back( MeshData::Vertex(mPath.GetControlPoint(controlPointIndex+1),Vector2::ZERO, Vector3::ZERO ));
+      }
+      controlPointIndex += 2;
+    }
+
+    size_t segmentCount = 2*(pointCount-2)+2;
+    unsigned short index=0;
+    for( size_t i(0); i<segmentCount; ++i, ++index )
+    {
+      vIndex.push_back(index);
+      vIndex.push_back(index+1);
+
+      if( ~i & 1 )
+      {
+        index++;
+      }
+    }
+
+    meshData.SetLineData( vVertex, vIndex, material );
+    meshData.SetMaterial(material);
+    mesh = Dali::Mesh::New( meshData );
+    if( mMeshHandlers )
+    {
+      stage.Remove( mMeshHandlers );
+    }
+    mMeshHandlers = Dali::MeshActor::New( mesh );
+    mMeshHandlers.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+    mMeshHandlers.SetParentOrigin( ParentOrigin::TOP_LEFT );
+    stage.Add( mMeshHandlers );
+
+
+    //Create actors representing interpolation points
+    for( size_t i(0); i<pointCount; ++i )
+    {
+      if( !mKnot[i] )
+      {
+        std::string name( "Knot");
+        name.push_back(i);
+        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) );
+        mContentLayer.Add(mKnot[i] );
+      }
+
+      mKnot[i].SetPosition( mPath.GetPoint(i) );
+    }
+
+    //Create actors representing control points
+    size_t controlPointCount=2*(pointCount-1);
+    for( size_t i(0); i<controlPointCount; ++i )
+    {
+      if( !mControlPoint[i])
+      {
+        std::string name( "ControlPoint");
+        name.push_back(i);
+        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) );
+        mContentLayer.Add(mControlPoint[i] );
+      }
+
+      mControlPoint[i].SetPosition( mPath.GetControlPoint(i) );
+    }
+  }
+
+  bool OnTouchPoint(Actor actor, const TouchEvent& event)
+  {
+    if(event.GetPointCount()>0)
+    {
+      const TouchPoint& point = event.GetPoint(0);
+
+      if(point.state==TouchPoint::Down)
+      {
+        // Start dragging
+        mDragActor = actor;
+      }
+    }
+    return false;
+  }
+
+  bool OnTouchLayer(Actor actor, const TouchEvent& event)
+  {
+    if(event.GetPointCount()>0)
+    {
+      const TouchPoint& point = event.GetPoint(0);
+
+      if(point.state==TouchPoint::Up)
+      {
+        //Stop dragging
+        mDragActor.Reset();
+      }
+      else if(!mDragActor && point.state==TouchPoint::Down && mPath.GetPointCount()<10 )
+      {
+        // Add new point
+        const TouchPoint& point = event.GetPoint(0);
+        Vector3 newPoint = Vector3(point.screen.x, point.screen.y, 0.0f);
+
+        size_t pointCount = mPath.GetPointCount();
+        Vector3 lastPoint = mPath.GetPoint( pointCount-1);
+        mPath.AddPoint( newPoint );
+
+        Vector3 displacement = (newPoint-lastPoint)/8;
+
+        mPath.AddControlPoint( lastPoint + displacement );
+        mPath.AddControlPoint( newPoint - displacement);
+
+        DrawPath( 200u );
+        CreateAnimation();
+      }
+      else
+      {
+        if( mDragActor )
+        {
+          const TouchPoint& point = event.GetPoint(0);
+          Vector3 newPosition = Vector3(point.screen.x, point.screen.y, 0.0f);
+
+          std::string actorName(mDragActor.GetName());
+
+          if( actorName.compare(0, 4, "Knot") == 0)
+          {
+             int index = actorName[4];
+             mPath.GetPoint(index) = newPosition;
+          }
+          else
+          {
+            int index = actorName[12];
+            mPath.GetControlPoint(index) = newPosition;
+          }
+
+          DrawPath( 200u );
+          CreateAnimation();
+        }
+      }
+    }
+    return false;
+  }
+
+ /**
+  * Main key event handler.
+  * Quit on escape key.
+  */
+  void OnKeyEvent(const KeyEvent& event)
+  {
+    if( event.state == KeyEvent::Down )
+    {
+      if( IsKey( event, Dali::DALI_KEY_ESCAPE ) ||
+          IsKey( event, Dali::DALI_KEY_BACK ) )
+      {
+        mApplication.Quit();
+      }
+    }
+  }
+
+  /**
+   * Callback called when user end to input text in any of the TextInput
+   * @param[in] textInput The text input that has generated the signal
+   */
+  void OnTextInputEnd( TextInput textInput)
+  {
+    mForward.x = (float)atof( mTextInput[0].GetText().c_str() );
+    mForward.y = (float)atof( mTextInput[1].GetText().c_str() );
+    mForward.z = (float)atof( mTextInput[2].GetText().c_str() );
+    CreateAnimation();
+  }
+
+  /**
+   * Create the path animation.
+   */
+  void CreateAnimation()
+  {
+    if( !mAnimation )
+    {
+      mAnimation = Animation::New( 2.0f );
+    }
+    else
+    {
+      mAnimation.Pause();
+      mAnimation.Clear();
+      mActor.SetRotation( Quaternion() );
+    }
+
+    mAnimation.Animate( mActor, mPath, mForward );
+    mAnimation.SetLooping( true );
+    mAnimation.Play();
+  }
+
+private:
+  Application&  mApplication;
+
+  Layer      mContentLayer;       ///< The content layer
+
+  Path       mPath;               ///< The path used in the animation
+  ImageActor mActor;              ///< Actor being animated
+  Vector3    mForward;            ///< Current forward vector
+  Animation  mAnimation;          ///< Path animation
+
+  MeshActor  mMeshPath;           ///< Mesh actor for the path
+  MeshActor  mMeshHandlers;       ///< Mesh actor for the segments connecting points and control points
+  Actor mKnot[10];           ///< ImageActors for the interpolation points
+  Actor mControlPoint[18];   ///< ImageActors for the control points
+
+  Actor      mDragActor;          ///< Reference to the actor currently being dragged
+  TextInput  mTextInput[3];       ///< Text input to specify forward vector of the path animation
+};
+
+void RunTest( Application& application )
+{
+  PathController test( application );
+
+  application.MainLoop();
+}
+
+/** Entry point for Linux & Tizen applications */
+int main( int argc, char **argv )
+{
+  Application application = Application::New( &argc, &argv );
+
+  RunTest( application );
+
+  return 0;
+}