Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-demo.git] / examples / metaball-refrac / metaball-refrac-example.cpp
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( DEMO_IMAGE_DIR "background-2.jpg" );
31 const char * const TOOLBAR_IMAGE( DEMO_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   TextureSet        mTextureSetRefraction;
200   Shader            mShaderRefraction;
201   TextureSet        mTextureSetNormal;
202   Shader            mShaderNormal;
203
204   //Animations
205   Animation         mGravityAnimation[METABALL_NUMBER];
206   Animation         mRadiusDecAnimation[METABALL_NUMBER];
207   Animation         mRadiusIncFastAnimation[METABALL_NUMBER];
208   Animation         mRadiusIncSlowAnimation[METABALL_NUMBER];
209   Animation         mRadiusVarAnimation[METABALL_NUMBER];
210   Animation         mPositionVarAnimation[METABALL_NUMBER];
211
212   //Private functions
213   Geometry          CreateGeometry();
214   Geometry          CreateGeometryComposition();
215
216   void              CreateMetaballActors();
217   void              CreateMetaballImage();
218   void              AddRefractionImage();
219   void              CreateAnimations();
220
221   void              LaunchRadiusIncSlowAnimations(Animation &source);
222   void              LaunchGetBackToPositionAnimation(Animation &source);
223
224   void              StopClickAnimations();
225   void              StopAfterClickAnimations();
226
227   void              ResetMetaballsState();
228
229   void              SetPositionToMetaballs(Vector2 & metaballCenter);
230 };
231
232
233 //-----------------------------------------------------------------------------------------------
234 //
235 //  IMPLEMENTATION
236 //
237 //----------------
238
239 MetaballRefracController::MetaballRefracController( Application& application )
240   : mApplication( application )
241 {
242   // Connect to the Application's Init signal
243   mApplication.InitSignal().Connect( this, &MetaballRefracController::Create );
244 }
245
246 MetaballRefracController::~MetaballRefracController()
247 {
248   // Nothing to do here;
249 }
250
251 /*
252  * Setter function for gravity
253  */
254 void MetaballRefracController::SetGravity(const Vector2 & gravity)
255 {
256   mGravity = gravity;
257 }
258
259 /**
260  * Main create function, it creates the metaballs and all the
261  */
262 void MetaballRefracController::Create( Application& app )
263 {
264   Stage stage = Stage::GetCurrent();
265
266   stage.KeyEventSignal().Connect(this, &MetaballRefracController::OnKeyEvent);
267
268   mScreenSize = stage.GetSize();
269
270   stage.SetBackgroundColor(Color::BLACK);
271
272   //Set background image for the view
273   mBackImage = ResourceImage::New( BACKGROUND_IMAGE );
274
275   mGravity = Vector2(GRAVITY_X,GRAVITY_Y);
276   mGravityVar = Vector2(0,0);
277
278   //Create internal data
279   CreateMetaballActors();
280   CreateMetaballImage();
281   AddRefractionImage();
282
283   CreateAnimations();
284
285   // Connect the callback to the touch signal on the mesh actor
286   stage.GetRootLayer().TouchedSignal().Connect( this, &MetaballRefracController::OnTouch );
287 }
288
289 /**
290  * Create a mesh data with the geometry for the metaball rendering
291  */
292 Geometry MetaballRefracController::CreateGeometry()
293 {
294   float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
295
296   // Create vertices and specify their color
297   float xsize = mScreenSize.x * 0.5;
298
299   //We create the meshdata for the metaballs
300   struct VertexPosition { Vector2 position; };
301   struct VertexTexture { Vector2 texture; };
302   struct VertexNormal { Vector3 normal; };
303
304   VertexPosition vertices[] = {
305     { Vector2( -xsize, -xsize * aspect) },
306     { Vector2(  xsize, -xsize * aspect) },
307     { Vector2( -xsize,  xsize * aspect) },
308     { Vector2(  xsize,  xsize * aspect) }
309   };
310
311   VertexTexture textures[] = {
312     { Vector2(0.0f, 0.0f) },
313     { Vector2(1.0f, 0.0f) },
314     { Vector2(0.0f, 1.0f * aspect) },
315     { Vector2(1.0f, 1.0f * aspect) }
316   };
317
318   VertexNormal normals [] = {
319     { Vector3(0.0f, 0.0f, 1.0f) },
320     { Vector3(0.0f, 0.0f, 1.0f) },
321     { Vector3(0.0f, 0.0f, 1.0f) },
322     { Vector3(0.0f, 0.0f, 1.0f) }
323   };
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 );
331   positionVertices.SetData( vertices, numberOfVertices );
332
333   //Textures
334   Property::Map textureVertexFormat;
335   textureVertexFormat["aTexture"] = Property::VECTOR2;
336   PropertyBuffer textureVertices = PropertyBuffer::New( textureVertexFormat );
337   textureVertices.SetData( textures, numberOfVertices );
338
339   //Normals
340   Property::Map normalVertexFormat;
341   normalVertexFormat["aNormal"] = Property::VECTOR3;
342   PropertyBuffer normalVertices = PropertyBuffer::New( normalVertexFormat );
343   normalVertices.SetData( normals, numberOfVertices );
344
345   //Indices
346   unsigned short indices[] = { 0, 3, 1, 0, 2, 3 };
347
348   // Create the geometry object
349   Geometry texturedQuadGeometry = Geometry::New();
350   texturedQuadGeometry.AddVertexBuffer( positionVertices );
351   texturedQuadGeometry.AddVertexBuffer( textureVertices );
352   texturedQuadGeometry.AddVertexBuffer( normalVertices );
353
354   texturedQuadGeometry.SetIndexBuffer ( &indices[0], 6 );
355
356   return texturedQuadGeometry;
357 }
358
359 /**
360  * Create a mesh data with the geometry for the metaball rendering
361  */
362 Geometry MetaballRefracController::CreateGeometryComposition()
363 {
364   float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
365
366   // Create vertices and specify their color
367   float xsize = mScreenSize.x * 0.5;
368
369   //We create the meshdata for the metaballs
370   struct VertexPosition { Vector2 position; };
371   struct VertexTexture { Vector2 texture; };
372   struct VertexNormal { Vector3 normal; };
373
374   VertexPosition vertices[] = {
375     { Vector2( -xsize, -xsize * aspect) },
376     { Vector2(  xsize, -xsize * aspect) },
377     { Vector2( -xsize,  xsize * aspect) },
378     { Vector2(  xsize,  xsize * aspect) }
379   };
380
381   VertexTexture textures[] = {
382     { Vector2(0.0f, 0.0f) },
383     { Vector2(1.0f, 0.0f) },
384     { Vector2(0.0f, 1.0f) },
385     { Vector2(1.0f, 1.0f) }
386   };
387
388   VertexNormal normals [] = {
389     { Vector3(0.0f, 0.0f, 1.0f) },
390     { Vector3(0.0f, 0.0f, 1.0f) },
391     { Vector3(0.0f, 0.0f, 1.0f) },
392     { Vector3(0.0f, 0.0f, 1.0f) }
393   };
394
395   unsigned int numberOfVertices = sizeof(vertices)/sizeof(VertexPosition);
396
397   //Vertices
398   Property::Map positionVertexFormat;
399   positionVertexFormat["aPosition"] = Property::VECTOR2;
400   PropertyBuffer positionVertices = PropertyBuffer::New( positionVertexFormat );
401   positionVertices.SetData( vertices, numberOfVertices );
402
403   //Textures
404   Property::Map textureVertexFormat;
405   textureVertexFormat["aTexture"] = Property::VECTOR2;
406   PropertyBuffer textureVertices = PropertyBuffer::New( textureVertexFormat );
407   textureVertices.SetData( textures, numberOfVertices );
408
409   //Normals
410   Property::Map normalVertexFormat;
411   normalVertexFormat["aNormal"] = Property::VECTOR3;
412   PropertyBuffer normalVertices = PropertyBuffer::New( normalVertexFormat );
413   normalVertices.SetData( normals, numberOfVertices );
414
415   //Indices
416   unsigned short indices[] = { 0, 3, 1, 0, 2, 3 };
417
418   // Create the geometry object
419   Geometry texturedQuadGeometry = Geometry::New();
420   texturedQuadGeometry.AddVertexBuffer( positionVertices );
421   texturedQuadGeometry.AddVertexBuffer( textureVertices );
422   texturedQuadGeometry.AddVertexBuffer( normalVertices );
423
424   texturedQuadGeometry.SetIndexBuffer ( &indices[0], sizeof( indices )/ sizeof( indices[0] ) );
425
426   return texturedQuadGeometry;
427 }
428
429 /**
430  * Create a mesh actor for the metaballs
431  */
432 void MetaballRefracController::CreateMetaballActors()
433 {
434   //We create metaball structures
435   //With MeshData Textured
436   float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
437
438   //Create the renderer for the metaballs
439   Shader shader = Shader::New( METABALL_VERTEX_SHADER, METABALL_FRAG_SHADER );
440   Geometry metaballGeom = CreateGeometry();
441   Renderer renderer = Renderer::New( metaballGeom, shader );
442   renderer.SetProperty( Renderer::Property::BLENDING_MODE, BlendingMode::ON );
443   renderer.SetBlendFunc(BlendingFactor::ONE, BlendingFactor::ONE, BlendingFactor::ONE, BlendingFactor::ONE);
444
445   //Each metaball has a different radius
446   mMetaballs[0].radius = mMetaballs[0].initRadius = 0.0145f;
447   mMetaballs[1].radius = mMetaballs[1].initRadius = 0.012f;
448   mMetaballs[2].radius = mMetaballs[2].initRadius = 0.0135f;
449   mMetaballs[3].radius = mMetaballs[3].initRadius = 0.0135f;
450
451   //Initialization of each of the metaballs
452   for (int i = 0 ; i < METABALL_NUMBER ; i++)
453   {
454     mMetaballs[i].position = Vector2(0.0f, 0.0f);
455
456     mMetaballs[i].actor = Actor::New( );
457     mMetaballs[i].actor.SetName("Metaball");
458     mMetaballs[i].actor.SetScale( 1.0f );
459     mMetaballs[i].actor.SetParentOrigin( ParentOrigin::CENTER );
460
461
462     mMetaballs[i].actor.AddRenderer( renderer );
463
464     mMetaballs[i].positionIndex = mMetaballs[i].actor.RegisterProperty( "uPositionMetaball", mMetaballs[i].position );
465
466     mMetaballs[i].positionVarIndex = mMetaballs[i].actor.RegisterProperty( "uPositionVar", Vector2(0.f,0.f) );
467
468     mMetaballs[i].gravityIndex = mMetaballs[i].actor.RegisterProperty( "uGravityVector", Vector2(0.f,0.f) );
469
470     mMetaballs[i].radiusIndex = mMetaballs[i].actor.RegisterProperty( "uRadius", mMetaballs[i].radius );
471
472     mMetaballs[i].radiusVarIndex = mMetaballs[i].actor.RegisterProperty( "uRadiusVar", 0.f );
473
474     mMetaballs[i].aspectIndex = mMetaballs[i].actor.RegisterProperty( "uAspect", aspect );
475
476     mMetaballs[i].actor.SetSize(400, 400);
477   }
478
479   //Root creation
480   mMetaballRoot = Actor::New();
481   mMetaballRoot.SetParentOrigin( ParentOrigin::CENTER );
482   for (int i = 0 ; i < METABALL_NUMBER ; i++)
483   {
484     mMetaballRoot.Add( mMetaballs[i].actor );
485   }
486
487   //Initialization of variables related to metaballs
488   mMetaballPosVariation = Vector2(0,0);
489   mMetaballPosVariationFrom = Vector2(0,0);
490   mMetaballPosVariationTo = Vector2(0,0);
491   mCurrentTouchPosition = Vector2(0,0);
492 }
493
494 /**
495  * Create the render task and FBO to render the metaballs into a texture
496  */
497 void MetaballRefracController::CreateMetaballImage()
498 {
499   //We create an FBO and a render task to create to render the metaballs with a fragment shader
500   Stage stage = Stage::GetCurrent();
501   mMetaballFBO = FrameBufferImage::New(mScreenSize.x, mScreenSize.y );
502
503   stage.Add(mMetaballRoot);
504
505   //Creation of the render task used to render the metaballs
506   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
507   RenderTask task = taskList.CreateTask();
508   task.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
509   task.SetSourceActor( mMetaballRoot );
510   task.SetExclusive(true);
511   task.SetClearColor( Color::BLACK );
512   task.SetClearEnabled( true );
513   task.SetTargetFrameBuffer( mMetaballFBO );
514 }
515
516 /**
517  * Create a mesh image to render the final composition
518  */
519 void MetaballRefracController::AddRefractionImage()
520 {
521   //Creation of the composition image
522
523   //Create geometry
524   Geometry metaballGeom = CreateGeometryComposition();
525
526   //Create Refraction shader and renderer
527   mShaderRefraction = Shader::New( METABALL_VERTEX_SHADER, REFRACTION_FRAG_SHADER );
528
529   //Create new texture set
530   mTextureSetRefraction = TextureSet::New();
531   mTextureSetRefraction.SetImage( 0u, mBackImage );
532   mTextureSetRefraction.SetImage( 1u, mMetaballFBO );
533
534   //Create normal shader
535   mShaderNormal = Shader::New( METABALL_VERTEX_SHADER, FRAG_SHADER );
536
537   //Create new texture set
538   mTextureSetNormal = TextureSet::New();
539   mTextureSetNormal.SetImage( 0u, mBackImage );
540
541   //Create actor
542   mCompositionActor = Actor::New( );
543   mCompositionActor.SetParentOrigin(ParentOrigin::CENTER);
544   mCompositionActor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
545   mCompositionActor.SetSize(mScreenSize.x, mScreenSize.y);
546
547   mRendererRefraction = Renderer::New( metaballGeom, mShaderNormal );
548   mRendererRefraction.SetTextures( mTextureSetNormal );
549   mCompositionActor.AddRenderer( mRendererRefraction );
550
551   Stage stage = Stage::GetCurrent();
552   stage.Add( mCompositionActor );
553 }
554
555 /**
556  * Creation of all the metaballs animations (gravity, movement, size, etc.)
557  */
558 void MetaballRefracController::CreateAnimations()
559 {
560   int i = 0;
561   float key;
562
563   mPositionVarAnimation[1] = Animation::New(2.f);
564   mPositionVarAnimation[1].SetLooping( false );
565   mPositionVarAnimation[1].Pause();
566   mPositionVarAnimation[1].FinishedSignal().Connect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
567
568   KeyFrames keySinCosVariation = KeyFrames::New();
569   Vector2 sinCosVariation(0,0);
570   for ( i = 0 ; i < 360 ; i++)
571   {
572     sinCosVariation.x = 0.05f * (-sin(i * Math::PI/180.f) + cos(i * Math::PI/180.f));
573     sinCosVariation.y = 0.05f * (sin(i * Math::PI/180.f) - cos(i * Math::PI/180.f));
574     key = i/360.f;
575     keySinCosVariation.Add(key, sinCosVariation);
576   }
577
578   mPositionVarAnimation[2] = Animation::New(6.f);
579   mPositionVarAnimation[2].AnimateBetween(Property( mMetaballs[2].actor, mMetaballs[2].positionVarIndex ), keySinCosVariation);
580   mPositionVarAnimation[2].SetLooping( true );
581   mPositionVarAnimation[2].Pause();
582
583   KeyFrames keyCosSinVariation = KeyFrames::New();
584   Vector2 cosSinVariation(0,0);
585   for ( i = 0 ; i < 360 ; i++)
586   {
587     cosSinVariation.x = 0.05f * (-sin(i * Math::PI/180.f) - cos(i * Math::PI/180.f));
588     cosSinVariation.y = 0.05f * (sin(i * Math::PI/180.f) + cos(i * Math::PI/180.f));
589     key = i/360.f;
590     keyCosSinVariation.Add(key, cosSinVariation);
591   }
592
593   mPositionVarAnimation[3] = Animation::New(6.f);
594   mPositionVarAnimation[3].AnimateBetween(Property( mMetaballs[3].actor, mMetaballs[3].positionVarIndex ), keyCosSinVariation);
595   mPositionVarAnimation[3].SetLooping( true );
596   mPositionVarAnimation[3].Pause();
597
598   //Animations for gravity
599   for ( i = 0 ; i < METABALL_NUMBER ; i++)
600   {
601     mGravityAnimation[i] = Animation::New(25.f);
602     mGravityAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].gravityIndex ), mGravity * 25.f * 3.f);
603     mGravityAnimation[i].SetLooping( false );
604     mGravityAnimation[i].Pause();
605   }
606
607   //Animation to decrease size of metaballs when there is no click
608   for ( i = 0 ; i < METABALL_NUMBER ; i++)
609   {
610     mRadiusDecAnimation[i] = Animation::New(25.f);
611     mRadiusDecAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), -0.004f * 25.f * 3.f);
612     mRadiusDecAnimation[i].SetLooping( false );
613     mRadiusDecAnimation[i].Pause();
614   }
615
616   //Animation to grow the size of the metaballs the first second of the click
617   for ( i = 0 ; i < METABALL_NUMBER ; i++)
618   {
619     mRadiusIncFastAnimation[i] = Animation::New(0.3f);
620     mRadiusIncFastAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), 0.06f);
621     mRadiusIncFastAnimation[i].SetLooping( false );
622     mRadiusIncFastAnimation[i].Pause();
623   }
624   mRadiusIncFastAnimation[0].FinishedSignal().Connect( this, &MetaballRefracController::LaunchRadiusIncSlowAnimations );
625
626   //Animation to grow the size of the metaballs afterwards
627   for ( i = 0 ; i < METABALL_NUMBER ; i++)
628   {
629     mRadiusIncSlowAnimation[i] = Animation::New(20.f);
630     mRadiusIncSlowAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), 0.04f);
631     mRadiusIncSlowAnimation[i].SetLooping( false );
632     mRadiusIncSlowAnimation[i].Pause();
633   }
634
635   //keyframes of a sin function
636   KeyFrames keySin = KeyFrames::New();
637   float val;
638   for ( i = 0 ; i < 360 ; i++)
639   {
640     val = 0.01f * sin(i * Math::PI/180.f);
641     key = i/360.f;
642     keySin.Add(key, val);
643   }
644
645   //Animation to change the size of the metaball
646   mRadiusVarAnimation[2] = Animation::New(8.f);
647   mRadiusVarAnimation[2].AnimateBetween(Property( mMetaballs[2].actor, mMetaballs[2].radiusVarIndex ), keySin);
648   mRadiusVarAnimation[2].SetLooping( true );
649
650   //keyframes of a cos function
651   KeyFrames keyCos = KeyFrames::New();
652   for ( i = 0 ; i < 360 ; i++)
653   {
654     val = 0.01f * cos(i * Math::PI/180.f);
655     key = i/360.f;
656     keyCos.Add(key, val);
657   }
658
659   //Animation to change the size of the metaball
660   mRadiusVarAnimation[3] = Animation::New(8.f);
661   mRadiusVarAnimation[3].AnimateBetween(Property( mMetaballs[3].actor, mMetaballs[3].radiusVarIndex ), keyCos);
662   mRadiusVarAnimation[3].SetLooping( true );
663 }
664
665 /**
666  * Function to launch the animation to get the metaball[1] back to the center
667  */
668 void MetaballRefracController::LaunchGetBackToPositionAnimation(Animation &source)
669 {
670   mMetaballPosVariationTo = Vector2(0,0);
671
672   mPositionVarAnimation[1] = Animation::New(1.f);
673   mPositionVarAnimation[1].SetLooping( false );
674   mPositionVarAnimation[1].AnimateTo(Property( mMetaballs[1].actor, mMetaballs[1].positionVarIndex ), Vector2(0,0));
675   mPositionVarAnimation[1].Play();
676 }
677
678 /**
679  * Function to launch the gro slow radius for the metaballs, and also the small variations for metaball[2] and [3]
680  */
681 void MetaballRefracController::LaunchRadiusIncSlowAnimations(Animation &source)
682 {
683   for (int i = 0 ; i < METABALL_NUMBER ; i++)
684   {
685     mRadiusIncSlowAnimation[i].Play();
686   }
687   mPositionVarAnimation[2].Play();
688   mPositionVarAnimation[3].Play();
689 }
690
691 /**
692  * Function to stop all animations related to the click of the user in the screen
693  */
694 void MetaballRefracController::StopClickAnimations()
695 {
696   for (int i = 0 ; i < METABALL_NUMBER ; i++)
697   {
698     mRadiusIncSlowAnimation[i].Stop();
699     mRadiusIncFastAnimation[i].Stop();
700   }
701   mPositionVarAnimation[1].Stop();
702   mPositionVarAnimation[2].Stop();
703   mPositionVarAnimation[3].Stop();
704 }
705
706 /**
707  * Function to stop all animations related to the after click of the user in the screen
708  */
709 void MetaballRefracController::StopAfterClickAnimations()
710 {
711   for (int i = 0 ; i < METABALL_NUMBER ; i++)
712   {
713     mGravityAnimation[i].Stop();
714     mRadiusDecAnimation[i].Stop();
715
716     mMetaballs[i].radius = mMetaballs[i].initRadius;
717
718     mMetaballs[i].actor.SetProperty(mMetaballs[i].gravityIndex, Vector2(0,0));
719     mMetaballs[i].actor.SetProperty(mMetaballs[i].radiusIndex, mMetaballs[i].radius);
720     mMetaballs[i].actor.SetProperty(mMetaballs[i].radiusVarIndex, 0.f);
721   }
722   mRadiusVarAnimation[2].Stop();
723   mRadiusVarAnimation[3].Stop();
724 }
725
726 /*
727  * Function that resets the sate of the different Metaballs
728  */
729 void MetaballRefracController::ResetMetaballsState()
730 {
731   mRendererRefraction.SetTextures(mTextureSetNormal);
732   mRendererRefraction.SetShader( mShaderNormal );
733
734   for (int i = 0 ; i < METABALL_NUMBER ; i++)
735   {
736     mMetaballs[i].radius = mMetaballs[i].initRadius;
737   }
738
739   mMetaballPosVariationTo = Vector2(0,0);
740   mMetaballPosVariationFrom = Vector2(0,0);
741   mMetaballPosVariation = Vector2(0,0);
742
743   mGravityVar = Vector2(0,0);
744 }
745
746 /**
747  * Function to set the actual position of the metaballs when the user clicks the screen
748  */
749 void MetaballRefracController::SetPositionToMetaballs(Vector2 & metaballCenter)
750 {
751   //We set the position for the metaballs based on click position
752   for (int i = 0 ; i < METABALL_NUMBER ; i++)
753   {
754     mMetaballs[i].position = metaballCenter;
755     mMetaballs[i].actor.SetProperty(mMetaballs[i].positionIndex, mMetaballs[0].position);  // 0 y no i ?!?!?!
756   }
757 }
758
759 bool MetaballRefracController::OnTouch( Actor actor, const TouchEvent& touch )
760 {
761   const TouchPoint &point = touch.GetPoint(0);
762   float aspectR = mScreenSize.y / mScreenSize.x;
763   switch(point.state)
764   {
765     case TouchPoint::Down:
766     {
767       StopAfterClickAnimations();
768       for (int i = 0 ; i < METABALL_NUMBER ; i++)
769         mRadiusIncFastAnimation[i].Play();
770       mRadiusVarAnimation[2].Play();
771       mRadiusVarAnimation[3].Play();
772
773       //We draw with the refraction-composition shader
774       mRendererRefraction.SetTextures(mTextureSetRefraction);
775       mRendererRefraction.SetShader( mShaderRefraction );
776       mCurrentTouchPosition = point.screen;
777
778       //we use the click position for the metaballs
779       Vector2 metaballCenter = Vector2((point.screen.x / mScreenSize.x) - 0.5, (aspectR * (mScreenSize.y - point.screen.y) / mScreenSize.y) - 0.5) * 2.0;
780       SetPositionToMetaballs(metaballCenter);
781       break;
782     }
783     case TouchPoint::Motion:
784     {
785       Vector2 displacement = point.screen - mCurrentTouchPosition;
786       mCurrentTouchPosition = point.screen;
787
788       mMetaballPosVariationTo.x += (displacement.x / mScreenSize.x) * 2.2;
789       mMetaballPosVariationTo.y += (- displacement.y / mScreenSize.y) * 2.2;
790
791       if (mPositionVarAnimation[1])
792       {
793         mPositionVarAnimation[1].FinishedSignal().Disconnect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
794         mPositionVarAnimation[1].Stop();
795       }
796       mPositionVarAnimation[1] = Animation::New(1.f);
797       mPositionVarAnimation[1].SetLooping( false );
798       mPositionVarAnimation[1].AnimateTo(Property( mMetaballs[1].actor, mMetaballs[1].positionVarIndex ), mMetaballPosVariationTo);
799       mPositionVarAnimation[1].FinishedSignal().Connect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
800       mPositionVarAnimation[1].Play();
801
802       //we use the click position for the metaballs
803       Vector2 metaballCenter = Vector2((point.screen.x / mScreenSize.x) - 0.5, (aspectR * (mScreenSize.y - point.screen.y) / mScreenSize.y) - 0.5) * 2.0;
804       SetPositionToMetaballs(metaballCenter);
805       break;
806     }
807     case TouchPoint::Up:
808     case TouchPoint::Leave:
809     case TouchPoint::Interrupted:
810     {
811       //Stop click animations
812       StopClickAnimations();
813
814       //Launch out of screen animations
815       for (int i = 0 ; i < METABALL_NUMBER ; i++)
816         mGravityAnimation[i].Play();
817
818       for (int i = 0 ; i < METABALL_NUMBER ; i++)
819         mRadiusDecAnimation[i].Play();
820
821       break;
822     }
823     default:
824       break;
825     }
826   return true;
827 }
828
829
830 void MetaballRefracController::OnKeyEvent(const KeyEvent& event)
831 {
832   if(event.state == KeyEvent::Down)
833   {
834     if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
835     {
836       mApplication.Quit();
837     }
838   }
839 }
840
841
842 //
843 //
844 //-----------------------------------------------------------------------------------------------
845
846 void RunTest( Application& application )
847 {
848   MetaballRefracController test( application );
849
850   application.MainLoop();
851 }
852
853 // Entry point for Linux & Tizen applications
854 //
855 int DALI_EXPORT_API main( int argc, char **argv )
856 {
857   Application application = Application::New( &argc, &argv );
858
859   RunTest( application );
860
861   return 0;
862 }