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 <dali-toolkit/devel-api/controls/bubble-effect/bubble-emitter.h>
21 #include "shared/view.h"
27 const char * const TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
28 const char * const APPLICATION_TITLE( "Bubble Effect" );
29 const char * const CHANGE_BACKGROUND_ICON( DEMO_IMAGE_DIR "icon-change.png" );
30 const char * const CHANGE_BACKGROUND_ICON_SELECTED( DEMO_IMAGE_DIR "icon-change-selected.png" );
31 const char * const CHANGE_BUBBLE_SHAPE_ICON( DEMO_IMAGE_DIR "icon-replace.png" );
32 const char * const CHANGE_BUBBLE_SHAPE_ICON_SELECTED( DEMO_IMAGE_DIR "icon-replace-selected.png" );
34 const char* BACKGROUND_IMAGES[]=
36 DEMO_IMAGE_DIR "background-1.jpg",
37 DEMO_IMAGE_DIR "background-2.jpg",
38 DEMO_IMAGE_DIR "background-3.jpg",
39 DEMO_IMAGE_DIR "background-4.jpg",
40 DEMO_IMAGE_DIR "background-5.jpg",
42 const unsigned int NUM_BACKGROUND_IMAGES( sizeof( BACKGROUND_IMAGES ) / sizeof( BACKGROUND_IMAGES[0] ) );
44 const char* BUBBLE_SHAPE_IMAGES[] =
46 DEMO_IMAGE_DIR "bubble-ball.png",
47 DEMO_IMAGE_DIR "icon-effect-cross.png",
48 DEMO_IMAGE_DIR "icon-item-view-layout-spiral.png",
49 DEMO_IMAGE_DIR "icon-replace.png"
51 const unsigned int NUM_BUBBLE_SHAPE_IMAGES( sizeof( BUBBLE_SHAPE_IMAGES ) / sizeof( BUBBLE_SHAPE_IMAGES[0] ) );
53 const Vector2 DEFAULT_BUBBLE_SIZE( 10.f, 30.f );
54 const unsigned int DEFAULT_NUMBER_OF_BUBBLES( 1000 );
57 * @brief Load an image, scaled-down to no more than the stage dimensions.
59 * Uses image scaling mode FittingMode::SCALE_TO_FILL to resize the image at
60 * load time to cover the entire stage with pixels with no borders,
61 * and filter mode BOX_THEN_LINEAR to sample the image with
64 ResourceImage LoadStageFillingImage( const char * const imagePath )
66 Size stageSize = Stage::GetCurrent().GetSize();
67 return ResourceImage::New( imagePath, Dali::ImageDimensions( stageSize.x, stageSize.y ), Dali::FittingMode::SCALE_TO_FILL, Dali::SamplingMode::BOX_THEN_LINEAR );
72 // This example shows the usage of BubbleEmitter which displays lots of moving bubbles on the stage.
73 class BubbleEffectExample : public ConnectionTracker
76 BubbleEffectExample(Application &app)
78 mHSVDelta( Vector3( 0.f, 0.f, 0.5f ) ),
80 mCurrentBackgroundImageId( 0 ),
81 mCurrentBubbleShapeImageId( 0 ),
82 mNeedNewAnimation( true )
84 // Connect to the Application's Init signal
85 app.InitSignal().Connect(this, &BubbleEffectExample::Create);
88 ~BubbleEffectExample()
94 // The Init signal is received once (only) during the Application lifetime
95 void Create(Application& app)
97 Stage stage = Stage::GetCurrent();
98 Vector2 stageSize = stage.GetSize();
100 stage.KeyEventSignal().Connect(this, &BubbleEffectExample::OnKeyEvent);
102 // Creates a default view with a default tool bar.
103 // The view is added to the stage.
104 Toolkit::ToolBar toolBar;
105 Layer content = DemoHelper::CreateView( app,
112 // Add a button to change background. (right of toolbar)
113 mChangeBackgroundButton = Toolkit::PushButton::New();
114 mChangeBackgroundButton.SetUnselectedImage( CHANGE_BACKGROUND_ICON );
115 mChangeBackgroundButton.SetSelectedImage( CHANGE_BACKGROUND_ICON_SELECTED );
116 mChangeBackgroundButton.ClickedSignal().Connect( this, &BubbleEffectExample::OnChangeIconClicked );
117 toolBar.AddControl( mChangeBackgroundButton,
118 DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
119 Toolkit::Alignment::HorizontalRight,
120 DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
121 // Add a button to change bubble shape. ( left of bar )
122 mChangeBubbleShapeButton = Toolkit::PushButton::New();
123 mChangeBubbleShapeButton.SetUnselectedImage( CHANGE_BUBBLE_SHAPE_ICON );
124 mChangeBubbleShapeButton.SetSelectedImage( CHANGE_BUBBLE_SHAPE_ICON_SELECTED );
125 mChangeBubbleShapeButton.ClickedSignal().Connect( this, &BubbleEffectExample::OnChangeIconClicked );
126 toolBar.AddControl( mChangeBubbleShapeButton,
127 DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
128 Toolkit::Alignment::HorizontalLeft,
129 DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
131 // Create and initialize the BubbleEmitter object
132 mBubbleEmitter = Toolkit::BubbleEmitter::New( stageSize,
133 ResourceImage::New( BUBBLE_SHAPE_IMAGES[mCurrentBubbleShapeImageId] ),
134 DEFAULT_NUMBER_OF_BUBBLES,
135 DEFAULT_BUBBLE_SIZE);
136 mBackgroundImage = LoadStageFillingImage( BACKGROUND_IMAGES[mCurrentBackgroundImageId] );
137 mBubbleEmitter.SetBackground( mBackgroundImage, mHSVDelta );
139 // Get the root actor of all bubbles, and add it to stage.
140 Actor bubbleRoot = mBubbleEmitter.GetRootActor();
141 bubbleRoot.SetParentOrigin(ParentOrigin::CENTER);
142 bubbleRoot.SetZ(0.1f); // Make sure the bubbles displayed on top og the background.
143 content.Add( bubbleRoot );
145 // Add the background image actor to stage
146 mBackground.SetBackgroundImage( mBackgroundImage );
148 // Set up the timer to emit bubble regularly when the finger is touched down but not moved
149 mTimerForBubbleEmission = Timer::New( mTimerInterval );
150 mTimerForBubbleEmission.TickSignal().Connect(this, &BubbleEffectExample::OnTimerTick);
152 // Connect the callback to the touch signal on the background
153 mBackground.TouchSignal().Connect( this, &BubbleEffectExample::OnTouch );
161 // Set up the animation of emitting bubbles, to be efficient, every animation controls multiple emission ( 4 here )
162 void SetUpAnimation( Vector2 emitPosition, Vector2 direction )
164 if( mNeedNewAnimation )
166 float duration = Random::Range(1.f, 1.5f);
167 mEmitAnimation = Animation::New( duration );
168 mNeedNewAnimation = false;
169 mAnimateComponentCount = 0;
172 mBubbleEmitter.EmitBubble( mEmitAnimation, emitPosition, direction + Vector2(0.f, 30.f) /* upwards */, Vector2(300, 600) );
174 mAnimateComponentCount++;
176 if( mAnimateComponentCount % 4 ==0 )
178 mEmitAnimation.Play();
179 mNeedNewAnimation = true;
183 // Emit bubbles when the finger touches down but keep stationary.
184 // And stops emitting new bubble after being stationary for 2 seconds
187 if(mEmitPosition == mCurrentTouchPosition) // finger is not moving
190 if(mNonMovementCount < (1000 / mTimerInterval)) // 1 seconds
192 for(int i = 0; i < 4; i++) // emit 4 bubbles every timer tick
194 SetUpAnimation( mCurrentTouchPosition+Vector2(rand()%5, rand()%5), Vector2(rand()%60-30, rand()%100-50) );
200 mNonMovementCount = 0;
201 mEmitPosition = mCurrentTouchPosition;
207 // Callback function of the touch signal on the background
208 bool OnTouch(Dali::Actor actor, const Dali::TouchData& event)
210 switch( event.GetState( 0 ) )
212 case PointState::DOWN:
214 mCurrentTouchPosition = mEmitPosition = event.GetScreenPosition( 0 );
215 mTimerForBubbleEmission.Start();
216 mNonMovementCount = 0;
220 case PointState::MOTION:
222 Vector2 displacement = event.GetScreenPosition( 0 ) - mCurrentTouchPosition;
223 mCurrentTouchPosition = event.GetScreenPosition( 0 );
224 //emit multiple bubbles along the moving direction when the finger moves quickly
225 float step = std::min(5.f, displacement.Length());
226 for( float i=0.25f; i<step; i=i+1.f)
228 SetUpAnimation( mCurrentTouchPosition+displacement*(i/step), displacement );
233 case PointState::LEAVE:
234 case PointState::INTERRUPTED:
236 mTimerForBubbleEmission.Stop();
237 mEmitAnimation.Play();
238 mNeedNewAnimation = true;
239 mAnimateComponentCount = 0;
242 case PointState::STATIONARY:
252 bool OnChangeIconClicked( Toolkit::Button button )
254 if(button == mChangeBackgroundButton)
256 mBackgroundImage = LoadStageFillingImage( BACKGROUND_IMAGES[ ++mCurrentBackgroundImageId % NUM_BACKGROUND_IMAGES ] );
258 mBubbleEmitter.SetBackground( mBackgroundImage, mHSVDelta );
260 mBackground.SetBackgroundImage( mBackgroundImage );
262 else if( button == mChangeBubbleShapeButton )
264 mBubbleEmitter.SetShapeImage( ResourceImage::New( BUBBLE_SHAPE_IMAGES[ ++mCurrentBubbleShapeImageId % NUM_BUBBLE_SHAPE_IMAGES ] ) );
270 * Main key event handler
272 void OnKeyEvent(const KeyEvent& event)
274 if(event.state == KeyEvent::Down)
276 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
286 Image mBackgroundImage;
287 Dali::Toolkit::Control mBackground;
289 Toolkit::BubbleEmitter mBubbleEmitter;
290 Animation mEmitAnimation;
291 Toolkit::PushButton mChangeBackgroundButton;
292 Toolkit::PushButton mChangeBubbleShapeButton;
293 Timer mTimerForBubbleEmission;
296 Vector2 mCurrentTouchPosition;
297 Vector2 mEmitPosition;
299 unsigned int mAnimateComponentCount;
300 unsigned int mNonMovementCount;
301 unsigned int mTimerInterval;
302 unsigned int mCurrentBackgroundImageId;
303 unsigned int mCurrentBubbleShapeImageId;
305 bool mNeedNewAnimation;
308 /*****************************************************************************/
311 RunTest(Application& app)
313 BubbleEffectExample theApp(app);
317 /*****************************************************************************/
319 int DALI_EXPORT_API main(int argc, char **argv)
321 Application app = Application::New(&argc, &argv, DEMO_THEME_PATH);