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