2 * Copyright (c) 2014 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 "shared/view.h"
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" );
31 const char* BACKGROUND_IMAGES[]=
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",
39 const unsigned int NUM_BACKGROUND_IMAGES( sizeof( BACKGROUND_IMAGES ) / sizeof( BACKGROUND_IMAGES[0] ) );
41 const char* BUBBLE_SHAPE_IMAGES[] =
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"
48 const unsigned int NUM_BUBBLE_SHAPE_IMAGES( sizeof( BUBBLE_SHAPE_IMAGES ) / sizeof( BUBBLE_SHAPE_IMAGES[0] ) );
50 const Vector2 DEFAULT_BUBBLE_SIZE( 10.f, 30.f );
51 const unsigned int DEFAULT_NUMBER_OF_BUBBLES( 1000 );
54 * @brief Load an image, scaled-down to no more than the stage dimensions.
56 * Uses image scaling mode ImageAttributes::ScaleToFill to resize the image at
57 * load time to cover the entire stage with pixels with no borders,
58 * and filter mode ImageAttributes::BoxThenLinear to sample the image with
61 ResourceImage LoadStageFillingImage( const char * const imagePath )
63 Size stageSize = Stage::GetCurrent().GetSize();
64 ImageAttributes attributes;
65 attributes.SetSize( stageSize.x, stageSize.y );
66 attributes.SetFilterMode( ImageAttributes::BoxThenLinear );
67 attributes.SetScalingMode( ImageAttributes::ScaleToFill );
68 return ResourceImage::New( imagePath, attributes );
73 // This example shows the usage of BubbleEmitter which displays lots of moving bubbles on the stage.
74 class BubbleEffectExample : public ConnectionTracker
77 BubbleEffectExample(Application &app)
79 mHSVDelta( Vector3( 0.f, 0.f, 0.5f ) ),
80 mNeedNewAnimation( true ),
82 mCurrentBackgroundImageId( 0 ),
83 mCurrentBubbleShapeImageId( 0 )
85 // Connect to the Application's Init signal
86 app.InitSignal().Connect(this, &BubbleEffectExample::Create);
89 ~BubbleEffectExample()
95 // The Init signal is received once (only) during the Application lifetime
96 void Create(Application& app)
98 DemoHelper::RequestThemeChange();
100 Stage stage = Stage::GetCurrent();
101 Vector2 stageSize = stage.GetSize();
103 stage.KeyEventSignal().Connect(this, &BubbleEffectExample::OnKeyEvent);
105 // Creates a default view with a default tool bar.
106 // The view is added to the stage.
107 Toolkit::ToolBar toolBar;
109 Layer content = DemoHelper::CreateView( app,
116 // Add a button to change background. (right of toolbar)
117 mChangeBackgroundButton = Toolkit::PushButton::New();
118 mChangeBackgroundButton.SetBackgroundImage( ResourceImage::New( CHANGE_BACKGROUND_ICON ) );
119 mChangeBackgroundButton.ClickedSignal().Connect( this, &BubbleEffectExample::OnChangeIconClicked );
120 toolBar.AddControl( mChangeBackgroundButton,
121 DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
122 Toolkit::Alignment::HorizontalRight,
123 DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
124 // Add a button to change bubble shape. ( left of bar )
125 mChangeBubbleShapeButton = Toolkit::PushButton::New();
126 mChangeBubbleShapeButton.SetBackgroundImage( ResourceImage::New( CHANGE_BUBBLE_SHAPE_ICON ) );
127 mChangeBubbleShapeButton.ClickedSignal().Connect( this, &BubbleEffectExample::OnChangeIconClicked );
128 toolBar.AddControl( mChangeBubbleShapeButton,
129 DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
130 Toolkit::Alignment::HorizontalLeft,
131 DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
133 // Create and initialize the BubbleEmitter object
134 mBubbleEmitter = Toolkit::BubbleEmitter::New( stageSize,
135 ResourceImage::New( BUBBLE_SHAPE_IMAGES[mCurrentBubbleShapeImageId] ),
136 DEFAULT_NUMBER_OF_BUBBLES,
137 DEFAULT_BUBBLE_SIZE);
138 mBackgroundImage = LoadStageFillingImage( BACKGROUND_IMAGES[mCurrentBackgroundImageId] );
139 mBubbleEmitter.SetBackground( mBackgroundImage, mHSVDelta );
141 // Get the root actor of all bubbles, and add it to stage.
142 Actor bubbleRoot = mBubbleEmitter.GetRootActor();
143 bubbleRoot.SetParentOrigin(ParentOrigin::CENTER);
144 bubbleRoot.SetZ(0.1f); // Make sure the bubbles displayed on top og the background.
145 content.Add( bubbleRoot );
147 // Add the background image actor to stage
148 mBackgroundActor = ImageActor::New( mBackgroundImage );
149 view.SetBackground( mBackgroundActor );
151 // Set up the timer to emit bubble regularly when the finger is touched down but not moved
152 mTimerForBubbleEmission = Timer::New( mTimerInterval );
153 mTimerForBubbleEmission.TickSignal().Connect(this, &BubbleEffectExample::OnTimerTick);
155 // Connect the callback to the touch signal on the background
156 mBackgroundActor.TouchedSignal().Connect( this, &BubbleEffectExample::OnTouch );
164 // Set up the animation of emitting bubbles, to be efficient, every animation controls multiple bubbles ( 4 here )
165 void SetUpAnimation( Vector2 emitPosition, Vector2 direction )
167 if( mNeedNewAnimation )
169 float duration = Random::Range(1.f, 1.5f);
170 mEmitAnimation = Animation::New( duration );
171 mNeedNewAnimation = false;
172 mAnimateComponentCount = 0;
175 mBubbleEmitter.EmitBubble( mEmitAnimation, emitPosition, direction + Vector2(0.f, 30.f) /* upwards */, Vector2(300, 600) );
177 mAnimateComponentCount++;
179 if( mAnimateComponentCount % 4 ==0 )
181 mEmitAnimation.Play();
182 mNeedNewAnimation = true;
186 // Emit bubbles when the finger touches down but keep stationary.
187 // And stops emitting new bubble after being stationary for 2 seconds
190 if(mEmitPosition == mCurrentTouchPosition) // finger is not moving
193 if(mNonMovementCount < (1000 / mTimerInterval)) // 1 seconds
195 for(int i = 0; i < 4; i++) // emit 4 bubbles every timer tick
197 SetUpAnimation( mCurrentTouchPosition+Vector2(rand()%5, rand()%5), Vector2(rand()%60-30, rand()%100-50) );
203 mNonMovementCount = 0;
204 mEmitPosition = mCurrentTouchPosition;
210 // Callback function of the touch signal on the background
211 bool OnTouch(Dali::Actor actor, const Dali::TouchEvent& event)
213 const TouchPoint &point = event.GetPoint(0);
216 case TouchPoint::Down:
218 mCurrentTouchPosition = point.screen;
219 mEmitPosition = point.screen;
220 mTimerForBubbleEmission.Start();
221 mNonMovementCount = 0;
225 case TouchPoint::Motion:
227 Vector2 displacement = point.screen - mCurrentTouchPosition;
228 mCurrentTouchPosition = point.screen;
229 //emit multiple bubbles along the moving direction when the finger moves quickly
230 float step = std::min(5.f, displacement.Length());
231 for( float i=0.25f; i<step; i=i+1.f)
233 SetUpAnimation( mCurrentTouchPosition+displacement*(i/step), displacement );
238 case TouchPoint::Leave:
239 case TouchPoint::Interrupted:
241 mTimerForBubbleEmission.Stop();
244 case TouchPoint::Stationary:
245 case TouchPoint::Last:
255 bool OnChangeIconClicked( Toolkit::Button button )
257 if(button == mChangeBackgroundButton)
259 mBackgroundImage = LoadStageFillingImage( BACKGROUND_IMAGES[ ++mCurrentBackgroundImageId % NUM_BACKGROUND_IMAGES ] );
261 mBubbleEmitter.SetBackground( mBackgroundImage, mHSVDelta );
263 mBackgroundActor.SetImage( mBackgroundImage );
265 else if( button == mChangeBubbleShapeButton )
267 mBubbleEmitter.SetShapeImage( ResourceImage::New( BUBBLE_SHAPE_IMAGES[ ++mCurrentBubbleShapeImageId % NUM_BUBBLE_SHAPE_IMAGES ] ) );
273 * Main key event handler
275 void OnKeyEvent(const KeyEvent& event)
277 if(event.state == KeyEvent::Down)
279 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
289 Image mBackgroundImage;
290 ImageActor mBackgroundActor;
292 Toolkit::BubbleEmitter mBubbleEmitter;
295 Animation mEmitAnimation;
296 unsigned int mAnimateComponentCount;
297 bool mNeedNewAnimation;
299 Timer mTimerForBubbleEmission;
300 unsigned int mNonMovementCount;
301 unsigned int mTimerInterval;
303 Vector2 mCurrentTouchPosition;
304 Vector2 mEmitPosition;
306 Toolkit::PushButton mChangeBackgroundButton;
307 Toolkit::PushButton mChangeBubbleShapeButton;
308 unsigned int mCurrentBackgroundImageId;
309 unsigned int mCurrentBubbleShapeImageId;
312 /*****************************************************************************/
315 RunTest(Application& app)
317 BubbleEffectExample theApp(app);
321 /*****************************************************************************/
324 main(int argc, char **argv)
326 Application app = Application::New(&argc, &argv);