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.
19 #include "bubble-emitter-impl.h"
22 #include <dali/public-api/animation/animation.h>
23 #include <dali/public-api/render-tasks/render-task-list.h>
24 #include <dali/public-api/images/resource-image.h>
27 #include <dali-toolkit/public-api/shader-effects/bubble-effect/color-adjuster.h>
28 #include <dali-toolkit/internal/controls/bubble-effect/bubble-actor.h>
29 #include <dali-toolkit/internal/controls/bubble-effect/color-adjuster.h>
30 #include <dali-toolkit/internal/controls/bubble-effect/bubble-effect.h>
37 Dali::Vector2 position;
38 Dali::Vector2 textureCoord;
43 Vertex( float index, const Dali::Vector2& position, const Dali::Vector2& textureCoord )
44 : index( index ), position( position ), textureCoord( textureCoord )
49 * Return a random value between the given interval.
50 * @param[in] f0 The low bound
51 * @param[in] f1 The up bound
52 * @return A random value between the given interval
54 float RandomRange(float f0, float f1)
56 return f0 + (rand() & 0xfff) * (f1-f0) * (1.0f/4095.0f);
69 BubbleEmitter::BubbleEmitter( const Vector2& movementArea,
71 unsigned int maximumNumberOfBubble,
72 const Vector2& bubbleSizeRange )
73 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
74 mShapeImage( shapeImage ),
75 mMovementArea( movementArea ),
76 mBubbleSizeRange( bubbleSizeRange ),
78 mTotalNumOfBubble( maximumNumberOfBubble ),
80 mRenderTaskRunning(false)
82 // Calculate how many shaders are required
83 if( mTotalNumOfBubble>100 )
85 mNumBubblePerActor = 100;
86 mNumActor = mTotalNumOfBubble / 100;
87 if( mNumActor*mNumBubblePerActor < mTotalNumOfBubble )
90 mNumBubblePerActor = mTotalNumOfBubble / mNumActor+1;
91 mTotalNumOfBubble = mNumActor * mNumBubblePerActor;
96 mNumBubblePerActor = mTotalNumOfBubble;
101 BubbleEmitter::~BubbleEmitter()
105 Toolkit::BubbleEmitter BubbleEmitter::New( const Vector2& winSize,
107 unsigned int maximumNumberOfBubble,
108 const Vector2& bubbleSizeRange )
110 // Create the implementation
111 IntrusivePtr<BubbleEmitter> internalBubbleEmitter ( new BubbleEmitter( winSize, shapeImage,
112 maximumNumberOfBubble,bubbleSizeRange ) );
114 // Pass ownership to Toolkit::BubbleEmitter handle
115 Toolkit::BubbleEmitter bubbleEmitter( *internalBubbleEmitter );
117 //Second phase of implementeation : Initialization
118 internalBubbleEmitter->OnInitialize();
120 return bubbleEmitter;
123 void BubbleEmitter::OnInitialize()
125 // Create the root actor, all the meshActor should be its children
126 mBubbleRoot = Actor::New();
127 mBubbleRoot.SetSize(mMovementArea);
129 // Prepare the frame buffer to store the color adjusted background image
130 mEffectImage = FrameBufferImage::New( mMovementArea.width/4.f, mMovementArea.height/4.f, Pixel::RGBA8888, Dali::Image::UNUSED );
132 // Generate the samplers and geometry, which is used by all bubbleActors
133 mSamplerBackground = Sampler::New( mEffectImage, "sBackground" );
134 mSamplerBubbleShape = Sampler::New( mShapeImage, "sBubbleShape" );
135 mMeshGeometry = CreateGeometry( mNumBubblePerActor*mDensity );
137 Shader bubbleShader = CreateBubbleShader (mNumBubblePerActor );
139 mMaterial = Material::New( bubbleShader );
140 mMaterial.AddSampler( mSamplerBackground );
141 mMaterial.AddSampler( mSamplerBubbleShape );
143 mBubbleActors.resize( mNumActor );
145 // Create the meshActor group and bubbleEffect group to emit bubbles following the given track, such as finger touch track.
146 for(unsigned int i=0; i < mNumActor; i++ )
148 mBubbleActors[i] = new BubbleActor( mNumBubblePerActor, mMovementArea );
149 (mBubbleActors[i])->MakeRenderable( mMeshGeometry, mMaterial );
150 mBubbleRoot.Add( (mBubbleActors[i])->GetMeshActor() );
153 // Create a cameraActor for the off screen render task.
154 mCameraActor = CameraActor::New(mMovementArea);
155 mCameraActor.SetParentOrigin(ParentOrigin::CENTER);
157 Stage stage = Stage::GetCurrent();
159 stage.Add(mCameraActor);
160 stage.ContextRegainedSignal().Connect(this, &BubbleEmitter::OnContextRegained);
163 Actor BubbleEmitter::GetRootActor()
168 void BubbleEmitter::SetBackground( Image bgImage, const Vector3& hsvDelta )
170 mBackgroundImage = bgImage;
171 mHSVDelta = hsvDelta;
173 ImageActor sourceActor = ImageActor::New( bgImage );
174 sourceActor.SetSize( mMovementArea );
175 sourceActor.SetParentOrigin(ParentOrigin::CENTER);
176 Stage::GetCurrent().Add( sourceActor );
178 ShaderEffect colorAdjuster = CreateColorAdjuster( hsvDelta, true /*ignore alpha to make bubble color always*/ );
179 sourceActor.SetShaderEffect( colorAdjuster );
181 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
182 RenderTask task = taskList.CreateTask();
183 task.SetRefreshRate( RenderTask::REFRESH_ONCE );
184 task.SetSourceActor( sourceActor );
185 task.SetExclusive(true);
186 task.SetCameraActor(mCameraActor);
187 task.GetCameraActor().SetInvertYAxis(true);
188 task.SetTargetFrameBuffer( mEffectImage );
189 task.FinishedSignal().Connect(this, &BubbleEmitter::OnRenderFinished);
190 mRenderTaskRunning = true;
193 void BubbleEmitter::SetShapeImage( Image shapeImage )
195 mSamplerBubbleShape.SetImage( shapeImage );
198 void BubbleEmitter::SetBubbleScale( float scale )
200 for(unsigned int i=0; i < mNumActor; i++ )
202 (mBubbleActors[i])->SetDynamicScale( scale );
206 void BubbleEmitter::SetBubbleDensity( unsigned int density )
208 DALI_ASSERT_ALWAYS( density>0 && density<=9 && " Only densities between 1 to 9 are valid " );
210 if( density == mDensity )
217 mMeshGeometry = CreateGeometry( mNumBubblePerActor*mDensity );
218 for(unsigned int i=0; i < mNumActor; i++ )
220 (mBubbleActors[i])->SetGeometry( mMeshGeometry );
225 void BubbleEmitter::SetBlendMode( bool enable )
230 mMaterial.SetBlendFunc(BlendingFactor::SRC_ALPHA, BlendingFactor::ONE,
231 BlendingFactor::ZERO, BlendingFactor::ONE);
235 // using default blend func
236 mMaterial.SetBlendFunc( BlendingFactor::SRC_ALPHA, BlendingFactor::ONE_MINUS_SRC_ALPHA,
237 BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA );
241 // clear the resources created for the off screen rendering
242 void BubbleEmitter::OnRenderFinished(RenderTask& source)
244 mRenderTaskRunning = false;
245 Actor sourceActor = source.GetSourceActor();
248 ImageActor renderable = ImageActor::DownCast( sourceActor );
251 renderable.RemoveShaderEffect();
255 Stage stage = Stage::GetCurrent();
256 stage.Remove(sourceActor);
257 stage.GetRenderTaskList().RemoveTask(source);
260 void BubbleEmitter::OnContextRegained()
262 // Context was lost, so the framebuffer has been destroyed. Re-create render task
263 // and trigger re-draw if not already running
264 if( ! mRenderTaskRunning )
266 SetBackground( mBackgroundImage, mHSVDelta );
270 void BubbleEmitter::EmitBubble( Animation& animation, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement )
272 unsigned int curUniform = mCurrentBubble % mNumBubblePerActor;
273 unsigned int groupIdx = mCurrentBubble / mNumBubblePerActor;
274 SetBubbleParameter( mBubbleActors[groupIdx], curUniform, emitPosition, direction, displacement);
275 animation.AnimateTo( (mBubbleActors[groupIdx])->GetPercentageProperty(curUniform),
276 1.f, AlphaFunction::LINEAR );
278 mCurrentBubble = (mCurrentBubble + 1) % mTotalNumOfBubble;
281 void BubbleEmitter::Restore()
283 for(unsigned int i=0; i < mNumActor; i++ )
285 (mBubbleActors[i])->ResetProperties();
289 Geometry BubbleEmitter::CreateGeometry( unsigned int numOfPatch )
291 unsigned int numVertex = numOfPatch*4u;
292 std::vector<Vertex> vertexData;
293 vertexData.reserve( numVertex );
295 unsigned int numIndex = numOfPatch*6u;
296 Vector<unsigned int> indexData;
297 indexData.Reserve( numIndex );
299 for(unsigned int i = 0; i < numOfPatch; i++)
301 float curSize = RandomRange(mBubbleSizeRange.x, mBubbleSizeRange.y);
303 float index = static_cast<float>( i );
304 vertexData.push_back( Vertex( index, Vector2(0.f,0.f), Vector2(0.f,0.f) ) );
305 vertexData.push_back( Vertex( index, Vector2(0.f,curSize), Vector2(0.f,1.f) ) );
306 vertexData.push_back( Vertex( index, Vector2(curSize,curSize), Vector2(1.f,1.f) ) );
307 vertexData.push_back( Vertex( index, Vector2(curSize,0.f), Vector2(1.f,0.f) ) );
309 unsigned int idx = index * 4;
310 indexData.PushBack( idx );
311 indexData.PushBack( idx+1 );
312 indexData.PushBack( idx+2 );
313 indexData.PushBack( idx );
314 indexData.PushBack( idx+2 );
315 indexData.PushBack( idx+3 );
318 Property::Map vertexFormat;
319 vertexFormat["aIndex"] = Property::FLOAT;
320 vertexFormat["aPosition"] = Property::VECTOR2;
321 vertexFormat["aTexCoord"] = Property::VECTOR2;
322 PropertyBuffer vertices = PropertyBuffer::New( vertexFormat, numVertex );
323 vertices.SetData( &vertexData[0] );
325 Property::Map indexFormat;
326 indexFormat["indices"] = Property::UNSIGNED_INTEGER;
327 PropertyBuffer indices = PropertyBuffer::New( indexFormat, numIndex );
328 indices.SetData( &indexData[0] );
330 Geometry geometry = Geometry::New();
331 geometry.AddVertexBuffer( vertices );
332 geometry.SetIndexBuffer( indices );
337 void BubbleEmitter::SetBubbleParameter( BubbleActorPtr bubbleActor, unsigned int curUniform,
338 const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement )
340 Vector2 dir(direction);
342 int halfRange = displacement.x / 2;
343 // for the y coordinate, always negative, so bubbles always go upwards
344 Vector2 randomVec(rand()%static_cast<int>(displacement.x) - halfRange, -rand()%static_cast<int>(displacement.y));
346 randomVec.x -= dir.x*halfRange;
347 randomVec.y *= 1.0f - fabsf(dir.x)*0.33f;
349 if(randomVec.y > 0.0f)
351 randomVec.y *= 0.33f;
353 Vector4 startAndEndPos( emitPosition.x, emitPosition.y, emitPosition.x+randomVec.x, emitPosition.y+randomVec.y );
354 bubbleActor->SetStartAndEndPosition( curUniform, startAndEndPos );
356 bubbleActor->SetPercentage( curUniform, 0.f);
359 } // namespace Internal
361 } // namespace Toolkit