Demo of Dali toolkit and core capabilities
[platform/core/uifw/dali-demo.git] / examples / shader-effect / dissolve-effect-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 // EXTERNAL INCLUDES
18 #include <math.h>
19
20 // INTERNAL INCLUDES
21 #include "../shared/view.h"
22
23 #include <dali/dali.h>
24 #include <dali-toolkit/dali-toolkit.h>
25
26 using namespace Dali;
27
28 // LOCAL STUFF
29 namespace
30 {
31
32 const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
33 const char* APPLICATION_TITLE_HIGHP( "Dissolve Effect(highp)" );
34 const char* APPLICATION_TITLE_MEDIUMP( "Dissolve Effect(mediump)" );
35 const char* CHANGE_EFFECT_IMAGE( DALI_IMAGE_DIR "icon_mode.png" );
36 const char* PLAY_ICON( DALI_IMAGE_DIR "icon-play.png" );
37 const char* STOP_ICON( DALI_IMAGE_DIR "icon-stop.png" );
38
39 const char* IMAGES[] =
40 {
41   DALI_IMAGE_DIR "gallery-large-1.jpg",
42   DALI_IMAGE_DIR "gallery-large-2.jpg",
43   DALI_IMAGE_DIR "gallery-large-3.jpg",
44   DALI_IMAGE_DIR "gallery-large-4.jpg",
45   DALI_IMAGE_DIR "gallery-large-5.jpg",
46   DALI_IMAGE_DIR "gallery-large-6.jpg",
47   DALI_IMAGE_DIR "gallery-large-7.jpg",
48   DALI_IMAGE_DIR "gallery-large-8.jpg",
49   DALI_IMAGE_DIR "gallery-large-9.jpg",
50   DALI_IMAGE_DIR "gallery-large-10.jpg",
51   DALI_IMAGE_DIR "gallery-large-11.jpg",
52   DALI_IMAGE_DIR "gallery-large-12.jpg",
53   DALI_IMAGE_DIR "gallery-large-13.jpg",
54   DALI_IMAGE_DIR "gallery-large-14.jpg",
55   DALI_IMAGE_DIR "gallery-large-15.jpg",
56   DALI_IMAGE_DIR "gallery-large-16.jpg",
57   DALI_IMAGE_DIR "gallery-large-17.jpg",
58   DALI_IMAGE_DIR "gallery-large-18.jpg",
59   DALI_IMAGE_DIR "gallery-large-19.jpg",
60   DALI_IMAGE_DIR "gallery-large-20.jpg",
61   DALI_IMAGE_DIR "gallery-large-21.jpg",
62 };
63
64 const int NUM_IMAGES( sizeof(IMAGES) / sizeof(IMAGES[0]) );
65
66 // The duration of the current image staying on screen when slideshow is on
67 const int VIEWINGTIME = 2000; // 2 seconds
68
69 const float TRANSITION_DURATION = 2.5f; //2.5 second
70
71 const float INITIAL_DEPTH = -10.0f;
72 } // namespace
73
74 class DissolveEffectApp : public ConnectionTracker
75 {
76 public:
77
78   /**
79    * Constructor
80    * @param application class, stored as reference
81    */
82   DissolveEffectApp( Application& application );
83
84   ~DissolveEffectApp();
85
86 private:
87
88   /**
89    * This method gets called once the main loop of application is up and running
90    */
91   void OnInit( Application& application );
92   /**
93    * PanGesture callback. This method gets called when the pan gesture is detected.
94    * @param[in] actor The actor receiving the pan gesture.
95    * @param[in] gesture The detected pan gesture.
96    */
97   void OnPanGesture( Actor actor, PanGesture gesture );
98
99   /**
100    * Set up the animations for transition
101    * @param[in] position The point ( locates within rectange {(0,0),(0,1),(1,0),(1,1)} ) passing through the central line of the dissolve effect
102    * @param[in] displacement The direction of the central line of the dissolve effect
103    */
104   void StartTransition(Vector2 position, Vector2 displacement);
105   /**
106    * Callback function of effect-switch button
107    * Change the precision of the effect shader when the effect button is clicked
108    * @param[in] button The handle of the clicked button
109    */
110   bool OnEffectButtonClicked( Toolkit::Button button );
111   /**
112    * Callback function of slideshow button
113    * Start or stop the automatical image display when the slideshow button is clicked
114    * @param[in] button The handle of the clicked button
115    */
116   bool OnSildeshowButtonClicked( Toolkit::Button button );
117   /**
118    * Callback function of cube transition completed signal
119    * @param[in] effect The cube effect used for the transition
120    * @param[in] imageActor The target imageActor of the completed transition
121    */
122   void OnTransitionCompleted(Animation& source);
123   /**
124    * Callback function of timer tick
125    * The timer is used to count the image display duration after cube transition in slideshow,
126    */
127   bool OnTimerTick();
128
129   /**
130    * Main key event handler
131    */
132   void OnKeyEvent(const KeyEvent& event);
133
134 private:
135   Application&                    mApplication;
136   Toolkit::View                   mView;
137   Toolkit::ToolBar                mToolBar;
138   Layer                           mContent;
139   Toolkit::TextView               mTitleActor;
140
141   ImageActor                      mCurrentImage;
142   ImageActor                      mNextImage;
143   unsigned int                    mIndex;
144   Constraint                      mSizeConstraint;
145
146   Toolkit::DissolveEffect         mCurrentImageEffect;
147   Toolkit::DissolveEffect         mNextImageEffect;
148   bool                            mUseHighPrecision;
149   Animation                       mAnimation;
150
151   PanGestureDetector              mPanGestureDetector;
152   bool                            mIsTransiting;
153
154   bool                            mSlideshow;
155   Timer                           mViewTimer;
156   bool                            mTimerReady;
157   unsigned int                    mCentralLineIndex;
158
159   Image                           mIconPlay;
160   Image                           mIconStop;
161   Toolkit::PushButton             mPlayStopButton;
162 };
163
164 DissolveEffectApp::DissolveEffectApp( Application& application )
165 : mApplication( application ),
166   mIndex( 0 ),
167   mUseHighPrecision(true),
168   mIsTransiting( false ),
169   mSlideshow( false ),
170   mTimerReady( false ),
171   mCentralLineIndex( 0 )
172 {
173   mApplication.InitSignal().Connect( this, &DissolveEffectApp::OnInit );
174 }
175
176 DissolveEffectApp::~DissolveEffectApp()
177 {
178   //Nothing to do
179 }
180
181 void DissolveEffectApp::OnInit( Application& application )
182 {
183   Stage::GetCurrent().KeyEventSignal().Connect(this, &DissolveEffectApp::OnKeyEvent);
184
185   // Creates a default view with a default tool bar, the view is added to the stage.
186   mContent = DemoHelper::CreateView( application, mView,mToolBar, "", TOOLBAR_IMAGE, "" );
187
188   // Add an effect-changing button on the right of the tool bar.
189   Image imageChangeEffect = Image::New( CHANGE_EFFECT_IMAGE );
190   Toolkit::PushButton effectChangeButton = Toolkit::PushButton::New();
191   effectChangeButton.SetBackgroundImage(imageChangeEffect);
192   effectChangeButton.ClickedSignal().Connect( this, &DissolveEffectApp::OnEffectButtonClicked );
193   mToolBar.AddControl( effectChangeButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
194
195   // Add title to the tool bar.
196   mTitleActor = Toolkit::TextView::New();
197   mTitleActor.SetText( APPLICATION_TITLE_HIGHP );
198   mTitleActor.SetStyleToCurrentText(DemoHelper::GetDefaultTextStyle());
199   mToolBar.AddControl( mTitleActor, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Toolkit::Alignment::HorizontalCenter );
200
201   // Add an slide-show button on the right of the title
202   mIconPlay = Image::New( PLAY_ICON );
203   mIconStop = Image::New( STOP_ICON );
204   mPlayStopButton = Toolkit::PushButton::New();
205   mPlayStopButton.SetBackgroundImage( mIconPlay );
206   mPlayStopButton.ClickedSignal().Connect( this, &DissolveEffectApp::OnSildeshowButtonClicked );
207   mToolBar.AddControl( mPlayStopButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalCenter, DemoHelper::DEFAULT_PLAY_PADDING );
208
209   // use pan gesture to detect the cursor or finger movement
210   mPanGestureDetector = PanGestureDetector::New();
211   mPanGestureDetector.DetectedSignal().Connect( this, &DissolveEffectApp::OnPanGesture );
212
213   // create the dissolve effect object
214   mCurrentImageEffect = Toolkit::DissolveEffect::New(mUseHighPrecision);
215   mNextImageEffect = Toolkit::DissolveEffect::New(mUseHighPrecision);
216
217
218   mViewTimer = Timer::New( VIEWINGTIME );
219   mViewTimer.TickSignal().Connect( this, &DissolveEffectApp::OnTimerTick );
220   mTimerReady = true;
221
222   mSizeConstraint= Constraint::New<Vector3>( Actor::SCALE, LocalSource( Actor::SIZE ), ParentSource( Actor::SIZE ), ScaleToFitKeepAspectRatioConstraint() );
223
224   // show the first image
225   mCurrentImage = ImageActor::New( Image::New( IMAGES[mIndex] ) );
226   mCurrentImage.SetPositionInheritanceMode(USE_PARENT_POSITION_PLUS_LOCAL_POSITION);
227   mCurrentImage.ApplyConstraint( mSizeConstraint );
228   mContent.Add(mCurrentImage);
229   mPanGestureDetector.Attach( mCurrentImage );
230 }
231
232 // signal handler, called when the pan gesture is detected
233 void DissolveEffectApp::OnPanGesture( Actor actor, PanGesture gesture )
234 {
235   // does not response when the animation has not finished
236   if( mIsTransiting || mSlideshow )
237   {
238     return;
239   }
240
241   if( gesture.state == Gesture::Continuing )
242   {
243     if( gesture.displacement.x < 0)
244     {
245       mIndex = (mIndex + 1)%NUM_IMAGES;
246     }
247     else
248     {
249       mIndex = (mIndex + NUM_IMAGES -1)%NUM_IMAGES;
250     }
251
252     Image image = Image::New( IMAGES[ mIndex ] );
253     mNextImage = ImageActor::New( image );
254     mNextImage.SetPositionInheritanceMode(USE_PARENT_POSITION_PLUS_LOCAL_POSITION);
255     mNextImage.ApplyConstraint( mSizeConstraint );
256     mNextImage.SetZ(INITIAL_DEPTH);
257     mContent.Add(mNextImage);
258     Vector2 size = Vector2( mCurrentImage.GetCurrentSize() );
259     StartTransition( gesture.position / size, gesture.displacement * Vector2(1.0, size.x/size.y));
260   }
261 }
262
263 void DissolveEffectApp::StartTransition(Vector2 position, Vector2 displacement)
264 {
265   mAnimation = Animation::New(TRANSITION_DURATION);
266
267   mCurrentImageEffect.SetCentralLine(position,displacement);
268   mCurrentImageEffect.SetDistortion(0.0f);
269   mCurrentImage.SetShaderEffect(mCurrentImageEffect);
270   mAnimation.AnimateTo( Property(mCurrentImageEffect, mCurrentImageEffect.GetDistortionPropertyName()), 1.0f, AlphaFunctions::Linear );
271
272   mNextImage.SetOpacity(0.0f);
273   mAnimation.OpacityTo( mNextImage, 1.0, AlphaFunctions::Linear );
274
275   if(mUseHighPrecision)
276   {
277     mNextImageEffect.SetCentralLine(position,-displacement);
278     mNextImageEffect.SetDistortion(1.0f);
279     mNextImage.SetShaderEffect(mNextImageEffect);
280     mAnimation.AnimateTo( Property(mNextImageEffect, mNextImageEffect.GetDistortionPropertyName()), 0.0f, AlphaFunctions::Linear );
281   }
282   else
283   {
284     mAnimation.MoveTo(mNextImage, Vector3(0.0f, 0.0f, 0.0f), AlphaFunctions::Linear);
285   }
286
287   mAnimation.FinishedSignal().Connect( this, &DissolveEffectApp::OnTransitionCompleted );
288   mAnimation.Play();
289   mIsTransiting = true;
290 }
291
292 void DissolveEffectApp::OnKeyEvent(const KeyEvent& event)
293 {
294   if(event.state == KeyEvent::Down)
295   {
296     if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
297     {
298       mApplication.Quit();
299     }
300   }
301 }
302
303 bool DissolveEffectApp::OnEffectButtonClicked( Toolkit::Button button )
304 {
305   mUseHighPrecision = !mUseHighPrecision;
306   mCurrentImageEffect = Toolkit::DissolveEffect::New(mUseHighPrecision);
307   if(mUseHighPrecision)
308   {
309     mTitleActor.SetText( APPLICATION_TITLE_HIGHP );
310   }
311   else
312   {
313     mTitleActor.SetText( APPLICATION_TITLE_MEDIUMP );
314   }
315   mTitleActor.SetStyleToCurrentText(DemoHelper::GetDefaultTextStyle());
316
317   return true;
318 }
319
320 bool DissolveEffectApp::OnSildeshowButtonClicked( Toolkit::Button button )
321 {
322   mSlideshow = !mSlideshow;
323   if( mSlideshow )
324   {
325     mPlayStopButton.SetBackgroundImage( mIconStop );
326     mPanGestureDetector.Detach( mContent );
327     mViewTimer.Start();
328     mTimerReady = false;
329   }
330   else
331   {
332     mPlayStopButton.SetBackgroundImage( mIconPlay );
333     mTimerReady = true;
334     mPanGestureDetector.Attach( mContent );
335   }
336   return true;
337 }
338
339 void DissolveEffectApp::OnTransitionCompleted( Animation& source )
340 {
341   mCurrentImage.RemoveShaderEffect();
342   mNextImage.RemoveShaderEffect();
343   mContent.Remove(mCurrentImage);
344   mPanGestureDetector.Detach( mCurrentImage );
345   mCurrentImage = mNextImage;
346   mPanGestureDetector.Attach( mCurrentImage );
347   mIsTransiting = false;
348
349   if( mSlideshow)
350   {
351     mViewTimer.Start();
352     mTimerReady = false;
353   }
354 }
355
356 bool DissolveEffectApp::OnTimerTick()
357 {
358   mTimerReady = true;
359   if(mSlideshow)
360   {
361     mIndex = (mIndex + 1)%NUM_IMAGES;
362     Image image = Image::New( IMAGES[ mIndex ] );
363     mNextImage = ImageActor::New( image );
364     mNextImage.SetPositionInheritanceMode(USE_PARENT_POSITION_PLUS_LOCAL_POSITION);
365     mNextImage.ApplyConstraint( mSizeConstraint );
366     mNextImage.SetZ(INITIAL_DEPTH);
367     mContent.Add(mNextImage);
368     switch(mCentralLineIndex%4)
369     {
370       case 0:
371       {
372         StartTransition(Vector2(1.0f,0.5f), Vector2(-1.0f, 0.0f));
373         break;
374       }
375       case 1:
376       {
377         StartTransition(Vector2(0.5f,0.0f), Vector2(0.0f, 1.0f));
378         break;
379       }
380       case 2:
381       {
382         StartTransition(Vector2(0.0f,0.5f), Vector2(1.0f, 0.0f));
383         break;
384       }
385       default:
386       {
387         StartTransition(Vector2(0.5f,1.0f), Vector2(0.0f, -1.0f));
388         break;
389       }
390
391     }
392     mCentralLineIndex++;
393   }
394   return false;   //return false to stop the timer
395 }
396
397 // Entry point for Linux & SLP applications
398 int main( int argc, char **argv )
399 {
400   Application application = Application::New( &argc, &argv );
401   DissolveEffectApp test( application );
402   application.MainLoop();
403
404   return 0;
405 }