(Shader Effect) update the bubble effect demo
[platform/core/uifw/dali-demo.git] / examples / shader-effect / bubble-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 #include <dali/dali.h>
18 #include <dali-toolkit/dali-toolkit.h>
19 #include "../shared/view.h"
20
21 using namespace Dali;
22
23 namespace
24 {
25 const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
26 const char * const APPLICATION_TITLE( "Bubble Effect" );
27 const char * const CHANGE_BACKGROUND_ICON( DALI_IMAGE_DIR "icon-change.png" );
28 const char * const CHANGE_BUBBLE_SHAPE_ICON( DALI_IMAGE_DIR "icon-replace.png" );
29
30 const char* BACKGROUND_IMAGES[]=
31 {
32   DALI_IMAGE_DIR "background-1.jpg",
33   DALI_IMAGE_DIR "background-2.jpg",
34   DALI_IMAGE_DIR "background-3.jpg",
35   DALI_IMAGE_DIR "background-4.jpg",
36   DALI_IMAGE_DIR "background-5.jpg",
37 };
38 const unsigned int NUM_BACKGROUND_IMAGES( sizeof( BACKGROUND_IMAGES ) / sizeof( BACKGROUND_IMAGES[0] ) );
39
40 const char* BUBBLE_SHAPE_IMAGES[] =
41 {
42   DALI_IMAGE_DIR "blocks-ball.png",
43   DALI_IMAGE_DIR "icon-item-view-layout-spiral.png",
44   DALI_IMAGE_DIR "icon-replace.png",
45   DALI_IMAGE_DIR "icon-effect-cross.png"
46 };
47 const unsigned int NUM_BUBBLE_SHAPE_IMAGES( sizeof( BUBBLE_SHAPE_IMAGES ) / sizeof( BUBBLE_SHAPE_IMAGES[0] ) );
48
49 const Vector2 DEFAULT_BUBBLE_SIZE( 10.f, 30.f );
50 const unsigned int DEFAULT_NUMBER_OF_BUBBLES( 1000 );
51 }// end LOCAL_STUFF
52
53 // This example shows the usage of BubbleEmitter which displays lots of moving bubbles on the stage.
54 class BubbleEffectExample : public ConnectionTracker
55 {
56 public:
57   BubbleEffectExample(Application &app)
58   : mApp(app),
59     mHSVDelta( Vector3( 0.f, 0.f, 0.5f ) ),
60     mNeedNewAnimation( true ),
61     mTimerInterval( 16 ),
62     mCurrentBackgroundImageId( 0 ),
63     mCurrentBubbleShapeImageId( 0 )
64   {
65     // Connect to the Application's Init signal
66     app.InitSignal().Connect(this, &BubbleEffectExample::Create);
67   }
68
69   ~BubbleEffectExample()
70   {
71   }
72
73 private:
74
75   // The Init signal is received once (only) during the Application lifetime
76   void Create(Application& app)
77   {
78     Stage stage = Stage::GetCurrent();
79     Vector2 stageSize = stage.GetSize();
80
81     stage.KeyEventSignal().Connect(this, &BubbleEffectExample::OnKeyEvent);
82
83     // Creates a default view with a default tool bar.
84     // The view is added to the stage.
85     Toolkit::ToolBar toolBar;
86     Toolkit::View    view;
87     Layer content = DemoHelper::CreateView( app,
88                                             view,
89                                             toolBar,
90                                             "",
91                                             TOOLBAR_IMAGE,
92                                             APPLICATION_TITLE );
93
94     // Add a button to change background. (right of toolbar)
95     mChangeBackgroundButton = Toolkit::PushButton::New();
96     mChangeBackgroundButton.SetBackgroundImage( Image::New( CHANGE_BACKGROUND_ICON ) );
97     mChangeBackgroundButton.ClickedSignal().Connect( this, &BubbleEffectExample::OnChangeIconClicked );
98     toolBar.AddControl( mChangeBackgroundButton,
99                         DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
100                         Toolkit::Alignment::HorizontalRight,
101                         DemoHelper::DEFAULT_MODE_SWITCH_PADDING  );
102     // Add a button to change bubble shape. ( left of bar )
103     mChangeBubbleShapeButton = Toolkit::PushButton::New();
104     mChangeBubbleShapeButton.SetBackgroundImage( Image::New( CHANGE_BUBBLE_SHAPE_ICON ) );
105     mChangeBubbleShapeButton.ClickedSignal().Connect( this, &BubbleEffectExample::OnChangeIconClicked );
106     toolBar.AddControl( mChangeBubbleShapeButton,
107                         DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
108                         Toolkit::Alignment::HorizontalLeft,
109                         DemoHelper::DEFAULT_MODE_SWITCH_PADDING  );
110
111     // Create and initialize the BubbleEmitter object
112     mBubbleEmitter = Toolkit::BubbleEmitter::New( stageSize,
113                                                   Image::New( BUBBLE_SHAPE_IMAGES[mCurrentBubbleShapeImageId] ),
114                                                   DEFAULT_NUMBER_OF_BUBBLES,
115                                                   DEFAULT_BUBBLE_SIZE);
116     mBackgroundImage = Image::New( BACKGROUND_IMAGES[mCurrentBackgroundImageId] );
117     mBubbleEmitter.SetBackground( mBackgroundImage, mHSVDelta );
118
119     // Get the root actor of all bubbles, and add it to stage.
120     Actor bubbleRoot = mBubbleEmitter.GetRootActor();
121     bubbleRoot.SetParentOrigin(ParentOrigin::CENTER);
122     bubbleRoot.SetZ(0.1f); // Make sure the bubbles displayed on top og the background.
123     content.Add( bubbleRoot );
124
125     // Add the background image actor to stage
126     mBackgroundActor = ImageActor::New( mBackgroundImage );
127     view.SetBackground( mBackgroundActor );
128
129     // Set up the timer to emit bubble regularly when the finger is touched down but not moved
130     mTimerForBubbleEmission = Timer::New( mTimerInterval );
131     mTimerForBubbleEmission.TickSignal().Connect(this, &BubbleEffectExample::OnTimerTick);
132
133     // Connect the callback to the touch signal on the background
134     mBackgroundActor.TouchedSignal().Connect( this, &BubbleEffectExample::OnTouch );
135   }
136
137
138 /***********
139  * Emit bubbles
140  *****************/
141
142   // Set up the animation of emitting bubbles, to be efficient, every animation controls multiple bubbles ( 4 here )
143   void SetUpAnimation( Vector2 emitPosition, Vector2 direction )
144   {
145     if( mNeedNewAnimation )
146     {
147       float duration = Random::Range(1.f, 1.5f);
148       mEmitAnimation = Animation::New( duration );
149       mNeedNewAnimation = false;
150       mAnimateComponentCount = 0;
151     }
152
153     mBubbleEmitter.EmitBubble( mEmitAnimation, emitPosition, direction + Vector2(0.f, 30.f) /* upwards */, Vector2(300, 600) );
154
155     mAnimateComponentCount++;
156
157     if( mAnimateComponentCount % 4 ==0 )
158     {
159       mEmitAnimation.Play();
160       mNeedNewAnimation = true;
161     }
162   }
163
164   // Emit bubbles when the finger touches down but keep stationary.
165   // And stops emitting new bubble after being stationary for 2 seconds
166   bool OnTimerTick()
167   {
168     if(mEmitPosition == mCurrentTouchPosition) // finger is not moving
169     {
170       mNonMovementCount++;
171       if(mNonMovementCount < (1000 / mTimerInterval)) // 1 seconds
172       {
173         for(int i = 0; i < 4; i++) // emit 4 bubbles every timer tick
174         {
175           SetUpAnimation( mCurrentTouchPosition+Vector2(rand()%5, rand()%5), Vector2(rand()%60-30, rand()%100-50) );
176         }
177       }
178     }
179     else
180     {
181       mNonMovementCount = 0;
182       mEmitPosition = mCurrentTouchPosition;
183     }
184
185     return true;
186   }
187
188   // Callback function of the touch signal on the background
189   bool OnTouch(Dali::Actor actor, const Dali::TouchEvent& event)
190   {
191     const TouchPoint &point = event.GetPoint(0);
192     switch(point.state)
193     {
194       case TouchPoint::Down:
195       {
196         mCurrentTouchPosition = point.screen;
197         mEmitPosition = point.screen;
198         mTimerForBubbleEmission.Start();
199         mNonMovementCount = 0;
200
201         break;
202       }
203       case TouchPoint::Motion:
204       {
205         Vector2 displacement = point.screen - mCurrentTouchPosition;
206         mCurrentTouchPosition = point.screen;
207         //emit multiple bubbles along the moving direction when the finger moves quickly
208         float step = std::min(5.f, displacement.Length());
209         for( float i=0.25f; i<step; i=i+1.f)
210         {
211           SetUpAnimation( mCurrentTouchPosition+displacement*(i/step), displacement );
212         }
213         break;
214       }
215       case TouchPoint::Up:
216       case TouchPoint::Leave:
217       case TouchPoint::Interrupted:
218       {
219         mTimerForBubbleEmission.Stop();
220         break;
221       }
222       case TouchPoint::Stationary:
223       case TouchPoint::Last:
224       default:
225       {
226         break;
227       }
228
229     }
230     return true;
231   }
232
233   bool OnChangeIconClicked( Toolkit::Button button )
234   {
235     if(button == mChangeBackgroundButton)
236     {
237       mBackgroundImage = Image::New( BACKGROUND_IMAGES[ ++mCurrentBackgroundImageId % NUM_BACKGROUND_IMAGES  ] );
238
239       mBubbleEmitter.SetBackground( mBackgroundImage, mHSVDelta );
240
241       mBackgroundActor.SetImage( mBackgroundImage );
242     }
243     else if( button == mChangeBubbleShapeButton )
244     {
245       mBubbleEmitter.SetShapeImage( Image::New( BUBBLE_SHAPE_IMAGES[ ++mCurrentBubbleShapeImageId % NUM_BUBBLE_SHAPE_IMAGES ] ) );
246     }
247     return true;
248   }
249
250   /**
251    * Main key event handler
252    */
253   void OnKeyEvent(const KeyEvent& event)
254   {
255     if(event.state == KeyEvent::Down)
256     {
257       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
258       {
259         mApp.Quit();
260       }
261     }
262   }
263
264 private:
265
266   Application&               mApp;
267   Image                      mBackgroundImage;
268   ImageActor                 mBackgroundActor;
269
270   Toolkit::BubbleEmitter     mBubbleEmitter;
271   Vector3                    mHSVDelta;
272
273   Animation                  mEmitAnimation;
274   unsigned int               mAnimateComponentCount;
275   bool                       mNeedNewAnimation;
276
277   Timer                      mTimerForBubbleEmission;
278   unsigned int               mNonMovementCount;
279   unsigned int               mTimerInterval;
280
281   Vector2                    mCurrentTouchPosition;
282   Vector2                    mEmitPosition;
283
284   Toolkit::PushButton        mChangeBackgroundButton;
285   Toolkit::PushButton        mChangeBubbleShapeButton;
286   unsigned int               mCurrentBackgroundImageId;
287   unsigned int               mCurrentBubbleShapeImageId;
288 };
289
290 /*****************************************************************************/
291
292 static void
293 RunTest(Application& app)
294 {
295   BubbleEffectExample theApp(app);
296   app.MainLoop();
297 }
298
299 /*****************************************************************************/
300
301 int
302 main(int argc, char **argv)
303 {
304   Application app = Application::New(&argc, &argv);
305
306   RunTest(app);
307
308   return 0;
309 }
310
311
312