2 * Copyright (c) 2019 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 #include <dali-toolkit/dali-toolkit.h>
23 using namespace Dali::Toolkit;
27 const Property::Value BACKGROUND
29 { Toolkit::Visual::Property::TYPE, Visual::GRADIENT },
30 { GradientVisual::Property::STOP_COLOR, Property::Array{ Vector4( 167.0f, 207.0f, 223.0f, 255.0f ) / 255.0f,
31 Vector4( 0.0f, 64.0f, 137.0f, 255.0f ) / 255.0f } },
32 { GradientVisual::Property::START_POSITION, Vector2( 0.0f, -0.5f ) },
33 { GradientVisual::Property::END_POSITION, Vector2( 0.0f, 0.5f ) }
36 const Property::Value CONTROL_BACKGROUND
38 { Toolkit::Visual::Property::TYPE, Visual::GRADIENT },
39 { GradientVisual::Property::STOP_COLOR, Property::Array{ Vector4( 234.0f, 185.0f, 45.0f, 255.0f ) / 255.0f,
40 Vector4( 199.0f, 152.0f, 16.0f, 255.0f ) / 255.0f } },
41 { GradientVisual::Property::CENTER, Vector2::ZERO },
42 { GradientVisual::Property::RADIUS, 0.5f }
45 const float HELP_ANIMATION_DURATION( 25.0f );
46 const float HELP_ANIMATION_SEGMENT_TIME( 5.0f );
47 const float HELP_ANIMATION_TRANSITION_DURATION( 0.75f );
48 const Vector2 HELP_TEXT_POSITION_MULTIPLIER( 0.25f, 0.13f );
50 const float SHAKY_ANIMATION_DURATION( 0.1f );
51 const float SHAKY_ANIMATION_SEGMENT_TIME( 0.05f );
52 const float SHAKY_ANIMATION_ANGLE( 1.0f );
54 const float TOUCH_MODE_ANIMATION_DURATION( 0.1f );
55 const Vector4 TOUCH_MODE_COLOR( 1.0f, 0.7f, 0.7f, 1.0f );
57 const float PAN_MODE_CHANGE_ANIMATION_DURATION( 0.25f );
58 const Vector3 PAN_MODE_START_ANIMATION_SCALE( 1.2f, 1.2f, 1.0f );
59 const Vector3 PAN_MODE_END_ANIMATION_SCALE( 0.8f, 0.8f, 1.0f );
61 const float TAP_ANIMATION_DURATON( 0.5f );
62 const Vector4 TAP_ANIMATION_COLOR( 0.8f, 0.5, 0.2f, 0.6f );
64 const Vector3 MINIMUM_SCALE( Vector3::ONE );
65 const Vector3 MAXIMUM_SCALE( Vector3::ONE * 2.0f );
66 const float SCALE_BACK_ANIMATION_DURATION( 0.25f );
69 * @brief Shows the given string between the given start and end times.
71 * Appropriately animates the string into and out of the scene.
73 * @param[in] string The label to display, this is an rvalue reference & will be moved
74 * @param[in] parent The parent to add the label to
75 * @param[in] animation The animation to add the animators created in this function
76 * @param[in] startTime When to start the animators
77 * @param[in] endTime When to end the animators
79 void AddHelpInfo( const std::string&& string, Actor parent, Animation animation, float startTime, float endTime )
81 Actor text = TextLabel::New( std::move( string ) );
82 Vector3 position( Stage::GetCurrent().GetSize() * HELP_TEXT_POSITION_MULTIPLIER );
84 text.SetAnchorPoint( AnchorPoint::TOP_CENTER );
85 text.SetParentOrigin( ParentOrigin::TOP_CENTER );
86 text.SetPosition( position );
87 text.SetOpacity( 0.0f );
88 text.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, Text::HorizontalAlignment::CENTER );
92 TimePeriod timePeriod( startTime, HELP_ANIMATION_TRANSITION_DURATION );
93 animation.AnimateTo( Property( text, Actor::Property::COLOR_ALPHA ), 1.0f, timePeriod );
94 animation.AnimateBy( Property( text, Actor::Property::POSITION_X ), -position.x, timePeriod );
97 timePeriod.delaySeconds = endTime;
98 animation.AnimateTo( Property( text, Actor::Property::COLOR_ALPHA ), 0.0f, timePeriod );
99 animation.AnimateBy( Property( text, Actor::Property::POSITION_X ), -position.x, timePeriod );
102 } // unnamed namespace
105 * @brief This example shows how to use the different gesture detectors available.
107 * - Tapping on the control shows a small rotation animation.
108 * - A Long press on the control puts it into Pan Mode.
109 * - When in Pan mode, the control can be panned (moved).
110 * - When the pan ends, we exit the Pan mode via an animation.
111 * - Pinching the control changes the scale of the control.
113 class GestureExample : public ConnectionTracker
118 * @brief Constructor.
120 * @param[in] application Reference to the application
122 GestureExample( Application &application )
123 : mApplication( application )
125 // Connect to the Application's Init signal
126 application.InitSignal().Connect( this, &GestureExample::Create );
132 * @brief Creates the scene as described in this class' description.
134 * @param[in] application Reference to the application class
136 void Create( Application& application )
138 // Get a handle to the stage & connect to the key event signal
139 Stage stage = Stage::GetCurrent();
140 stage.KeyEventSignal().Connect(this, &GestureExample::OnKeyEvent);
142 // Create a background with a linear gradient which matches parent size & is placed in the center.
143 Actor background = Control::New();
144 background.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
145 background.SetParentOrigin( ParentOrigin::CENTER );
146 background.SetProperty( Control::Property::BACKGROUND, BACKGROUND );
147 stage.Add( background );
149 // Create a control with a circular gradient that we'll use for the gestures and be a quarter of the size of the stage.
150 Actor touchControl = Control::New();
151 touchControl.SetSize( stage.GetSize() * 0.25f );
152 touchControl.SetParentOrigin( ParentOrigin::CENTER );
153 touchControl.SetProperty( Control::Property::BACKGROUND, CONTROL_BACKGROUND );
154 background.Add( touchControl );
156 // Connect to the touch signal
157 touchControl.TouchSignal().Connect( this, &GestureExample::OnTouch );
158 touchControl.SetLeaveRequired( true );
160 // Create a long press gesture detector, attach the actor & connect
161 mLongPressDetector = LongPressGestureDetector::New();
162 mLongPressDetector.Attach( touchControl );
163 mLongPressDetector.DetectedSignal().Connect( this, &GestureExample::OnLongPress );
165 // Create a pan gesture detector, attach the actor & connect
166 mPanDetector = PanGestureDetector::New();
167 mPanDetector.Attach( touchControl );
168 mPanDetector.DetectedSignal().Connect( this, &GestureExample::OnPan );
170 // Create a tap gesture detector, attach the actor & connect
171 mTapDetector = TapGestureDetector::New();
172 mTapDetector.Attach( touchControl );
173 mTapDetector.DetectedSignal().Connect( this, &GestureExample::OnTap );
175 // Create a pinch gesture detector, attach the actor & connect
176 mPinchDetector = PinchGestureDetector::New();
177 mPinchDetector.Attach( touchControl );
178 mPinchDetector.DetectedSignal().Connect( this, &GestureExample::OnPinch );
180 // Create an animation which shakes the actor when in Pan mode
181 mShakeAnimation = Animation::New( SHAKY_ANIMATION_DURATION );
182 mShakeAnimation.AnimateBy( Property( touchControl, Actor::Property::ORIENTATION ),
183 Quaternion( Degree( SHAKY_ANIMATION_ANGLE ), Vector3::ZAXIS ),
184 AlphaFunction::BOUNCE,
185 TimePeriod( 0.0f, SHAKY_ANIMATION_SEGMENT_TIME ) );
186 mShakeAnimation.AnimateBy( Property( touchControl, Actor::Property::ORIENTATION ),
187 Quaternion( Degree( -SHAKY_ANIMATION_ANGLE ), Vector3::ZAXIS ),
188 AlphaFunction::BOUNCE,
189 TimePeriod( SHAKY_ANIMATION_SEGMENT_TIME, SHAKY_ANIMATION_SEGMENT_TIME ) );
191 // Animate help information
192 // Here we just animate some text on the screen to show tips on how to use this example
193 // The help animation loops
194 Animation helpAnimation = Animation::New( HELP_ANIMATION_DURATION );
196 float startTime( 0.0f );
197 float endTime( startTime + HELP_ANIMATION_SEGMENT_TIME );
199 AddHelpInfo( "Tap image for animation", background, helpAnimation, startTime, endTime );
200 AddHelpInfo( "Press & Hold image to drag", background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME );
201 AddHelpInfo( "Pinch image to resize", background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME );
202 helpAnimation.SetLooping( true );
203 helpAnimation.Play();
207 * @brief Called when our actor is touched.
209 * @param[in] actor The touched actor
210 * @param[in] touch The touch event
212 bool OnTouch( Actor actor, const TouchData& touch )
214 switch( touch.GetState( 0 ) )
216 case PointState::DOWN:
218 // When we get a touch point, change the color of the actor.
220 Animation anim = Animation::New( TOUCH_MODE_ANIMATION_DURATION );
221 anim.AnimateTo( Property( actor, Actor::Property::COLOR ), TOUCH_MODE_COLOR );
226 case PointState::LEAVE:
228 case PointState::INTERRUPTED:
232 // If we're not panning, change the color back to normal.
234 Animation anim = Animation::New( TOUCH_MODE_ANIMATION_DURATION );
235 anim.AnimateTo( Property( actor, Actor::Property::COLOR ), Vector4::ONE );
238 // Stop the shake animation from looping.
239 mShakeAnimation.SetLooping( false );
253 * @brief Called when a long-press gesture is detected on our control.
255 * @param[in] actor The actor that's been long-pressed
256 * @param[in] longPress The long-press gesture information
258 void OnLongPress( Actor actor, const LongPressGesture& longPress )
260 switch( longPress.state )
262 case Gesture::Started:
264 // When we first receive a long press, change state to pan mode.
266 // Do a small animation to indicate to the user that we are in pan mode.
267 Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION );
268 anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentScale() * PAN_MODE_START_ANIMATION_SCALE, AlphaFunction::BOUNCE );
272 // Start the shake animation so the user knows when they are in pan mode.
273 mShakeAnimation.SetLooping( true );
274 mShakeAnimation.Play();
278 case Gesture::Finished:
279 case Gesture::Cancelled:
281 // We get this state when all touches are released after a long press. We end pan mode...
294 * @brief Called when a pan gesture is detected on our control.
296 * @param[in] actor The actor that's been panned
297 * @param[in] pan The pan gesture information
299 void OnPan( Actor actor, const PanGesture& pan )
301 if( mPanMode || mPanStarted )
303 // When we are in Pan mode, just move the actor by the displacement.
305 // As the displacement is in local actor coords, we will have to multiply the displacement by the
306 // actor's scale so that it moves the correct amount in the parent's coordinate system.
307 Vector3 scaledDisplacement( pan.displacement );
308 scaledDisplacement *= actor.GetCurrentScale();
310 Vector3 currentPosition;
311 actor.GetProperty( Actor::Property::POSITION ).Get( currentPosition );
313 Vector3 newPosition = currentPosition + scaledDisplacement;
314 actor.SetPosition( newPosition );
318 case Gesture::Started:
324 case Gesture::Finished:
325 case Gesture::Cancelled:
327 // If we cancel or finish the pan, do an animation to indicate this and stop the shake animation.
329 Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION );
330 anim.AnimateTo( Property( actor, Actor::Property::COLOR ), Vector4::ONE );
331 anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentScale() * PAN_MODE_END_ANIMATION_SCALE, AlphaFunction::BOUNCE );
333 // Move actor back to center if we're out of bounds
334 Vector2 halfStageSize = Stage::GetCurrent().GetSize() * 0.5f;
335 if( ( std::abs( newPosition.x ) > halfStageSize.width ) ||
336 ( std::abs( newPosition.y ) > halfStageSize.height ) )
338 anim.AnimateTo( Property( actor, Actor::Property::POSITION ), Vector3::ZERO, AlphaFunction::EASE_IN );
342 mShakeAnimation.SetLooping( false );
356 * @brief Called when a tap gesture is detected on our control.
358 * @param[in] actor The actor that's been tapped
359 * @param[in] tap The tap gesture information
361 void OnTap( Actor actor, const TapGesture& tap )
363 // Do a short animation to show a tap has happened.
365 Animation anim = Animation::New( TAP_ANIMATION_DURATON );
366 anim.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Degree( 360.0f ), Vector3::ZAXIS ) );
367 anim.AnimateTo( Property( actor, Actor::Property::SCALE ), Vector3::ONE, AlphaFunction::LINEAR );
368 anim.AnimateTo( Property( actor, Actor::Property::COLOR ), TAP_ANIMATION_COLOR, AlphaFunction::BOUNCE );
373 * @brief Called when a pinch gesture is detected on our control.
375 * @param[in] actor The actor that's been pinched
376 * @param[in] pinch The pinch gesture information
378 void OnPinch( Actor actor, const PinchGesture& pinch )
380 switch( pinch.state )
382 case Gesture::Started:
384 // Starting scale is required so that we know what to multiply the pinch.scale by.
385 mStartingScale = actor.GetCurrentScale();
389 case Gesture::Finished:
390 case Gesture::Cancelled:
392 Vector3 scale( actor.GetCurrentScale() );
394 // Ensure the actor sizes itself to be within the limits defined.
395 if ( scale.x < MINIMUM_SCALE.x )
397 scale = MINIMUM_SCALE;
399 else if ( scale.x > MAXIMUM_SCALE.x )
401 scale = MAXIMUM_SCALE;
404 // Do an animation to come back to go back to the limits.
405 Animation anim = Animation::New( SCALE_BACK_ANIMATION_DURATION );
406 anim.AnimateTo( Property( actor, Actor::Property::SCALE ), scale, AlphaFunction::LINEAR );
417 actor.SetScale( mStartingScale * pinch.scale );
421 * @brief Called when any key event is received.
423 * Will use this to quit the application if Back or the Escape key is received.
424 * @param[in] event The key event information
426 void OnKeyEvent( const KeyEvent& event )
428 if( event.state == KeyEvent::Down )
430 if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
438 Application& mApplication;
440 PanGestureDetector mPanDetector;
441 LongPressGestureDetector mLongPressDetector;
442 TapGestureDetector mTapDetector;
443 PinchGestureDetector mPinchDetector;
445 Vector3 mStartingScale; ///< Set to the scale of the control when pinch starts.
446 Animation mShakeAnimation; ///< "Shake" animation to show when we are in panning mode.
447 bool mPanMode = false; ///< Set to true when we have long-pressed to put us into panning mode.
448 bool mPanStarted = false; ///< Set to true to state that panning has started.
451 int DALI_EXPORT_API main( int argc, char **argv )
453 Application application = Application::New( &argc, &argv );
454 GestureExample controller( application );
455 application.MainLoop();