X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=examples%2Fgestures%2Fgesture-example.cpp;h=d04c63eccc9a0785f7ff730311f9c8db2e90e1ac;hb=b26d446b0cb6a316abc3a79d4fc70d0ae1b7994c;hp=bbae267123bf6f142bf7cfee7da1164c645c5fc1;hpb=fe0d158d3bfda0a9ce9c65cdbc605114d5678747;p=platform%2Fcore%2Fuifw%2Fdali-demo.git diff --git a/examples/gestures/gesture-example.cpp b/examples/gestures/gesture-example.cpp index bbae267..d04c63e 100644 --- a/examples/gestures/gesture-example.cpp +++ b/examples/gestures/gesture-example.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -21,18 +21,27 @@ using namespace Dali; using namespace Dali::Toolkit; +using namespace std; namespace { -const Vector4 BACKGROUND_GRADIENT_1 = Vector4( 167.0f, 207.0f, 223.0f, 255.0f ) / 255.0f; -const Vector4 BACKGROUND_GRADIENT_2 = Vector4( 0.0f, 64.0f, 137.0f, 255.0f ) / 255.0f; -const Vector2 BACKGROUND_GRADIENT_START_POSITION( 0.0f, -0.5f ); -const Vector2 BACKGROUND_GRADIENT_END_POSITION( 0.0f, 0.5f ); +const Property::Value BACKGROUND +{ + { Toolkit::Visual::Property::TYPE, Visual::GRADIENT }, + { GradientVisual::Property::STOP_COLOR, Property::Array{ Vector4( 167.0f, 207.0f, 223.0f, 255.0f ) / 255.0f, + Vector4( 0.0f, 64.0f, 137.0f, 255.0f ) / 255.0f } }, + { GradientVisual::Property::START_POSITION, Vector2( 0.0f, -0.5f ) }, + { GradientVisual::Property::END_POSITION, Vector2( 0.0f, 0.5f ) } +}; -const Vector4 CONTROL_GRADIENT_1 = Vector4( 234.0f, 185.0f, 45.0f, 255.0f ) / 255.0f; -const Vector4 CONTROL_GRADIENT_2 = Vector4( 199.0f, 152.0f, 16.0f, 255.0f ) / 255.0f; -const Vector2 CONTROL_GRADIENT_CENTER( Vector2::ZERO ); -const float CONTROL_GRADIENT_RADIUS( 0.5f ); +const Property::Value CONTROL_BACKGROUND +{ + { Toolkit::Visual::Property::TYPE, Visual::GRADIENT }, + { GradientVisual::Property::STOP_COLOR, Property::Array{ Vector4( 234.0f, 185.0f, 45.0f, 255.0f ) / 255.0f, + Vector4( 199.0f, 152.0f, 16.0f, 255.0f ) / 255.0f } }, + { GradientVisual::Property::CENTER, Vector2::ZERO }, + { GradientVisual::Property::RADIUS, 0.5f } +}; const float HELP_ANIMATION_DURATION( 25.0f ); const float HELP_ANIMATION_SEGMENT_TIME( 5.0f ); @@ -50,51 +59,13 @@ const float PAN_MODE_CHANGE_ANIMATION_DURATION( 0.25f ); const Vector3 PAN_MODE_START_ANIMATION_SCALE( 1.2f, 1.2f, 1.0f ); const Vector3 PAN_MODE_END_ANIMATION_SCALE( 0.8f, 0.8f, 1.0f ); -const float TAP_ANIMATION_DURATON( 0.5f ); +const float TAP_ANIMATION_DURATION( 0.5f ); const Vector4 TAP_ANIMATION_COLOR( 0.8f, 0.5, 0.2f, 0.6f ); const Vector3 MINIMUM_SCALE( Vector3::ONE ); const Vector3 MAXIMUM_SCALE( Vector3::ONE * 2.0f ); const float SCALE_BACK_ANIMATION_DURATION( 0.25f ); - -/** - * @brief Creates a background with a linear gradient which matches parent size & is placed in the center. - */ -Actor CreateBackground() -{ - Actor background = Control::New(); - background.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); - background.SetParentOrigin( ParentOrigin::CENTER ); - background.SetProperty( - Control::Property::BACKGROUND, - Property::Map().Add( Toolkit::Visual::Property::TYPE, Visual::GRADIENT ) - .Add( GradientVisual::Property::STOP_COLOR, Property::Array().Add( BACKGROUND_GRADIENT_1 ) - .Add( BACKGROUND_GRADIENT_2 ) ) - .Add( GradientVisual::Property::START_POSITION, BACKGROUND_GRADIENT_START_POSITION ) - .Add( GradientVisual::Property::END_POSITION, BACKGROUND_GRADIENT_END_POSITION ) ); - return background; -} - -/** - * @brief Create a control with a circular gradient & a specific size & is placed in the center of its parent. - * - * @param[in] size The size we want the control to be. - */ -Actor CreateTouchControl( const Vector2& size ) -{ - Actor touchControl = Control::New(); - touchControl.SetSize( size ); - touchControl.SetParentOrigin( ParentOrigin::CENTER ); - touchControl.SetProperty( - Control::Property::BACKGROUND, - Property::Map().Add( Toolkit::Visual::Property::TYPE, Visual::GRADIENT ) - .Add( GradientVisual::Property::STOP_COLOR, Property::Array().Add( CONTROL_GRADIENT_1 ) - .Add( CONTROL_GRADIENT_2 ) ) - .Add( GradientVisual::Property::CENTER, CONTROL_GRADIENT_CENTER ) - .Add( GradientVisual::Property::RADIUS, CONTROL_GRADIENT_RADIUS ) - ); - return touchControl; -} +const float ROTATE_BACK_ANIMATION_DURATION( 0.25f ); /** * @brief Shows the given string between the given start and end times. @@ -107,16 +78,17 @@ Actor CreateTouchControl( const Vector2& size ) * @param[in] startTime When to start the animators * @param[in] endTime When to end the animators */ -void AddHelpInfo( const std::string&& string, Actor parent, Animation animation, float startTime, float endTime ) +void AddHelpInfo( const std::string&& string, const Vector2& windowSize, Actor parent, Animation animation, float startTime, float endTime ) { Actor text = TextLabel::New( std::move( string ) ); - Vector3 position( Stage::GetCurrent().GetSize() * HELP_TEXT_POSITION_MULTIPLIER ); + Vector3 position( windowSize * HELP_TEXT_POSITION_MULTIPLIER ); - text.SetAnchorPoint( AnchorPoint::TOP_CENTER ); - text.SetParentOrigin( ParentOrigin::TOP_CENTER ); - text.SetPosition( position ); - text.SetOpacity( 0.0f ); + text.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER ); + text.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER ); + text.SetProperty( Actor::Property::POSITION, position ); + text.SetProperty( Actor::Property::OPACITY, 0.0f ); text.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, Text::HorizontalAlignment::CENTER ); + text.SetProperty( TextLabel::Property::MULTI_LINE, true ); parent.Add( text ); // Animate IN @@ -166,30 +138,36 @@ private: */ void Create( Application& application ) { - // Get a handle to the stage & connect to the key event signal - Stage stage = Stage::GetCurrent(); - stage.KeyEventSignal().Connect(this, &GestureExample::OnKeyEvent); - - // Create a background with a gradient - Actor background = CreateBackground(); - stage.Add( background ); - - // Create a control that we'll use for the gestures to be a quarter of the size of the stage - Actor touchControl = CreateTouchControl( stage.GetSize() * 0.25f ); + // Get a handle to the window & connect to the key event signal + auto window = application.GetWindow(); + Vector2 windowSize = window.GetSize(); + window.KeyEventSignal().Connect(this, &GestureExample::OnKeyEvent); + + // Create a background with a linear gradient which matches parent size & is placed in the center. + Actor background = Control::New(); + background.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); + background.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + background.SetProperty( Control::Property::BACKGROUND, BACKGROUND ); + window.Add( background ); + + // Create a control with a circular gradient that we'll use for the gestures and be a quarter of the size of the window. + Actor touchControl = Control::New(); + touchControl.SetProperty( Actor::Property::SIZE, windowSize * 0.25f ); + touchControl.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + touchControl.SetProperty( Control::Property::BACKGROUND, CONTROL_BACKGROUND ); background.Add( touchControl ); // Connect to the touch signal - touchControl.TouchSignal().Connect( this, &GestureExample::OnTouch ); - touchControl.SetLeaveRequired( true ); + touchControl.TouchedSignal().Connect( this, &GestureExample::OnTouch ); + touchControl.SetProperty( Actor::Property::LEAVE_REQUIRED, true ); // Create a long press gesture detector, attach the actor & connect mLongPressDetector = LongPressGestureDetector::New(); mLongPressDetector.Attach( touchControl ); mLongPressDetector.DetectedSignal().Connect( this, &GestureExample::OnLongPress ); - // Create a pan gesture detector, attach the actor & connect + // Create a pan gesture detector & connect, don't attach the actor as we'll attach it when we detect a long-press mPanDetector = PanGestureDetector::New(); - mPanDetector.Attach( touchControl ); mPanDetector.DetectedSignal().Connect( this, &GestureExample::OnPan ); // Create a tap gesture detector, attach the actor & connect @@ -202,6 +180,11 @@ private: mPinchDetector.Attach( touchControl ); mPinchDetector.DetectedSignal().Connect( this, &GestureExample::OnPinch ); + // Create a rotation gesture detector, attach the actor & connect + mRotationDetector = RotationGestureDetector::New(); + mRotationDetector.Attach( touchControl ); + mRotationDetector.DetectedSignal().Connect( this, &GestureExample::OnRotation ); + // Create an animation which shakes the actor when in Pan mode mShakeAnimation = Animation::New( SHAKY_ANIMATION_DURATION ); mShakeAnimation.AnimateBy( Property( touchControl, Actor::Property::ORIENTATION ), @@ -221,9 +204,10 @@ private: float startTime( 0.0f ); float endTime( startTime + HELP_ANIMATION_SEGMENT_TIME ); - AddHelpInfo( "Tap image for animation", background, helpAnimation, startTime, endTime ); - AddHelpInfo( "Press & Hold image to drag", background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME ); - AddHelpInfo( "Pinch image to resize", background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME ); + AddHelpInfo( "Tap image for animation", windowSize, background, helpAnimation, startTime, endTime ); + AddHelpInfo( "Press & Hold image to drag", windowSize, background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME ); + AddHelpInfo( "Pinch image to resize", windowSize, background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME ); + AddHelpInfo( "Move fingers in a circular motion on image to rotate", windowSize, background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME ); helpAnimation.SetLooping( true ); helpAnimation.Play(); } @@ -234,7 +218,7 @@ private: * @param[in] actor The touched actor * @param[in] touch The touch event */ - bool OnTouch( Actor actor, const TouchData& touch ) + bool OnTouch( Actor actor, const TouchEvent& touch ) { switch( touch.GetState( 0 ) ) { @@ -271,7 +255,7 @@ private: break; } } - return true; + return false; } /** @@ -282,36 +266,19 @@ private: */ void OnLongPress( Actor actor, const LongPressGesture& longPress ) { - switch( longPress.state ) + if( longPress.GetState() == GestureState::STARTED ) { - case Gesture::Started: - { - // When we first receive a long press, change state to pan mode. + // When we first receive a long press, attach the actor to the pan detector. + mPanDetector.Attach( actor ); - // Do a small animation to indicate to the user that we are in pan mode. - Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION ); - anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentScale() * PAN_MODE_START_ANIMATION_SCALE, AlphaFunction::BOUNCE ); - anim.Play(); - mPanMode = true; - - // Start the shake animation so the user knows when they are in pan mode. - mShakeAnimation.SetLooping( true ); - mShakeAnimation.Play(); - break; - } + // Do a small animation to indicate to the user that we are in pan mode. + Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION ); + anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentProperty< Vector3 >( Actor::Property::SCALE ) * PAN_MODE_START_ANIMATION_SCALE, AlphaFunction::BOUNCE ); + anim.Play(); - case Gesture::Finished: - case Gesture::Cancelled: - { - // We get this state when all touches are released after a long press. We end pan mode... - mPanMode = false; - break; - } - - default: - { - break; - } + // Start the shake animation so the user knows when they are in pan mode. + mShakeAnimation.SetLooping( true ); + mShakeAnimation.Play(); } } @@ -323,56 +290,55 @@ private: */ void OnPan( Actor actor, const PanGesture& pan ) { - if( mPanMode || mPanStarted ) - { - // When we are in Pan mode, just move the actor by the displacement. + // Just move the actor by the displacement. - // As the displacement is in local actor coords, we will have to multiply the displacement by the - // actor's scale so that it moves the correct amount in the parent's coordinate system. - Vector3 scaledDisplacement( pan.displacement ); - scaledDisplacement *= actor.GetCurrentScale(); + // As the displacement is in local actor coords, we will have to multiply the displacement by the + // actor's scale so that it moves the correct amount in the parent's coordinate system. + Vector3 scaledDisplacement( pan.GetDisplacement() ); + scaledDisplacement *= actor.GetCurrentProperty< Vector3 >( Actor::Property::SCALE ); - Vector3 currentPosition; - actor.GetProperty( Actor::Property::POSITION ).Get( currentPosition ); + Vector3 currentPosition; + actor.GetProperty( Actor::Property::POSITION ).Get( currentPosition ); - Vector3 newPosition = currentPosition + scaledDisplacement; - actor.SetPosition( newPosition ); + Vector3 newPosition = currentPosition + scaledDisplacement; + actor.SetProperty( Actor::Property::POSITION, newPosition ); - switch( pan.state ) + switch( pan.GetState() ) + { + case GestureState::STARTED: { - case Gesture::Started: - { - mPanStarted = true; - break; - } - - case Gesture::Finished: - case Gesture::Cancelled: - { - // If we cancel or finish the pan, do an animation to indicate this and stop the shake animation. + mPanStarted = true; + break; + } - Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION ); - anim.AnimateTo( Property( actor, Actor::Property::COLOR ), Vector4::ONE ); - anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentScale() * PAN_MODE_END_ANIMATION_SCALE, AlphaFunction::BOUNCE ); - - // Move actor back to center if we're out of bounds - Vector2 halfStageSize = Stage::GetCurrent().GetSize() * 0.5f; - if( ( std::abs( newPosition.x ) > halfStageSize.width ) || - ( std::abs( newPosition.y ) > halfStageSize.height ) ) - { - anim.AnimateTo( Property( actor, Actor::Property::POSITION ), Vector3::ZERO, AlphaFunction::EASE_IN ); - } - anim.Play(); + case GestureState::FINISHED: + case GestureState::CANCELLED: + { + // If we cancel or finish the pan, do an animation to indicate this and stop the shake animation. - mShakeAnimation.SetLooping( false ); - mPanStarted = false; - break; - } + Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION ); + anim.AnimateTo( Property( actor, Actor::Property::COLOR ), Vector4::ONE ); + anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentProperty< Vector3 >( Actor::Property::SCALE ) * PAN_MODE_END_ANIMATION_SCALE, AlphaFunction::BOUNCE ); - default: + // Move actor back to center if we're out of bounds + Vector2 halfWindowSize = Vector2(mApplication.GetWindow().GetSize()) * 0.5f; + if( ( abs( newPosition.x ) > halfWindowSize.width ) || + ( abs( newPosition.y ) > halfWindowSize.height ) ) { - break; + anim.AnimateTo( Property( actor, Actor::Property::POSITION ), Vector3::ZERO, AlphaFunction::EASE_IN ); } + anim.Play(); + + // Set end of pan configuration and disconnect the actor from the pan detector + mShakeAnimation.SetLooping( false ); + mPanStarted = false; + mPanDetector.Detach( actor ); + break; + } + + default: + { + break; } } } @@ -387,10 +353,11 @@ private: { // Do a short animation to show a tap has happened. - Animation anim = Animation::New( TAP_ANIMATION_DURATON ); - anim.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Degree( 360.0f ), Vector3::ZAXIS ) ); + Animation anim = Animation::New( TAP_ANIMATION_DURATION ); + anim.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( ANGLE_360, Vector3::ZAXIS ) ); anim.AnimateTo( Property( actor, Actor::Property::SCALE ), Vector3::ONE, AlphaFunction::LINEAR ); anim.AnimateTo( Property( actor, Actor::Property::COLOR ), TAP_ANIMATION_COLOR, AlphaFunction::BOUNCE ); + anim.AnimateTo( Property( actor, Actor::Property::POSITION ), Vector3::ZERO, AlphaFunction::EASE_OUT_SQUARE ); anim.Play(); } @@ -402,19 +369,19 @@ private: */ void OnPinch( Actor actor, const PinchGesture& pinch ) { - switch( pinch.state ) + switch( pinch.GetState() ) { - case Gesture::Started: + case GestureState::STARTED: { // Starting scale is required so that we know what to multiply the pinch.scale by. - mStartingScale = actor.GetCurrentScale(); + mStartingScale = actor.GetCurrentProperty< Vector3 >( Actor::Property::SCALE ); break; } - case Gesture::Finished: - case Gesture::Cancelled: + case GestureState::FINISHED: + case GestureState::CANCELLED: { - Vector3 scale( actor.GetCurrentScale() ); + Vector3 scale( actor.GetCurrentProperty< Vector3 >( Actor::Property::SCALE ) ); // Ensure the actor sizes itself to be within the limits defined. if ( scale.x < MINIMUM_SCALE.x ) @@ -439,7 +406,43 @@ private: } } - actor.SetScale( mStartingScale * pinch.scale ); + actor.SetProperty( Actor::Property::SCALE, mStartingScale * pinch.GetScale() ); + } + + /** + * @brief Called when a rotation gesture is detected on our control. + * + * @param[in] actor The actor that's been pinched + * @param[in] rotation The rotation gesture information + */ + void OnRotation( Actor actor, const RotationGesture& rotation ) + { + switch( rotation.GetState() ) + { + case GestureState::STARTED: + { + // Starting orientation is required so that we know what to multiply the rotation.rotation by. + mStartingOrientation = actor.GetCurrentProperty< Quaternion >( Actor::Property::ORIENTATION ); + break; + } + + case GestureState::FINISHED: + case GestureState::CANCELLED: + { + // Do an animation to come back to go back to the original orientation. + Animation anim = Animation::New( ROTATE_BACK_ANIMATION_DURATION ); + anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion::IDENTITY, AlphaFunction::LINEAR ); + anim.Play(); + break; + } + + default: + { + break; + } + } + + actor.SetProperty( Actor::Property::ORIENTATION, Quaternion( mStartingOrientation * Quaternion( rotation.GetRotation(), Vector3::ZAXIS ) ) ); } /** @@ -450,7 +453,7 @@ private: */ void OnKeyEvent( const KeyEvent& event ) { - if( event.state == KeyEvent::Down ) + if( event.GetState() == KeyEvent::DOWN ) { if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) ) { @@ -466,10 +469,11 @@ private: LongPressGestureDetector mLongPressDetector; TapGestureDetector mTapDetector; PinchGestureDetector mPinchDetector; + RotationGestureDetector mRotationDetector; Vector3 mStartingScale; ///< Set to the scale of the control when pinch starts. + Quaternion mStartingOrientation; ///< Set to the orientation of the control when the rotation starts. Animation mShakeAnimation; ///< "Shake" animation to show when we are in panning mode. - bool mPanMode = false; ///< Set to true when we have long-pressed to put us into panning mode. bool mPanStarted = false; ///< Set to true to state that panning has started. };