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