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