Commit 2e58e3edad52dc74c6d6c74addf40d8f14f2e455

Authored by Kimmo Hoikka
Committed by Gerrit Code Review
2 parents bc6d9b4b 17730e15

Merge "Metaballs demos" into devel/master

com.samsung.dali-demo.xml
... ... @@ -34,9 +34,15 @@
34 34 <ui-application appid="item-view.example" exec="/usr/apps/com.samsung.dali-demo/bin/item-view.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
35 35 <label>Item View</label>
36 36 </ui-application>
37   - <ui-application appid="magnifier.example" exec="/usr/apps/com.samsung.dali-demo/bin/magnifier.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
38   - <label>Magnifier</label>
39   - </ui-application>
  37 + <ui-application appid="magnifier.example" exec="/usr/apps/com.samsung.dali-demo/bin/magnifier.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
  38 + <label>Magnifier</label>
  39 + </ui-application>
  40 + <ui-application appid="metaball-explosion.example" exec="/usr/apps/com.samsung.dali-demo/bin/metaball-explosion.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
  41 + <label>Metaball Explosion</label>
  42 + </ui-application>
  43 + <ui-application appid="metaball-refrac.example" exec="/usr/apps/com.samsung.dali-demo/bin/metaball-refrac.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
  44 + <label>Metaball Refractions</label>
  45 + </ui-application>
40 46 <ui-application appid="motion-blur.example" exec="/usr/apps/com.samsung.dali-demo/bin/motion-blur.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
41 47 <label>Motion Blur</label>
42 48 </ui-application>
... ...
demo/dali-demo.cpp
... ... @@ -63,6 +63,8 @@ int main(int argc, char **argv)
63 63 demo.AddExample(Example("logging.example", DALI_DEMO_STR_TITLE_LOGGING));
64 64 demo.AddExample(Example("mesh-morph.example", DALI_DEMO_STR_TITLE_MESH_MORPH));
65 65 demo.AddExample(Example("mesh-sorting.example", DALI_DEMO_STR_TITLE_MESH_SORTING));
  66 + demo.AddExample(Example("metaball-explosion.example", DALI_DEMO_STR_TITLE_METABALL_EXPLOSION));
  67 + demo.AddExample(Example("metaball-refrac.example", DALI_DEMO_STR_TITLE_METABALL_REFRAC));
