2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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"
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" );
35 const char* BACKGROUND_IMAGES[]=
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",
43 const unsigned int NUM_BACKGROUND_IMAGES( sizeof( BACKGROUND_IMAGES ) / sizeof( BACKGROUND_IMAGES[0] ) );
45 const char* BUBBLE_SHAPE_IMAGES[] =
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"
52 const unsigned int NUM_BUBBLE_SHAPE_IMAGES( sizeof( BUBBLE_SHAPE_IMAGES ) / sizeof( BUBBLE_SHAPE_IMAGES[0] ) );
54 const Vector2 DEFAULT_BUBBLE_SIZE( 10.f, 30.f );
55 const unsigned int DEFAULT_NUMBER_OF_BUBBLES( 1000 );
59 // This example shows the usage of BubbleEmitter which displays lots of moving bubbles on the window.
60 class BubbleEffectExample : public ConnectionTracker
63 BubbleEffectExample(Application &app)
68 mChangeBackgroundButton(),
69 mChangeBubbleShapeButton(),
70 mTimerForBubbleEmission(),
71 mHSVDelta( Vector3( 0.f, 0.f, 0.5f ) ),
72 mCurrentTouchPosition(),
74 mAnimateComponentCount( 0 ),
75 mNonMovementCount( 0 ),
77 mCurrentBackgroundImageId( 0 ),
78 mCurrentBubbleShapeImageId( 0 ),
79 mNeedNewAnimation( true )
81 // Connect to the Application's Init signal
82 app.InitSignal().Connect(this, &BubbleEffectExample::Create);
85 ~BubbleEffectExample()
91 // The Init signal is received once (only) during the Application lifetime
92 void Create(Application& app)
94 Window window = app.GetWindow();
95 Vector2 windowSize = window.GetSize();
97 window.KeyEventSignal().Connect(this, &BubbleEffectExample::OnKeyEvent);
99 // Creates a default view with a default tool bar.
100 // The view is added to the window.
101 Toolkit::ToolBar toolBar;
102 Layer content = DemoHelper::CreateView( app,
109 // Add a button to change background. (right of toolbar)
110 mChangeBackgroundButton = Toolkit::PushButton::New();
111 mChangeBackgroundButton.SetProperty( Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL, CHANGE_BACKGROUND_ICON );
112 mChangeBackgroundButton.SetProperty( Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL, CHANGE_BACKGROUND_ICON_SELECTED );
113 mChangeBackgroundButton.ClickedSignal().Connect( this, &BubbleEffectExample::OnChangeIconClicked );
114 toolBar.AddControl( mChangeBackgroundButton,
115 DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
116 Toolkit::Alignment::HorizontalRight,
117 DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
118 // Add a button to change bubble shape. ( left of bar )
119 mChangeBubbleShapeButton = Toolkit::PushButton::New();
120 mChangeBubbleShapeButton.SetProperty( Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL, CHANGE_BUBBLE_SHAPE_ICON );
121 mChangeBubbleShapeButton.SetProperty( Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL, CHANGE_BUBBLE_SHAPE_ICON_SELECTED );
122 mChangeBubbleShapeButton.ClickedSignal().Connect( this, &BubbleEffectExample::OnChangeIconClicked );
123 toolBar.AddControl( mChangeBubbleShapeButton,
124 DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
125 Toolkit::Alignment::HorizontalLeft,
126 DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
128 // Create and initialize the BubbleEmitter object
129 mBubbleEmitter = Toolkit::BubbleEmitter::New( windowSize,
130 DemoHelper::LoadTexture( BUBBLE_SHAPE_IMAGES[mCurrentBubbleShapeImageId] ),
131 DEFAULT_NUMBER_OF_BUBBLES,
132 DEFAULT_BUBBLE_SIZE);
134 mBubbleEmitter.SetBackground( DemoHelper::LoadWindowFillingTexture( window.GetSize(), BACKGROUND_IMAGES[mCurrentBackgroundImageId] ), mHSVDelta );
136 // Get the root actor of all bubbles, and add it to window.
137 Actor bubbleRoot = mBubbleEmitter.GetRootActor();
138 bubbleRoot.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
139 bubbleRoot.SetProperty( Actor::Property::POSITION_Z, 0.1f); // Make sure the bubbles displayed on top og the background.
140 content.Add( bubbleRoot );
142 // Set the application background
143 mBackground.SetProperty( Toolkit::Control::Property::BACKGROUND, BACKGROUND_IMAGES[ mCurrentBackgroundImageId ] );
145 // Set up the timer to emit bubble regularly when the finger is touched down but not moved
146 mTimerForBubbleEmission = Timer::New( mTimerInterval );
147 mTimerForBubbleEmission.TickSignal().Connect(this, &BubbleEffectExample::OnTimerTick);
149 // Connect the callback to the touch signal on the background
150 mBackground.TouchSignal().Connect( this, &BubbleEffectExample::OnTouch );
158 // Set up the animation of emitting bubbles, to be efficient, every animation controls multiple emission ( 4 here )
159 void SetUpAnimation( Vector2 emitPosition, Vector2 direction )
161 if( mNeedNewAnimation )
163 float duration = Random::Range(1.f, 1.5f);
164 mEmitAnimation = Animation::New( duration );
165 mNeedNewAnimation = false;
166 mAnimateComponentCount = 0;
169 mBubbleEmitter.EmitBubble( mEmitAnimation, emitPosition, direction + Vector2(0.f, 30.f) /* upwards */, Vector2(300, 600) );
171 mAnimateComponentCount++;
173 if( mAnimateComponentCount % 4 ==0 )
175 mEmitAnimation.Play();
176 mNeedNewAnimation = true;
180 // Emit bubbles when the finger touches down but keep stationary.
181 // And stops emitting new bubble after being stationary for 2 seconds
184 if(mEmitPosition == mCurrentTouchPosition) // finger is not moving
187 if(mNonMovementCount < (1000 / mTimerInterval)) // 1 seconds
189 for(int i = 0; i < 4; i++) // emit 4 bubbles every timer tick
191 SetUpAnimation( mCurrentTouchPosition+Vector2(rand()%5, rand()%5), Vector2(rand()%60-30, rand()%100-50) );
197 mNonMovementCount = 0;
198 mEmitPosition = mCurrentTouchPosition;
204 // Callback function of the touch signal on the background
205 bool OnTouch(Dali::Actor actor, const Dali::TouchEvent& event)
207 switch( event.GetState( 0 ) )
209 case PointState::DOWN:
211 mCurrentTouchPosition = mEmitPosition = event.GetScreenPosition( 0 );
212 mTimerForBubbleEmission.Start();
213 mNonMovementCount = 0;
217 case PointState::MOTION:
219 Vector2 displacement = event.GetScreenPosition( 0 ) - mCurrentTouchPosition;
220 mCurrentTouchPosition = event.GetScreenPosition( 0 );
221 //emit multiple bubbles along the moving direction when the finger moves quickly
222 float step = std::min(5.f, displacement.Length());
223 for( float i=0.25f; i<step; i=i+1.f)
225 SetUpAnimation( mCurrentTouchPosition+displacement*(i/step), displacement );
230 case PointState::LEAVE:
231 case PointState::INTERRUPTED:
233 mTimerForBubbleEmission.Stop();
234 mEmitAnimation.Play();
235 mNeedNewAnimation = true;
236 mAnimateComponentCount = 0;
239 case PointState::STATIONARY:
249 bool OnChangeIconClicked( Toolkit::Button button )
251 if(button == mChangeBackgroundButton)
253 mCurrentBackgroundImageId = (mCurrentBackgroundImageId+1) % NUM_BACKGROUND_IMAGES;
255 //Update bubble emitter background
256 mBubbleEmitter.SetBackground( DemoHelper::LoadWindowFillingTexture( mApp.GetWindow().GetSize(), BACKGROUND_IMAGES[ mCurrentBackgroundImageId ] ), mHSVDelta );
258 // Set the application background
259 mBackground.SetProperty( Toolkit::Control::Property::BACKGROUND, BACKGROUND_IMAGES[ mCurrentBackgroundImageId ] );
261 else if( button == mChangeBubbleShapeButton )
263 mBubbleEmitter.SetBubbleShape( DemoHelper::LoadTexture( BUBBLE_SHAPE_IMAGES[ ++mCurrentBubbleShapeImageId % NUM_BUBBLE_SHAPE_IMAGES ] ) );
269 * Main key event handler
271 void OnKeyEvent(const KeyEvent& event)
273 if(event.GetState() == KeyEvent::Down)
275 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
285 Dali::Toolkit::Control mBackground;
287 Toolkit::BubbleEmitter mBubbleEmitter;
288 Animation mEmitAnimation;
289 Toolkit::PushButton mChangeBackgroundButton;
290 Toolkit::PushButton mChangeBubbleShapeButton;
291 Timer mTimerForBubbleEmission;
294 Vector2 mCurrentTouchPosition;
295 Vector2 mEmitPosition;
297 unsigned int mAnimateComponentCount;
298 unsigned int mNonMovementCount;
299 unsigned int mTimerInterval;
300 unsigned int mCurrentBackgroundImageId;
301 unsigned int mCurrentBubbleShapeImageId;
303 bool mNeedNewAnimation;
306 /*****************************************************************************/
308 int DALI_EXPORT_API main(int argc, char **argv)
310 Application app = Application::New(&argc, &argv, DEMO_THEME_PATH);
311 BubbleEffectExample theApp(app);