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