From: Xiangyin Ma Date: Mon, 18 May 2015 17:59:52 +0000 (+0100) Subject: update bubble-emitter to use new mesh X-Git-Tag: dali_1.0.47~13^2~27 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=6e44b7e1d2a1ba9f24fb48751e8969eb63cfa716 update bubble-emitter to use new mesh Change-Id: I2a46b496e3c1f4938978416f518b1330e62fa328 --- diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h index 36cb94b..516b366 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h @@ -1548,6 +1548,30 @@ public: // TEST FUNCTIONS inline TraceCallStack& GetDrawTrace() { return mDrawTrace; } template + inline bool GetUniformValue( const char* name, T& value ) const + { + for( ProgramUniformMap::const_iterator program_it = mUniforms.begin(); + program_it != mUniforms.end(); + ++program_it ) + { + const UniformIDMap &uniformIDs = program_it->second; + + UniformIDMap::const_iterator uniform_it = uniformIDs.find( name ); + if( uniform_it != uniformIDs.end() ) + { + // found one matching uniform name, lets check the value... + GLuint programId = program_it->first; + GLint uniformId = uniform_it->second; + + const ProgramUniformValue &mProgramUniforms = GetProgramUniformsForType( value ); + return mProgramUniforms.GetUniformValue( programId, uniformId, value ); + } + } + return false; + } + + + template inline bool CheckUniformValue( const char* name, const T& value ) const { for( ProgramUniformMap::const_iterator program_it = mUniforms.begin(); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-BubbleEmitter.cpp b/automated-tests/src/dali-toolkit/utc-Dali-BubbleEmitter.cpp index e6062f2..33a0c2c 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-BubbleEmitter.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-BubbleEmitter.cpp @@ -24,8 +24,6 @@ #include #include -#include -#include using namespace Dali; using namespace Dali::Toolkit; @@ -140,13 +138,40 @@ int UtcDaliBubbleEmitterNew(void) END_TEST; } +int UtcDaliBubbleEmitterDownCast01(void) +{ + ToolkitTestApplication application; + + tet_infoline(" UtcDaliBubbleEmitterDownCast01 "); + + Image shapeImage = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); + BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 200, Vector2( 5.f, 10.f )); + + BaseHandle handle(emitter); + BubbleEmitter emitter2 = BubbleEmitter::DownCast(handle); + DALI_TEST_EQUALS( (bool)emitter2, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliBubbleEmitterDownCast02(void) +{ + ToolkitTestApplication application; + + tet_infoline(" UtcDaliBubbleEmitterDownCast02 "); + + Handle handle = Handle::New(); // Create a custom object + BubbleEmitter emitter = BubbleEmitter::DownCast(handle); + DALI_TEST_EQUALS( (bool)emitter, false, TEST_LOCATION ); + END_TEST; +} + int UtcDaliBubbleEmitterGetRootActor(void) { ToolkitTestApplication application; tet_infoline( " UtcDaliBubbleEmitterGetRootActor " ); Image shapeImage = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); - BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 200, Vector2( 5.f, 10.f )); + BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 270, Vector2( 5.f, 10.f )); Actor root = emitter.GetRootActor(); DALI_TEST_CHECK( root ); @@ -175,56 +200,39 @@ int UtcDaliBubbleEmitterSetBackground(void) END_TEST; } -int UtcDaliBubbleEmitterSetShapeImage(void) +//TODO: test case for BubbleEmitter::SetShapeImage(Image) +// To test that the bubble-shape image is successfully switched in the sampler +/*int UtcDaliBubbleEmitterSetShapeImage(void) { - ToolkitTestApplication application; - tet_infoline( " UtcDaliBubbleEmitterSetShapeImage " ); - - Image shapeImage1 = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); - BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage1, 200, Vector2( 5.f, 10.f )); - - Actor root = emitter.GetRootActor(); - MeshActor bubbleMesh = MeshActor::DownCast( root.GetChildAt( 0 ) ); - Material material = bubbleMesh.GetMaterial(); - - DALI_TEST_CHECK( material.GetDiffuseTexture() == shapeImage1 ); - - Image shapeImage2 = CreateSolidColorImage( application, Color::RED, 8, 8 ); - emitter.SetShapeImage( shapeImage2 ); - - DALI_TEST_CHECK( material.GetDiffuseTexture() == shapeImage2 ); - END_TEST; -} +}*/ int UtcDaliBubbleEmitterSetBubbleScale(void) { ToolkitTestApplication application; tet_infoline( " UtcDaliBubbleEmitterSetBubbleScale " ); - Image shapeImage1 = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); - BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage1, 200, Vector2( 5.f, 10.f )); - + Image shapeImage = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); + BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 150, Vector2( 5.f, 10.f )); Actor root = emitter.GetRootActor(); - MeshActor bubbleMesh = MeshActor::DownCast( root.GetChildAt( 0 ) ); - ShaderEffect effect = bubbleMesh.GetShaderEffect(); - DALI_TEST_CHECK( effect ); + Stage::GetCurrent().Add( root ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + Wait(application); - Property::Index scalePropertyIndex = effect.GetPropertyIndex( "uDynamicScale" ); float scaleValue; - (effect.GetProperty(scalePropertyIndex)).Get( scaleValue ); - DALI_TEST_EQUALS(scaleValue, 1.f, TEST_LOCATION ); + DALI_TEST_CHECK( gl.GetUniformValue( "uDynamicScale", scaleValue ) ); + DALI_TEST_EQUALS( scaleValue, 1.f, TEST_LOCATION ); emitter.SetBubbleScale( 2.f ); - application.SendNotification(); - application.Render(); - (effect.GetProperty(scalePropertyIndex)).Get( scaleValue ); - DALI_TEST_EQUALS(scaleValue, 2.f, TEST_LOCATION ); + Wait(application); + DALI_TEST_CHECK( gl.GetUniformValue( "uDynamicScale", scaleValue ) ); + DALI_TEST_EQUALS( scaleValue, 2.f, TEST_LOCATION ); emitter.SetBubbleScale( 0.5f ); - application.SendNotification(); - application.Render(); - (effect.GetProperty(scalePropertyIndex)).Get( scaleValue ); - DALI_TEST_EQUALS(scaleValue, 0.5f, TEST_LOCATION ); + Wait(application); + DALI_TEST_CHECK( gl.GetUniformValue( "uDynamicScale", scaleValue ) ); + DALI_TEST_EQUALS( scaleValue, 0.5f, TEST_LOCATION ); END_TEST; } @@ -233,8 +241,8 @@ int UtcDaliBubbleEmitterSetBubbleDensity01(void) ToolkitTestApplication application; tet_infoline( " UtcDaliBubbleEmitterSetBubbleDensity " ); - Image shapeImage1 = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); - BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage1, 200, Vector2( 5.f, 10.f )); + Image shapeImage = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); + BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 200, Vector2( 5.f, 10.f )); try { @@ -254,8 +262,8 @@ int UtcDaliBubbleEmitterSetBubbleDensity02(void) ToolkitTestApplication application; tet_infoline( " UtcDaliBubbleEmitterSetBubbleDensity " ); - Image shapeImage1 = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); - BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage1, 200, Vector2( 5.f, 10.f )); + Image shapeImage = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); + BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 200, Vector2( 5.f, 10.f )); try { @@ -274,27 +282,32 @@ int UtcDaliBubbleEmitterSetBlendMode(void) ToolkitTestApplication application; tet_infoline( " UtcDaliBubbleEmitterSetBlendMode " ); - Image shapeImage1 = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); - BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage1, 200, Vector2( 5.f, 10.f )); - + Image shapeImage = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); + BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 150, Vector2( 5.f, 10.f )); Actor root = emitter.GetRootActor(); - MeshActor bubbleMesh = MeshActor::DownCast( root.GetChildAt( 0 ) ); + Stage::GetCurrent().Add( root ); - BlendingFactor::Type srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + Wait(application); + DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA, glAbstraction.GetLastBlendFuncSrcRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_ALPHA, glAbstraction.GetLastBlendFuncDstRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE, glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_ALPHA, glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION ); emitter.SetBlendMode( true ); - bubbleMesh.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); - DALI_TEST_CHECK( srcFactorRgb == BlendingFactor::SRC_ALPHA ); - DALI_TEST_CHECK( destFactorRgb == BlendingFactor::ONE ); - DALI_TEST_CHECK( srcFactorAlpha == BlendingFactor::ZERO ); - DALI_TEST_CHECK( destFactorAlpha == BlendingFactor::ONE ); + Wait(application); + DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA, glAbstraction.GetLastBlendFuncSrcRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE, glAbstraction.GetLastBlendFuncDstRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ZERO, glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE, glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION ); emitter.SetBlendMode( false ); - bubbleMesh.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); - DALI_TEST_CHECK( srcFactorRgb == BlendingFactor::SRC_ALPHA ); - DALI_TEST_CHECK( destFactorRgb == BlendingFactor::ONE_MINUS_SRC_ALPHA ); - DALI_TEST_CHECK( srcFactorAlpha == BlendingFactor::ONE ); - DALI_TEST_CHECK( destFactorAlpha == BlendingFactor::ONE_MINUS_SRC_ALPHA ); + Wait(application); + DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA, glAbstraction.GetLastBlendFuncSrcRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_ALPHA, glAbstraction.GetLastBlendFuncDstRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE, glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_ALPHA, glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION ); + END_TEST; } @@ -307,103 +320,90 @@ int UtcDaliBubbleEmitterEmitBubble(void) BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage1, 200, Vector2( 5.f, 10.f )); Actor root = emitter.GetRootActor(); - MeshActor bubbleMesh = MeshActor::DownCast( root.GetChildAt( 0 ) ); - ShaderEffect effect = bubbleMesh.GetShaderEffect(); - DALI_TEST_CHECK( effect ); + Actor bubbleMesh = root.GetChildAt( 0 ); + Stage::GetCurrent().Add( root ); + DALI_TEST_CHECK( bubbleMesh ); - Property::Index propertyIndex0 = effect.GetPropertyIndex( "uPercentage[0]" ); - Property::Index propertyIndex1 = effect.GetPropertyIndex( "uPercentage[1]" ); + Property::Index propertyIndex0 = bubbleMesh.GetPropertyIndex( "percentage-0" ); + Property::Index propertyIndex1 = bubbleMesh.GetPropertyIndex( "percentage-1" ); float value0, value1; Animation animation = Animation::New( 0.5f ); emitter.EmitBubble( animation, Vector2(40.f,40.f), Vector2(-5.f,-5.f), Vector2(30.f,30.f) ); emitter.EmitBubble( animation, Vector2(10.f,10.f), Vector2(5.f,5.f), Vector2(30.f,30.f) ); - (effect.GetProperty(propertyIndex0)).Get( value0 ); - (effect.GetProperty(propertyIndex1)).Get( value1 ); + (bubbleMesh.GetProperty(propertyIndex0)).Get( value0 ); + (bubbleMesh.GetProperty(propertyIndex1)).Get( value1 ); DALI_TEST_EQUALS(value0, 0.f, TEST_LOCATION ); DALI_TEST_EQUALS(value1, 0.f, TEST_LOCATION ); animation.Play(); Wait(application, 300); - (effect.GetProperty(propertyIndex0)).Get( value0 ); - (effect.GetProperty(propertyIndex1)).Get( value1 ); + propertyIndex0 = bubbleMesh.GetPropertyIndex( "percentage-0" ); + propertyIndex1 = bubbleMesh.GetPropertyIndex( "percentage-1" ); + (bubbleMesh.GetProperty(propertyIndex0)).Get( value0 ); + (bubbleMesh.GetProperty(propertyIndex1)).Get( value1 ); DALI_TEST_CHECK( value0 >= 0.6f ); DALI_TEST_CHECK( value1 >= 0.6f ); - Wait(application, 600); - (effect.GetProperty(propertyIndex0)).Get( value0 ); - (effect.GetProperty(propertyIndex1)).Get( value1 ); + Wait(application,500); + (bubbleMesh.GetProperty(propertyIndex0)).Get( value0 ); + (bubbleMesh.GetProperty(propertyIndex1)).Get( value1 ); DALI_TEST_EQUALS(value0, 1.f, TEST_LOCATION ); DALI_TEST_EQUALS(value1, 1.f, TEST_LOCATION ); END_TEST; } -int UtcDaliBubbleEmitterStartExplosion(void) +int UtcDaliBubbleEmitterRestore(void) { ToolkitTestApplication application; - tet_infoline( " UtcDaliBubbleEmitterStartExplosion " ); + tet_infoline( " UtcDaliBubbleEmitterRestore " ); - Image shapeImage1 = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); - BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage1, 200, Vector2( 5.f, 10.f )); + Image shapeImage = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); + BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 90, Vector2( 5.f, 10.f )); Actor root = emitter.GetRootActor(); - MeshActor bubbleMesh = MeshActor::DownCast( root.GetChildAt( 0 ) ); - ShaderEffect effect = bubbleMesh.GetShaderEffect(); - DALI_TEST_CHECK( effect ); - - Property::Index propertyIndex = effect.GetPropertyIndex( "uMagnification" ); - float value; - (effect.GetProperty(propertyIndex)).Get( value ); - DALI_TEST_EQUALS(value, 1.f, TEST_LOCATION ); - - emitter.StartExplosion( 0.4, 4.f ); + Stage::GetCurrent().Add( root ); - Wait(application, 200); // 0.2s - (effect.GetProperty(propertyIndex)).Get( value ); - DALI_TEST_CHECK( value >= 2.f ); + Actor bubbleMesh = root.GetChildAt( 0 ); + Renderer renderer = bubbleMesh.GetRendererAt( 0 ); + DALI_TEST_CHECK( renderer ); - Wait(application, 100); // 0.3s - (effect.GetProperty(propertyIndex)).Get( value ); - DALI_TEST_CHECK( value >= 3.f ); + TestGlAbstraction& gl = application.GetGlAbstraction(); - Wait(application, 100); // 0.4s - (effect.GetProperty(propertyIndex)).Get( value ); - DALI_TEST_EQUALS(value, 1.f, TEST_LOCATION ); - END_TEST; -} + float percentageValue; + Vector4 startEndPosValue; -int UtcDaliBubbleEmitterRestore(void) -{ - ToolkitTestApplication application; - tet_infoline( " UtcDaliBubbleEmitterRestore " ); + Animation animation = Animation::New( 0.5f ); + emitter.EmitBubble( animation, Vector2(40.f,40.f), Vector2(-5.f,-5.f), Vector2(30.f,30.f) ); - Image shapeImage1 = CreateSolidColorImage( application, Color::GREEN, 5, 5 ); - BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage1, 200, Vector2( 5.f, 10.f )); - Actor root = emitter.GetRootActor(); - MeshActor bubbleMesh = MeshActor::DownCast( root.GetChildAt( 0 ) ); - ShaderEffect effect = bubbleMesh.GetShaderEffect(); - DALI_TEST_CHECK( effect ); + Wait(application); - Property::Index percentagePropertyIndex = effect.GetPropertyIndex( "uPercentage[0]" ); - float percentage; + DALI_TEST_CHECK( gl.GetUniformValue( "uPercentage[0]", percentageValue ) ); + DALI_TEST_EQUALS( percentageValue, 0.f, TEST_LOCATION ); - Animation animation = Animation::New( 0.5f ); - emitter.EmitBubble( animation, Vector2(40.f,40.f), Vector2(-5.f,-5.f), Vector2(30.f,30.f) ); - (effect.GetProperty(percentagePropertyIndex)).Get( percentage ); - DALI_TEST_EQUALS(percentage, 0.f, TEST_LOCATION ); + DALI_TEST_CHECK( gl.GetUniformValue( "uStartAndEndPos[0]", startEndPosValue ) ); + DALI_TEST_EQUALS( startEndPosValue.x, 40.f, TEST_LOCATION ); + DALI_TEST_EQUALS( startEndPosValue.y, 40.f, TEST_LOCATION ); animation.Play(); Wait(application, 200); animation.Clear(); - (effect.GetProperty(percentagePropertyIndex)).Get( percentage ); - DALI_TEST_CHECK( percentage < 0.5f && percentage >= 0.4); + DALI_TEST_CHECK( gl.GetUniformValue( "uPercentage[0]", percentageValue ) ); + DALI_TEST_CHECK( percentageValue < 0.5f && percentageValue >= 0.4); + + DALI_TEST_CHECK( gl.GetUniformValue( "uStartAndEndPos[0]", startEndPosValue ) ); + DALI_TEST_EQUALS( startEndPosValue.x, 40.f, TEST_LOCATION ); + DALI_TEST_EQUALS( startEndPosValue.y, 40.f, TEST_LOCATION ); emitter.Restore(); application.SendNotification(); application.Render(); - (effect.GetProperty(percentagePropertyIndex)).Get( percentage ); - DALI_TEST_EQUALS(percentage, 1.f, TEST_LOCATION ); + DALI_TEST_CHECK( gl.GetUniformValue( "uPercentage[0]", percentageValue ) ); + DALI_TEST_EQUALS( percentageValue, 0.f, TEST_LOCATION ); + + DALI_TEST_CHECK( gl.GetUniformValue( "uStartAndEndPos[0]", startEndPosValue ) ); + DALI_TEST_EQUALS( startEndPosValue, Vector4::ZERO, TEST_LOCATION ); END_TEST; } diff --git a/dali-toolkit/internal/controls/bubble-effect/bubble-actor.cpp b/dali-toolkit/internal/controls/bubble-effect/bubble-actor.cpp new file mode 100644 index 0000000..d3b0563 --- /dev/null +++ b/dali-toolkit/internal/controls/bubble-effect/bubble-actor.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include "bubble-actor.h" + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES + +namespace +{ + +/** + * Register a property and map it as uniform. + * @param[in] handle The handle to register new property. + * @param[in] propertyName The name of the property. + * @param[in] unifoemName The name of the uniform. + * @param[in] value The initial value of the property. + * @return The index of theproperty + */ +Dali::Property::Index RegisterUniform( Dali::Handle& handle, + const std::string& propertyName, + const std::string& uniformName, + Dali::Property::Value value) +{ + Dali::Property::Index propertyIndex = handle.RegisterProperty( propertyName, value ); + handle.AddUniformMapping( propertyIndex, uniformName ); + + return propertyIndex; +} + +}// end LOCAL_STUFF + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +BubbleActor::BubbleActor( unsigned int numberOfBubble, + const Vector2& movementArea) +: mMovementArea( movementArea ), + mNumBubble( numberOfBubble ) +{ + mActor = Actor::New(); +} + +void BubbleActor::MakeRenderable( Geometry geometry, Material material ) +{ + if( mRenderer ) + { + // This function is supposed to be called once + return; + } + + mRenderer = Renderer::New( geometry, material ); + + mActor.AddRenderer( mRenderer ); + mActor.SetSize( mMovementArea ); + mActor.SetParentOrigin(ParentOrigin::TOP_LEFT); + + // register uniforms + mIndexGravity = RegisterUniform( mActor, "gravity", "uGravity", 50.f ); + mIndexDynamicScale = RegisterUniform( mActor, "dynamic-scale", "uDynamicScale", 1.f ); + + mIndexInvertedMovementArea = RegisterUniform( mActor, "inverted-movement-area", "uInvertedMovementArea", Vector2(1.f,1.f) / mMovementArea ); + + srand(time(NULL)); + mIndicesOffset.resize(9); + int offset = mMovementArea.Length() / 10.f; + mIndicesOffset[0] = RegisterUniform(mActor, "offset-0", "offset[0]", Vector2(0.f,0.f)); + mIndicesOffset[1] = RegisterUniform(mActor, "offset-1", "offset[1]", Vector2(rand()%offset,rand()%offset) ); + mIndicesOffset[2] = RegisterUniform(mActor, "offset-2", "offset[2]", Vector2(rand()%offset,-rand()%offset) ); + mIndicesOffset[3] = RegisterUniform(mActor, "offset-3", "offset[3]", Vector2(-rand()%offset,rand()%offset) ); + mIndicesOffset[4] = RegisterUniform(mActor, "offset-4", "offset[4]", Vector2(-rand()%offset,-rand()%offset) ); + mIndicesOffset[5] = RegisterUniform(mActor, "offset-5", "offset[5]", Vector2(rand()%offset,0.f)); + mIndicesOffset[6] = RegisterUniform(mActor, "offset-6", "offset[6]", Vector2(-rand()%offset,0.f)); + mIndicesOffset[7] = RegisterUniform(mActor, "offset-7", "offset[7]", Vector2(0.f,rand()%offset)); + mIndicesOffset[8] = RegisterUniform(mActor, "offset-8", "offset[8]", Vector2(0.f,-rand()%offset)); + + Vector4 zeroVector; + mIndiceStartEndPos.resize( mNumBubble ); + mIndicesPercentage.resize( mNumBubble ); + for( unsigned int i=0; i +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * BubbleActor is a group of bubbles.Each bubble can be moved separately. + * Its custom shader achieves similar effect of particle system by applying on a specially created mesh + * Each bubble is rendered on a patch with two triangles; and each mesh can contain multiple such patches, thus a group. + */ +class BubbleActor : public RefObject +{ +public: + + /** + * Constructor + * @param[in] numberOfBubble How many groups of uniforms are used to control the bubble movement. + * Note: Limited by the maximum available uniforms, this parameter cannot be bigger than 100. + * Ideally use one group of uniform to control one bubble. + * If the num of patches in the MeshActor is more than groups of uniforms, + * the uniform values will be shared by multiple bubbles. Allow up to 9 times. + * @param[in] movementArea The size of the bubble moving area, usually the same size as the background image actor. + * @return A newly allocated object. + */ + BubbleActor( unsigned int numberOfBubble, + const Vector2& movementArea); + + /** + * @brief Destructor + */ + ~BubbleActor(){} + + /** + * Prepare for the rendering: create and add renderer, and register properties + * @param[in] geometry The geometry to be used by the renderer + * @param[in] material The material to be used by the renderer + */ + void MakeRenderable( Geometry geometry, Material material ); + + /** + * Return the mesh actor which is used to display the bubbles + */ + Actor GetMeshActor(); + + /** + * Sets the geometry to be used by the renderer + * @param[in] geometry The geometry to be used by the renderer + */ + void SetGeometry( Geometry geometry ); + + /** + * Set the bubble movement area for the BubbleEffect + * @param[in] movementArea The size of bubble movement area; by default, it is the stage size + */ + void SetMovementArea( const Vector2& movementArea ); + + /** + * Set the start and end positions of the index-th bubble's movement. + * @param[in] index Indicate which bubble these properties are applied on. + * @param[in] startAndEndPosition The start and the end position of movement. + */ + void SetStartAndEndPosition( unsigned int index, const Vector4& startAndEndPosition ); + + /** + * Set the movement completed percentage of the index-th bubble. + * The bubble will appear at start position when percentage equals to zero, + * and disappear near end position (affected by gravity) when percentage equals to one. + * This percentage property is used to animate the bubble movement. + * @param[in] index Indicate which bubble this property is applied on. + * @param[in] percentage Set the percentage property value ( between zero and one ). + */ + void SetPercentage( unsigned int index, float percentage ); + + /** + * Set the gravity applied to the y direction, which makes the bubbles no longer moving on a straight line. + * @param[in] gravity The gravity on the y direction. + */ + void SetGravity( float gravity ); + + /** + * Set the scale factor applied to the bubbles + * @param[in] scale The scale factor applied on all bubbles. + */ + void SetDynamicScale( float scale ); + + /** + * Get the idx-th percentage property. + * @param[in] idx The percentage property index. + * @return the idx-th percentage property. + */ + Property GetPercentageProperty( unsigned int idx ); + + /** + * Reset the uniform values to default. + */ + void ResetProperties(); + +private: + + Actor mActor; + Renderer mRenderer; + + Vector2 mMovementArea; ///< The size of the bubble moving area, usually the same size as the background image actor. + + //properties mapped as uniforms + std::vector mIndicesOffset; ///< Indices of the properties mapping to uniform array 'uOffset' + std::vector mIndiceStartEndPos; ///< Indices of the properties mapping to uniform array 'uStartAndEndPos' + std::vector mIndicesPercentage; ///< Indices of the properties mapping to uniform array 'uPercentage' + Property::Index mIndexGravity; ///< Index of the property mapping to uniform 'uGravity' + Property::Index mIndexDynamicScale; ///< Index of the property mapping to uniform 'uDynamicScale' + Property::Index mIndexInvertedMovementArea; ///< Index of the property mapping to uniform 'uInvertedMovementArea' + + unsigned int mNumBubble; ///< How many groups of uniforms are used to control the bubble movement. +}; + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + +#endif /* __DALI_TOOLKIT_INTERNAL_BUBBLE_ACTOR_H_ */ diff --git a/dali-toolkit/internal/controls/bubble-effect/bubble-effect.h b/dali-toolkit/internal/controls/bubble-effect/bubble-effect.h new file mode 100644 index 0000000..5f35d20 --- /dev/null +++ b/dali-toolkit/internal/controls/bubble-effect/bubble-effect.h @@ -0,0 +1,131 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_BUBBLE_EFFECT_H_ +#define __DALI_TOOLKIT_INTERNAL_BUBBLE_EFFECT_H_ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * Create the shader to be used by the material + * @param[in] numberOfBubble How many groups of uniforms are used to control the bubble movement. + * @return A handle to the newly created shader. + */ +inline Shader CreateBubbleShader( unsigned int numBubble ) +{ + const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( + attribute mediump float aIndex;\n + attribute mediump vec2 aPosition;\n + attribute highp vec2 aTexCoord;\n + varying mediump vec2 vTexCoord;\n + uniform mediump mat4 uMvpMatrix;\n + // the gravity applied to the y direction + uniform mediump float uGravity;\n + // xy: the emit position of the bubble; zw: the destination of the bubble. + // The bubble is moving from (xy) to (zw plus the y drop influenced by gravity). + uniform vec4 uStartAndEndPos[NUMBER_OF_BUBBLE];\n + // The undergoing percentage of the bubble movement. 0.0: start from emit position, 1.0: reach the destination + uniform float uPercentage[NUMBER_OF_BUBBLE];\n + uniform vec2 uInvertedMovementArea;\n + // The bubble number is restricted by the available uniform num. + // To increase the displayed bubble, every uStartAndEndPos and uPercentage uniform is applied to a small bunch of bubbles (9 here) + // The offset defines the random offset between bubbles within the bunch. + uniform vec2 offset[9];\n + // This uniform is used to change the bubble size during running time + uniform float uDynamicScale;\n + varying float vPercentage;\n + varying vec2 vEffectTexCoord;\n + void main()\n + {\n + vec4 position = vec4( aPosition, 0.0, 1.0 );\n + // The Z coordinate is used to record the bubble index within current mesh actor + int index = int(aIndex); \n + //for some i between 0 ~ NUMBER_OF_BUBBLE-1: i,i+NUMBER_OF_BUBBLE, i+NUMBER_OF_BUBBLE*2, ... (up to i+NUMBER_OF_BUBBLE*8) belongs to the same bunch. + int groupIdx = index / NUMBER_OF_BUBBLE;\n + // The bubbles within the same bunch applies the same uniforms uStartAndEndPos[idx] & uPercentage[idx] + int idx = index - groupIdx*NUMBER_OF_BUBBLE;\n + float percentage = uPercentage[idx]; + // early out if uPercentage is (zero || one) setting position to zero (zero sized triangles) + if( percentage <= 0.0 || percentage >= 1.0 )\n + {\n + gl_Position = vec4(0.0);\n + return;\n + }\n + vec4 startAndEnd = uStartAndEndPos[idx];\n + // The final position is added up different offset for bubbles + startAndEnd.zw += offset[groupIdx];\n + \n + // increase the bubble size from 0% to 100% during the first 1/5 of movement & apply the dynamic scale + // the new xy value containes both the new scale and new bubble position + position.xy *= uDynamicScale*min(percentage*5.0, 1.0);\n + position.xy += mix(startAndEnd.xy, startAndEnd.zw, percentage);\n + // The gravity is g*t*t on the y direction + position.y += uGravity * pow(percentage, 2.0);\n + gl_Position = uMvpMatrix * position;\n + \n + // Add multiple bubble shapes in the effect + vTexCoord = aTexCoord;\n + vPercentage = percentage;\n + // Use the emit position color for the bubble + vEffectTexCoord = startAndEnd.xy * uInvertedMovementArea;\n + }\n + ); + + const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( + varying mediump vec2 vTexCoord;\n + uniform lowp vec4 uColor;\n + uniform sampler2D sBackground;\n + uniform sampler2D sBubbleShape;\n + varying mediump float vPercentage;\n + varying mediump vec2 vEffectTexCoord;\n + \n + void main()\n + {\n + // Get the emit pisition color, and Mix with the actor color + mediump vec4 fragColor = texture2D(sBackground, vEffectTexCoord)*uColor;\n + // Apply the shape defined by the texture contained in the material + // And make the opacity being 0.7, and animate from 0.7 to 0 during the last 1/3 of movement + fragColor.a *= texture2D(sBubbleShape, vTexCoord).a * ( 2.1 - max( vPercentage*2.1, 1.4 ) );\n + gl_FragColor = fragColor;\n + }\n + ); + + std::ostringstream vertexShaderStringStream; + vertexShaderStringStream << "#define NUMBER_OF_BUBBLE "<< numBubble << "\n" + << VERTEX_SHADER; + Shader shader = Shader::New( vertexShaderStringStream.str(), FRAGMENT_SHADER ); + + return shader; +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali +#endif /* __DALI_TOOLKIT_INTERNAL_BUBBLE_EFFECT_H_ */ diff --git a/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp b/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp index ae17a0d..08ccb15 100644 --- a/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp +++ b/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp @@ -19,13 +19,44 @@ #include "bubble-emitter-impl.h" // EXTERNAL INCLUDES -#include #include #include #include // INTERNAL INCLUDES #include +#include +#include +#include + +namespace +{ +struct Vertex +{ + float index; + Dali::Vector2 position; + Dali::Vector2 textureCoord; + + Vertex() + {} + + Vertex( float index, const Dali::Vector2& position, const Dali::Vector2& textureCoord ) + : index( index ), position( position ), textureCoord( textureCoord ) + {} +}; + +/** + * Return a random value between the given interval. + * @param[in] f0 The low bound + * @param[in] f1 The up bound + * @return A random value between the given interval + */ +float RandomRange(float f0, float f1) +{ + return f0 + (rand() & 0xfff) * (f1-f0) * (1.0f/4095.0f); +} + +} namespace Dali { @@ -40,24 +71,30 @@ BubbleEmitter::BubbleEmitter( const Vector2& movementArea, unsigned int maximumNumberOfBubble, const Vector2& bubbleSizeRange ) : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ), - mMovementArea( movementArea ), mShapeImage( shapeImage ), - mTotalNumOfBubble( maximumNumberOfBubble ), - mRenderTaskRunning(false), + mMovementArea( movementArea ), mBubbleSizeRange( bubbleSizeRange ), - mCurrentUniform( 0 ), - mDensity( 5 ) + mDensity( 5 ), + mTotalNumOfBubble( maximumNumberOfBubble ), + mCurrentBubble( 0 ), + mRenderTaskRunning(false) { - // Calculate how many BubbleEffect shaders are required + // Calculate how many shaders are required if( mTotalNumOfBubble>100 ) { - mNumBubblePerShader = 100; - mNumShader = mTotalNumOfBubble / 100; + mNumBubblePerActor = 100; + mNumActor = mTotalNumOfBubble / 100; + if( mNumActor*mNumBubblePerActor < mTotalNumOfBubble ) + { + mNumActor++; + mNumBubblePerActor = mTotalNumOfBubble / mNumActor+1; + mTotalNumOfBubble = mNumActor * mNumBubblePerActor; + } } else { - mNumBubblePerShader = mTotalNumOfBubble; - mNumShader = 1; + mNumBubblePerActor = mTotalNumOfBubble; + mNumActor = 1; } } @@ -92,39 +129,27 @@ void BubbleEmitter::OnInitialize() // Prepare the frame buffer to store the color adjusted background image mEffectImage = FrameBufferImage::New( mMovementArea.width/4.f, mMovementArea.height/4.f, Pixel::RGBA8888, Dali::Image::UNUSED ); - // Generate the material object, which is used by all meshActors - GenMaterial(); + // Generate the samplers and geometry, which is used by all bubbleActors + mSamplerBackground = Sampler::New( mEffectImage, "sBackground" ); + mSamplerBubbleShape = Sampler::New( mShapeImage, "sBubbleShape" ); + mMeshGeometry = CreateGeometry( mNumBubblePerActor*mDensity ); - mMesh.resize( mNumShader ); - mMeshActor.resize( mNumShader ); - mEffect.resize( mNumShader ); + Shader bubbleShader = CreateBubbleShader (mNumBubblePerActor ); + + mMaterial = Material::New( bubbleShader ); + mMaterial.AddSampler( mSamplerBackground ); + mMaterial.AddSampler( mSamplerBubbleShape ); + + mBubbleActors.resize( mNumActor ); // Create the meshActor group and bubbleEffect group to emit bubbles following the given track, such as finger touch track. - MeshData meshData; - ConstructBubbleMesh( meshData, mNumBubblePerShader*mDensity); - for(unsigned int i=0; i < mNumShader; i++ ) + for(unsigned int i=0; i < mNumActor; i++ ) { - mMesh[i] = Mesh::New( meshData ); - mMeshActor[i] = MeshActor::New( mMesh[i] ); - mMeshActor[i].SetParentOrigin(ParentOrigin::TOP_LEFT); - mEffect[i] = BubbleEffect::New( mNumBubblePerShader ); - mEffect[i].SetEffectImage( mEffectImage ); - mEffect[i].SetMovementArea( mMovementArea ); - mMeshActor[i].SetShaderEffect( mEffect[i] ); - mBubbleRoot.Add( mMeshActor[i] ); + mBubbleActors[i] = new BubbleActor( mNumBubblePerActor, mMovementArea ); + (mBubbleActors[i])->MakeRenderable( mMeshGeometry, mMaterial ); + mBubbleRoot.Add( (mBubbleActors[i])->GetMeshActor() ); } - // Create the extra meshActor and bubbleEffect to emit bubbles in totally random angle. - MeshData meshDataForNoise; - ConstructBubbleMesh( meshDataForNoise, mNumBubblePerShader); - mMeshActorForNoise = MeshActor::New( Mesh::New(meshDataForNoise) ); - mMeshActorForNoise.SetParentOrigin(ParentOrigin::TOP_LEFT); - mEffectForNoise = BubbleEffect::New( mNumBubblePerShader ); - mEffectForNoise.SetMovementArea( mMovementArea ); - mEffectForNoise.SetEffectImage( mEffectImage ); - mMeshActorForNoise.SetShaderEffect( mEffectForNoise ); - mBubbleRoot.Add( mMeshActorForNoise ); - // Create a cameraActor for the off screen render task. mCameraActor = CameraActor::New(mMovementArea); mCameraActor.SetParentOrigin(ParentOrigin::CENTER); @@ -150,7 +175,7 @@ void BubbleEmitter::SetBackground( Image bgImage, const Vector3& hsvDelta ) sourceActor.SetParentOrigin(ParentOrigin::CENTER); Stage::GetCurrent().Add( sourceActor ); - ColorAdjuster colorAdjuster = ColorAdjuster::New( hsvDelta, true /*ignore alpha to make bubble color always*/ ); + ShaderEffect colorAdjuster = CreateColorAdjuster( hsvDelta, true /*ignore alpha to make bubble color always*/ ); sourceActor.SetShaderEffect( colorAdjuster ); RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); @@ -167,16 +192,15 @@ void BubbleEmitter::SetBackground( Image bgImage, const Vector3& hsvDelta ) void BubbleEmitter::SetShapeImage( Image shapeImage ) { - mCustomMaterial.SetDiffuseTexture( shapeImage ); + mSamplerBubbleShape.SetImage( shapeImage ); } void BubbleEmitter::SetBubbleScale( float scale ) { - for(unsigned int i=0; i < mNumShader; i++ ) + for(unsigned int i=0; i < mNumActor; i++ ) { - mEffect[i].SetDynamicScale( scale ); + (mBubbleActors[i])->SetDynamicScale( scale ); } - mEffectForNoise.SetDynamicScale( scale ); } void BubbleEmitter::SetBubbleDensity( unsigned int density ) @@ -190,15 +214,30 @@ void BubbleEmitter::SetBubbleDensity( unsigned int density ) else { mDensity = density; - MeshData meshData; - ConstructBubbleMesh( meshData, mNumBubblePerShader*mDensity); - for(unsigned int i=0; i < mNumShader; i++ ) + mMeshGeometry = CreateGeometry( mNumBubblePerActor*mDensity ); + for(unsigned int i=0; i < mNumActor; i++ ) { - mMesh[i].UpdateMeshData(meshData); + (mBubbleActors[i])->SetGeometry( mMeshGeometry ); } } } +void BubbleEmitter::SetBlendMode( bool enable ) +{ + if(enable) + { + // linear overlay + mMaterial.SetBlendFunc(BlendingFactor::SRC_ALPHA, BlendingFactor::ONE, + BlendingFactor::ZERO, BlendingFactor::ONE); + } + else + { + // using default blend func + mMaterial.SetBlendFunc( BlendingFactor::SRC_ALPHA, BlendingFactor::ONE_MINUS_SRC_ALPHA, + BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA ); + } +} + // clear the resources created for the off screen rendering void BubbleEmitter::OnRenderFinished(RenderTask& source) { @@ -206,7 +245,7 @@ void BubbleEmitter::OnRenderFinished(RenderTask& source) Actor sourceActor = source.GetSourceActor(); if( sourceActor ) { - RenderableActor renderable = RenderableActor::DownCast( sourceActor ); + ImageActor renderable = ImageActor::DownCast( sourceActor ); if( renderable ) { renderable.RemoveShaderEffect(); @@ -228,152 +267,74 @@ void BubbleEmitter::OnContextRegained() } } -void BubbleEmitter::SetBlendMode( bool enable ) -{ - if(enable) - { - for(unsigned int i=0; i < mNumShader; i++ ) - { - // linear overlay - // TODO: if BlendColor would be public api from renderable actor, then can optimize the constant color - mMeshActor[i].SetBlendFunc(BlendingFactor::SRC_ALPHA, BlendingFactor::ONE, - BlendingFactor::ZERO, BlendingFactor::ONE); - } - mMeshActorForNoise.SetBlendFunc(BlendingFactor::SRC_ALPHA, BlendingFactor::ONE, - BlendingFactor::ZERO, BlendingFactor::ONE); - } - else - { - for(unsigned int i=0; i < mNumShader; i++ ) - { - // using default blend func - mMeshActor[i].SetBlendFunc( BlendingFactor::SRC_ALPHA, BlendingFactor::ONE_MINUS_SRC_ALPHA, - BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA ); - } - mMeshActorForNoise.SetBlendFunc( BlendingFactor::SRC_ALPHA, BlendingFactor::ONE_MINUS_SRC_ALPHA, - BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA ); - } -} - void BubbleEmitter::EmitBubble( Animation& animation, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ) { - unsigned int curUniform = mCurrentUniform % mNumBubblePerShader; - unsigned int groupIdx = mCurrentUniform / mNumBubblePerShader; - SetBubbleParameter( mEffect[groupIdx], curUniform, emitPosition, direction, displacement); - animation.AnimateTo( Property( mEffect[groupIdx], mEffect[groupIdx].GetPercentagePropertyName(curUniform) ), + unsigned int curUniform = mCurrentBubble % mNumBubblePerActor; + unsigned int groupIdx = mCurrentBubble / mNumBubblePerActor; + SetBubbleParameter( mBubbleActors[groupIdx], curUniform, emitPosition, direction, displacement); + animation.AnimateTo( (mBubbleActors[groupIdx])->GetPercentageProperty(curUniform), 1.f, AlphaFunction::LINEAR ); - if( mCurrentUniform % mNumShader == 0 ) - { - unsigned int uniform = mCurrentUniform / mNumShader; - SetBubbleParameter(mEffectForNoise, uniform, emitPosition, displacement); - animation.AnimateTo( Property( mEffectForNoise, mEffectForNoise.GetPercentagePropertyName(uniform) ), - 1.f, AlphaFunction::LINEAR ); - } - - mCurrentUniform = (mCurrentUniform + 1) % mTotalNumOfBubble; -} - -void BubbleEmitter::StartExplosion( float duration, float multiple ) -{ - Animation animation = Animation::New( duration ); - for(unsigned int i=0; i < mNumShader; i++ ) - { - animation.AnimateTo( Property( mEffect[i], mEffect[i].GetMagnificationPropertyName() ), - multiple, AlphaFunction::EASE_OUT); - } - animation.AnimateTo( Property( mEffectForNoise, mEffectForNoise.GetMagnificationPropertyName() ), - multiple, AlphaFunction::EASE_OUT); - animation.Play(); - - animation.FinishedSignal().Connect(this, &BubbleEmitter::OnExplosionFinished); + mCurrentBubble = (mCurrentBubble + 1) % mTotalNumOfBubble; } void BubbleEmitter::Restore() { - for(unsigned int i=0; i < mNumShader; i++ ) + for(unsigned int i=0; i < mNumActor; i++ ) { - mEffect[i].ResetParameters(); + (mBubbleActors[i])->ResetProperties(); } - mEffectForNoise.ResetParameters(); -} - -void BubbleEmitter::GenMaterial() -{ - mCustomMaterial = Material::New("CustomMaterial"); - mCustomMaterial.SetOpacity(1.0f); - mCustomMaterial.SetDiffuseColor(Color::WHITE); - mCustomMaterial.SetAmbientColor(Vector4(0.0, 0.1, 0.1, 1.0)); - mCustomMaterial.SetMapU( Material::MAPPING_MODE_WRAP ); - mCustomMaterial.SetMapV( Material::MAPPING_MODE_WRAP ); - mCustomMaterial.SetDiffuseTexture( mShapeImage ); } -void BubbleEmitter::AddVertex(MeshData::VertexContainer& vertices, Vector3 XYZ, Vector2 UV) +Geometry BubbleEmitter::CreateGeometry( unsigned int numOfPatch ) { - MeshData::Vertex meshVertex; - meshVertex.x = XYZ.x; - meshVertex.y = XYZ.y; - meshVertex.z = XYZ.z; - meshVertex.u = UV.x; - meshVertex.v = UV.y; - vertices.push_back(meshVertex); -} - -void BubbleEmitter::AddTriangle(MeshData::FaceIndices& faces, -size_t v0, size_t v1, size_t v2) -{ - faces.push_back(v0); - faces.push_back(v1); - faces.push_back(v2); -} + unsigned int numVertex = numOfPatch*4u; + std::vector vertexData; + vertexData.reserve( numVertex ); -void BubbleEmitter::ConstructBubbleMesh( MeshData& meshData, unsigned int numOfBubble) -{ - MeshData::VertexContainer vertices; - MeshData::FaceIndices faces; - BoneContainer bones(0); + unsigned int numIndex = numOfPatch*6u; + Vector indexData; + indexData.Reserve( numIndex ); - for(unsigned int index = 0; index < numOfBubble; index ++) + for(unsigned int i = 0; i < numOfPatch; i++) { float curSize = RandomRange(mBubbleSizeRange.x, mBubbleSizeRange.y); - if(rand()%100 < 1) - { - curSize *= 2.f; - } - float depth = static_cast( index ); - AddVertex( vertices, Vector3(0.f,0.f,depth), Vector2(0.f,0.f) ); - AddVertex( vertices, Vector3(0.f,curSize,depth), Vector2( 0.f,1.f )); - AddVertex( vertices, Vector3(curSize,curSize,depth), Vector2(1.f,1.f) ); - AddVertex( vertices, Vector3(curSize,0.f,depth), Vector2(1.f,0.f) ); + + float index = static_cast( i ); + vertexData.push_back( Vertex( index, Vector2(0.f,0.f), Vector2(0.f,0.f) ) ); + vertexData.push_back( Vertex( index, Vector2(0.f,curSize), Vector2(0.f,1.f) ) ); + vertexData.push_back( Vertex( index, Vector2(curSize,curSize), Vector2(1.f,1.f) ) ); + vertexData.push_back( Vertex( index, Vector2(curSize,0.f), Vector2(1.f,0.f) ) ); unsigned int idx = index * 4; - AddTriangle( faces, idx, idx+1, idx+2); - AddTriangle( faces, idx, idx+2, idx+3); + indexData.PushBack( idx ); + indexData.PushBack( idx+1 ); + indexData.PushBack( idx+2 ); + indexData.PushBack( idx ); + indexData.PushBack( idx+2 ); + indexData.PushBack( idx+3 ); } - meshData.SetData(vertices, faces, bones, mCustomMaterial); - meshData.SetHasColor(false); - meshData.SetHasTextureCoords(true); -} + Property::Map vertexFormat; + vertexFormat["aIndex"] = Property::FLOAT; + vertexFormat["aPosition"] = Property::VECTOR2; + vertexFormat["aTexCoord"] = Property::VECTOR2; + PropertyBuffer vertices = PropertyBuffer::New( PropertyBuffer::STATIC, vertexFormat, numVertex ); + vertices.SetData( &vertexData[0] ); -void BubbleEmitter::SetBubbleParameter( BubbleEffect& effect, unsigned int curUniform, - const Vector2& emitPosition, const Vector2& displacement ) -{ - int halfRange = displacement.x / 2; - Vector2 randomVec(rand()%static_cast(displacement.x) - halfRange, rand()%static_cast(displacement.y) - halfRange); - if(randomVec.y > 0.0f) - { - randomVec.y *= 0.33f; - } + Property::Map indexFormat; + indexFormat["indices"] = Property::UNSIGNED_INTEGER; + PropertyBuffer indices = PropertyBuffer::New( PropertyBuffer::STATIC, indexFormat, numIndex ); + indices.SetData( &indexData[0] ); - Vector4 startAndEndPos( emitPosition.x, emitPosition.y, emitPosition.x+randomVec.x, emitPosition.y+randomVec.y ); - effect.SetStartAndEndPosition( curUniform, startAndEndPos ); + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( vertices ); + geometry.SetIndexBuffer( indices ); - effect.SetPercentage( curUniform, 0.f); + return geometry; } -void BubbleEmitter::SetBubbleParameter( BubbleEffect& effect, unsigned int curUniform, +void BubbleEmitter::SetBubbleParameter( BubbleActorPtr bubbleActor, unsigned int curUniform, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ) { Vector2 dir(direction); @@ -390,19 +351,9 @@ void BubbleEmitter::SetBubbleParameter( BubbleEffect& effect, unsigned int curUn randomVec.y *= 0.33f; } Vector4 startAndEndPos( emitPosition.x, emitPosition.y, emitPosition.x+randomVec.x, emitPosition.y+randomVec.y ); - effect.SetStartAndEndPosition( curUniform, startAndEndPos ); + bubbleActor->SetStartAndEndPosition( curUniform, startAndEndPos ); - effect.SetPercentage( curUniform, 0.f); -} - -void BubbleEmitter::OnExplosionFinished( Animation& source ) -{ - Restore(); -} - -float BubbleEmitter::RandomRange(float f0, float f1) -{ - return f0 + (rand() & 0xfff) * (f1-f0) * (1.0f/4095.0f); + bubbleActor->SetPercentage( curUniform, 0.f); } } // namespace Internal diff --git a/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.h b/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.h index 6cac58b..135a634 100644 --- a/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.h +++ b/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.h @@ -2,7 +2,7 @@ #define __DALI_TOOLKIT_INTERNAL_BUBBLE_EMITTER_IMPL_H__ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2015 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,13 +22,15 @@ #include #include #include +#include #include #include +#include +#include // INTERNAL INCLUDES #include #include -#include namespace Dali { @@ -39,6 +41,9 @@ namespace Toolkit namespace Internal { +class BubbleActor; +typedef IntrusivePtr BubbleActorPtr; + /** * BubbleEmitter implementation class. */ @@ -95,11 +100,6 @@ public: void EmitBubble( Animation& animation, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ); /** - * @copydoc Toolkit::BubbleEmitter::StartExplosion - */ - void StartExplosion( float duration, float multiple ); - - /** * @copydoc Toolkit::BubbleEmitter::Restore */ void Restore(); @@ -125,6 +125,13 @@ private: void OnInitialize(); /** + * Create the geometry of a mesh. + * @param[in] numOfPatch The triangle number in the mesh is 2*numOfPatch; two triangles for each bubble. + * @return The mesh geometry. + */ + Geometry CreateGeometry( unsigned int numOfPatch ); + + /** * Callback function of the finished signal of off-screen render task. * @param[in] source The render task used to create the color adjusted background image. */ @@ -136,98 +143,41 @@ private: void OnContextRegained(); /** - * Generate the material object which is attached to the meshActor to describe its color, texture, texture mapping mode etc. - */ - void GenMaterial(); - - /** - * Add a vertex to the mesh data. - * @param[in] vertices The collection of vertices. - * @param[in] XYZ The vertex position coordinates. - * @param[in] UV The vertex texture coordinate. - */ - void AddVertex(MeshData::VertexContainer& vertices, Vector3 XYZ, Vector2 UV); - - /** - * Add a triangle to the mesh data. - * @param[in] faces The collection od FaceIndex items. - * @param[in] v0 The index of the first point of the triangle. - * @param[in] v1 The index of the second point of the triangle. - * @param[in] v3 The index of the first point of the triangle. - */ - void AddTriangle(MeshData::FaceIndices& faces,size_t v0, size_t v1, size_t v2); - - /** - * Create a new mesh. - * @param[in] meshData The MeshData object which encompasses all the data required to describe and render the 3D mesh. - * @param[in] numberOfBubble The triangle number in the meshData is 2*numOfBubble; two triangles for each bubble - */ - void ConstructBubbleMesh( MeshData& meshData, unsigned int numOfBubble); - - /** - * Set the uniform values to the shader effect to emit a bubble - * @param[in] effect The BubbleEffect to render the current bubble - * @param[in] curUniform The index of the uniform array in the shader - * @param[in] emitPosition The start position of the bubble movement. - * @param[in] displacement The displacement used to bound the moving distance of the bubble. - */ - void SetBubbleParameter( BubbleEffect& effect, unsigned int curUniform, - const Vector2& emitPosition, const Vector2& displacement ); - - /** * Set the uniform values to the shader effect to emit a bubble - * @param[in] effect The BubbleEffect to render the current bubble + * @param[in] bubbleActor The BubbleActor to render the current bubble * @param[in] curUniform The index of the uniform array in the shader * @param[in] emitPosition The start position of the bubble movement. * @param[in] direction The direction used to constrain the bubble to move in an adjacent direction around it. * @param[in] displacement The displacement used to bound the moving distance of the bubble. */ - void SetBubbleParameter( BubbleEffect& effect, unsigned int curUniform, + void SetBubbleParameter( BubbleActorPtr bubbleActor, unsigned int curUniform, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ); - /** - * Callback function of the explosion animation finished signal to reset the shader parameters - * @param[in] source The explosion animation. - */ - void OnExplosionFinished( Animation& source ); - - /** - * Return a random value between the given interval. - * @param[in] f0 The low bound - * @param[in] f1 The up bound - * @return A random value between the given interval - */ - float RandomRange(float f0, float f1); - private: - Vector2 mMovementArea; ///< The size of the bubble moving area, usually the same size as the background image actor. - Image mShapeImage; ///< The alpha channnel of this texture defines the bubble shape. Actor mBubbleRoot; /// mMesh; ///< The mesh vector, each mesh is used to create a meshActor which applies a BubbleEffect. - std::vector mMeshActor; ///< The meshActor vector, its size is mNumShader. - MeshActor mMeshActorForNoise; ///< An Extra mesh data to emit bubbles which emit bubble in totally random angle. - Material mCustomMaterial; ///< The material object which is attached to the meshActor to describe its color, texture, texture mapping mode etc. - - std::vector mEffect; ///< The bubbleEffect vector, corresponding to the mMeshActoe vector. - BubbleEffect mEffectForNoise; ///< The extra bubbleEffect, corresponding to the mMeshActorForNoise. - - unsigned int mCurrentUniform; ///< Keep track of the uniform index for the newly emitted bubble - - Vector3 mHSVDelta; ///< The HSV difference used to adjust the background image color. + Image mShapeImage; ///< The alpha channnel of this texture defines the bubble shape. Image mBackgroundImage; ///< The original background image FrameBufferImage mEffectImage; ///< The image stores the adjusted color of the background image.The bubbles pick color from this image. CameraActor mCameraActor; ///< The render task views the scene from the perspective of this actor. + Sampler mSamplerBackground; ///< The sampler which provides the background image to material + Sampler mSamplerBubbleShape; ///< The sampler which provides the bubble shape image to material + Geometry mMeshGeometry; ///< The mesh geometry which contains the vertices and indices data + Material mMaterial; ///< The material which controls the bubble display + std::vector mBubbleActors; ///< The meshActor vector, its size is mNumShader. + + Vector2 mMovementArea; ///< The size of the bubble moving area, usually the same size as the background image actor. + Vector2 mBubbleSizeRange; ///< The size range of the bubbles; x component is the low bound, and y component is the up bound. + Vector3 mHSVDelta; ///< The HSV difference used to adjust the background image color. + + unsigned int mNumBubblePerActor; ///< How many bubbles for each BubbleActor. + unsigned int mNumActor; ///< How many BubbleActors are used. unsigned int mDensity; ///< How many bubbles will emit at each time, they are controlled by same uniforms in the shader. + unsigned int mTotalNumOfBubble; ///< mNumBubblePerShader*mNumShader. + unsigned int mCurrentBubble; ///< Keep track of the index for the newly emitted bubble + + bool mRenderTaskRunning; ///< If the background render task is currently running }; diff --git a/dali-toolkit/internal/controls/bubble-effect/color-adjuster.h b/dali-toolkit/internal/controls/bubble-effect/color-adjuster.h new file mode 100644 index 0000000..8e24326 --- /dev/null +++ b/dali-toolkit/internal/controls/bubble-effect/color-adjuster.h @@ -0,0 +1,94 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_COLOR_ADJUSTER_H_ +#define __DALI_TOOLKIT_INTERNAL_COLOR_ADJUSTER_H_ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** +* Creates a new ColorAdjuster effect. +* ColorAdjuster is a custom shader effect to adjust the image color in HSV space. +* @param[in] hsvDelta The color difference to apply to the HSV channel. +* @param[in] ignoreAlpha If true, the result color will be opaque even though source has alpha value +* @return A handle to a newly allocated Dali resource. +*/ +inline ShaderEffect CreateColorAdjuster( const Vector3& hsvDelta, bool ignoreAlpha = false ) +{ + std::string fragmentShader = DALI_COMPOSE_SHADER( + precision highp float;\n + uniform vec3 uHSVDelta;\n + uniform float uIgnoreAlpha;\n + float rand(vec2 co) \n + {\n + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); \n} + \n + vec3 rgb2hsv(vec3 c)\n + {\n + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n + \n + float d = q.x - min(q.w, q.y);\n + float e = 1.0e-10;\n + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n + }\n + vec3 hsv2rgb(vec3 c)\n + {\n + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n + }\n + void main() {\n + vec4 color = texture2D(sTexture, vTexCoord); \n + vec3 hsvColor = rgb2hsv( color.rgb );\n + // modify the hsv Value + hsvColor += uHSVDelta * rand(vTexCoord); \n + // if the new vale exceeds one, then decrease it + hsvColor -= max(hsvColor*2.0 - vec3(2.0), 0.0);\n + // if the new vale drops below zero, then increase it + hsvColor -= min(hsvColor*2.0, 0.0);\n + color.rgb = hsv2rgb( hsvColor ); \n + // uIgnoreAlpha decide the result alpha will be 1.0 or source's alpha + color.a += uIgnoreAlpha;\n + gl_FragColor = color; \n + }\n + ); + + ShaderEffect shaderEffect = ShaderEffect::New("", fragmentShader); + shaderEffect.SetUniform( "uHSVDelta", hsvDelta ); + shaderEffect.SetUniform( "uIgnoreAlpha", ignoreAlpha?1.0f:0.0f ); + + return shaderEffect; +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + +#endif /* __DALI_TOOLKIT_INTERNAL_COLOR_ADJUSTER_H_ */ diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 7eaa5cd..e9ea95a 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -14,6 +14,8 @@ toolkit_src_files = \ $(toolkit_src_dir)/builder/replacement.cpp \ $(toolkit_src_dir)/controls/alignment/alignment-impl.cpp \ $(toolkit_src_dir)/controls/bloom-view/bloom-view-impl.cpp \ + $(toolkit_src_dir)/controls/bubble-effect/bubble-emitter-impl.cpp \ + $(toolkit_src_dir)/controls/bubble-effect/bubble-actor.cpp \ $(toolkit_src_dir)/controls/buttons/button-impl.cpp \ $(toolkit_src_dir)/controls/buttons/check-box-button-impl.cpp \ $(toolkit_src_dir)/controls/buttons/push-button-impl.cpp \ diff --git a/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.cpp b/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.cpp index b719b22..9c1fa2c 100644 --- a/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.cpp +++ b/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.cpp @@ -109,11 +109,6 @@ void BubbleEmitter::EmitBubble( Animation& animation, const Vector2& emitPositio GetImpl(*this).EmitBubble( animation, emitPosition, direction, displacement ); } -void BubbleEmitter::StartExplosion( float duration, float multiple ) -{ - GetImpl(*this).StartExplosion( duration, multiple ); -} - void BubbleEmitter::Restore() { GetImpl(*this).Restore(); diff --git a/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.h b/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.h index 0141454..461e564 100644 --- a/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.h +++ b/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.h @@ -131,9 +131,9 @@ public: /** * @brief Set the density of the bubble. * - * Ideally every bubble's moving track is controlled by different uniforms in BubbleEffect shaders. + * Ideally every bubble's moving track is controlled by different uniforms in shader. * To increase the density, 'density' number of bubbles are sharing one group of uniforms, but with random offsets between these bubbles. - * The available density is one to nine. The default density is five. + * The available densities are one to nine only. The default value is five. * By set the density bigger than one, instead of emit one bubble each time, a 'density' number of bubbles are emitted. * @param[in] density The density of the bubble. */ @@ -158,14 +158,6 @@ public: void EmitBubble( Animation& animation, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ); /** - * @brief Start an animation to enlarge every activated bubble's size and moving speed. - * - * @param[in] duration The duration of the animation - * @param[in] multiple The bubble size and moving speed will be increased gradually to multiple speed during the animation. - */ - void StartExplosion( float duration, float multiple ); - - /** * @brief Reset all the parameters controlling the bubbles after animation. */ void Restore(); diff --git a/dali-toolkit/public-api/file.list b/dali-toolkit/public-api/file.list index 9493cef..f275660 100755 --- a/dali-toolkit/public-api/file.list +++ b/dali-toolkit/public-api/file.list @@ -7,6 +7,7 @@ public_api_src_files = \ $(public_api_src_dir)/controls/control-impl.cpp \ $(public_api_src_dir)/controls/control.cpp \ $(public_api_src_dir)/controls/alignment/alignment.cpp \ + $(public_api_src_dir)/controls/bubble-effect/bubble-emitter.cpp \ $(public_api_src_dir)/controls/buttons/button.cpp \ $(public_api_src_dir)/controls/buttons/check-box-button.cpp \ $(public_api_src_dir)/controls/buttons/push-button.cpp \