PropertyBuffer SetData clean-up
[platform/core/uifw/dali-demo.git] / examples / metaball-refrac / metaball-refrac-example.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <dali/dali.h>
19 #include <dali/devel-api/rendering/renderer.h>
20 #include <dali-toolkit/dali-toolkit.h>
21
22 #include <cstdio>
23 #include <string>
24
25 using namespace Dali;
26 using namespace Dali::Toolkit;
27
28 namespace
29 {
30 const char * const BACKGROUND_IMAGE( DEMO_IMAGE_DIR "background-2.jpg" );
31 const char * const TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
32
33 const float GRAVITY_X(0);
34 const float GRAVITY_Y(-0.09);
35 }
36
37 #define METABALL_NUMBER 4
38
39 const char*const METABALL_VERTEX_SHADER = DALI_COMPOSE_SHADER (
40     attribute mediump vec2    aPosition;\n
41     attribute mediump vec2    aTexture;\n
42     attribute mediump vec3    aNormal;\n
43     uniform   mediump mat4    uMvpMatrix;\n
44     uniform   mediump vec3    uSize;\n
45     uniform   lowp    vec4    uColor;\n
46     varying   mediump vec2    vTexCoord;\n
47
48     void main()\n
49     {\n
50       mediump vec4 vertexPosition = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n
51       vertexPosition = uMvpMatrix * vertexPosition;\n
52       gl_Position = vertexPosition;\n
53       vTexCoord = aTexture;\n
54     }\n
55 );
56
57
58 const char*const METABALL_FRAG_SHADER = DALI_COMPOSE_SHADER (
59   precision mediump float;\n
60   varying vec2 vTexCoord;\n
61   uniform vec2 uPositionMetaball;\n
62   uniform vec2 uPositionVar;\n
63   uniform vec2 uGravityVector;\n
64   uniform float uRadius;\n
65   uniform float uRadiusVar;\n
66   uniform float uAspect;\n
67   void main()\n
68   {\n
69     vec2 adjustedCoords = vTexCoord * 2.0 - 1.0;\n
70     vec2 finalMetaballPosition = uPositionMetaball + uGravityVector + uPositionVar;\n
71
72     float distance = (adjustedCoords.x - finalMetaballPosition.x) * (adjustedCoords.x - finalMetaballPosition.x) +
73                      (adjustedCoords.y - finalMetaballPosition.y) * (adjustedCoords.y - finalMetaballPosition.y);\n
74     float finalRadius = uRadius + uRadiusVar;\n
75     float color = finalRadius / sqrt( distance );\n
76     vec2 bordercolor = vec2(0.0,0.0);\n
77     if (vTexCoord.x < 0.1)\n
78     {\n
79       bordercolor.x = (0.1 - vTexCoord.x) * 0.8;\n
80     }\n
81     if (vTexCoord.x > 0.9)\n
82     {\n
83       bordercolor.x = (vTexCoord.x - 0.9) * 0.8;\n
84     }\n
85     if (vTexCoord.y < 0.1)\n
86     {\n
87       bordercolor.y = (0.1 - vTexCoord.y) * 0.8;\n
88     }\n
89     if (vTexCoord.y > (0.9 * uAspect))\n
90     {\n
91       bordercolor.y = (vTexCoord.y - (0.9 * uAspect)) * 0.8;\n
92     }\n
93     float border = (bordercolor.x + bordercolor.y) * 0.5;\n
94     gl_FragColor = vec4(color + border,color + border,color + border,1.0);\n
95   }\n
96 );
97
98 const char*const REFRACTION_FRAG_SHADER = DALI_COMPOSE_SHADER (
99   precision mediump float;\n
100   varying vec2 vTexCoord;\n
101   uniform sampler2D sTexture;\n
102   uniform sampler2D sEffect;\n
103   void main()\n
104   {\n
105     vec4 metaColor = texture2D(sEffect, vTexCoord);\n
106     vec2 zoomCoords;\n
107     float bright = 1.0;\n
108     if (metaColor.r > 0.85)\n
109     {\n
110       zoomCoords = ((vTexCoord - 0.5) * 0.95) + 0.5;\n
111     }\n
112     else if (metaColor.r > 0.81)\n
113     {\n
114       float interpolation = mix(0.95, 1.05, (0.85 - metaColor.r) * 50.0);\n
115       zoomCoords = ((vTexCoord - 0.5) * interpolation) + 0.5;\n
116       bright = 1.2;\n
117     }\n
118     else\n
119     {\n
120       zoomCoords = vTexCoord;\n
121     }\n
122
123     gl_FragColor = texture2D(sTexture, zoomCoords) * bright;\n
124   }\n
125  );
126
127 const char*const FRAG_SHADER = DALI_COMPOSE_SHADER (
128   precision mediump float;\n
129   varying vec2 vTexCoord;\n
130   uniform sampler2D sTexture;\n
131   void main()\n
132   {\n
133     gl_FragColor = texture2D(sTexture, vTexCoord);\n
134   }\n
135 );
136
137
138 struct MetaballInfo
139 {
140   //ShaderEffect shader;
141   Actor   actor;
142   Vector2 position;
143   float   radius;
144   float   initRadius;
145
146   //Properties needed for animations
147   Property::Index positionIndex;
148   Property::Index positionVarIndex;
149   Property::Index gravityIndex;
150   Property::Index radiusIndex;
151   Property::Index radiusVarIndex;
152   Property::Index aspectIndex;
153 };
154
155
156 /***************************************************************************/
157 /* Demo using Metaballs for Refraction when clicking the screen ************/
158 /* The concept is similar to the Note 5 ScreenLock              ************/
159 /***************************************************************************/
160 class MetaballRefracController : public ConnectionTracker
161 {
162 public:
163   MetaballRefracController( Application& application );
164   ~MetaballRefracController();
165
166   void Create( Application& app );
167   bool OnTouch( Actor actor, const TouchEvent& touch );
168   void OnKeyEvent(const KeyEvent& event);
169
170   void SetGravity(const Vector2 & gravity);
171
172
173 private:
174   Application&      mApplication;
175   Vector2           mScreenSize;
176
177   Layer             mContentLayer;
178
179   Image             mBackImage;
180   FrameBufferImage  mMetaballFBO;
181
182   Actor             mMetaballRoot;
183   MetaballInfo      mMetaballs[METABALL_NUMBER];
184
185   Actor             mCompositionActor;
186
187   //Motion
188   bool              mExitClick;
189   Vector2           mCurrentTouchPosition;
190   Vector2           mMetaballPosVariation;
191   Vector2           mMetaballPosVariationFrom;
192   Vector2           mMetaballPosVariationTo;
193   Vector2           mMetaballCenter;
194
195   Vector2           mGravity;
196   Vector2           mGravityVar;
197
198   Renderer          mRendererRefraction;
199   Material          mMaterialRefraction;
200   Material          mMaterialNormal;
201
202   //Animations
203   Animation         mGravityAnimation[METABALL_NUMBER];
204   Animation         mRadiusDecAnimation[METABALL_NUMBER];
205   Animation         mRadiusIncFastAnimation[METABALL_NUMBER];
206   Animation         mRadiusIncSlowAnimation[METABALL_NUMBER];
207   Animation         mRadiusVarAnimation[METABALL_NUMBER];
208   Animation         mPositionVarAnimation[METABALL_NUMBER];
209
210   //Private functions
211   Geometry          CreateGeometry();
212   Geometry          CreateGeometryComposition();
213
214   void              CreateMetaballActors();
215   void              CreateMetaballImage();
216   void              AddRefractionImage();
217   void              CreateAnimations();
218
219   void              LaunchRadiusIncSlowAnimations(Animation &source);
220   void              LaunchGetBackToPositionAnimation(Animation &source);
221
222   void              StopClickAnimations();
223   void              StopAfterClickAnimations();
224
225   void              ResetMetaballsState();
226
227   void              SetPositionToMetaballs(Vector2 & metaballCenter);
228 };
229
230
231 //-----------------------------------------------------------------------------------------------
232 //
233 //  IMPLEMENTATION
234 //
235 //----------------
236
237 MetaballRefracController::MetaballRefracController( Application& application )
238   : mApplication( application )
239 {
240   // Connect to the Application's Init signal
241   mApplication.InitSignal().Connect( this, &MetaballRefracController::Create );
242 }
243
244 MetaballRefracController::~MetaballRefracController()
245 {
246   // Nothing to do here;
247 }
248
249 /*
250  * Setter function for gravity
251  */
252 void MetaballRefracController::SetGravity(const Vector2 & gravity)
253 {
254   mGravity = gravity;
255 }
256
257 /**
258  * Main create function, it creates the metaballs and all the
259  */
260 void MetaballRefracController::Create( Application& app )
261 {
262   Stage stage = Stage::GetCurrent();
263
264   stage.KeyEventSignal().Connect(this, &MetaballRefracController::OnKeyEvent);
265
266   mScreenSize = stage.GetSize();
267
268   stage.SetBackgroundColor(Color::BLACK);
269
270   //Set background image for the view
271   mBackImage = ResourceImage::New( BACKGROUND_IMAGE );
272
273   mGravity = Vector2(GRAVITY_X,GRAVITY_Y);
274   mGravityVar = Vector2(0,0);
275
276   //Create internal data
277   CreateMetaballActors();
278   CreateMetaballImage();
279   AddRefractionImage();
280
281   CreateAnimations();
282
283   // Connect the callback to the touch signal on the mesh actor
284   stage.GetRootLayer().TouchedSignal().Connect( this, &MetaballRefracController::OnTouch );
285 }
286
287 /**
288  * Create a mesh data with the geometry for the metaball rendering
289  */
290 Geometry MetaballRefracController::CreateGeometry()
291 {
292   float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
293
294   // Create vertices and specify their color
295   float xsize = mScreenSize.x * 0.5;
296
297   //We create the meshdata for the metaballs
298   struct VertexPosition { Vector2 position; };
299   struct VertexTexture { Vector2 texture; };
300   struct VertexNormal { Vector3 normal; };
301
302   VertexPosition vertices[] = {
303     { Vector2( -xsize, -xsize * aspect) },
304     { Vector2(  xsize, -xsize * aspect) },
305     { Vector2( -xsize,  xsize * aspect) },
306     { Vector2(  xsize,  xsize * aspect) }
307   };
308
309   VertexTexture textures[] = {
310     { Vector2(0.0f, 0.0f) },
311     { Vector2(1.0f, 0.0f) },
312     { Vector2(0.0f, 1.0f * aspect) },
313     { Vector2(1.0f, 1.0f * aspect) }
314   };
315
316   VertexNormal normals [] = {
317     { Vector3(0.0f, 0.0f, 1.0f) },
318     { Vector3(0.0f, 0.0f, 1.0f) },
319     { Vector3(0.0f, 0.0f, 1.0f) },
320     { Vector3(0.0f, 0.0f, 1.0f) }
321   };
322
323   int indices[] = { 0, 3, 1, 0, 2, 3 };
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   Property::Map indicesVertexFormat;
347   indicesVertexFormat["aIndices"] = Property::INTEGER;
348   PropertyBuffer indicesToVertices = PropertyBuffer::New( indicesVertexFormat );
349   indicesToVertices.SetData( indices, 6 );
350
351
352   // Create the geometry object
353   Geometry texturedQuadGeometry = Geometry::New();
354   texturedQuadGeometry.AddVertexBuffer( positionVertices );
355   texturedQuadGeometry.AddVertexBuffer( textureVertices );
356   texturedQuadGeometry.AddVertexBuffer( normalVertices );
357
358   texturedQuadGeometry.SetIndexBuffer ( indicesToVertices );
359
360   return texturedQuadGeometry;
361 }
362
363 /**
364  * Create a mesh data with the geometry for the metaball rendering
365  */
366 Geometry MetaballRefracController::CreateGeometryComposition()
367 {
368   float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
369
370   // Create vertices and specify their color
371   float xsize = mScreenSize.x * 0.5;
372
373   //We create the meshdata for the metaballs
374   struct VertexPosition { Vector2 position; };
375   struct VertexTexture { Vector2 texture; };
376   struct VertexNormal { Vector3 normal; };
377
378   VertexPosition vertices[] = {
379     { Vector2( -xsize, -xsize * aspect) },
380     { Vector2(  xsize, -xsize * aspect) },
381     { Vector2( -xsize,  xsize * aspect) },
382     { Vector2(  xsize,  xsize * aspect) }
383   };
384
385   VertexTexture textures[] = {
386     { Vector2(0.0f, 0.0f) },
387     { Vector2(1.0f, 0.0f) },
388     { Vector2(0.0f, 1.0f) },
389     { Vector2(1.0f, 1.0f) }
390   };
391
392   VertexNormal normals [] = {
393     { Vector3(0.0f, 0.0f, 1.0f) },
394     { Vector3(0.0f, 0.0f, 1.0f) },
395     { Vector3(0.0f, 0.0f, 1.0f) },
396     { Vector3(0.0f, 0.0f, 1.0f) }
397   };
398
399   int indices[] = { 0, 3, 1, 0, 2, 3 };
400
401   unsigned int numberOfVertices = sizeof(vertices)/sizeof(VertexPosition);
402
403   //Vertices
404   Property::Map positionVertexFormat;
405   positionVertexFormat["aPosition"] = Property::VECTOR2;
406   PropertyBuffer positionVertices = PropertyBuffer::New( positionVertexFormat );
407   positionVertices.SetData( vertices, numberOfVertices );
408
409   //Textures
410   Property::Map textureVertexFormat;
411   textureVertexFormat["aTexture"] = Property::VECTOR2;
412   PropertyBuffer textureVertices = PropertyBuffer::New( textureVertexFormat );
413   textureVertices.SetData( textures, numberOfVertices );
414
415   //Normals
416   Property::Map normalVertexFormat;
417   normalVertexFormat["aNormal"] = Property::VECTOR3;
418   PropertyBuffer normalVertices = PropertyBuffer::New( normalVertexFormat );
419   normalVertices.SetData( normals, numberOfVertices );
420
421   //Indices
422   Property::Map indicesVertexFormat;
423   indicesVertexFormat["aIndices"] = Property::INTEGER;
424   PropertyBuffer indicesToVertices = PropertyBuffer::New( indicesVertexFormat );
425   indicesToVertices.SetData( indices, 6 );
426
427   // Create the geometry object
428   Geometry texturedQuadGeometry = Geometry::New();
429   texturedQuadGeometry.AddVertexBuffer( positionVertices );
430   texturedQuadGeometry.AddVertexBuffer( textureVertices );
431   texturedQuadGeometry.AddVertexBuffer( normalVertices );
432
433   texturedQuadGeometry.SetIndexBuffer ( indicesToVertices );
434
435   return texturedQuadGeometry;
436 }
437
438 /**
439  * Create a mesh actor for the metaballs
440  */
441 void MetaballRefracController::CreateMetaballActors()
442 {
443   //We create metaball structures
444   //With MeshData Textured
445   float aspect = (float)mScreenSize.y / (float)mScreenSize.x;
446
447   //Create the shader for the metaballs
448
449   Shader shader = Shader::New( METABALL_VERTEX_SHADER, METABALL_FRAG_SHADER );
450
451   Material material = Material::New( shader );
452
453   Geometry metaballGeom = CreateGeometry();
454
455   //Each metaball has a different radius
456   mMetaballs[0].radius = mMetaballs[0].initRadius = 0.0145f;
457   mMetaballs[1].radius = mMetaballs[1].initRadius = 0.012f;
458   mMetaballs[2].radius = mMetaballs[2].initRadius = 0.0135f;
459   mMetaballs[3].radius = mMetaballs[3].initRadius = 0.0135f;
460
461   //Initialization of each of the metaballs
462   for (int i = 0 ; i < METABALL_NUMBER ; i++)
463   {
464     mMetaballs[i].position = Vector2(0.0f, 0.0f);
465
466     mMetaballs[i].actor = Actor::New( );
467     mMetaballs[i].actor.SetName("Metaball");
468     mMetaballs[i].actor.SetScale( 1.0f );
469     mMetaballs[i].actor.SetParentOrigin( ParentOrigin::CENTER );
470
471     Renderer renderer = Renderer::New( metaballGeom, material );
472     renderer.SetProperty( Renderer::Property::BLENDING_MODE, BlendingMode::ON );
473     renderer.SetBlendFunc(BlendingFactor::ONE, BlendingFactor::ONE, BlendingFactor::ONE, BlendingFactor::ONE);
474     mMetaballs[i].actor.AddRenderer( renderer );
475
476     mMetaballs[i].positionIndex = mMetaballs[i].actor.RegisterProperty( "uPositionMetaball", mMetaballs[i].position );
477
478     mMetaballs[i].positionVarIndex = mMetaballs[i].actor.RegisterProperty( "uPositionVar", Vector2(0.f,0.f) );
479
480     mMetaballs[i].gravityIndex = mMetaballs[i].actor.RegisterProperty( "uGravityVector", Vector2(0.f,0.f) );
481
482     mMetaballs[i].radiusIndex = mMetaballs[i].actor.RegisterProperty( "uRadius", mMetaballs[i].radius );
483
484     mMetaballs[i].radiusVarIndex = mMetaballs[i].actor.RegisterProperty( "uRadiusVar", 0.f );
485
486     mMetaballs[i].aspectIndex = mMetaballs[i].actor.RegisterProperty( "uAspect", aspect );
487
488     mMetaballs[i].actor.SetSize(400, 400);
489   }
490
491   //Root creation
492   mMetaballRoot = Actor::New();
493   mMetaballRoot.SetParentOrigin( ParentOrigin::CENTER );
494   for (int i = 0 ; i < METABALL_NUMBER ; i++)
495   {
496     mMetaballRoot.Add( mMetaballs[i].actor );
497   }
498
499   //Initialization of variables related to metaballs
500   mMetaballPosVariation = Vector2(0,0);
501   mMetaballPosVariationFrom = Vector2(0,0);
502   mMetaballPosVariationTo = Vector2(0,0);
503   mCurrentTouchPosition = Vector2(0,0);
504 }
505
506 /**
507  * Create the render task and FBO to render the metaballs into a texture
508  */
509 void MetaballRefracController::CreateMetaballImage()
510 {
511   //We create an FBO and a render task to create to render the metaballs with a fragment shader
512   Stage stage = Stage::GetCurrent();
513   mMetaballFBO = FrameBufferImage::New(mScreenSize.x, mScreenSize.y );
514
515   stage.Add(mMetaballRoot);
516
517   //Creation of the render task used to render the metaballs
518   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
519   RenderTask task = taskList.CreateTask();
520   task.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
521   task.SetSourceActor( mMetaballRoot );
522   task.SetExclusive(true);
523   task.SetClearColor( Color::BLACK );
524   task.SetClearEnabled( true );
525   task.SetTargetFrameBuffer( mMetaballFBO );
526 }
527
528 /**
529  * Create a mesh image to render the final composition
530  */
531 void MetaballRefracController::AddRefractionImage()
532 {
533   //Creation of the composition image
534
535   //Create geometry
536   Geometry metaballGeom = CreateGeometryComposition();
537
538   //Create Refraction shader and renderer
539   Shader shader = Shader::New( METABALL_VERTEX_SHADER, REFRACTION_FRAG_SHADER );
540   //Create new material
541   mMaterialRefraction = Material::New( shader );
542
543   //Add Textures
544   mMaterialRefraction.AddTexture(mBackImage, "sTexture");
545   mMaterialRefraction.AddTexture(mMetaballFBO, "sEffect");
546
547   //Create normal shader
548   Shader shaderNormal = Shader::New( METABALL_VERTEX_SHADER, FRAG_SHADER );
549   //Create new material
550   mMaterialNormal = Material::New( shaderNormal );
551
552   //Add samplers
553   mMaterialNormal.AddTexture(mBackImage, "sTexture");
554
555
556   //Create actor
557   mCompositionActor = Actor::New( );
558   mCompositionActor.SetParentOrigin(ParentOrigin::CENTER);
559   mCompositionActor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
560   mCompositionActor.SetSize(mScreenSize.x, mScreenSize.y);
561
562
563   mRendererRefraction = Renderer::New( metaballGeom, mMaterialNormal );
564   mCompositionActor.AddRenderer( mRendererRefraction );
565
566   Stage stage = Stage::GetCurrent();
567   stage.Add( mCompositionActor );
568 }
569
570 /**
571  * Creation of all the metaballs animations (gravity, movement, size, etc.)
572  */
573 void MetaballRefracController::CreateAnimations()
574 {
575   int i = 0;
576   float key;
577
578   mPositionVarAnimation[1] = Animation::New(2.f);
579   mPositionVarAnimation[1].SetLooping( false );
580   mPositionVarAnimation[1].Pause();
581   mPositionVarAnimation[1].FinishedSignal().Connect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
582
583   KeyFrames keySinCosVariation = KeyFrames::New();
584   Vector2 sinCosVariation(0,0);
585   for ( i = 0 ; i < 360 ; i++)
586   {
587     sinCosVariation.x = 0.05f * (-sin(i * Math::PI/180.f) + cos(i * Math::PI/180.f));
588     sinCosVariation.y = 0.05f * (sin(i * Math::PI/180.f) - cos(i * Math::PI/180.f));
589     key = i/360.f;
590     keySinCosVariation.Add(key, sinCosVariation);
591   }
592
593   mPositionVarAnimation[2] = Animation::New(6.f);
594   mPositionVarAnimation[2].AnimateBetween(Property( mMetaballs[2].actor, mMetaballs[2].positionVarIndex ), keySinCosVariation);
595   mPositionVarAnimation[2].SetLooping( true );
596   mPositionVarAnimation[2].Pause();
597
598   KeyFrames keyCosSinVariation = KeyFrames::New();
599   Vector2 cosSinVariation(0,0);
600   for ( i = 0 ; i < 360 ; i++)
601   {
602     cosSinVariation.x = 0.05f * (-sin(i * Math::PI/180.f) - cos(i * Math::PI/180.f));
603     cosSinVariation.y = 0.05f * (sin(i * Math::PI/180.f) + cos(i * Math::PI/180.f));
604     key = i/360.f;
605     keyCosSinVariation.Add(key, cosSinVariation);
606   }
607
608   mPositionVarAnimation[3] = Animation::New(6.f);
609   mPositionVarAnimation[3].AnimateBetween(Property( mMetaballs[3].actor, mMetaballs[3].positionVarIndex ), keyCosSinVariation);
610   mPositionVarAnimation[3].SetLooping( true );
611   mPositionVarAnimation[3].Pause();
612
613   //Animations for gravity
614   for ( i = 0 ; i < METABALL_NUMBER ; i++)
615   {
616     mGravityAnimation[i] = Animation::New(25.f);
617     mGravityAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].gravityIndex ), mGravity * 25.f * 3.f);
618     mGravityAnimation[i].SetLooping( false );
619     mGravityAnimation[i].Pause();
620   }
621
622   //Animation to decrease size of metaballs when there is no click
623   for ( i = 0 ; i < METABALL_NUMBER ; i++)
624   {
625     mRadiusDecAnimation[i] = Animation::New(25.f);
626     mRadiusDecAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), -0.004f * 25.f * 3.f);
627     mRadiusDecAnimation[i].SetLooping( false );
628     mRadiusDecAnimation[i].Pause();
629   }
630
631   //Animation to grow the size of the metaballs the first second of the click
632   for ( i = 0 ; i < METABALL_NUMBER ; i++)
633   {
634     mRadiusIncFastAnimation[i] = Animation::New(0.3f);
635     mRadiusIncFastAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), 0.06f);
636     mRadiusIncFastAnimation[i].SetLooping( false );
637     mRadiusIncFastAnimation[i].Pause();
638   }
639   mRadiusIncFastAnimation[0].FinishedSignal().Connect( this, &MetaballRefracController::LaunchRadiusIncSlowAnimations );
640
641   //Animation to grow the size of the metaballs afterwards
642   for ( i = 0 ; i < METABALL_NUMBER ; i++)
643   {
644     mRadiusIncSlowAnimation[i] = Animation::New(20.f);
645     mRadiusIncSlowAnimation[i].AnimateBy( Property( mMetaballs[i].actor, mMetaballs[i].radiusIndex ), 0.04f);
646     mRadiusIncSlowAnimation[i].SetLooping( false );
647     mRadiusIncSlowAnimation[i].Pause();
648   }
649
650   //keyframes of a sin function
651   KeyFrames keySin = KeyFrames::New();
652   float val;
653   for ( i = 0 ; i < 360 ; i++)
654   {
655     val = 0.01f * sin(i * Math::PI/180.f);
656     key = i/360.f;
657     keySin.Add(key, val);
658   }
659
660   //Animation to change the size of the metaball
661   mRadiusVarAnimation[2] = Animation::New(8.f);
662   mRadiusVarAnimation[2].AnimateBetween(Property( mMetaballs[2].actor, mMetaballs[2].radiusVarIndex ), keySin);
663   mRadiusVarAnimation[2].SetLooping( true );
664
665   //keyframes of a cos function
666   KeyFrames keyCos = KeyFrames::New();
667   for ( i = 0 ; i < 360 ; i++)
668   {
669     val = 0.01f * cos(i * Math::PI/180.f);
670     key = i/360.f;
671     keyCos.Add(key, val);
672   }
673
674   //Animation to change the size of the metaball
675   mRadiusVarAnimation[3] = Animation::New(8.f);
676   mRadiusVarAnimation[3].AnimateBetween(Property( mMetaballs[3].actor, mMetaballs[3].radiusVarIndex ), keyCos);
677   mRadiusVarAnimation[3].SetLooping( true );
678 }
679
680 /**
681  * Function to launch the animation to get the metaball[1] back to the center
682  */
683 void MetaballRefracController::LaunchGetBackToPositionAnimation(Animation &source)
684 {
685   mMetaballPosVariationTo = Vector2(0,0);
686
687   mPositionVarAnimation[1] = Animation::New(1.f);
688   mPositionVarAnimation[1].SetLooping( false );
689   mPositionVarAnimation[1].AnimateTo(Property( mMetaballs[1].actor, mMetaballs[1].positionVarIndex ), Vector2(0,0));
690   mPositionVarAnimation[1].Play();
691 }
692
693 /**
694  * Function to launch the gro slow radius for the metaballs, and also the small variations for metaball[2] and [3]
695  */
696 void MetaballRefracController::LaunchRadiusIncSlowAnimations(Animation &source)
697 {
698   for (int i = 0 ; i < METABALL_NUMBER ; i++)
699   {
700     mRadiusIncSlowAnimation[i].Play();
701   }
702   mPositionVarAnimation[2].Play();
703   mPositionVarAnimation[3].Play();
704 }
705
706 /**
707  * Function to stop all animations related to the click of the user in the screen
708  */
709 void MetaballRefracController::StopClickAnimations()
710 {
711   for (int i = 0 ; i < METABALL_NUMBER ; i++)
712   {
713     mRadiusIncSlowAnimation[i].Stop();
714     mRadiusIncFastAnimation[i].Stop();
715   }
716   mPositionVarAnimation[1].Stop();
717   mPositionVarAnimation[2].Stop();
718   mPositionVarAnimation[3].Stop();
719 }
720
721 /**
722  * Function to stop all animations related to the after click of the user in the screen
723  */
724 void MetaballRefracController::StopAfterClickAnimations()
725 {
726   for (int i = 0 ; i < METABALL_NUMBER ; i++)
727   {
728     mGravityAnimation[i].Stop();
729     mRadiusDecAnimation[i].Stop();
730
731     mMetaballs[i].radius = mMetaballs[i].initRadius;
732
733     mMetaballs[i].actor.SetProperty(mMetaballs[i].gravityIndex, Vector2(0,0));
734     mMetaballs[i].actor.SetProperty(mMetaballs[i].radiusIndex, mMetaballs[i].radius);
735     mMetaballs[i].actor.SetProperty(mMetaballs[i].radiusVarIndex, 0.f);
736   }
737   mRadiusVarAnimation[2].Stop();
738   mRadiusVarAnimation[3].Stop();
739 }
740
741 /*
742  * Function that resets the sate of the different Metaballs
743  */
744 void MetaballRefracController::ResetMetaballsState()
745 {
746   mRendererRefraction.SetMaterial(mMaterialNormal);
747
748   for (int i = 0 ; i < METABALL_NUMBER ; i++)
749   {
750     mMetaballs[i].radius = mMetaballs[i].initRadius;
751   }
752
753   mMetaballPosVariationTo = Vector2(0,0);
754   mMetaballPosVariationFrom = Vector2(0,0);
755   mMetaballPosVariation = Vector2(0,0);
756
757   mGravityVar = Vector2(0,0);
758 }
759
760 /**
761  * Function to set the actual position of the metaballs when the user clicks the screen
762  */
763 void MetaballRefracController::SetPositionToMetaballs(Vector2 & metaballCenter)
764 {
765   //We set the position for the metaballs based on click position
766   for (int i = 0 ; i < METABALL_NUMBER ; i++)
767   {
768     mMetaballs[i].position = metaballCenter;
769     mMetaballs[i].actor.SetProperty(mMetaballs[i].positionIndex, mMetaballs[0].position);  // 0 y no i ?!?!?!
770   }
771 }
772
773 bool MetaballRefracController::OnTouch( Actor actor, const TouchEvent& touch )
774 {
775   const TouchPoint &point = touch.GetPoint(0);
776   float aspectR = mScreenSize.y / mScreenSize.x;
777   switch(point.state)
778   {
779     case TouchPoint::Down:
780     {
781       StopAfterClickAnimations();
782       for (int i = 0 ; i < METABALL_NUMBER ; i++)
783         mRadiusIncFastAnimation[i].Play();
784       mRadiusVarAnimation[2].Play();
785       mRadiusVarAnimation[3].Play();
786
787       //We draw with the refraction-composition shader
788       mRendererRefraction.SetMaterial(mMaterialRefraction);
789
790       mCurrentTouchPosition = point.screen;
791
792       //we use the click position for the metaballs
793       Vector2 metaballCenter = Vector2((point.screen.x / mScreenSize.x) - 0.5, (aspectR * (mScreenSize.y - point.screen.y) / mScreenSize.y) - 0.5) * 2.0;
794       SetPositionToMetaballs(metaballCenter);
795       break;
796     }
797     case TouchPoint::Motion:
798     {
799       Vector2 displacement = point.screen - mCurrentTouchPosition;
800       mCurrentTouchPosition = point.screen;
801
802       mMetaballPosVariationTo.x += (displacement.x / mScreenSize.x) * 2.2;
803       mMetaballPosVariationTo.y += (- displacement.y / mScreenSize.y) * 2.2;
804
805       if (mPositionVarAnimation[1])
806       {
807         mPositionVarAnimation[1].FinishedSignal().Disconnect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
808         mPositionVarAnimation[1].Stop();
809       }
810       mPositionVarAnimation[1] = Animation::New(1.f);
811       mPositionVarAnimation[1].SetLooping( false );
812       mPositionVarAnimation[1].AnimateTo(Property( mMetaballs[1].actor, mMetaballs[1].positionVarIndex ), mMetaballPosVariationTo);
813       mPositionVarAnimation[1].FinishedSignal().Connect( this, &MetaballRefracController::LaunchGetBackToPositionAnimation );
814       mPositionVarAnimation[1].Play();
815
816       //we use the click position for the metaballs
817       Vector2 metaballCenter = Vector2((point.screen.x / mScreenSize.x) - 0.5, (aspectR * (mScreenSize.y - point.screen.y) / mScreenSize.y) - 0.5) * 2.0;
818       SetPositionToMetaballs(metaballCenter);
819       break;
820     }
821     case TouchPoint::Up:
822     case TouchPoint::Leave:
823     case TouchPoint::Interrupted:
824     {
825       //Stop click animations
826       StopClickAnimations();
827
828       //Launch out of screen animations
829       for (int i = 0 ; i < METABALL_NUMBER ; i++)
830         mGravityAnimation[i].Play();
831
832       for (int i = 0 ; i < METABALL_NUMBER ; i++)
833         mRadiusDecAnimation[i].Play();
834
835       break;
836     }
837     default:
838       break;
839     }
840   return true;
841 }
842
843
844 void MetaballRefracController::OnKeyEvent(const KeyEvent& event)
845 {
846   if(event.state == KeyEvent::Down)
847   {
848     if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
849     {
850       mApplication.Quit();
851     }
852   }
853 }
854
855
856 //
857 //
858 //-----------------------------------------------------------------------------------------------
859
860 void RunTest( Application& application )
861 {
862   MetaballRefracController test( application );
863
864   application.MainLoop();
865 }
866
867 // Entry point for Linux & Tizen applications
868 //
869 int main( int argc, char **argv )
870 {
871   Application application = Application::New( &argc, &argv );
872
873   RunTest( application );
874
875   return 0;
876 }