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