[dali_1.0.48] Merge branch 'devel/master'
[platform/core/uifw/dali-demo.git] / examples / motion-blur / motion-blur-example.cpp
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 #include <sstream>
19 #include <iomanip>
20
21 #include "shared/view.h"
22 #include <dali/dali.h>
23 #include <dali-toolkit/dali-toolkit.h>
24 #include <dali-toolkit/devel-api/shader-effects/motion-blur-effect.h>
25 #include <dali-toolkit/devel-api/controls/popup/popup.h>
26
27 using namespace Dali;
28 using namespace Dali::Toolkit;
29
30
31
32 namespace // unnamed namespace
33 {
34
35 ////////////////////////////////////////////////////
36 //
37 // Demo setup parameters
38 //
39
40 //#define MULTIPLE_MOTION_BLURRED_ACTORS
41 #ifndef MULTIPLE_MOTION_BLURRED_ACTORS
42
43 const float MOTION_BLUR_ACTOR_WIDTH = 256;                                          // actor size on screen
44 const float MOTION_BLUR_ACTOR_HEIGHT = 256;                                         // ""
45
46 #else //#ifndef MULTIPLE_MOTION_BLURRED_ACTORS
47
48 const float MOTION_BLUR_ACTOR_WIDTH = 150;                                          // actor size on screen
49 const float MOTION_BLUR_ACTOR_HEIGHT = 112;                                         // ""
50
51 #endif //#ifndef MULTIPLE_MOTION_BLURRED_ACTORS
52
53
54 const unsigned int MOTION_BLUR_NUM_SAMPLES = 8;
55
56 const int MOTION_BLUR_NUM_ACTOR_IMAGES = 5;
57 const char* MOTION_BLUR_ACTOR_IMAGE1( DALI_IMAGE_DIR "image-with-border-1.jpg" );
58 const char* MOTION_BLUR_ACTOR_IMAGE2( DALI_IMAGE_DIR "image-with-border-2.jpg" );
59 const char* MOTION_BLUR_ACTOR_IMAGE3( DALI_IMAGE_DIR "image-with-border-3.jpg" );
60 const char* MOTION_BLUR_ACTOR_IMAGE4( DALI_IMAGE_DIR "image-with-border-4.jpg" );
61 const char* MOTION_BLUR_ACTOR_IMAGE5( DALI_IMAGE_DIR "image-with-border-1.jpg" );
62
63 const char* MOTION_BLUR_ACTOR_IMAGES[] = {
64   MOTION_BLUR_ACTOR_IMAGE1,
65   MOTION_BLUR_ACTOR_IMAGE2,
66   MOTION_BLUR_ACTOR_IMAGE3,
67   MOTION_BLUR_ACTOR_IMAGE4,
68   MOTION_BLUR_ACTOR_IMAGE5,
69 };
70
71 const int NUM_ACTOR_ANIMATIONS = 4;
72 const int NUM_CAMERA_ANIMATIONS = 2;
73
74
75 const char* BACKGROUND_IMAGE_PATH = DALI_IMAGE_DIR "background-default.png";
76
77 const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
78 const char* LAYOUT_IMAGE( DALI_IMAGE_DIR "icon-change.png" );
79 const char* LAYOUT_IMAGE_SELECTED( DALI_IMAGE_DIR "icon-change-selected.png" );
80 const char* APPLICATION_TITLE( "Motion Blur" );
81 const char* EFFECTS_OFF_ICON( DALI_IMAGE_DIR "icon-effects-off.png" );
82 const char* EFFECTS_OFF_ICON_SELECTED( DALI_IMAGE_DIR "icon-effects-off-selected.png" );
83 const char* EFFECTS_ON_ICON( DALI_IMAGE_DIR "icon-effects-on.png" );
84 const char* EFFECTS_ON_ICON_SELECTED( DALI_IMAGE_DIR "icon-effects-on-selected.png" );
85
86 const float UI_MARGIN = 4.0f;                              ///< Screen Margin for placement of UI buttons
87
88 const Vector3 BUTTON_SIZE_CONSTRAINT( 0.24f, 0.09f, 1.0f );
89 const Vector3 BUTTON_TITLE_LABEL_TAP_HERE_SIZE_CONSTRAINT( 0.55f, 0.06f, 1.0f );
90 const Vector3 BUTTON_TITLE_LABEL_INSTRUCTIONS_POPUP_SIZE_CONSTRAINT( 1.0f, 1.0f, 1.0f );
91
92 // move this button down a bit so it is visible on target and not covered up by toolbar
93 const float BUTTON_TITLE_LABEL_Y_OFFSET = 0.05f;
94
95 const float ORIENTATION_DURATION = 0.5f;                  ///< Time to rotate to new orientation.
96
97 /**
98  * @brief Load an image, scaled-down to no more than the dimensions passed in.
99  *
100  * Uses SHRINK_TO_FIT which ensures the resulting image is
101  * smaller than or equal to the specified dimensions while preserving its
102  * original aspect ratio.
103  */
104 ResourceImage LoadImageFittedInBox( const char * const imagePath, uint32_t maxWidth, uint32_t maxHeight )
105 {
106   // Load the image nicely scaled-down to fit within the specified max width and height:
107   return ResourceImage::New( imagePath, ImageDimensions( maxWidth, maxHeight ), FittingMode::SHRINK_TO_FIT, Dali::SamplingMode::BOX_THEN_LINEAR );
108 }
109
110 } // unnamed namespace
111
112
113 //
114 class MotionBlurExampleApp : public ConnectionTracker
115 {
116 public:
117
118   /**
119      * DeviceOrientation describes the four different
120      * orientations the device can be in based on accelerometer reports.
121      */
122   enum DeviceOrientation
123   {
124     PORTRAIT = 0,
125     LANDSCAPE = 90,
126     PORTRAIT_INVERSE = 180,
127     LANDSCAPE_INVERSE = 270
128   };
129
130   /**
131    * Constructor
132    * @param application class, stored as reference
133    */
134   MotionBlurExampleApp(Application &app)
135   : mApplication(app),
136     mActorEffectsEnabled(false),
137     mCurrentActorAnimation(0),
138     mCurrentImage(0)
139   {
140     // Connect to the Application's Init signal
141     app.InitSignal().Connect(this, &MotionBlurExampleApp::OnInit);
142   }
143
144   ~MotionBlurExampleApp()
145   {
146     // Nothing to do here; everything gets deleted automatically
147   }
148
149   /**
150    * This method gets called once the main loop of application is up and running
151    */
152   void OnInit(Application& app)
153   {
154     // The Init signal is received once (only) during the Application lifetime
155
156     Stage::GetCurrent().KeyEventSignal().Connect(this, &MotionBlurExampleApp::OnKeyEvent);
157
158
159     // Creates a default view with a default tool bar.
160     // The view is added to the stage.
161     mContentLayer = DemoHelper::CreateView( mApplication,
162                                             mView,
163                                             mToolBar,
164                                             BACKGROUND_IMAGE_PATH,
165                                             TOOLBAR_IMAGE,
166                                             APPLICATION_TITLE );
167
168     //Add an effects icon on the right of the title
169     mIconEffectsOff = ResourceImage::New( EFFECTS_OFF_ICON );
170     mIconEffectsOffSelected = ResourceImage::New( EFFECTS_OFF_ICON_SELECTED );
171     mIconEffectsOn = ResourceImage::New( EFFECTS_ON_ICON );
172     mIconEffectsOnSelected = ResourceImage::New( EFFECTS_ON_ICON_SELECTED );
173     mActorEffectsButton = Toolkit::PushButton::New();
174     mActorEffectsButton.SetButtonImage( mIconEffectsOff );
175     mActorEffectsButton.SetSelectedImage( mIconEffectsOffSelected );
176     mActorEffectsButton.ClickedSignal().Connect( this, &MotionBlurExampleApp::OnEffectButtonClicked );
177     mToolBar.AddControl( mActorEffectsButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalCenter, DemoHelper::DEFAULT_PLAY_PADDING );
178
179     // Creates a mode button.
180     // Create a effect toggle button. (right of toolbar)
181     Image imageLayout = ResourceImage::New( LAYOUT_IMAGE );
182     Image imageLayoutSelected = ResourceImage::New( LAYOUT_IMAGE_SELECTED );
183     Toolkit::PushButton layoutButton = Toolkit::PushButton::New();
184     layoutButton.SetButtonImage( imageLayout );
185     layoutButton.SetSelectedImage( imageLayoutSelected );
186     layoutButton.ClickedSignal().Connect( this, &MotionBlurExampleApp::OnLayoutButtonClicked);
187     layoutButton.SetLeaveRequired( true );
188     mToolBar.AddControl( layoutButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
189
190     // Input
191     mTapGestureDetector = TapGestureDetector::New();
192     mTapGestureDetector.Attach( mContentLayer );
193     mTapGestureDetector.DetectedSignal().Connect( this, &MotionBlurExampleApp::OnTap );
194
195     Dali::Window winHandle = app.GetWindow();
196     winHandle.AddAvailableOrientation( Dali::Window::PORTRAIT );
197     winHandle.AddAvailableOrientation( Dali::Window::LANDSCAPE );
198     winHandle.AddAvailableOrientation( Dali::Window::PORTRAIT_INVERSE  );
199     winHandle.AddAvailableOrientation( Dali::Window::LANDSCAPE_INVERSE );
200
201     // set initial orientation
202    // winHandle.GetOrientation().ChangedSignal().Connect( this, &MotionBlurExampleApp::OnOrientationChanged );
203     unsigned int degrees = 0;
204     Rotate( static_cast< DeviceOrientation >( degrees ) );
205
206
207     ///////////////////////////////////////////////////////
208     //
209     // Motion blurred actor
210     //
211
212     // Scale down actor to fit on very low resolution screens with space to interact:
213     Size stageSize = Stage::GetCurrent().GetSize();
214     mMotionBlurActorSize = Size( std::min( stageSize.x * 0.3f, MOTION_BLUR_ACTOR_WIDTH ), std::min( stageSize.y * 0.3f, MOTION_BLUR_ACTOR_HEIGHT ) );
215     mMotionBlurActorSize = Size( std::min( mMotionBlurActorSize.x, mMotionBlurActorSize.y ), std::min( mMotionBlurActorSize.x, mMotionBlurActorSize.y ) );
216
217     Image image = LoadImageFittedInBox( MOTION_BLUR_ACTOR_IMAGE1, mMotionBlurActorSize.x, mMotionBlurActorSize.y );
218     mMotionBlurImageActor = ImageActor::New(image);
219     mMotionBlurImageActor.SetParentOrigin( ParentOrigin::CENTER );
220     mMotionBlurImageActor.SetSize(mMotionBlurActorSize.x, mMotionBlurActorSize.y);
221
222     mContentLayer.Add( mMotionBlurImageActor );
223
224     // Create shader used for doing motion blur
225     mMotionBlurEffect = Toolkit::CreateMotionBlurEffect();
226     Dali::Property::Index uModelProperty = mMotionBlurEffect.GetPropertyIndex( "uModelLastFrame" );
227     Constraint constraint = Constraint::New<Matrix>( mMotionBlurEffect, uModelProperty, EqualToConstraint() );
228     constraint.AddSource( Source( mMotionBlurImageActor , Actor::Property::WORLD_MATRIX ) );
229     constraint.Apply();
230     mMotionBlurImageActor.SetShaderEffect( mMotionBlurEffect );
231
232
233 #ifdef MULTIPLE_MOTION_BLURRED_ACTORS
234
235     ///////////////////////////////////////////////////////
236     //
237     // Motion blurred actor 2
238     //
239
240     mMotionBlurImageActor2 = ImageActor::New(image);
241     mMotionBlurImageActor2.SetParentOrigin( ParentOrigin::CENTER );
242     mMotionBlurImageActor2.SetSize(mMotionBlurActorSize.x, mMotionBlurActorSize.y);
243     mMotionBlurImageActor2.SetPosition(mMotionBlurActorSize.x * 1.1f, 0.0f);
244     mMotionBlurImageActor.Add( mMotionBlurImageActor2 );
245
246     // Create shader used for doing motion blur
247     mMotionBlurEffect2 = CreateMotionBlurEffect(MOTION_BLUR_NUM_SAMPLES);
248
249     // set actor shader to the blur one
250     mMotionBlurImageActor2.SetShaderEffect( mMotionBlurEffect2 );
251
252
253     ///////////////////////////////////////////////////////
254     //
255     // Motion blurred actor 3
256     //
257
258     mMotionBlurImageActor3 = ImageActor::New(image);
259     mMotionBlurImageActor3.SetParentOrigin( ParentOrigin::CENTER );
260     mMotionBlurImageActor3.SetSize(mMotionBlurActorSize.x, mMotionBlurActorSize.y);
261     mMotionBlurImageActor3.SetPosition(-mMotionBlurActorSize.x * 1.1f, 0.0f);
262     mMotionBlurImageActor.Add( mMotionBlurImageActor3 );
263
264     // Create shader used for doing motion blur
265     mMotionBlurEffect3 = CreateMotionBlurEffect(MOTION_BLUR_NUM_SAMPLES);
266
267     // set actor shader to the blur one
268     mMotionBlurImageActor3.SetShaderEffect( mMotionBlurEffect3 );
269
270
271     ///////////////////////////////////////////////////////
272     //
273     // Motion blurred actor 4
274     //
275
276     mMotionBlurImageActor4 = ImageActor::New(image);
277     mMotionBlurImageActor4.SetParentOrigin( ParentOrigin::CENTER );
278     mMotionBlurImageActor4.SetSize(mMotionBlurActorSize.x, mMotionBlurActorSize.y);
279     mMotionBlurImageActor4.SetPosition(0.0f, mMotionBlurActorSize.y * 1.1f);
280     mMotionBlurImageActor.Add( mMotionBlurImageActor4 );
281
282     // Create shader used for doing motion blur
283     mMotionBlurEffect4 = CreateMotionBlurEffect(MOTION_BLUR_NUM_SAMPLES);
284
285     // set actor shader to the blur one
286     mMotionBlurImageActor4.SetShaderEffect( mMotionBlurEffect4 );
287
288
289     ///////////////////////////////////////////////////////
290     //
291     // Motion blurred actor 5
292     //
293
294     mMotionBlurImageActor5 = ImageActor::New(image);
295     mMotionBlurImageActor5.SetParentOrigin( ParentOrigin::CENTER );
296     mMotionBlurImageActor5.SetSize(mMotionBlurActorSize.x, mMotionBlurActorSize.y);
297     mMotionBlurImageActor5.SetPosition(0.0f, -mMotionBlurActorSize.y * 1.1f);
298     mMotionBlurImageActor.Add( mMotionBlurImageActor5 );
299
300     // Create shader used for doing motion blur
301     mMotionBlurEffect5 = CreateMotionBlurEffect(MOTION_BLUR_NUM_SAMPLES);
302
303     // set actor shader to the blur one
304     mMotionBlurImageActor5.SetShaderEffect( mMotionBlurEffect5 );
305 #endif //#ifdef MULTIPLE_MOTION_BLURRED_ACTORS
306   }
307
308   //////////////////////////////////////////////////////////////
309   //
310   // Device Orientation Support
311   //
312   //
313
314   void OnOrientationChanged( Orientation orientation )
315   {
316     unsigned int degrees = orientation.GetDegrees();
317     Rotate( static_cast< DeviceOrientation >( degrees ) );
318   }
319
320   void Rotate( DeviceOrientation orientation )
321   {
322     // Resize the root actor
323     Vector2 stageSize = Stage::GetCurrent().GetSize();
324     Vector2 targetSize = stageSize;
325     if( orientation == LANDSCAPE ||
326         orientation == LANDSCAPE_INVERSE )
327     {
328       targetSize = Vector2( stageSize.y, stageSize.x );
329     }
330
331     if( mOrientation != orientation )
332     {
333       mOrientation = orientation;
334
335       // check if actor is on stage
336       if( mView.GetParent() )
337       {
338         // has parent so we expect it to be on stage, start animation
339         mRotateAnimation = Animation::New( ORIENTATION_DURATION );
340         mRotateAnimation.AnimateTo( Property( mView, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( -orientation ) ), Vector3::ZAXIS ), AlphaFunction::EASE_OUT );
341         mRotateAnimation.AnimateTo( Property( mView, Actor::Property::SIZE_WIDTH ), targetSize.width );
342         mRotateAnimation.AnimateTo( Property( mView, Actor::Property::SIZE_HEIGHT ), targetSize.height );
343         mRotateAnimation.Play();
344       }
345       else
346       {
347         // set the rotation to match the orientation
348         mView.SetOrientation( Degree( -orientation ), Vector3::ZAXIS );
349         mView.SetSize( targetSize );
350       }
351     }
352     else
353     {
354       // for first time just set size
355       mView.SetSize( targetSize );
356     }
357   }
358
359
360   //////////////////////////////////////////////////////////////
361   //
362   // Actor Animation
363   //
364   //
365
366   // move to point on screen that was tapped
367   void OnTap( Actor actor, const TapGesture& tapGesture )
368   {
369     Vector3 destPos;
370     float originOffsetX, originOffsetY;
371
372     // rotate offset (from top left origin to centre) into actor space
373     Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
374     actor.ScreenToLocal(originOffsetX, originOffsetY, stageSize.width * 0.5f, stageSize.height * 0.5f);
375
376     // get dest point in local actor space
377     destPos.x = tapGesture.localPoint.x - originOffsetX;
378     destPos.y = tapGesture.localPoint.y - originOffsetY;
379     destPos.z = 0.0f;
380
381     float animDuration = 0.5f;
382     mActorTapMovementAnimation = Animation::New( animDuration );
383     if ( mMotionBlurImageActor )
384     {
385       mActorTapMovementAnimation.AnimateTo( Property(mMotionBlurImageActor, Actor::Property::POSITION), destPos, AlphaFunction::EASE_IN_OUT_SINE, TimePeriod(animDuration) );
386     }
387     mActorTapMovementAnimation.SetEndAction( Animation::Bake );
388     mActorTapMovementAnimation.Play();
389
390
391     // perform some spinning etc
392     if(mActorEffectsEnabled)
393     {
394       switch(mCurrentActorAnimation)
395       {
396         // spin around y
397         case 0:
398         {
399           float animDuration = 1.0f;
400           mActorAnimation = Animation::New(animDuration);
401           mActorAnimation.AnimateBy( Property( mMotionBlurImageActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree(360.0f) ), Vector3::YAXIS ), AlphaFunction::EASE_IN_OUT );
402           mActorAnimation.SetEndAction( Animation::Bake );
403           mActorAnimation.Play();
404         }
405         break;
406
407         // spin around z
408         case 1:
409         {
410           float animDuration = 1.0f;
411           mActorAnimation = Animation::New(animDuration);
412           mActorAnimation.AnimateBy( Property( mMotionBlurImageActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree(360.0f) ), Vector3::ZAXIS ), AlphaFunction::EASE_IN_OUT );
413           mActorAnimation.SetEndAction( Animation::Bake );
414           mActorAnimation.Play();
415         }
416         break;
417
418         // spin around y and z
419         case 2:
420         {
421           float animDuration = 1.0f;
422           mActorAnimation = Animation::New(animDuration);
423           mActorAnimation.AnimateBy( Property( mMotionBlurImageActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree(360.0f) ), Vector3::YAXIS ), AlphaFunction::EASE_IN_OUT );
424           mActorAnimation.AnimateBy( Property( mMotionBlurImageActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree(360.0f) ), Vector3::ZAXIS ), AlphaFunction::EASE_IN_OUT );
425           mActorAnimation.SetEndAction( Animation::Bake );
426           mActorAnimation.Play();
427         }
428         break;
429
430         // scale
431         case 3:
432         {
433           float animDuration = 1.0f;
434           mActorAnimation = Animation::New(animDuration);
435           mActorAnimation.AnimateBy( Property( mMotionBlurImageActor, Actor::Property::SCALE ), Vector3(2.0f, 2.0f, 2.0f), AlphaFunction::BOUNCE, TimePeriod( 0.0f, 1.0f ) );
436           mActorAnimation.SetEndAction( Animation::Bake );
437           mActorAnimation.Play();
438         }
439         break;
440
441         default:
442           break;
443       }
444
445       mCurrentActorAnimation++;
446       if(NUM_ACTOR_ANIMATIONS == mCurrentActorAnimation)
447       {
448         mCurrentActorAnimation = 0;
449       }
450     }
451   }
452
453   void ToggleActorEffects()
454   {
455     if(!mActorEffectsEnabled)
456     {
457       mActorEffectsEnabled = true;
458       mActorEffectsButton.SetButtonImage( mIconEffectsOn );
459       mActorEffectsButton.SetSelectedImage( mIconEffectsOnSelected );
460     }
461     else
462     {
463       mActorEffectsEnabled = false;
464       mActorEffectsButton.SetButtonImage( mIconEffectsOff );
465       mActorEffectsButton.SetSelectedImage( mIconEffectsOffSelected );
466     }
467   }
468
469   //////////////////////////////////////////////////////////////
470   //
471   // Input handlers
472   //
473   //
474
475   bool OnLayoutButtonClicked( Toolkit::Button button )
476   {
477     ChangeImage();
478     return true;
479   }
480
481   bool OnEffectButtonClicked( Toolkit::Button button )
482   {
483     ToggleActorEffects();
484     return true;
485   }
486
487   /**
488    * Main key event handler
489    */
490   void OnKeyEvent(const KeyEvent& event)
491   {
492     if(event.state == KeyEvent::Down)
493     {
494       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
495       {
496         mApplication.Quit();
497       }
498     }
499   }
500
501   //////////////////////////////////////////////////////////////
502   //
503   // Misc
504   //
505   //
506
507
508   void ChangeImage()
509   {
510     mCurrentImage++;
511     if(MOTION_BLUR_NUM_ACTOR_IMAGES == mCurrentImage)
512     {
513       mCurrentImage = 0;
514     }
515
516     Image blurImage = LoadImageFittedInBox( MOTION_BLUR_ACTOR_IMAGES[mCurrentImage], mMotionBlurActorSize.x, mMotionBlurActorSize.y );
517     mMotionBlurImageActor.SetImage(blurImage);
518   }
519
520
521 private:
522   Application&               mApplication;            ///< Application instance
523   Toolkit::Control           mView;
524   Toolkit::ToolBar           mToolBar;
525   Image                      mIconEffectsOff;
526   Image                      mIconEffectsOffSelected;
527   Image                      mIconEffectsOn;
528   Image                      mIconEffectsOnSelected;
529
530   Layer                      mContentLayer;           ///< Content layer (contains actor for this blur demo)
531
532   PushButton                 mActorEffectsButton;     ///< The actor effects toggling Button.
533
534   // Motion blur
535   ShaderEffect mMotionBlurEffect;
536   ImageActor mMotionBlurImageActor;
537   Size mMotionBlurActorSize;
538
539 #ifdef MULTIPLE_MOTION_BLURRED_ACTORS
540   ShaderEffect mMotionBlurEffect2;
541   ShaderEffect mMotionBlurEffect3;
542   ShaderEffect mMotionBlurEffect4;
543   ShaderEffect mMotionBlurEffect5;
544
545   ImageActor mMotionBlurImageActor2;
546   ImageActor mMotionBlurImageActor3;
547   ImageActor mMotionBlurImageActor4;
548   ImageActor mMotionBlurImageActor5;
549 #endif //#ifdef MULTIPLE_MOTION_BLURRED_ACTORS
550
551   // animate actor to position where user taps screen
552   Animation mActorTapMovementAnimation;
553
554   // show different animations to demonstrate blur effect working on an object only movement basis
555   bool mActorEffectsEnabled;
556   Animation mActorAnimation;
557   int mCurrentActorAnimation;
558
559   // offer a selection of images that user can cycle between
560   int mCurrentImage;
561
562   TapGestureDetector mTapGestureDetector;
563
564   DeviceOrientation mOrientation;               ///< Current Device orientation
565   Animation mRotateAnimation;                   ///< Animation for rotating between landscape and portrait.
566
567   Popup mInstructionsPopup;                     ///< Info Popup
568 };
569
570 void RunTest(Application& app)
571 {
572   MotionBlurExampleApp test(app);
573
574   app.MainLoop();
575 }
576
577 // Entry point for Linux & Tizen applications
578 //
579 int main(int argc, char **argv)
580 {
581   Application app = Application::New(&argc, &argv, DALI_DEMO_THEME_PATH);
582
583   RunTest(app);
584
585   return 0;
586 }