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