66 68 demo.AddExample(Example("textured-mesh.example", DALI_DEMO_STR_TITLE_TEXTURED_MESH));
67 69 demo.AddExample(Example("line-mesh.example", DALI_DEMO_STR_TITLE_LINE_MESH));
68 70 demo.AddExample(Example("gradients.example", DALI_DEMO_STR_TITLE_COLOR_GRADIENT));
... ...
examples/metaball-explosion/metaball-explosion-example.cpp 0 → 100644
  1 +/*
  2 + * Copyright (c) 2014 Samsung Electronics Co., Ltd.
  3 + *
  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
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  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.
  15 + *
  16 + */
  17 +
  18 +//External includes
  19 +#include <cstdio>
  20 +#include <string>
  21 +
  22 +//Internal includes
  23 +#include <dali/dali.h>
  24 +#include <dali/devel-api/rendering/renderer.h>
  25 +#include <dali-toolkit/dali-toolkit.h>
  26 +
  27 +#include "shared/view.h"
  28 +
  29 +using namespace Dali;
  30 +using namespace Dali::Toolkit;
  31 +
  32 +namespace
  33 +{
  34 +const char * const BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-2.jpg" );
  35 +const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
  36 +
  37 +const float GRAVITY_X(0);
  38 +const float GRAVITY_Y(-0.09);
  39 +}
  40 +
  41 +#define METABALL_NUMBER 12
  42 +
  43 +
  44 +const char*const METABALL_VERTEX_SHADER = DALI_COMPOSE_SHADER (
  45 + attribute mediump vec2 aPosition;\n
  46 + attribute mediump vec2 aTexture;\n
  47 + uniform mediump mat4 uMvpMatrix;\n
  48 + uniform mediump vec3 uSize;\n
  49 + uniform lowp vec4 uColor;\n
  50 + varying mediump vec2 vTexCoord;\n
  51 +
  52 + void main()\n
  53 + {\n
  54 + vTexCoord = aTexture;\n
  55 + mediump vec4 vertexPosition = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n
  56 + gl_Position = uMvpMatrix * vertexPosition;\n
  57 + }\n
  58 +);
  59 +
  60 +
  61 +const char*const METABALL_FRAG_SHADER = DALI_COMPOSE_SHADER (
  62 + precision mediump float;\n
  63 + varying vec2 vTexCoord;\n
  64 + uniform vec2 uPositionMetaball;\n
  65 + uniform vec2 uPositionVar;\n
  66 + uniform vec2 uGravityVector;\n
  67 + uniform float uRadius;\n
  68 + uniform float uRadiusVar;\n
  69 + void main()\n
  70 + {\n
  71 + vec2 adjustedCoords = vTexCoord * 2.0 - 1.0;\n
  72 + vec2 finalMetaballPosition = uPositionMetaball + uGravityVector + uPositionVar;\n
  73 + \n
  74 + float finalRadius = uRadius + uRadiusVar;\n
  75 + vec2 distanceVec = adjustedCoords - finalMetaballPosition;\n
  76 + float result = dot(distanceVec, distanceVec);\n
  77 + float color = inversesqrt(result) * finalRadius;\n
  78 + \n
  79 + gl_FragColor = vec4(color,color,color,1.0);\n
  80 + }\n
  81 +);
  82 +
  83 +const char*const REFRACTION_FRAG_SHADER = DALI_COMPOSE_SHADER (
  84 + precision highp float;\n
  85 + varying vec2 vTexCoord;\n
  86 + uniform sampler2D sTexture;\n
  87 + uniform sampler2D sEffect;\n
  88 + uniform vec2 uPositionMetaball;\n
  89 + void main()\n
  90 + {\n
  91 + vec2 zoomCoords;\n
  92 + vec3 normal = vec3(0.0,0.0,1.0);\n
  93 + vec2 fakePos = vec2(0.0,0.0);\n
  94 + vec3 color = vec3(1.0, 1.0, 1.0);
  95 + float ambient = 0.2;
  96 + \n
  97 + vec4 metaColor = texture2D(sEffect, vTexCoord);\n
  98 + \n
  99 + vec2 adjustedCoords = vTexCoord.xy * vec2(2.0) - vec2(1.0);\n
  100 + fakePos = adjustedCoords.xy - vec2(uPositionMetaball.x, -uPositionMetaball.y);
  101 + float len = length(fakePos) + 0.01;\n
  102 + vec3 colorPos = vec3(0,0,1);
  103 + \n
  104 + if (metaColor.r > 0.85)\n
  105 + {\n
  106 + zoomCoords = ((vTexCoord - 0.5) * 0.9);\n
  107 + zoomCoords = zoomCoords + 0.5;\n
  108 + \n
  109 + float interpNormal = mix(0.7, 1.0, (metaColor.r - 0.85) * 4.);\n
  110 + normal.xyz = vec3(fakePos.x * (1.0 - interpNormal) / len, fakePos.y * (1.0 - interpNormal) / len, interpNormal);\n
  111 + normal.xyz = normalize(normal.xyz);\n
  112 + color = vec3(0.65, 1.0, 0);\n
  113 + colorPos = vec3(fakePos.x,fakePos.y,0);
  114 + }\n
  115 + else if (metaColor.r > 0.75)\n
  116 + {\n
  117 + float interpolation = mix(0.9, 1.15, (0.85 - metaColor.r) * 10.0);\n
  118 + zoomCoords = ((vTexCoord - 0.5) * interpolation);\n
  119 + zoomCoords = zoomCoords + 0.5;\n
  120 + \n
  121 + float interpNormal = mix(0.7, 0.0, (0.85 - metaColor.r) * 10.0);\n
  122 + normal.xyz = vec3(fakePos.x * (1.0 - interpNormal) / len, fakePos.y * (1.0 - interpNormal) / len, interpNormal);\n
  123 + normal.xyz = normalize(normal.xyz);\n
  124 + color = vec3(0.65, 1.0, 0);\n
  125 + colorPos = vec3(fakePos.x,fakePos.y,0);
  126 + }\n
  127 + else\n
  128 + {\n
  129 + zoomCoords = vTexCoord;\n
  130 + normal = vec3(0,0,0);\n
  131 + ambient = 0.5;\n
  132 + }\n
  133 + \n
  134 + vec3 lightPosition = vec3(-750.0,-1000.0,2000.0);\n
  135 + vec3 vertex = vec3(adjustedCoords.x,adjustedCoords.y,0.0);\n
  136 + \n
  137 + vec3 vecToLight = normalize( lightPosition - vertex );\n
  138 + \n
  139 + float lightDiffuse = dot( vecToLight, normal );\n
  140 + lightDiffuse = max(0.0,lightDiffuse);\n
  141 + lightDiffuse = lightDiffuse * 0.5 + 0.5;
  142 + \n
  143 + vec3 vertexToEye = vec3(0,0,1) - vertex;\n
  144 + vertexToEye = normalize(vertexToEye);
  145 + vec3 lightReflect = normalize(reflect(-vecToLight, normal));\n
  146 + float specularFactor = max(0.0,dot(vertexToEye, lightReflect));\n
  147 + specularFactor = pow(specularFactor, 32.0) * 0.7;
  148 + \n
  149 + vec4 texColor = texture2D(sTexture, zoomCoords);\n
  150 + gl_FragColor.rgb = texColor.rgb * ambient + color.rgb * texColor.rgb * lightDiffuse + vec3(specularFactor);\n
  151 + gl_FragColor.a = 1.0;
  152 + }\n
  153 + );
  154 +
  155 +const char*const FRAG_SHADER = DALI_COMPOSE_SHADER (
  156 + precision mediump float;\n
  157 + void main()\n
  158 + {\n
  159 + gl_FragColor = texture2D(sTexture, vTexCoord);\n
  160 + }\n
  161 +);
  162 +
  163 +
  164 +struct MetaballInfo
  165 +{
  166 + Actor actor;
  167 + Vector2 position;
  168 + float radius;
  169 + float initRadius;
  170 +
  171 + //new shader stuff
  172 + Property::Index positionIndex;
  173 + Property::Index positionVarIndex;
  174 +};
  175 +
  176 +
  177 +/**************************************************************************/
  178 +/* Demo using Metaballs ***********/
  179 +/* When the metaball is clicked it explodes in different balls ***********/
  180 +/**************************************************************************/
  181 +class MetaballExplosionController : public ConnectionTracker
  182 +{
  183 +public:
  184 + MetaballExplosionController( Application& application );
  185 + ~MetaballExplosionController();
  186 +
  187 + /**
  188 + * Main create function, it creates the metaballs and all the related data
  189 + */
  190 + void Create( Application& app );
  191 +
  192 + /**
  193 + * Touch event function
  194 + */
  195 + bool OnTouch( Actor actor, const TouchEvent& touch );
  196 +
  197 + /**
  198 + * Key event function
  199 + */
  200 + void OnKeyEvent(const KeyEvent& event);
  201 +
  202 +
  203 +private:
  204 + Application& mApplication;
  205 + Vector2 mScreenSize;
  206 +
  207 + Layer mContentLayer;
  208 +
  209 + Image mBackImage;
  210 + FrameBufferImage mMetaballFBO;
  211 +
  212 + Actor mMetaballRoot;
  213 + MetaballInfo mMetaballs[METABALL_NUMBER];
  214 +
  215 + Property::Index mPositionIndex;
  216 + Actor mCompositionActor;
  217 +
  218 + //Motion
  219 + Vector2 mCurrentTouchPosition;
  220 + Vector2 mMetaballPosVariation;
  221 + Vector2 mMetaballPosVariationFrom;
  222 + Vector2 mMetaballPosVariationTo;
  223 + Vector2 mMetaballCenter;
  224 +
  225 + //Animations
  226 + Animation mPositionVarAnimation[METABALL_NUMBER];
  227 +
  228 + int mDispersion;
  229 + Animation mDispersionAnimation[METABALL_NUMBER];
  230 +
  231 + Timer mTimerDispersion;
  232 +
  233 + float mTimeMult;
  234 +
  235 + //Private functions
  236 +
  237 + /**
  238 + * Create a mesh data with the geometry for the metaball rendering
  239 + */
  240 + Geometry CreateGeometry();
  241 +
  242 + /**
  243 + * Create a mesh data with the geometry for the final composition
  244 + */
  245 + Geometry CreateGeometryComposition();
  246 +
  247 + /**
  248 + * Create a mesh actor for the metaballs
  249 + */
  250 + void CreateMetaballActors();
  251 +
  252 + /**
  253 + * Create the render task and FBO to render the metaballs into a texture
  254 + */
  255 + void CreateMetaballImage();
  256 +
  257 + /**
  258 + * Create a mesh image to render the final composition
  259 + */
  260 + void AddRefractionImage();
  261 +
  262 + /**
  263 + * Function to create animations for the small variations of position inside the metaball
  264 + */
  265 + void CreateAnimations();
  266 +
  267 + /**
  268 + * Function to reset metaball state
  269 + */
  270 + void ResetMetaballs(bool resetAnims);
  271 +
  272 + /**
  273 + * Function to create disperse each of the ball that compose the metaball when exploding
  274 + */
  275 + void DisperseBallAnimation(int ball);
  276 +
  277 + /**
  278 + * Function to make metaballs come back to reset position
  279 + */
  280 + void LaunchResetMetaballPosition(Animation &source);
  281 +
  282 + /**
  283 + * Function to set things at the end of the animation
  284 + */
  285 + void EndDisperseAnimation(Animation &source);
  286 +
  287 + /**
  288 + * Function to init dispersion of the metaballs one by one using a timer
  289 + * (so not all the balls begin moving at the same time)
  290 + */
  291 + bool OnTimerDispersionTick();
  292 +
  293 + /**
  294 + * Function to set the actual position of the metaballs when the user clicks the screen
  295 + */
  296 + void SetPositionToMetaballs(Vector2 & metaballCenter);
  297 +};
  298 +
  299 +
  300 +//-----------------------------------------------------------------------------------------------
  301 +//
  302 +// IMPLEMENTATION
  303 +//
  304 +//----------------
  305 +
  306 +MetaballExplosionController::MetaballExplosionController( Application& application )
  307 + : mApplication( application )
  308 +{
  309 + // Connect to the Application's Init signal
  310 + mApplication.InitSignal().Connect( this, &MetaballExplosionController::Create );
  311 +}
  312 +
  313 +MetaballExplosionController::~MetaballExplosionController()
  314 +{
  315 + // Nothing to do here;
  316 +}
  317 +
  318 +void MetaballExplosionController::Create( Application& app )
  319 +{
  320 + Stage stage = Stage::GetCurrent();
  321 +
  322 + stage.KeyEventSignal().Connect(this, &MetaballExplosionController::OnKeyEvent);
  323 +
  324 + mScreenSize = stage.GetSize();
  325 +
  326 + mTimeMult = 1.0f;
  327 +
  328 + stage.SetBackgroundColor(Color::BLACK);
  329 +
  330 + //Set background image for the view
  331 + mBackImage = ResourceImage::New( BACKGROUND_IMAGE );
  332 +
  333 + srand((unsigned)time(0));
  334 +
  335 + //Create internal data
  336 + CreateMetaballActors();
  337 + CreateMetaballImage();
  338 + AddRefractionImage();
  339 +
  340 + CreateAnimations();
  341 +
  342 + mDispersion = 0;
  343 + mTimerDispersion = Timer::New( 150 );
  344 + mTimerDispersion.TickSignal().Connect(this, &MetaballExplosionController::OnTimerDispersionTick);
  345 +
  346 + // Connect the callback to the touch signal on the mesh actor
  347 + stage.GetRootLayer().TouchedSignal().Connect( this, &MetaballExplosionController::OnTouch );
  348 +}
  349 +
  350 +Geometry MetaballExplosionController::CreateGeometry()
  351 +{
  352 + float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
  353 +
  354 + // Create vertices and specify their color
  355 + float xsize = mScreenSize.x * 0.5;
  356 +
  357 + //We create the meshdata for the metaballs
  358 + struct VertexPosition { Vector2 position; };
  359 + struct VertexTexture { Vector2 texture; };
  360 + struct VertexNormal { Vector3 normal; };
  361 +
  362 + VertexPosition vertices[] = {
  363 + { Vector2( -xsize, -xsize * aspect) },
  364 + { Vector2( xsize, -xsize * aspect) },
  365 + { Vector2( -xsize, xsize * aspect) },
  366 + { Vector2( xsize, xsize * aspect) }
  367 + };
  368 +
  369 + VertexTexture textures[] = {
  370 + { Vector2(0.0f, 0.0f) },
  371 + { Vector2(1.0f, 0.0f) },
  372 + { Vector2(0.0f, 1.0f * aspect) },
  373 + { Vector2(1.0f, 1.0f * aspect) }
  374 + };
  375 +
  376 + int indices[] = { 0, 3, 1, 0, 2, 3 };
  377 +
  378 + unsigned int numberOfVertices = sizeof(vertices)/sizeof(VertexPosition);
  379 +
  380 + //Vertices
  381 + Property::Map positionVertexFormat;
  382 + positionVertexFormat["aPosition"] = Property::VECTOR2;
  383 + PropertyBuffer positionVertices = PropertyBuffer::New( positionVertexFormat, numberOfVertices );
  384 + positionVertices.SetData(vertices);
  385 +
  386 + //Textures
  387 + Property::Map textureVertexFormat;
  388 + textureVertexFormat["aTexture"] = Property::VECTOR2;
  389 + PropertyBuffer textureVertices = PropertyBuffer::New( textureVertexFormat, numberOfVertices );
  390 + textureVertices.SetData(textures);
  391 +
  392 + //Indices
  393 + Property::Map indicesVertexFormat;
  394 + indicesVertexFormat["aIndices"] = Property::INTEGER;
  395 + PropertyBuffer indicesToVertices = PropertyBuffer::New( indicesVertexFormat, 6 );
  396 + indicesToVertices.SetData(indices);
  397 +
  398 + // Create the geometry object
  399 + Geometry texturedQuadGeometry = Geometry::New();
  400 + texturedQuadGeometry.AddVertexBuffer( positionVertices );
  401 + texturedQuadGeometry.AddVertexBuffer( textureVertices );
  402 +
  403 + texturedQuadGeometry.SetIndexBuffer ( indicesToVertices );
  404 +
  405 + return texturedQuadGeometry;
  406 +}
  407 +
  408 +Geometry MetaballExplosionController::CreateGeometryComposition()
  409 +{
  410 + float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
  411 +
  412 + // Create vertices and specify their color
  413 + float xsize = mScreenSize.x * 0.5;
  414 +
  415 + //We create the meshdata for the metaballs
  416 + struct VertexPosition { Vector2 position; };
  417 + struct VertexTexture { Vector2 texture; };
  418 + struct VertexNormal { Vector3 normal; };
  419 +
  420 + VertexPosition vertices[] = {
  421 + { Vector2( -xsize, -xsize * aspect) },
  422 + { Vector2( xsize, -xsize * aspect) },
  423 + { Vector2( -xsize, xsize * aspect) },
  424 + { Vector2( xsize, xsize * aspect) }
  425 + };
  426 +
  427 + VertexTexture textures[] = {
  428 + { Vector2(0.0f, 0.0f) },
  429 + { Vector2(1.0f, 0.0f) },
  430 + { Vector2(0.0f, 1.0f) },
  431 + { Vector2(1.0f, 1.0f) }
  432 + };
  433 +
  434 + int indices[] = { 0, 3, 1, 0, 2, 3 };
  435 +
  436 + unsigned int numberOfVertices = sizeof(vertices)/sizeof(VertexPosition);
  437 +
  438 + //Vertices
  439 + Property::Map positionVertexFormat;
  440 + positionVertexFormat["aPosition"] = Property::VECTOR2;
  441 + PropertyBuffer positionVertices = PropertyBuffer::New( positionVertexFormat, numberOfVertices );
  442 + positionVertices.SetData(vertices);
  443 +
  444 + //Textures
  445 + Property::Map textureVertexFormat;
  446 + textureVertexFormat["aTexture"] = Property::VECTOR2;
  447 + PropertyBuffer textureVertices = PropertyBuffer::New( textureVertexFormat, numberOfVertices );
  448 + textureVertices.SetData(textures);
  449 +
  450 + //Indices
  451 + Property::Map indicesVertexFormat;
  452 + indicesVertexFormat["aIndices"] = Property::INTEGER;
  453 + PropertyBuffer indicesToVertices = PropertyBuffer::New( indicesVertexFormat, 6 );
  454 + indicesToVertices.SetData(indices);
  455 +
  456 + // Create the geometry object
  457 + Geometry texturedQuadGeometry = Geometry::New();
  458 + texturedQuadGeometry.AddVertexBuffer( positionVertices );
  459 + texturedQuadGeometry.AddVertexBuffer( textureVertices );
  460 +
  461 + texturedQuadGeometry.SetIndexBuffer ( indicesToVertices );
  462 +
  463 + return texturedQuadGeometry;
  464 +}
  465 +
  466 +float randomNumber(float lowest, float highest)
  467 +{
  468 + float range=(highest-lowest);
  469 + return lowest+range*rand()/RAND_MAX;
  470 +}
  471 +
  472 +void MetaballExplosionController::CreateMetaballActors()
  473 +{
  474 + //Create the shader for the metaballs
  475 + Shader shader = Shader::New( METABALL_VERTEX_SHADER, METABALL_FRAG_SHADER );
  476 +
  477 + Material material = Material::New( shader );
  478 + material.SetBlendMode(BlendingMode::ON );
  479 + material.SetBlendFunc(BlendingFactor::ONE, BlendingFactor::ONE, BlendingFactor::ONE, BlendingFactor::ONE);
  480 +
  481 + Geometry metaballGeom = CreateGeometry();
  482 +
  483 + //Initialization of each of the metaballs
  484 + for( int i = 0; i < METABALL_NUMBER; i++ )
  485 + {
  486 + mMetaballs[i].position = Vector2(0.0f, 0.0f);
  487 + mMetaballs[i].radius = mMetaballs[i].initRadius = randomNumber(0.025f,0.035f);
  488 +
  489 + mMetaballs[i].actor = Actor::New( );
  490 + mMetaballs[i].actor.SetName("Metaball");
  491 + mMetaballs[i].actor.SetScale( 1.0f );
  492 + mMetaballs[i].actor.SetParentOrigin( ParentOrigin::CENTER );
  493 +
  494 + Renderer renderer = Renderer::New( metaballGeom, material );
  495 + mMetaballs[i].actor.AddRenderer( renderer );
  496 +
  497 + mMetaballs[i].positionIndex = mMetaballs[i].actor.RegisterProperty( "uPositionMetaball", mMetaballs[i].position );
  498 +
  499 + mMetaballs[i].positionVarIndex = mMetaballs[i].actor.RegisterProperty( "uPositionVar", Vector2(0.f,0.f) );
  500 +
  501 + mMetaballs[i].actor.RegisterProperty( "uGravityVector", Vector2(randomNumber(-0.2,0.2),randomNumber(-0.2,0.2)) );
  502 +
  503 + mMetaballs[i].actor.RegisterProperty( "uRadius", mMetaballs[i].radius );
  504 +
  505 + mMetaballs[i].actor.RegisterProperty( "uRadiusVar", 0.f );
  506 +
  507 + mMetaballs[i].actor.SetSize(400, 400);
  508 + }
  509 +
  510 + //Root creation
  511 + mMetaballRoot = Actor::New();
  512 + mMetaballRoot.SetParentOrigin( ParentOrigin::CENTER );
  513 + for( int i = 0; i < METABALL_NUMBER; i++ )
  514 + {
  515 + mMetaballRoot.Add( mMetaballs[i].actor );
  516 + }
  517 +
  518 + //Initialization of variables related to metaballs
  519 + mMetaballPosVariation = Vector2(0,0);
  520 + mMetaballPosVariationFrom = Vector2(0,0);
  521 + mMetaballPosVariationTo = Vector2(0,0);
  522 + mCurrentTouchPosition = Vector2(0,0);
  523 +}
  524 +
  525 +void MetaballExplosionController::CreateMetaballImage()
  526 +{
  527 + //We create an FBO and a render task to create to render the metaballs with a fragment shader
  528 + Stage stage = Stage::GetCurrent();
  529 + mMetaballFBO = FrameBufferImage::New(mScreenSize.x, mScreenSize.y, Pixel::RGBA8888, RenderBuffer::COLOR_DEPTH);
  530 +
  531 +
  532 + stage.Add(mMetaballRoot);
  533 +
  534 + //Creation of the render task used to render the metaballs
  535 + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
  536 + RenderTask task = taskList.CreateTask();
  537 + task.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
  538 + task.SetSourceActor( mMetaballRoot );
  539 + task.SetExclusive(true);
  540 + task.SetClearColor( Color::BLACK );
  541 + task.SetClearEnabled( true );
  542 + task.SetTargetFrameBuffer( mMetaballFBO );
  543 +}
  544 +
  545 +void MetaballExplosionController::AddRefractionImage()
  546 +{
  547 + //Create Gaussian blur for the rendered image
  548 + FrameBufferImage fbo;
  549 + fbo = FrameBufferImage::New( mScreenSize.x, mScreenSize.y, Pixel::RGBA8888, RenderBuffer::COLOR_DEPTH);
  550 +
  551 + GaussianBlurView gbv = GaussianBlurView::New(5, 2.0f, Pixel::RGBA8888, 0.5f, 0.5f, true);
  552 + gbv.SetBackgroundColor(Color::TRANSPARENT);
  553 + gbv.SetUserImageAndOutputRenderTarget( mMetaballFBO, fbo );
  554 + gbv.SetSize(mScreenSize.x, mScreenSize.y);
  555 + Stage::GetCurrent().Add(gbv);
  556 + gbv.Activate();
  557 +
  558 + //Create new shader
  559 + Shader shader = Shader::New( METABALL_VERTEX_SHADER, REFRACTION_FRAG_SHADER );
  560 + //Create new material
  561 + Material material = Material::New( shader );
  562 +
  563 + //Add Textures
  564 + material.AddTexture(mBackImage, "sTexture");
  565 + material.AddTexture(fbo, "sEffect");
  566 +
  567 + //Create geometry
  568 + Geometry metaballGeom = CreateGeometryComposition();
  569 +
  570 + Renderer mRenderer = Renderer::New( metaballGeom, material );
  571 +
  572 + mCompositionActor = Actor::New( );
  573 + mCompositionActor.SetParentOrigin(ParentOrigin::CENTER);
  574 + mCompositionActor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
  575 + mCompositionActor.SetSize(mScreenSize.x, mScreenSize.y);
  576 +
  577 + mCompositionActor.AddRenderer( mRenderer );
  578 +
  579 + Vector2 metaballCenter(0.0,0);
  580 + metaballCenter.x = metaballCenter.x * 0.5;
  581 + metaballCenter.y = metaballCenter.y * 0.5;
  582 +
  583 + mPositionIndex = mCompositionActor.RegisterProperty( "uPositionMetaball", metaballCenter );
  584 +
  585 + SetPositionToMetaballs(metaballCenter);
  586 +
  587 + mCompositionActor.SetSize(mScreenSize.x, mScreenSize.y);
  588 +
  589 + Stage stage = Stage::GetCurrent();
  590 + stage.Add( mCompositionActor );
  591 +}
  592 +
  593 +void MetaballExplosionController::CreateAnimations()
  594 +{
  595 + Vector2 direction;
  596 +
  597 + for( int i = 0; i < METABALL_NUMBER; i++ )
  598 + {
  599 + float key;
  600 + KeyFrames keySinCosVariation = KeyFrames::New();
  601 + Vector2 sinCosVariation(0,0);
  602 +
  603 + direction.x = randomNumber(-100.f,100.f);
  604 + direction.y = randomNumber(-100.f,100.f);
  605 +
  606 + direction.Normalize();
  607 + direction *= 0.1f;
  608 +
  609 + for( int j = 0; j < 360; j++ )
  610 + {
  611 + sinCosVariation.x = sin(j * Math::PI/180.f) * direction.x;
  612 + sinCosVariation.y = cos(j * Math::PI/180.f) * direction.y;
  613 + key = j/360.f;
  614 + keySinCosVariation.Add(key, sinCosVariation);
  615 + }
  616 +
  617 + mPositionVarAnimation[i] = Animation::New(3.f);
  618 + mPositionVarAnimation[i].AnimateBetween(Property( mMetaballs[i].actor, mMetaballs[i].positionVarIndex ), keySinCosVariation);
  619 + mPositionVarAnimation[i].SetLooping( true );
  620 + mPositionVarAnimation[i].Play();
  621 + }
  622 +}
  623 +
  624 +void MetaballExplosionController::ResetMetaballs(bool resetAnims)
  625 +{
  626 + for( int i = 0; i < METABALL_NUMBER; i++ )
  627 + {
  628 + if (mDispersionAnimation[i])
  629 + mDispersionAnimation[i].Clear();
  630 +
  631 + mMetaballs[i].position = Vector2(0.0f, 0.0f);
  632 + mMetaballs[i].actor.SetProperty(mMetaballs[i].positionIndex, mMetaballs[i].position);
  633 + }
  634 + mTimerDispersion.Stop();
  635 + mDispersion = 0;
  636 +
  637 + mCompositionActor.SetProperty( mPositionIndex, Vector2(0,0) );
  638 +}
  639 +
  640 +void MetaballExplosionController::DisperseBallAnimation(int ball)
  641 +{
  642 + Vector2 position;
  643 + position.x = randomNumber(-1.5f,1.5f);
  644 + position.y = randomNumber(-1.5f,1.5f);
  645 +
  646 + mDispersionAnimation[ball] = Animation::New(2.0f * mTimeMult);
  647 + mDispersionAnimation[ball].AnimateTo( Property(mMetaballs[ball].actor, mMetaballs[ball].positionIndex), position);
  648 + mDispersionAnimation[ball].Play();
  649 +
  650 + if( ball == METABALL_NUMBER - 1 )
  651 + mDispersionAnimation[ball].FinishedSignal().Connect( this, &MetaballExplosionController::LaunchResetMetaballPosition );
  652 +}
  653 +
  654 +void MetaballExplosionController::LaunchResetMetaballPosition(Animation &source)
  655 +{
  656 + for( int i = 0; i < METABALL_NUMBER; i++ )
  657 + {
  658 + mDispersionAnimation[i] = Animation::New(1.5f + i*0.25f*mTimeMult);
  659 + mDispersionAnimation[i].AnimateTo(Property(mMetaballs[i].actor, mMetaballs[i].positionIndex), Vector2(0,0));
  660 + mDispersionAnimation[i].Play();
  661 +
  662 + if( i == METABALL_NUMBER - 1 )
  663 + mDispersionAnimation[i].FinishedSignal().Connect( this, &MetaballExplosionController::EndDisperseAnimation );
  664 + }
  665 +}
  666 +
  667 +void MetaballExplosionController::EndDisperseAnimation(Animation &source)
  668 +{
  669 + mCompositionActor.SetProperty( mPositionIndex, Vector2(0,0) );
  670 +}
  671 +
  672 +bool MetaballExplosionController::OnTimerDispersionTick()
  673 +{
  674 + if( mDispersion < METABALL_NUMBER )
  675 + {
  676 + DisperseBallAnimation(mDispersion);
  677 + mDispersion++;
  678 + }
  679 + return true;
  680 +}
  681 +
  682 +void MetaballExplosionController::SetPositionToMetaballs(Vector2 & metaballCenter)
  683 +{
  684 + //We set the position for the metaballs based on click position
  685 + for( int i = 0; i < METABALL_NUMBER; i++ )
  686 + {
  687 + mMetaballs[i].position = metaballCenter;
  688 + mMetaballs[i].actor.SetProperty(mMetaballs[i].positionIndex, mMetaballs[i].position);
  689 + }
  690 +
  691 + mCompositionActor.SetProperty( mPositionIndex, metaballCenter );
  692 +}
  693 +
  694 +bool MetaballExplosionController::OnTouch( Actor actor, const TouchEvent& touch )
  695 +{
  696 + const TouchPoint &point = touch.GetPoint(0);
  697 + float aspectR = mScreenSize.y / mScreenSize.x;
  698 +
  699 + switch( point.state )
  700 + {
  701 + case TouchPoint::Down:
  702 + {
  703 + ResetMetaballs(true);
  704 +
  705 + Vector2 metaballCenter = Vector2((point.screen.x / mScreenSize.x) - 0.5, (aspectR * (mScreenSize.y - point.screen.y) / mScreenSize.y) - 0.5) * 2.0;
  706 + SetPositionToMetaballs(metaballCenter);
  707 +
  708 + break;
  709 + }
  710 + case TouchPoint::Motion:
  711 + {
  712 + Vector2 metaballCenter = Vector2((point.screen.x / mScreenSize.x) - 0.5, (aspectR * (mScreenSize.y - point.screen.y) / mScreenSize.y) - 0.5) * 2.0;
  713 + SetPositionToMetaballs(metaballCenter);
  714 + break;
  715 + }
  716 + case TouchPoint::Up:
  717 + case TouchPoint::Leave:
  718 + case TouchPoint::Interrupted:
  719 + {
  720 + mTimerDispersion.Start();
  721 + break;
  722 + }
  723 + default:
  724 + break;
  725 + }
  726 + return true;
  727 +}
  728 +
  729 +void MetaballExplosionController::OnKeyEvent(const KeyEvent& event)
  730 +{
  731 + if(event.state == KeyEvent::Down)
  732 + {
  733 + if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
  734 + {
  735 + mApplication.Quit();
  736 + }
  737 + }
  738 +}
  739 +
  740 +
  741 +//-----------------------------------------------------------------------------------------------
  742 +//
  743 +// Main functions
  744 +//
  745 +//-----------------------------------------------------------------------------------------------
  746 +
  747 +void RunTest( Application& application )
  748 +{
  749 + MetaballExplosionController test( application );
  750 +
  751 + application.MainLoop();
  752 +}
  753 +
  754 +// Entry point for Linux & Tizen applications
  755 +//
  756 +int main( int argc, char **argv )
  757 +{
  758 + Application application = Application::New( &argc, &argv );
  759 +
  760 + RunTest( application );
  761 +
  762 + return 0;
  763 +}
