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