Prepare for Tizen 4.0 Build
[platform/core/uifw/dali-demo.git] / examples / metaball-refrac / metaball-refrac-example.cpp
1 /*
2  * Copyright (c) 2016 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/images/texture-set-image.h>
20 #include <dali/public-api/rendering/renderer.h>
21 #include <dali-toolkit/dali-toolkit.h>
22
23 #include <cstdio>
24 #include <string>
25 #include "shared/utility.h"
26
27 using namespace Dali;
28 using namespace Dali::Toolkit;
29
30 namespace
31 {
32 const char * const BACKGROUND_IMAGE( DEMO_IMAGE_DIR "background-2.jpg" );
33 const char * const TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
34
35 const float GRAVITY_X(0);
36 const float GRAVITY_Y(-0.09);
37 }
38
39 #define METABALL_NUMBER 4
40
41 const char*const METABALL_VERTEX_SHADER = DALI_COMPOSE_SHADER (
42     attribute mediump vec2    aPosition;\n
43     attribute mediump vec2    aTexture;\n
44     attribute mediump vec3    aNormal;\n
45     uniform   mediump mat4    uMvpMatrix;\n
46     uniform   mediump vec3    uSize;\n
47     uniform   lowp    vec4    uColor;\n
48     varying   mediump vec2    vTexCoord;\n
49
50     void main()\n
51     {\n
52       mediump vec4 vertexPosition = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n
53       vertexPosition = uMvpMatrix * vertexPosition;\n
54       gl_Position = vertexPosition;\n
55       vTexCoord = aTexture;\n
56     }\n
57 );
58
59
60 const char*const METABALL_FRAG_SHADER = DALI_COMPOSE_SHADER (
61   precision mediump float;\n
62   varying vec2 vTexCoord;\n
63   uniform vec2 uPositionMetaball;\n
64   uniform vec2 uPositionVar;\n
65   uniform vec2 uGravityVector;\n
66   uniform float uRadius;\n
67   uniform float uRadiusVar;\n
68   uniform float uAspect;\n
69   void main()\n
70   {\n
71     vec2 adjustedCoords = vTexCoord * 2.0 - 1.0;\n
72     vec2 finalMetaballPosition = uPositionMetaball + uGravityVector + uPositionVar;\n
73
74     float distance = (adjustedCoords.x - finalMetaballPosition.x) * (adjustedCoords.x - finalMetaballPosition.x) +
75                      (adjustedCoords.y - finalMetaballPosition.y) * (adjustedCoords.y - finalMetaballPosition.y);\n
76     float finalRadius = uRadius + uRadiusVar;\n
77     float color = finalRadius / sqrt( distance );\n
78     vec2 bordercolor = vec2(0.0,0.0);\n
79     if (vTexCoord.x < 0.1)\n
80     {\n
81       bordercolor.x = (0.1 - vTexCoord.x) * 0.8;\n
82     }\n
83     if (vTexCoord.x > 0.9)\n
84     {\n
85       bordercolor.x = (vTexCoord.x - 0.9) * 0.8;\n
86     }\n
87     if (vTexCoord.y < 0.1)\n
88     {\n
89       bordercolor.y = (0.1 - vTexCoord.y) * 0.8;\n
90     }\n
91     if (vTexCoord.y > (0.9 * uAspect))\n
92     {\n
93       bordercolor.y = (vTexCoord.y - (0.9 * uAspect)) * 0.8;\n
94     }\n
95     float border = (bordercolor.x + bordercolor.y) * 0.5;\n
96     gl_FragColor = vec4(color + border,color + border,color + border,1.0);\n
97   }\n
98 );
99
100 const char*const REFRACTION_FRAG_SHADER = DALI_COMPOSE_SHADER (
101   precision mediump float;\n
102   varying vec2 vTexCoord;\n
103   uniform sampler2D sTexture;\n
104   uniform sampler2D sEffect;\n
105   void main()\n
106   {\n
107     vec4 metaColor = texture2D(sEffect, vTexCoord);\n
108     vec2 zoomCoords;\n
109     float bright = 1.0;\n
110     if (metaColor.r > 0.85)\n
111     {\n
112       zoomCoords = ((vTexCoord - 0.5) * 0.95) + 0.5;\n
113     }\n
114     else if (metaColor.r > 0.81)\n
115     {\n
116       float interpolation = mix(0.95, 1.05, (0.85 - metaColor.r) * 50.0);\n
117       zoomCoords = ((vTexCoord - 0.5) * interpolation) + 0.5;\n
118       bright = 1.2;\n
119     }\n
120     else\n
121     {\n
122       zoomCoords = vTexCoord;\n
123     }\n
124
125     gl_FragColor = texture2D(sTexture, zoomCoords) * bright;\n
126   }\n
127  );
128
129 const char*const FRAG_SHADER = DALI_COMPOSE_SHADER (
130   precision mediump float;\n
131   varying vec2 vTexCoord;\n
132   uniform sampler2D sTexture;\n
133   void main()\n
134   {\n
135     gl_FragColor = texture2D(sTexture, vTexCoord);\n
136   }\n
137 );
138
139
140 struct MetaballInfo
141 {
142   Actor   actor;
143   Vector2 position;
144   float   radius;
145   float   initRadius;
146
147   //Properties needed for animations
148   Property::Index positionIndex;
149   Property::Index positionVarIndex;
150   Property::Index gravityIndex;
151   Property::Index radiusIndex;
152   Property::Index radiusVarIndex;
153   Property::Index aspectIndex;
154 };
155
156
157 /***************************************************************************/
158 /* Demo using Metaballs for Refraction when clicking the screen ************/
159 /* The concept is similar to the Note 5 ScreenLock              ************/
160 /***************************************************************************/
161 class MetaballRefracController : public ConnectionTracker
162 {
163 public:
164   MetaballRefracController( Application& application );
165   ~MetaballRefracController();
166
167   void Create( Application& app );
168   bool OnTouch( Actor actor, const TouchData& touch );
169   void OnKeyEvent(const KeyEvent& event);
170
171   void SetGravity(const Vector2 & gravity);
172
173
174 private:
175   Application&      mApplication;
176   Vector2           mScreenSize;
177
178   Layer             mContentLayer;
179
180   Image             mBackImage;
181   FrameBufferImage  mMetaballFBO;
182
183   Actor             mMetaballRoot;
184   MetaballInfo      mMetaballs[METABALL_NUMBER];
185
186   Actor             mCompositionActor;
187
188   //Motion
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 = DemoHelper::LoadImage( 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().TouchSignal().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::BLEND_MODE, BlendMode::ON );
443   renderer.SetProperty( Renderer::Property::BLEND_FACTOR_SRC_RGB,    BlendFactor::ONE );
444   renderer.SetProperty( Renderer::Property::BLEND_FACTOR_DEST_RGB,   BlendFactor::ONE );
445   renderer.SetProperty( Renderer::Property::BLEND_FACTOR_SRC_ALPHA,  BlendFactor::ONE );
446   renderer.SetProperty( Renderer::Property::BLEND_FACTOR_DEST_ALPHA, BlendFactor::ONE  );
447
448   //Each metaball has a different radius
449   mMetaballs[0].radius = mMetaballs[0].initRadius = 0.0145f;
450   mMetaballs[1].radius = mMetaballs[1].initRadius = 0.012f;
451   mMetaballs[2].radius = mMetaballs[2].initRadius = 0.0135f;
452   mMetaballs[3].radius = mMetaballs[3].initRadius = 0.0135f;
453
454   //Initialization of each of the metaballs
455   for (int i = 0 ; i < METABALL_NUMBER ; i++)
456   {
457     mMetaballs[i].position = Vector2(0.0f, 0.0f);
458
459     mMetaballs[i].actor = Actor::New( );
460     mMetaballs[i].actor.SetName("Metaball");
461     mMetaballs[i].actor.SetScale( 1.0f );
462     mMetaballs[i].actor.SetParentOrigin( ParentOrigin::CENTER );
463
464
465     mMetaballs[i].actor.AddRenderer( renderer );
466
467     mMetaballs[i].positionIndex = mMetaballs[i].actor.RegisterProperty( "uPositionMetaball", mMetaballs[i].position );
468
469     mMetaballs[i].positionVarIndex = mMetaballs[i].actor.RegisterProperty( "uPositionVar", Vector2(0.f,0.f) );
470
471     mMetaballs[i].gravityIndex = mMetaballs[i].actor.RegisterProperty( "uGravityVector", Vector2(0.f,0.f) );
472
473     mMetaballs[i].radiusIndex = mMetaballs[i].actor.RegisterProperty( "uRadius", mMetaballs[i].radius );
474
475     mMetaballs[i].radiusVarIndex = mMetaballs[i].actor.RegisterProperty( "uRadiusVar", 0.f );
476
477     mMetaballs[i].aspectIndex = mMetaballs[i].actor.RegisterProperty( "uAspect", aspect );
478
479     mMetaballs[i].actor.SetSize(400, 400);
480   }
481
482   //Root creation
483   mMetaballRoot = Actor::New();
484   mMetaballRoot.SetParentOrigin( ParentOrigin::CENTER );
485   for (int i = 0 ; i < METABALL_NUMBER ; i++)
486   {
487     mMetaballRoot.Add( mMetaballs[i].actor );
488   }
489
490   //Initialization of variables related to metaballs
491   mMetaballPosVariation = Vector2(0,0);
492   mMetaballPosVariationFrom = Vector2(0,0);
493   mMetaballPosVariationTo = Vector2(0,0);
494   mCurrentTouchPosition = Vector2(0,0);
495 }
496
497 /**
498  * Create the render task and FBO to render the metaballs into a texture
499  */
500 void MetaballRefracController::CreateMetaballImage()
501 {
502   //We create an FBO and a render task to create to render the metaballs with a fragment shader
503   Stage stage = Stage::GetCurrent();
504   mMetaballFBO = FrameBufferImage::New(mScreenSize.x, mScreenSize.y );
505
506   stage.Add(mMetaballRoot);
507
508   //Creation of the render task used to render the metaballs
509   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
510   RenderTask task = taskList.CreateTask();
511   task.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
512   task.SetSourceActor( mMetaballRoot );
513   task.SetExclusive(true);
514   task.SetClearColor( Color::BLACK );
515   task.SetClearEnabled( true );
516   task.SetTargetFrameBuffer( mMetaballFBO );
517 }
518
519 /**
520  * Create a mesh image to render the final composition
521  */
522 void MetaballRefracController::AddRefractionImage()
523 {
524   //Creation of the composition image
525
526   //Create geometry
527   Geometry metaballGeom = CreateGeometryComposition();
528
529   //Create Refraction shader and renderer
530   mShaderRefraction = Shader::New( METABALL_VERTEX_SHADER, REFRACTION_FRAG_SHADER );
531
532   //Create new texture set
533   mTextureSetRefraction = TextureSet::New();
534   TextureSetImage( mTextureSetRefraction, 0u, mBackImage );
535   TextureSetImage( mTextureSetRefraction, 1u, mMetaballFBO );
536
537   //Create normal shader
538   mShaderNormal = Shader::New( METABALL_VERTEX_SHADER, FRAG_SHADER );
539
540   //Create new texture set
541   mTextureSetNormal = TextureSet::New();
542   TextureSetImage( mTextureSetNormal, 0u, mBackImage );
543
544   //Create actor
545   mCompositionActor = Actor::New( );
546   mCompositionActor.SetParentOrigin(ParentOrigin::CENTER);
547   mCompositionActor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
548   mCompositionActor.SetSize(mScreenSize.x, mScreenSize.y);
549
550   mRendererRefraction = Renderer::New( metaballGeom, mShaderNormal );
551   mRendererRefraction.SetTextures( mTextureSetNormal );
552   mCompositionActor.AddRenderer( mRendererRefraction );
553
554   Stage stage = Stage::GetCurrent();
555   stage.Add( mCompositionActor );
556 }
557
558 /**
559  * Creation of all the metaballs animations (gravity, movement, size, etc.)
560  */
561 void MetaballRefracController::CreateAnimations()
562 {
563   int i = 0;
564   float key;
565
566   mPositionVarAnimation[1] = Animation::New(2.f);
567   mPositionVarAnimation[1].SetLooping( false );
568   mPositionVarAnimation[1].Pause();
569   mPositionVarAnimation[1].FinishedSignal().Connect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
570
571   KeyFrames keySinCosVariation = KeyFrames::New();
572   Vector2 sinCosVariation(0,0);
573   for ( i = 0 ; i < 360 ; i++)
574   {
575     sinCosVariation.x = 0.05f * (-sin(i * Math::PI/180.f) + cos(i * Math::PI/180.f));
576     sinCosVariation.y = 0.05f * (sin(i * Math::PI/180.f) - cos(i * Math::PI/180.f));
577     key = i/360.f;
578     keySinCosVariation.Add(key, sinCosVariation);
579   }
580
581   mPositionVarAnimation[2] = Animation::New(6.f);
582   mPositionVarAnimation[2].AnimateBetween(Property( mMetaballs[2].actor, mMetaballs[2].positionVarIndex ), keySinCosVariation);
583   mPositionVarAnimation[2].SetLooping( true );
584   mPositionVarAnimation[2].Pause();
585
586   KeyFrames keyCosSinVariation = KeyFrames::New();
587   Vector2 cosSinVariation(0,0);
588   for ( i = 0 ; i < 360 ; i++)
589   {
590     cosSinVariation.x = 0.05f * (-sin(i * Math::PI/180.f) - cos(i * Math::PI/180.f));
591     cosSinVariation.y = 0.05f * (sin(i * Math::PI/180.f) + cos(i * Math::PI/180.f));
592     key = i/360.f;
593     keyCosSinVariation.Add(key, cosSinVariation);
594   }
595
596   mPositionVarAnimation[3] = Animation::New(6.f);
597   mPositionVarAnimation[3].AnimateBetween(Property( mMetaballs[3].actor, mMetaballs[3].positionVarIndex ), keyCosSinVariation);
598   mPositionVarAnimation[3].SetLooping( true );
599   mPositionVarAnimation[3].Pause();
600
601   //Animations for gravity
602   for ( i = 0 ; i < METABALL_NUMBER ; i++)
603   {
604     mGravityAnimation[i] = Animation::New(25.f);
605     mGravityAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].gravityIndex ), mGravity * 25.f * 3.f);
606     mGravityAnimation[i].SetLooping( false );
607     mGravityAnimation[i].Pause();
608   }
609
610   //Animation to decrease size of metaballs when there is no click
611   for ( i = 0 ; i < METABALL_NUMBER ; i++)
612   {
613     mRadiusDecAnimation[i] = Animation::New(25.f);
614     mRadiusDecAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), -0.004f * 25.f * 3.f);
615     mRadiusDecAnimation[i].SetLooping( false );
616     mRadiusDecAnimation[i].Pause();
617   }
618
619   //Animation to grow the size of the metaballs the first second of the click
620   for ( i = 0 ; i < METABALL_NUMBER ; i++)
621   {
622     mRadiusIncFastAnimation[i] = Animation::New(0.3f);
623     mRadiusIncFastAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), 0.06f);
624     mRadiusIncFastAnimation[i].SetLooping( false );
625     mRadiusIncFastAnimation[i].Pause();
626   }
627   mRadiusIncFastAnimation[0].FinishedSignal().Connect( this, &MetaballRefracController::LaunchRadiusIncSlowAnimations );
628
629   //Animation to grow the size of the metaballs afterwards
630   for ( i = 0 ; i < METABALL_NUMBER ; i++)
631   {
632     mRadiusIncSlowAnimation[i] = Animation::New(20.f);
633     mRadiusIncSlowAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), 0.04f);
634     mRadiusIncSlowAnimation[i].SetLooping( false );
635     mRadiusIncSlowAnimation[i].Pause();
636   }
637
638   //keyframes of a sin function
639   KeyFrames keySin = KeyFrames::New();
640   float val;
641   for ( i = 0 ; i < 360 ; i++)
642   {
643     val = 0.01f * sin(i * Math::PI/180.f);
644     key = i/360.f;
645     keySin.Add(key, val);
646   }
647
648   //Animation to change the size of the metaball
649   mRadiusVarAnimation[2] = Animation::New(8.f);
650   mRadiusVarAnimation[2].AnimateBetween(Property( mMetaballs[2].actor, mMetaballs[2].radiusVarIndex ), keySin);
651   mRadiusVarAnimation[2].SetLooping( true );
652
653   //keyframes of a cos function
654   KeyFrames keyCos = KeyFrames::New();
655   for ( i = 0 ; i < 360 ; i++)
656   {
657     val = 0.01f * cos(i * Math::PI/180.f);
658     key = i/360.f;
659     keyCos.Add(key, val);
660   }
661
662   //Animation to change the size of the metaball
663   mRadiusVarAnimation[3] = Animation::New(8.f);
664   mRadiusVarAnimation[3].AnimateBetween(Property( mMetaballs[3].actor, mMetaballs[3].radiusVarIndex ), keyCos);
665   mRadiusVarAnimation[3].SetLooping( true );
666 }
667
668 /**
669  * Function to launch the animation to get the metaball[1] back to the center
670  */
671 void MetaballRefracController::LaunchGetBackToPositionAnimation(Animation &source)
672 {
673   mMetaballPosVariationTo = Vector2(0,0);
674
675   mPositionVarAnimation[1] = Animation::New(1.f);
676   mPositionVarAnimation[1].SetLooping( false );
677   mPositionVarAnimation[1].AnimateTo(Property( mMetaballs[1].actor, mMetaballs[1].positionVarIndex ), Vector2(0,0));
678   mPositionVarAnimation[1].Play();
679 }
680
681 /**
682  * Function to launch the gro slow radius for the metaballs, and also the small variations for metaball[2] and [3]
683  */
684 void MetaballRefracController::LaunchRadiusIncSlowAnimations(Animation &source)
685 {
686   for (int i = 0 ; i < METABALL_NUMBER ; i++)
687   {
688     mRadiusIncSlowAnimation[i].Play();
689   }
690   mPositionVarAnimation[2].Play();
691   mPositionVarAnimation[3].Play();
692 }
693
694 /**
695  * Function to stop all animations related to the click of the user in the screen
696  */
697 void MetaballRefracController::StopClickAnimations()
698 {
699   for (int i = 0 ; i < METABALL_NUMBER ; i++)
700   {
701     mRadiusIncSlowAnimation[i].Stop();
702     mRadiusIncFastAnimation[i].Stop();
703   }
704   mPositionVarAnimation[1].Stop();
705   mPositionVarAnimation[2].Stop();
706   mPositionVarAnimation[3].Stop();
707 }
708
709 /**
710  * Function to stop all animations related to the after click of the user in the screen
711  */
712 void MetaballRefracController::StopAfterClickAnimations()
713 {
714   for (int i = 0 ; i < METABALL_NUMBER ; i++)
715   {
716     mGravityAnimation[i].Stop();
717     mRadiusDecAnimation[i].Stop();
718
719     mMetaballs[i].radius = mMetaballs[i].initRadius;
720
721     mMetaballs[i].actor.SetProperty(mMetaballs[i].gravityIndex, Vector2(0,0));
722     mMetaballs[i].actor.SetProperty(mMetaballs[i].radiusIndex, mMetaballs[i].radius);
723     mMetaballs[i].actor.SetProperty(mMetaballs[i].radiusVarIndex, 0.f);
724   }
725   mRadiusVarAnimation[2].Stop();
726   mRadiusVarAnimation[3].Stop();
727 }
728
729 /*
730  * Function that resets the sate of the different Metaballs
731  */
732 void MetaballRefracController::ResetMetaballsState()
733 {
734   mRendererRefraction.SetTextures(mTextureSetNormal);
735   mRendererRefraction.SetShader( mShaderNormal );
736
737   for (int i = 0 ; i < METABALL_NUMBER ; i++)
738   {
739     mMetaballs[i].radius = mMetaballs[i].initRadius;
740   }
741
742   mMetaballPosVariationTo = Vector2(0,0);
743   mMetaballPosVariationFrom = Vector2(0,0);
744   mMetaballPosVariation = Vector2(0,0);
745
746   mGravityVar = Vector2(0,0);
747 }
748
749 /**
750  * Function to set the actual position of the metaballs when the user clicks the screen
751  */
752 void MetaballRefracController::SetPositionToMetaballs(Vector2 & metaballCenter)
753 {
754   //We set the position for the metaballs based on click position
755   for (int i = 0 ; i < METABALL_NUMBER ; i++)
756   {
757     mMetaballs[i].position = metaballCenter;
758     mMetaballs[i].actor.SetProperty(mMetaballs[i].positionIndex, mMetaballs[0].position);  // 0 y no i ?!?!?!
759   }
760 }
761
762 bool MetaballRefracController::OnTouch( Actor actor, const TouchData& touch )
763 {
764   float aspectR = mScreenSize.y / mScreenSize.x;
765   switch( touch.GetState( 0 ) )
766   {
767     case PointState::DOWN:
768     {
769       StopAfterClickAnimations();
770       for (int i = 0 ; i < METABALL_NUMBER ; i++)
771         mRadiusIncFastAnimation[i].Play();
772       mRadiusVarAnimation[2].Play();
773       mRadiusVarAnimation[3].Play();
774
775       //We draw with the refraction-composition shader
776       mRendererRefraction.SetTextures(mTextureSetRefraction);
777       mRendererRefraction.SetShader( mShaderRefraction );
778       mCurrentTouchPosition = touch.GetScreenPosition( 0 );
779
780       //we use the click position for the metaballs
781       Vector2 metaballCenter = Vector2((mCurrentTouchPosition.x / mScreenSize.x) - 0.5, (aspectR * (mScreenSize.y - mCurrentTouchPosition.y) / mScreenSize.y) - 0.5) * 2.0;
782       SetPositionToMetaballs(metaballCenter);
783       break;
784     }
785     case PointState::MOTION:
786     {
787       Vector2 screen = touch.GetScreenPosition( 0 );
788       Vector2 displacement = screen - mCurrentTouchPosition;
789       mCurrentTouchPosition = screen;
790
791       mMetaballPosVariationTo.x += (displacement.x / mScreenSize.x) * 2.2;
792       mMetaballPosVariationTo.y += (- displacement.y / mScreenSize.y) * 2.2;
793
794       if (mPositionVarAnimation[1])
795       {
796         mPositionVarAnimation[1].FinishedSignal().Disconnect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
797         mPositionVarAnimation[1].Stop();
798       }
799       mPositionVarAnimation[1] = Animation::New(1.f);
800       mPositionVarAnimation[1].SetLooping( false );
801       mPositionVarAnimation[1].AnimateTo(Property( mMetaballs[1].actor, mMetaballs[1].positionVarIndex ), mMetaballPosVariationTo);
802       mPositionVarAnimation[1].FinishedSignal().Connect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
803       mPositionVarAnimation[1].Play();
804
805       //we use the click position for the metaballs
806       Vector2 metaballCenter = Vector2((screen.x / mScreenSize.x) - 0.5, (aspectR * (mScreenSize.y - screen.y) / mScreenSize.y) - 0.5) * 2.0;
807       SetPositionToMetaballs(metaballCenter);
808       break;
809     }
810     case PointState::UP:
811     case PointState::LEAVE:
812     case PointState::INTERRUPTED:
813     {
814       //Stop click animations
815       StopClickAnimations();
816
817       //Launch out of screen animations
818       for (int i = 0 ; i < METABALL_NUMBER ; i++)
819         mGravityAnimation[i].Play();
820
821       for (int i = 0 ; i < METABALL_NUMBER ; i++)
822         mRadiusDecAnimation[i].Play();
823
824       break;
825     }
826     default:
827       break;
828     }
829   return true;
830 }
831
832
833 void MetaballRefracController::OnKeyEvent(const KeyEvent& event)
834 {
835   if(event.state == KeyEvent::Down)
836   {
837     if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
838     {
839       mApplication.Quit();
840     }
841   }
842 }
843
844
845 //
846 //
847 //-----------------------------------------------------------------------------------------------
848
849 void RunTest( Application& application )
850 {
851   MetaballRefracController test( application );
852
853   application.MainLoop();
854 }
855
856 // Entry point for Linux & Tizen applications
857 //
858 int DALI_EXPORT_API main( int argc, char **argv )
859 {
860   Application application = Application::New( &argc, &argv );
861
862   RunTest( application );
863
864   return 0;
865 }