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