... ...
examples/metaball-refrac/metaball-refrac-example.cpp 0 → 100644
  1 +/*
  2 + * Copyright (c) 2014 Samsung Electronics Co., Ltd.
  3 + *
  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
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  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.
  15 + *
  16 + */
  17 +
  18 +#include <dali/dali.h>
  19 +#include <dali/devel-api/rendering/renderer.h>
  20 +#include <dali-toolkit/dali-toolkit.h>
  21 +
  22 +#include <cstdio>
  23 +#include <string>
  24 +
  25 +using namespace Dali;
  26 +using namespace Dali::Toolkit;
  27 +
  28 +namespace
  29 +{
  30 +const char * const BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-2.jpg" );
  31 +const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
  32 +
  33 +const float GRAVITY_X(0);
  34 +const float GRAVITY_Y(-0.09);
  35 +}
  36 +
  37 +#define METABALL_NUMBER 4
  38 +
  39 +const char*const METABALL_VERTEX_SHADER = DALI_COMPOSE_SHADER (
  40 + attribute mediump vec2 aPosition;\n
  41 + attribute mediump vec2 aTexture;\n
  42 + attribute mediump vec3 aNormal;\n
  43 + uniform mediump mat4 uMvpMatrix;\n
  44 + uniform mediump vec3 uSize;\n
  45 + uniform lowp vec4 uColor;\n
  46 + varying mediump vec2 vTexCoord;\n
  47 +
  48 + void main()\n
  49 + {\n
  50 + mediump vec4 vertexPosition = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n
  51 + vertexPosition = uMvpMatrix * vertexPosition;\n
  52 + gl_Position = vertexPosition;\n
  53 + vTexCoord = aTexture;\n
  54 + }\n
  55 +);
  56 +
  57 +
  58 +const char*const METABALL_FRAG_SHADER = DALI_COMPOSE_SHADER (
  59 + precision mediump float;\n
  60 + varying vec2 vTexCoord;\n
  61 + uniform vec2 uPositionMetaball;\n
  62 + uniform vec2 uPositionVar;\n
  63 + uniform vec2 uGravityVector;\n
  64 + uniform float uRadius;\n
  65 + uniform float uRadiusVar;\n
  66 + uniform float uAspect;\n
  67 + void main()\n
  68 + {\n
  69 + vec2 adjustedCoords = vTexCoord * 2.0 - 1.0;\n
  70 + vec2 finalMetaballPosition = uPositionMetaball + uGravityVector + uPositionVar;\n
  71 +
  72 + float distance = (adjustedCoords.x - finalMetaballPosition.x) * (adjustedCoords.x - finalMetaballPosition.x) +
  73 + (adjustedCoords.y - finalMetaballPosition.y) * (adjustedCoords.y - finalMetaballPosition.y);\n
  74 + float finalRadius = uRadius + uRadiusVar;\n
  75 + float color = finalRadius / sqrt( distance );\n
  76 + vec2 bordercolor = vec2(0.0,0.0);\n
  77 + if (vTexCoord.x < 0.1)\n
  78 + {\n
  79 + bordercolor.x = (0.1 - vTexCoord.x) * 0.8;\n
  80 + }\n
  81 + if (vTexCoord.x > 0.9)\n
  82 + {\n
  83 + bordercolor.x = (vTexCoord.x - 0.9) * 0.8;\n
  84 + }\n
  85 + if (vTexCoord.y < 0.1)\n
  86 + {\n
  87 + bordercolor.y = (0.1 - vTexCoord.y) * 0.8;\n
  88 + }\n
  89 + if (vTexCoord.y > (0.9 * uAspect))\n
  90 + {\n
  91 + bordercolor.y = (vTexCoord.y - (0.9 * uAspect)) * 0.8;\n
  92 + }\n
  93 + float border = (bordercolor.x + bordercolor.y) * 0.5;\n
  94 + gl_FragColor = vec4(color + border,color + border,color + border,1.0);\n
  95 + }\n
  96 +);
  97 +
  98 +const char*const REFRACTION_FRAG_SHADER = DALI_COMPOSE_SHADER (
  99 + precision mediump float;\n
  100 + varying vec2 vTexCoord;\n
  101 + uniform sampler2D sTexture;\n
  102 + uniform sampler2D sEffect;\n
  103 + void main()\n
  104 + {\n
  105 + vec4 metaColor = texture2D(sEffect, vTexCoord);\n
  106 + vec2 zoomCoords;\n
  107 + float bright = 1.0;\n
  108 + if (metaColor.r > 0.85)\n
  109 + {\n
  110 + zoomCoords = ((vTexCoord - 0.5) * 0.95) + 0.5;\n
  111 + }\n
  112 + else if (metaColor.r > 0.81)\n
  113 + {\n
  114 + float interpolation = mix(0.95, 1.05, (0.85 - metaColor.r) * 50.0);\n
  115 + zoomCoords = ((vTexCoord - 0.5) * interpolation) + 0.5;\n
  116 + bright = 1.2;\n
  117 + }\n
  118 + else\n
  119 + {\n
  120 + zoomCoords = vTexCoord;\n
  121 + }\n
  122 +
  123 + gl_FragColor = texture2D(sTexture, zoomCoords) * bright;\n
  124 + }\n
  125 + );
  126 +
  127 +const char*const FRAG_SHADER = DALI_COMPOSE_SHADER (
  128 + precision mediump float;\n
  129 + varying vec2 vTexCoord;\n
  130 + uniform sampler2D sTexture;\n
  131 + void main()\n
  132 + {\n
  133 + gl_FragColor = texture2D(sTexture, vTexCoord);\n
  134 + }\n
  135 +);
  136 +
  137 +
  138 +struct MetaballInfo
  139 +{
  140 + //ShaderEffect shader;
  141 + Actor actor;
  142 + Vector2 position;
  143 + float radius;
  144 + float initRadius;
  145 +
  146 + //Properties needed for animations
  147 + Property::Index positionIndex;
  148 + Property::Index positionVarIndex;
  149 + Property::Index gravityIndex;
  150 + Property::Index radiusIndex;
  151 + Property::Index radiusVarIndex;
  152 + Property::Index aspectIndex;
  153 +};
  154 +
  155 +
  156 +/***************************************************************************/
  157 +/* Demo using Metaballs for Refraction when clicking the screen ************/
  158 +/* The concept is similar to the Note 5 ScreenLock ************/
  159 +/***************************************************************************/
  160 +class MetaballRefracController : public ConnectionTracker
  161 +{
  162 +public:
  163 + MetaballRefracController( Application& application );
  164 + ~MetaballRefracController();
  165 +
  166 + void Create( Application& app );
  167 + bool OnTouch( Actor actor, const TouchEvent& touch );
  168 + void OnKeyEvent(const KeyEvent& event);
  169 +
  170 + void SetGravity(const Vector2 & gravity);
  171 +
  172 +
  173 +private:
  174 + Application& mApplication;
  175 + Vector2 mScreenSize;
  176 +
  177 + Layer mContentLayer;
  178 +
  179 + Image mBackImage;
  180 + FrameBufferImage mMetaballFBO;
  181 +
  182 + Actor mMetaballRoot;
  183 + MetaballInfo mMetaballs[METABALL_NUMBER];
  184 +
  185 + Actor mCompositionActor;
  186 +
  187 + //Motion
  188 + bool mExitClick;
  189 + Vector2 mCurrentTouchPosition;
  190 + Vector2 mMetaballPosVariation;
  191 + Vector2 mMetaballPosVariationFrom;
  192 + Vector2 mMetaballPosVariationTo;
  193 + Vector2 mMetaballCenter;
  194 +
  195 + Vector2 mGravity;
  196 + Vector2 mGravityVar;
  197 +
  198 + Renderer mRendererRefraction;
  199 + Material mMaterialRefraction;
  200 + Material mMaterialNormal;
  201 +
  202 + //Animations
  203 + Animation mGravityAnimation[METABALL_NUMBER];
  204 + Animation mRadiusDecAnimation[METABALL_NUMBER];
  205 + Animation mRadiusIncFastAnimation[METABALL_NUMBER];
  206 + Animation mRadiusIncSlowAnimation[METABALL_NUMBER];
  207 + Animation mRadiusVarAnimation[METABALL_NUMBER];
  208 + Animation mPositionVarAnimation[METABALL_NUMBER];
  209 +
  210 + //Private functions
  211 + Geometry CreateGeometry();
  212 + Geometry CreateGeometryComposition();
  213 +
  214 + void CreateMetaballActors();
  215 + void CreateMetaballImage();
  216 + void AddRefractionImage();
  217 + void CreateAnimations();
  218 +
  219 + void LaunchRadiusIncSlowAnimations(Animation &source);
  220 + void LaunchGetBackToPositionAnimation(Animation &source);
  221 +
  222 + void StopClickAnimations();
  223 + void StopAfterClickAnimations();
  224 +
  225 + void ResetMetaballsState();
  226 +
  227 + void SetPositionToMetaballs(Vector2 & metaballCenter);
  228 +};
  229 +
  230 +
  231 +//-----------------------------------------------------------------------------------------------
  232 +//
  233 +// IMPLEMENTATION
  234 +//
  235 +//----------------
  236 +
  237 +MetaballRefracController::MetaballRefracController( Application& application )
  238 + : mApplication( application )
  239 +{
  240 + // Connect to the Application's Init signal
  241 + mApplication.InitSignal().Connect( this, &MetaballRefracController::Create );
  242 +}
  243 +
  244 +MetaballRefracController::~MetaballRefracController()
  245 +{
  246 + // Nothing to do here;
  247 +}
  248 +
  249 +/*
  250 + * Setter function for gravity
  251 + */
  252 +void MetaballRefracController::SetGravity(const Vector2 & gravity)
  253 +{
  254 + mGravity = gravity;
  255 +}
  256 +
  257 +/**
  258 + * Main create function, it creates the metaballs and all the
  259 + */
  260 +void MetaballRefracController::Create( Application& app )
  261 +{
  262 + Stage stage = Stage::GetCurrent();
  263 +
  264 + stage.KeyEventSignal().Connect(this, &MetaballRefracController::OnKeyEvent);
  265 +
  266 + mScreenSize = stage.GetSize();
  267 +
  268 + stage.SetBackgroundColor(Color::BLACK);
  269 +
  270 + //Set background image for the view
  271 + mBackImage = ResourceImage::New( BACKGROUND_IMAGE );
  272 +
  273 + mGravity = Vector2(GRAVITY_X,GRAVITY_Y);
  274 + mGravityVar = Vector2(0,0);
  275 +
  276 + //Create internal data
  277 + CreateMetaballActors();
  278 + CreateMetaballImage();
  279 + AddRefractionImage();
  280 +
  281 + CreateAnimations();
  282 +
  283 + // Connect the callback to the touch signal on the mesh actor
  284 + stage.GetRootLayer().TouchedSignal().Connect( this, &MetaballRefracController::OnTouch );
  285 +}
  286 +
  287 +/**
  288 + * Create a mesh data with the geometry for the metaball rendering
  289 + */
  290 +Geometry MetaballRefracController::CreateGeometry()
  291 +{
  292 + float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
  293 +
  294 + // Create vertices and specify their color
  295 + float xsize = mScreenSize.x * 0.5;
  296 +
  297 + //We create the meshdata for the metaballs
  298 + struct VertexPosition { Vector2 position; };
  299 + struct VertexTexture { Vector2 texture; };
  300 + struct VertexNormal { Vector3 normal; };
  301 +
  302 + VertexPosition vertices[] = {
  303 + { Vector2( -xsize, -xsize * aspect) },
  304 + { Vector2( xsize, -xsize * aspect) },
  305 + { Vector2( -xsize, xsize * aspect) },
  306 + { Vector2( xsize, xsize * aspect) }
  307 + };
  308 +
  309 + VertexTexture textures[] = {
  310 + { Vector2(0.0f, 0.0f) },
  311 + { Vector2(1.0f, 0.0f) },
  312 + { Vector2(0.0f, 1.0f * aspect) },
  313 + { Vector2(1.0f, 1.0f * aspect) }
  314 + };
  315 +
  316 + VertexNormal normals [] = {
  317 + { Vector3(0.0f, 0.0f, 1.0f) },
  318 + { Vector3(0.0f, 0.0f, 1.0f) },
  319 + { Vector3(0.0f, 0.0f, 1.0f) },
  320 + { Vector3(0.0f, 0.0f, 1.0f) }
  321 + };
  322 +
  323 + int indices[] = { 0, 3, 1, 0, 2, 3 };
  324 +
  325 + unsigned int numberOfVertices = sizeof(vertices)/sizeof(VertexPosition);
  326 +
  327 + //Vertices
  328 + Property::Map positionVertexFormat;
  329 + positionVertexFormat["aPosition"] = Property::VECTOR2;
  330 + PropertyBuffer positionVertices = PropertyBuffer::New( positionVertexFormat, numberOfVertices );
  331 + positionVertices.SetData(vertices);
  332 +
  333 + //Textures
  334 + Property::Map textureVertexFormat;
  335 + textureVertexFormat["aTexture"] = Property::VECTOR2;
  336 + PropertyBuffer textureVertices = PropertyBuffer::New( textureVertexFormat, numberOfVertices );
  337 + textureVertices.SetData(textures);
  338 +
  339 + //Normals
  340 + Property::Map normalVertexFormat;
  341 + normalVertexFormat["aNormal"] = Property::VECTOR3;
  342 + PropertyBuffer normalVertices = PropertyBuffer::New( normalVertexFormat, numberOfVertices );
  343 + normalVertices.SetData(normals);
  344 +
  345 + //Indices
  346 + Property::Map indicesVertexFormat;
  347 + indicesVertexFormat["aIndices"] = Property::INTEGER;
  348 + PropertyBuffer indicesToVertices = PropertyBuffer::New( indicesVertexFormat, 6 );
  349 + indicesToVertices.SetData(indices);
  350 +
  351 +
  352 + // Create the geometry object
  353 + Geometry texturedQuadGeometry = Geometry::New();
  354 + texturedQuadGeometry.AddVertexBuffer( positionVertices );
  355 + texturedQuadGeometry.AddVertexBuffer( textureVertices );
  356 + texturedQuadGeometry.AddVertexBuffer( normalVertices );
  357 +
  358 + texturedQuadGeometry.SetIndexBuffer ( indicesToVertices );
  359 +
  360 + return texturedQuadGeometry;
  361 +}
  362 +
  363 +/**
  364 + * Create a mesh data with the geometry for the metaball rendering
  365 + */
  366 +Geometry MetaballRefracController::CreateGeometryComposition()
  367 +{
  368 + float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
  369 +
  370 + // Create vertices and specify their color
  371 + float xsize = mScreenSize.x * 0.5;
  372 +
  373 + //We create the meshdata for the metaballs
  374 + struct VertexPosition { Vector2 position; };
  375 + struct VertexTexture { Vector2 texture; };
  376 + struct VertexNormal { Vector3 normal; };
  377 +
  378 + VertexPosition vertices[] = {
  379 + { Vector2( -xsize, -xsize * aspect) },
  380 + { Vector2( xsize, -xsize * aspect) },
  381 + { Vector2( -xsize, xsize * aspect) },
  382 + { Vector2( xsize, xsize * aspect) }
  383 + };
  384 +
  385 + VertexTexture textures[] = {
  386 + { Vector2(0.0f, 0.0f) },
  387 + { Vector2(1.0f, 0.0f) },
  388 + { Vector2(0.0f, 1.0f) },
  389 + { Vector2(1.0f, 1.0f) }
  390 + };
  391 +
  392 + VertexNormal normals [] = {
  393 + { Vector3(0.0f, 0.0f, 1.0f) },
  394 + { Vector3(0.0f, 0.0f, 1.0f) },
  395 + { Vector3(0.0f, 0.0f, 1.0f) },
  396 + { Vector3(0.0f, 0.0f, 1.0f) }
  397 + };
  398 +
  399 + int indices[] = { 0, 3, 1, 0, 2, 3 };
  400 +
  401 + unsigned int numberOfVertices = sizeof(vertices)/sizeof(VertexPosition);
  402 +
  403 + //Vertices
  404 + Property::Map positionVertexFormat;
  405 + positionVertexFormat["aPosition"] = Property::VECTOR2;
  406 + PropertyBuffer positionVertices = PropertyBuffer::New( positionVertexFormat, numberOfVertices );
  407 + positionVertices.SetData(vertices);
  408 +
  409 + //Textures
  410 + Property::Map textureVertexFormat;
  411 + textureVertexFormat["aTexture"] = Property::VECTOR2;
  412 + PropertyBuffer textureVertices = PropertyBuffer::New( textureVertexFormat, numberOfVertices );
  413 + textureVertices.SetData(textures);
  414 +
  415 + //Normals
  416 + Property::Map normalVertexFormat;
  417 + normalVertexFormat["aNormal"] = Property::VECTOR3;
  418 + PropertyBuffer normalVertices = PropertyBuffer::New( normalVertexFormat, numberOfVertices );
  419 + normalVertices.SetData(normals);
  420 +
  421 + //Indices
  422 + Property::Map indicesVertexFormat;
  423 + indicesVertexFormat["aIndices"] = Property::INTEGER;
  424 + PropertyBuffer indicesToVertices = PropertyBuffer::New( indicesVertexFormat, 6 );
  425 + indicesToVertices.SetData(indices);
  426 +
  427 +
  428 + // Create the geometry object
  429 + Geometry texturedQuadGeometry = Geometry::New();
  430 + texturedQuadGeometry.AddVertexBuffer( positionVertices );
  431 + texturedQuadGeometry.AddVertexBuffer( textureVertices );
  432 + texturedQuadGeometry.AddVertexBuffer( normalVertices );
  433 +
  434 + texturedQuadGeometry.SetIndexBuffer ( indicesToVertices );
  435 +
  436 + return texturedQuadGeometry;
  437 +}
  438 +
  439 +/**
  440 + * Create a mesh actor for the metaballs
  441 + */
  442 +void MetaballRefracController::CreateMetaballActors()
  443 +{
  444 + //We create metaball structures
  445 + //With MeshData Textured
  446 + float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
  447 +
  448 + //Create the shader for the metaballs
  449 +
  450 + Shader shader = Shader::New( METABALL_VERTEX_SHADER, METABALL_FRAG_SHADER );
  451 +
  452 + Material material = Material::New( shader );
  453 + material.SetBlendMode(BlendingMode::ON );
  454 + material.SetBlendFunc(BlendingFactor::ONE, BlendingFactor::ONE, BlendingFactor::ONE, BlendingFactor::ONE);
  455 +
  456 + Geometry metaballGeom = CreateGeometry();
  457 +
  458 + //Each metaball has a different radius
  459 + mMetaballs[0].radius = mMetaballs[0].initRadius = 0.0145f;
  460 + mMetaballs[1].radius = mMetaballs[1].initRadius = 0.012f;
  461 + mMetaballs[2].radius = mMetaballs[2].initRadius = 0.0135f;
  462 + mMetaballs[3].radius = mMetaballs[3].initRadius = 0.0135f;
  463 +
  464 + //Initialization of each of the metaballs
  465 + for (int i = 0 ; i < METABALL_NUMBER ; i++)
  466 + {
  467 + mMetaballs[i].position = Vector2(0.0f, 0.0f);
  468 +
  469 + mMetaballs[i].actor = Actor::New( );
  470 + mMetaballs[i].actor.SetName("Metaball");
  471 + mMetaballs[i].actor.SetScale( 1.0f );
  472 + mMetaballs[i].actor.SetParentOrigin( ParentOrigin::CENTER );
  473 +
  474 + Renderer renderer = Renderer::New( metaballGeom, material );
  475 + mMetaballs[i].actor.AddRenderer( renderer );
  476 +
  477 + mMetaballs[i].positionIndex = mMetaballs[i].actor.RegisterProperty( "uPositionMetaball", mMetaballs[i].position );
  478 +
  479 + mMetaballs[i].positionVarIndex = mMetaballs[i].actor.RegisterProperty( "uPositionVar", Vector2(0.f,0.f) );
  480 +
  481 + mMetaballs[i].gravityIndex = mMetaballs[i].actor.RegisterProperty( "uGravityVector", Vector2(0.f,0.f) );
  482 +
  483 + mMetaballs[i].radiusIndex = mMetaballs[i].actor.RegisterProperty( "uRadius", mMetaballs[i].radius );
  484 +
  485 + mMetaballs[i].radiusVarIndex = mMetaballs[i].actor.RegisterProperty( "uRadiusVar", 0.f );
  486 +
  487 + mMetaballs[i].aspectIndex = mMetaballs[i].actor.RegisterProperty( "uAspect", aspect );
  488 +
  489 + mMetaballs[i].actor.SetSize(400, 400);
  490 + }
  491 +
  492 + //Root creation
  493 + mMetaballRoot = Actor::New();
  494 + mMetaballRoot.SetParentOrigin( ParentOrigin::CENTER );
  495 + for (int i = 0 ; i < METABALL_NUMBER ; i++)
  496 + {
  497 + mMetaballRoot.Add( mMetaballs[i].actor );
  498 + }
  499 +
  500 + //Initialization of variables related to metaballs
  501 + mMetaballPosVariation = Vector2(0,0);
  502 + mMetaballPosVariationFrom = Vector2(0,0);
  503 + mMetaballPosVariationTo = Vector2(0,0);
  504 + mCurrentTouchPosition = Vector2(0,0);
  505 +}
  506 +
  507 +/**
  508 + * Create the render task and FBO to render the metaballs into a texture
  509 + */
  510 +void MetaballRefracController::CreateMetaballImage()
  511 +{
  512 + //We create an FBO and a render task to create to render the metaballs with a fragment shader
  513 + Stage stage = Stage::GetCurrent();
  514 + mMetaballFBO = FrameBufferImage::New(mScreenSize.x, mScreenSize.y );
  515 +
  516 + stage.Add(mMetaballRoot);
  517 +
  518 + //Creation of the render task used to render the metaballs
  519 + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
  520 + RenderTask task = taskList.CreateTask();
  521 + task.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
  522 + task.SetSourceActor( mMetaballRoot );
  523 + task.SetExclusive(true);
  524 + task.SetClearColor( Color::BLACK );
  525 + task.SetClearEnabled( true );
  526 + task.SetTargetFrameBuffer( mMetaballFBO );
  527 +}
  528 +
  529 +/**
  530 + * Create a mesh image to render the final composition
  531 + */
  532 +void MetaballRefracController::AddRefractionImage()
  533 +{
  534 + //Creation of the composition image
  535 +
  536 + //Create geometry
  537 + Geometry metaballGeom = CreateGeometryComposition();
  538 +
  539 + //Create Refraction shader and renderer
  540 + Shader shader = Shader::New( METABALL_VERTEX_SHADER, REFRACTION_FRAG_SHADER );
  541 + //Create new material
  542 + mMaterialRefraction = Material::New( shader );
  543 +
  544 + //Add Textures
  545 + mMaterialRefraction.AddTexture(mBackImage, "sTexture");
  546 + mMaterialRefraction.AddTexture(mMetaballFBO, "sEffect");
  547 +
  548 + //Create normal shader
  549 + Shader shaderNormal = Shader::New( METABALL_VERTEX_SHADER, FRAG_SHADER );
  550 + //Create new material
  551 + mMaterialNormal = Material::New( shaderNormal );
  552 +
  553 + //Add samplers
  554 + mMaterialNormal.AddTexture(mBackImage, "sTexture");
  555 +
  556 +
  557 + //Create actor
  558 + mCompositionActor = Actor::New( );
  559 + mCompositionActor.SetParentOrigin(ParentOrigin::CENTER);
  560 + mCompositionActor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
  561 + mCompositionActor.SetSize(mScreenSize.x, mScreenSize.y);
  562 +
  563 +
  564 + mRendererRefraction = Renderer::New( metaballGeom, mMaterialNormal );
  565 + mCompositionActor.AddRenderer( mRendererRefraction );
  566 +
  567 + Stage stage = Stage::GetCurrent();
  568 + stage.Add( mCompositionActor );
  569 +}
  570 +
  571 +/**
  572 + * Creation of all the metaballs animations (gravity, movement, size, etc.)
  573 + */
  574 +void MetaballRefracController::CreateAnimations()
  575 +{
  576 + int i = 0;
  577 + float key;
  578 +
  579 + mPositionVarAnimation[1] = Animation::New(2.f);
  580 + mPositionVarAnimation[1].SetLooping( false );
  581 + mPositionVarAnimation[1].Pause();
  582 + mPositionVarAnimation[1].FinishedSignal().Connect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
  583 +
  584 + KeyFrames keySinCosVariation = KeyFrames::New();
  585 + Vector2 sinCosVariation(0,0);
  586 + for ( i = 0 ; i < 360 ; i++)
  587 + {
  588 + sinCosVariation.x = 0.05f * (-sin(i * Math::PI/180.f) + cos(i * Math::PI/180.f));
  589 + sinCosVariation.y = 0.05f * (sin(i * Math::PI/180.f) - cos(i * Math::PI/180.f));
  590 + key = i/360.f;
  591 + keySinCosVariation.Add(key, sinCosVariation);
  592 + }
  593 +
  594 + mPositionVarAnimation[2] = Animation::New(6.f);
  595 + mPositionVarAnimation[2].AnimateBetween(Property( mMetaballs[2].actor, mMetaballs[2].positionVarIndex ), keySinCosVariation);
  596 + mPositionVarAnimation[2].SetLooping( true );
  597 + mPositionVarAnimation[2].Pause();
  598 +
  599 + KeyFrames keyCosSinVariation = KeyFrames::New();
  600 + Vector2 cosSinVariation(0,0);
  601 + for ( i = 0 ; i < 360 ; i++)
  602 + {
  603 + cosSinVariation.x = 0.05f * (-sin(i * Math::PI/180.f) - cos(i * Math::PI/180.f));
  604 + cosSinVariation.y = 0.05f * (sin(i * Math::PI/180.f) + cos(i * Math::PI/180.f));
  605 + key = i/360.f;
  606 + keyCosSinVariation.Add(key, cosSinVariation);
  607 + }
  608 +
  609 + mPositionVarAnimation[3] = Animation::New(6.f);
  610 + mPositionVarAnimation[3].AnimateBetween(Property( mMetaballs[3].actor, mMetaballs[3].positionVarIndex ), keyCosSinVariation);
  611 + mPositionVarAnimation[3].SetLooping( true );
  612 + mPositionVarAnimation[3].Pause();
  613 +
  614 + //Animations for gravity
  615 + for ( i = 0 ; i < METABALL_NUMBER ; i++)
  616 + {
  617 + mGravityAnimation[i] = Animation::New(25.f);
  618 + mGravityAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].gravityIndex ), mGravity * 25.f * 3.f);
  619 + mGravityAnimation[i].SetLooping( false );
  620 + mGravityAnimation[i].Pause();
  621 + }
  622 +
  623 + //Animation to decrease size of metaballs when there is no click
  624 + for ( i = 0 ; i < METABALL_NUMBER ; i++)
  625 + {
  626 + mRadiusDecAnimation[i] = Animation::New(25.f);
  627 + mRadiusDecAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), -0.004f * 25.f * 3.f);
  628 + mRadiusDecAnimation[i].SetLooping( false );
  629 + mRadiusDecAnimation[i].Pause();
  630 + }
  631 +
  632 + //Animation to grow the size of the metaballs the first second of the click
  633 + for ( i = 0 ; i < METABALL_NUMBER ; i++)
  634 + {
  635 + mRadiusIncFastAnimation[i] = Animation::New(0.3f);
  636 + mRadiusIncFastAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), 0.06f);
  637 + mRadiusIncFastAnimation[i].SetLooping( false );
  638 + mRadiusIncFastAnimation[i].Pause();
  639 + }
  640 + mRadiusIncFastAnimation[0].FinishedSignal().Connect( this, &MetaballRefracController::LaunchRadiusIncSlowAnimations );
  641 +
  642 + //Animation to grow the size of the metaballs afterwards
  643 + for ( i = 0 ; i < METABALL_NUMBER ; i++)
  644 + {
  645 + mRadiusIncSlowAnimation[i] = Animation::New(20.f);
  646 + mRadiusIncSlowAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), 0.04f);
  647 + mRadiusIncSlowAnimation[i].SetLooping( false );
  648 + mRadiusIncSlowAnimation[i].Pause();
  649 + }
  650 +
  651 + //keyframes of a sin function
  652 + KeyFrames keySin = KeyFrames::New();
  653 + float val;
  654 + for ( i = 0 ; i < 360 ; i++)
  655 + {
  656 + val = 0.01f * sin(i * Math::PI/180.f);
  657 + key = i/360.f;
  658 + keySin.Add(key, val);
  659 + }
  660 +
  661 + //Animation to change the size of the metaball
  662 + mRadiusVarAnimation[2] = Animation::New(8.f);
  663 + mRadiusVarAnimation[2].AnimateBetween(Property( mMetaballs[2].actor, mMetaballs[2].radiusVarIndex ), keySin);
  664 + mRadiusVarAnimation[2].SetLooping( true );
  665 +
  666 + //keyframes of a cos function
  667 + KeyFrames keyCos = KeyFrames::New();
  668 + for ( i = 0 ; i < 360 ; i++)
  669 + {
  670 + val = 0.01f * cos(i * Math::PI/180.f);
  671 + key = i/360.f;
  672 + keyCos.Add(key, val);
  673 + }
  674 +
  675 + //Animation to change the size of the metaball
  676 + mRadiusVarAnimation[3] = Animation::New(8.f);
  677 + mRadiusVarAnimation[3].AnimateBetween(Property( mMetaballs[3].actor, mMetaballs[3].radiusVarIndex ), keyCos);
  678 + mRadiusVarAnimation[3].SetLooping( true );
  679 +}
  680 +
  681 +/**
  682 + * Function to launch the animation to get the metaball[1] back to the center
  683 + */
  684 +void MetaballRefracController::LaunchGetBackToPositionAnimation(Animation &source)
  685 +{
  686 + mMetaballPosVariationTo = Vector2(0,0);
  687 +
  688 + mPositionVarAnimation[1] = Animation::New(1.f);
  689 + mPositionVarAnimation[1].SetLooping( false );
  690 + mPositionVarAnimation[1].AnimateTo(Property( mMetaballs[1].actor, mMetaballs[1].positionVarIndex ), Vector2(0,0));
  691 + mPositionVarAnimation[1].Play();
  692 +}
  693 +
  694 +/**
  695 + * Function to launch the gro slow radius for the metaballs, and also the small variations for metaball[2] and [3]
  696 + */
  697 +void MetaballRefracController::LaunchRadiusIncSlowAnimations(Animation &source)
  698 +{
  699 + for (int i = 0 ; i < METABALL_NUMBER ; i++)
  700 + {
  701 + mRadiusIncSlowAnimation[i].Play();
  702 + }
  703 + mPositionVarAnimation[2].Play();
  704 + mPositionVarAnimation[3].Play();
  705 +}
  706 +
  707 +/**
  708 + * Function to stop all animations related to the click of the user in the screen
  709 + */
  710 +void MetaballRefracController::StopClickAnimations()
  711 +{
  712 + for (int i = 0 ; i < METABALL_NUMBER ; i++)
  713 + {
  714 + mRadiusIncSlowAnimation[i].Stop();
  715 + mRadiusIncFastAnimation[i].Stop();
  716 + }
  717 + mPositionVarAnimation[1].Stop();
  718 + mPositionVarAnimation[2].Stop();
  719 + mPositionVarAnimation[3].Stop();
  720 +}
  721 +
  722 +/**
  723 + * Function to stop all animations related to the after click of the user in the screen
  724 + */
  725 +void MetaballRefracController::StopAfterClickAnimations()
  726 +{
  727 + for (int i = 0 ; i < METABALL_NUMBER ; i++)
  728 + {
  729 + mGravityAnimation[i].Stop();
  730 + mRadiusDecAnimation[i].Stop();
  731 +
  732 + mMetaballs[i].radius = mMetaballs[i].initRadius;
  733 +
  734 + mMetaballs[i].actor.SetProperty(mMetaballs[i].gravityIndex, Vector2(0,0));
  735 + mMetaballs[i].actor.SetProperty(mMetaballs[i].radiusIndex, mMetaballs[i].radius);
  736 + mMetaballs[i].actor.SetProperty(mMetaballs[i].radiusVarIndex, 0.f);
  737 + }
  738 + mRadiusVarAnimation[2].Stop();
  739 + mRadiusVarAnimation[3].Stop();
  740 +}
  741 +
  742 +/*
  743 + * Function that resets the sate of the different Metaballs
  744 + */
  745 +void MetaballRefracController::ResetMetaballsState()
  746 +{
  747 + mRendererRefraction.SetMaterial(mMaterialNormal);
  748 +
  749 + for (int i = 0 ; i < METABALL_NUMBER ; i++)
  750 + {
  751 + mMetaballs[i].radius = mMetaballs[i].initRadius;
  752 + }
  753 +
  754 + mMetaballPosVariationTo = Vector2(0,0);
  755 + mMetaballPosVariationFrom = Vector2(0,0);
  756 + mMetaballPosVariation = Vector2(0,0);
  757 +
  758 + mGravityVar = Vector2(0,0);
  759 +}
  760 +
  761 +/**
  762 + * Function to set the actual position of the metaballs when the user clicks the screen
  763 + */
  764 +void MetaballRefracController::SetPositionToMetaballs(Vector2 & metaballCenter)
  765 +{
  766 + //We set the position for the metaballs based on click position
  767 + for (int i = 0 ; i < METABALL_NUMBER ; i++)
  768 + {
  769 + mMetaballs[i].position = metaballCenter;
  770 + mMetaballs[i].actor.SetProperty(mMetaballs[i].positionIndex, mMetaballs[0].position); // 0 y no i ?!?!?!
  771 + }
  772 +}
  773 +
  774 +bool MetaballRefracController::OnTouch( Actor actor, const TouchEvent& touch )
  775 +{
  776 + const TouchPoint &point = touch.GetPoint(0);
  777 + float aspectR = mScreenSize.y / mScreenSize.x;
  778 + switch(point.state)
  779 + {
  780 + case TouchPoint::Down:
  781 + {
  782 + StopAfterClickAnimations();
  783 + for (int i = 0 ; i < METABALL_NUMBER ; i++)
  784 + mRadiusIncFastAnimation[i].Play();
  785 + mRadiusVarAnimation[2].Play();
  786 + mRadiusVarAnimation[3].Play();
  787 +
  788 + //We draw with the refraction-composition shader
  789 + mRendererRefraction.SetMaterial(mMaterialRefraction);
  790 +
  791 + mCurrentTouchPosition = point.screen;
  792 +
  793 + //we use the click position for the metaballs
  794 + Vector2 metaballCenter = Vector2((point.screen.x / mScreenSize.x) - 0.5, (aspectR * (mScreenSize.y - point.screen.y) / mScreenSize.y) - 0.5) * 2.0;
  795 + SetPositionToMetaballs(metaballCenter);
  796 + break;
  797 + }
  798 + case TouchPoint::Motion:
  799 + {
  800 + Vector2 displacement = point.screen - mCurrentTouchPosition;
  801 + mCurrentTouchPosition = point.screen;
  802 +
  803 + mMetaballPosVariationTo.x += (displacement.x / mScreenSize.x) * 2.2;
  804 + mMetaballPosVariationTo.y += (- displacement.y / mScreenSize.y) * 2.2;
  805 +
  806 + if (mPositionVarAnimation[1])
  807 + {
  808 + mPositionVarAnimation[1].FinishedSignal().Disconnect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
  809 + mPositionVarAnimation[1].Stop();
  810 + }
  811 + mPositionVarAnimation[1] = Animation::New(1.f);
  812 + mPositionVarAnimation[1].SetLooping( false );
  813 + mPositionVarAnimation[1].AnimateTo(Property( mMetaballs[1].actor, mMetaballs[1].positionVarIndex ), mMetaballPosVariationTo);
  814 + mPositionVarAnimation[1].FinishedSignal().Connect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
  815 + mPositionVarAnimation[1].Play();
  816 +
  817 + //we use the click position for the metaballs
  818 + Vector2 metaballCenter = Vector2((point.screen.x / mScreenSize.x) - 0.5, (aspectR * (mScreenSize.y - point.screen.y) / mScreenSize.y) - 0.5) * 2.0;
  819 + SetPositionToMetaballs(metaballCenter);
  820 + break;
  821 + }
  822 + case TouchPoint::Up:
  823 + case TouchPoint::Leave:
  824 + case TouchPoint::Interrupted:
  825 + {
  826 + //Stop click animations
  827 + StopClickAnimations();
  828 +
  829 + //Launch out of screen animations
  830 + for (int i = 0 ; i < METABALL_NUMBER ; i++)
  831 + mGravityAnimation[i].Play();
  832 +
  833 + for (int i = 0 ; i < METABALL_NUMBER ; i++)
  834 + mRadiusDecAnimation[i].Play();
  835 +
  836 + break;
  837 + }
  838 + default:
  839 + break;
  840 + }
  841 + return true;
  842 +}
  843 +
  844 +
  845 +void MetaballRefracController::OnKeyEvent(const KeyEvent& event)
  846 +{
  847 + if(event.state == KeyEvent::Down)
  848 + {
  849 + if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
  850 + {
  851 + mApplication.Quit();
  852 + }
  853 + }
  854 +}
  855 +
  856 +
  857 +//
  858 +//
  859 +//-----------------------------------------------------------------------------------------------
  860 +
  861 +void RunTest( Application& application )
  862 +{
  863 + MetaballRefracController test( application );
  864 +
  865 + application.MainLoop();
  866 +}
  867 +
  868 +// Entry point for Linux & Tizen applications
  869 +//
  870 +int main( int argc, char **argv )
  871 +{
  872 + Application application = Application::New( &argc, &argv );
  873 +
  874 + RunTest( application );
  875 +
  876 + return 0;
  877 +}
  878 +
... ...
shared/dali-demo-strings.h
... ... @@ -91,6 +91,8 @@ extern &quot;C&quot;
91 91 #define DALI_DEMO_STR_TITLE_LOGGING "Logging"
92 92 #define DALI_DEMO_STR_TITLE_MESH_MORPH "Mesh Morph"
93 93 #define DALI_DEMO_STR_TITLE_MESH_SORTING "Mesh Sorting"
  94 +#define DALI_DEMO_STR_TITLE_METABALL_EXPLOSION "Metaball Explosion"
  95 +#define DALI_DEMO_STR_TITLE_METABALL_REFRAC "Metaball Refractions"
94 96 #define DALI_DEMO_STR_TITLE_TEXTURED_MESH "Mesh Texture"
95 97 #define DALI_DEMO_STR_TITLE_LINE_MESH "Mesh Line"
96 98 #define DALI_DEMO_STR_TITLE_COLOR_GRADIENT "Color Gradient"
... ...