diff --git a/examples/path-animation/path-animation.cpp b/examples/path-animation/path-animation.cpp index e4b12a3..3b62bda 100644 --- a/examples/path-animation/path-animation.cpp +++ b/examples/path-animation/path-animation.cpp @@ -34,7 +34,7 @@ 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" ); +const char* APPLICATION_TITLE( "Path Animation Example" ); }; //Unnamed namespace /** @@ -45,169 +45,85 @@ class PathController : public ConnectionTracker public: PathController( Application& application ) - : mApplication( 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 ) + /* + * Create a control composed of a label and an slider + * @param[in] label The text to be displayed ny the label + * @param[in] size The size of the slider + * @param[in] callback Pointer to the callback function to be called when user moves the slider + */ + Actor CreateVectorComponentControl( const std::string& label, const Vector3& size, bool(PathController::*callback)(Slider,float) ) { - // 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 ); + Dali::TextActor textActor = TextActor::New(label); + textActor.SetColor( Vector4(0.0f,0.0f,0.0f,1.0f)); + textActor.SetSize(size.y,size.y,0.0f); + + Slider slider = Slider::New(); + slider.SetAnchorPoint( AnchorPoint::CENTER_LEFT); + slider.SetParentOrigin( ParentOrigin::CENTER_RIGHT); + slider.SetProperty(Slider::LOWER_BOUND_PROPERTY, -1.0f ); + slider.SetProperty(Slider::UPPER_BOUND_PROPERTY, 1.0f ); + + Property::Array marks; + float mark = -1.0f; + for(unsigned short i(0); i<21; ++i ) + { + marks.push_back( mark ); + mark += 0.1f; + } - //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]); + slider.SetProperty(Slider::MARKS_PROPERTY, marks); + slider.SetProperty(Slider::SNAP_TO_MARKS_PROPERTY, true ); + slider.SetSize(size); + slider.SetScale( 0.5f ); + slider.ValueChangedSignal().Connect(this,callback); + textActor.Add( slider ); + return textActor; } /** - * 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 + * Crate all the GUI controls */ - Actor CreateControlPoint(const std::string& name, const Vector3& size, const Vector3& imageSize, const Vector4& color ) + void CreateControls() { - 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; + Stage stage = Stage::GetCurrent(); + + //TextInput + Dali::Layer controlsLayer = Dali::Layer::New(); + controlsLayer.SetSize( stage.GetSize().x, stage.GetSize().y*0.3f, 0.0 ); + controlsLayer.SetPosition( 0.0f, stage.GetSize().y*0.8f, 0.0f ); + controlsLayer.SetAnchorPoint( AnchorPoint::TOP_LEFT); + controlsLayer.SetParentOrigin( ParentOrigin::TOP_LEFT); + controlsLayer.TouchedSignal().Connect(this, &PathController::OnTouchGuiLayer); + stage.Add( controlsLayer ); + + Vector3 textInputSize( stage.GetSize().x, stage.GetSize().y*0.04f, 0.0f ); + Actor control0 = CreateVectorComponentControl("x:", textInputSize, &PathController::OnSliderXValueChange ); + control0.SetY( stage.GetSize().y*0.05f ); + control0.SetAnchorPoint(AnchorPoint::TOP_LEFT); + controlsLayer.Add( control0 ); + + Actor control1 = CreateVectorComponentControl("y:", textInputSize, &PathController::OnSliderYValueChange ); + control1.SetAnchorPoint(AnchorPoint::TOP_LEFT); + control1.SetParentOrigin( ParentOrigin::BOTTOM_LEFT ); + control1.SetPosition(0.0f,stage.GetSize().y*0.01,0.0f); + control0.Add( control1 ); + + Actor control2 =CreateVectorComponentControl("z:", textInputSize, &PathController::OnSliderZValueChange ); + control2.SetAnchorPoint(AnchorPoint::TOP_LEFT); + control2.SetParentOrigin( ParentOrigin::BOTTOM_LEFT ); + control2.SetPosition(0.0f,stage.GetSize().y*0.01,0.0f); + control1.Add( control2 ); } /** @@ -277,50 +193,107 @@ public: //Create actors representing interpolation points + index = 0; for( size_t i(0); i0) + if( !mAnimation ) { - const TouchPoint& point = event.GetPoint(0); + mAnimation = Animation::New( 2.0f ); + } + else + { + mAnimation.Pause(); + mAnimation.Clear(); + mActor.SetRotation( Quaternion() ); + } + + mAnimation.Animate( mActor, mPath, mForward ); + mAnimation.SetLooping( true ); + mAnimation.Play(); + } + + /** + * Get closest control point.void + * @param[in] point Point from where the distance is computed + * @return The closest actor if the distance is beyond 0.5cm or an uninitialized actor otherwise + */ + Actor GetClosestActor(const Vector3& point) + { + size_t pointCount = mPath.GetPointCount(); + size_t controlPointCount = 3*pointCount - 2; + Actor result; + float minDistance = 1.0/0.0; - if(point.state==TouchPoint::Down) + for( size_t i(0); i0) @@ -332,99 +305,177 @@ public: //Stop dragging mDragActor.Reset(); } - else if(!mDragActor && point.state==TouchPoint::Down && mPath.GetPointCount()<10 ) + else if(point.state==TouchPoint::Down) { - // 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 ) + Vector3 touchPoint = Vector3(event.GetPoint(0).screen.x, event.GetPoint(0).screen.y, 0.0f); + 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) + mDragActor = GetClosestActor( touchPoint ); + if( !mDragActor && mPath.GetPointCount() < 10 ) { - int index = actorName[4]; - mPath.GetPoint(index) = newPosition; + // Add new point + Vector3 lastPoint = mPath.GetPoint( mPath.GetPointCount()-1); + mPath.AddPoint( touchPoint ); + Vector3 displacement = (touchPoint-lastPoint)/8; + mPath.AddControlPoint( lastPoint + displacement ); + mPath.AddControlPoint( touchPoint - displacement); + + DrawPath( 200u ); + CreateAnimation(); } - else - { - int index = actorName[12]; - mPath.GetControlPoint(index) = newPosition; - } - - DrawPath( 200u ); - CreateAnimation(); } } + else if( mDragActor && point.state==TouchPoint::Motion ) + { + Vector3 touchPoint = Vector3(event.GetPoint(0).screen.x, event.GetPoint(0).screen.y, 0.0f); + std::string actorName(mDragActor.GetName()); + if( actorName.compare(0, 4, "Knot") == 0) + { + int index = actorName[4]; + mPath.GetPoint(index) = touchPoint; + } + else + { + int index = actorName[12]; + mPath.GetControlPoint(index) = touchPoint; + } + + DrawPath( 200u ); + CreateAnimation(); + } } - return false; + + return true; } - /** - * Main key event handler. - * Quit on escape key. - */ - void OnKeyEvent(const KeyEvent& event) + bool OnTouchGuiLayer(Actor actor, const TouchEvent& event) + { + mDragActor.Reset(); + return false; + } + /** + * Callback called when user changes slider X + * @param[in] slider The slider that has generated the signal + * @param[in] value The new value + */ + bool OnSliderXValueChange( Slider s, float value) { - if( event.state == KeyEvent::Down ) + if( fabs( value ) - Math::MACHINE_EPSILON_1000 < 0.0f ) { - if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || - IsKey( event, Dali::DALI_KEY_BACK ) ) - { - mApplication.Quit(); - } + mForward.x = 0.0f; + } + else + { + mForward.x = value; } + + CreateAnimation(); + return true; } /** - * Callback called when user end to input text in any of the TextInput - * @param[in] textInput The text input that has generated the signal + * Callback called when user changes slider Y + * @param[in] slider The slider that has generated the signal + * @param[in] value The new value */ - void OnTextInputEnd( TextInput textInput) + bool OnSliderYValueChange( Slider s, float value) { - 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() ); + if( fabs( value ) - Math::MACHINE_EPSILON_1000 < 0.0f ) + { + mForward.y = 0.0f; + } + else + { + mForward.y = value; + } CreateAnimation(); + return true; } /** - * Create the path animation. + * Callback called when user changes slider Z + * @param[in] slider The slider that has generated the signal + * @param[in] value The new value */ - void CreateAnimation() + bool OnSliderZValueChange( Slider s, float value) { - if( !mAnimation ) + if( fabs( value ) - Math::MACHINE_EPSILON_1000 < 0.0f ) { - mAnimation = Animation::New( 2.0f ); + mForward.z = 0.0f; } else { - mAnimation.Pause(); - mAnimation.Clear(); - mActor.SetRotation( Quaternion() ); + mForward.z = value; } - mAnimation.Animate( mActor, mPath, mForward ); - mAnimation.SetLooping( true ); - mAnimation.Play(); + CreateAnimation(); + return true; + } + + /** + * 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(); + } + } + } + + /** + * 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.5f, 0.0f )); + mPath.GenerateControlPoints(0.25f); + DrawPath( 200u ); + + //Actor + ImageAttributes attributes; + Image img = ResourceImage::New(ACTOR_IMAGE, attributes ); + mActor = ImageActor::New( img ); + mActor.SetAnchorPoint( AnchorPoint::CENTER ); + mActor.SetSize( 100, 50, 1 ); + stage.Add( mActor ); + + CreateAnimation(); + CreateControls(); } private: @@ -438,14 +489,14 @@ private: 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 + MeshActor mMeshHandlers; ///< Mesh actor for the handlers of the path + + Actor mControlPoint[28]; ///< ImageActors represeting control points of the path 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 );