Convert shaders in dali-demo to use shader compilation tool
[platform/core/uifw/dali-demo.git] / examples / metaball-refrac / metaball-refrac-example.cpp
1 /*
2  * Copyright (c) 2020 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 // EXTERNAL INCLUDES
19 #include <cstdint> // uint32_t, uint16_t etc
20 #include <cstdio>
21 #include <string>
22
23 #include <dali/public-api/rendering/frame-buffer.h>
24 #include <dali/public-api/rendering/renderer.h>
25 #include <dali/public-api/rendering/texture-set.h>
26 #include <dali/public-api/rendering/texture.h>
27
28 // INTERNAL INCLUDES
29 #include "shared/utility.h" // DemoHelper::LoadTexture
30 #include "generated/metaball-vert.h"
31 #include "generated/metaball-frag.h"
32 #include "generated/metaball-refraction-frag.h"
33 #include "generated/fragment-frag.h"
34
35 using namespace Dali;
36
37 namespace // unnamed namespace for constants
38 {
39 const char* const BACKGROUND_IMAGE(DEMO_IMAGE_DIR "background-2.jpg");
40 const float       GRAVITY_X(0);
41 const float       GRAVITY_Y(-0.09);
42
43 // number of metaballs
44 constexpr uint32_t METABALL_NUMBER = 6;
45
46 /**
47  * Metadata for each ball
48  */
49 struct MetaballInfo
50 {
51   Actor   actor;
52   Vector2 position;
53   float   radius;
54   float   initRadius;
55
56   //Properties needed for animations
57   Property::Index positionIndex;
58   Property::Index positionVarIndex;
59   Property::Index gravityIndex;
60   Property::Index radiusIndex;
61   Property::Index radiusVarIndex;
62   Property::Index aspectIndex;
63 };
64
65 } // unnamed namespace
66
67 /**
68  * Demo using Metaballs
69  *
70  * When the metaball is clicked it starts to grow and fuses into the closest edge of screen
71  */
72 class MetaballRefracController : public ConnectionTracker
73 {
74 public:
75   /**
76    * Constructor
77    * @param application
78    */
79   MetaballRefracController(Application& application);
80
81   /**
82    * Destructor
83    */
84   virtual ~MetaballRefracController();
85
86   /**
87    * Creates the metaballs and initializes the scene
88    */
89   void Create(Application& app);
90
91   /**
92    * Touch handler, start the grow animation and creates additional metaballs
93    */
94   bool OnTouch(Actor actor, const TouchEvent& touch);
95
96   /**
97    * Key event callback to quit the application on escape or back key
98    */
99   void OnKeyEvent(const KeyEvent& event);
100
101 private: // Data
102   Application& mApplication;
103   Vector2      mScreenSize;
104
105   Texture     mBackgroundTexture;
106   FrameBuffer mMetaballFBO;
107
108   Actor        mMetaballRoot;
109   MetaballInfo mMetaballs[METABALL_NUMBER];
110
111   Actor mCompositionActor;
112
113   //Motion
114   Vector2 mCurrentTouchPosition;
115   Vector2 mMetaballPosVariation;
116   Vector2 mMetaballPosVariationFrom;
117   Vector2 mMetaballPosVariationTo;
118   Vector2 mMetaballCenter;
119
120   Vector2 mGravity;
121   Vector2 mGravityVar;
122
123   Renderer   mRendererRefraction;
124   TextureSet mTextureSetRefraction;
125   Shader     mShaderRefraction;
126   TextureSet mTextureSetNormal;
127   Shader     mShaderNormal;
128
129   // Animations
130   Animation mGravityAnimation[METABALL_NUMBER];
131   Animation mRadiusDecAnimation[METABALL_NUMBER];
132   Animation mRadiusIncFastAnimation[METABALL_NUMBER];
133   Animation mRadiusIncSlowAnimation[METABALL_NUMBER];
134   Animation mRadiusVarAnimation[METABALL_NUMBER];
135   Animation mPositionVarAnimation[METABALL_NUMBER];
136
137   // Private Helper functions
138
139   /**
140    * Create a mesh data with the geometry for the metaball rendering
141    * @param aspectMappedTexture whether texture coords should be mapped based on aspect ratio
142    */
143   Geometry CreateGeometry(bool aspectMappedTexture = true);
144
145   /**
146    * Create a actor for the metaballs
147    */
148   void CreateMetaballActors();
149
150   /**
151    * Create the render task and FBO to render the metaballs into a texture
152    */
153   void CreateMetaballImage();
154
155   /**
156    * Create the the final composition
157    */
158   void CreateComposition();
159
160   /**
161    * Create all the metaballs animations (gravity, movement, size, etc.)
162    */
163   void CreateAnimations();
164
165   /**
166    * Function to launch the grow slow radius for the metaballs, and also the small variations for metaball[2] and [3]
167    */
168   void LaunchRadiusIncSlowAnimations(Animation& source);
169
170   /**
171    * Function to launch the animation to get the metaball[1] back to the center
172    */
173   void LaunchGetBackToPositionAnimation(Animation& source);
174
175   /**
176    * Function to stop all animations related to the click of the user in the screen
177    */
178   void StopClickAnimations();
179
180   /**
181    * Function to stop all animations related to the after click of the user in the screen
182    */
183   void StopAfterClickAnimations();
184
185   /**
186    * Function that resets the sate of the different Metaballs
187    */
188   void ResetMetaballsState();
189
190   /**
191    * Function to set the actual position of the metaballs when the user clicks the screen
192    */
193   void SetPositionToMetaballs(const Vector2& metaballCenter);
194 };
195
196 /**
197  * Implementation
198  */
199
200 MetaballRefracController::MetaballRefracController(Application& application)
201 : mApplication(application)
202 {
203   // Connect to the Application's Init signal
204   mApplication.InitSignal().Connect(this, &MetaballRefracController::Create);
205 }
206
207 MetaballRefracController::~MetaballRefracController()
208 {
209   // Nothing to do here;
210 }
211
212 void MetaballRefracController::Create(Application& app)
213 {
214   Window window = app.GetWindow();
215
216   window.KeyEventSignal().Connect(this, &MetaballRefracController::OnKeyEvent);
217
218   mScreenSize = window.GetSize();
219
220   window.SetBackgroundColor(Color::BLACK);
221
222   // Load background texture
223   mBackgroundTexture = DemoHelper::LoadTexture(BACKGROUND_IMAGE);
224
225   mGravity    = Vector2(GRAVITY_X, GRAVITY_Y);
226   mGravityVar = Vector2(0, 0);
227
228   CreateMetaballActors();
229   CreateMetaballImage();
230   CreateComposition();
231   CreateAnimations();
232
233   // Connect the callback to the touch signal on the mesh actor
234   window.GetRootLayer().TouchedSignal().Connect(this, &MetaballRefracController::OnTouch);
235 }
236
237 Geometry MetaballRefracController::CreateGeometry(bool aspectMappedTexture)
238 {
239   const float aspect = mScreenSize.y / mScreenSize.x;
240
241   // Create vertices and specify their color
242   const float xsize = mScreenSize.x * 0.5;
243
244   // Create the meshdata for the metaballs
245   struct VertexPosition
246   {
247     Vector2 position;
248   };
249   struct VertexTexture
250   {
251     Vector2 texture;
252   };
253
254   VertexPosition vertices[] =
255     {
256       {Vector2(-xsize, -xsize * aspect)},
257       {Vector2(xsize, -xsize * aspect)},
258       {Vector2(-xsize, xsize * aspect)},
259       {Vector2(xsize, xsize * aspect)}};
260
261   const float   textureAspect = (aspectMappedTexture) ? aspect : 1.0f;
262   VertexTexture textures[] =
263     {
264       {Vector2(0.0f, 0.0f)},
265       {Vector2(1.0f, 0.0f)},
266       {Vector2(0.0f, 1.0f * textureAspect)},
267       {Vector2(1.0f, 1.0f * textureAspect)}};
268
269   uint32_t numberOfVertices = sizeof(vertices) / sizeof(VertexPosition);
270
271   // Vertices
272   Property::Map positionVertexFormat;
273   positionVertexFormat["aPosition"] = Property::VECTOR2;
274   VertexBuffer positionVertices     = VertexBuffer::New(positionVertexFormat);
275   positionVertices.SetData(vertices, numberOfVertices);
276
277   // Textures
278   Property::Map textureVertexFormat;
279   textureVertexFormat["aTexture"] = Property::VECTOR2;
280   VertexBuffer textureVertices    = VertexBuffer::New(textureVertexFormat);
281   textureVertices.SetData(textures, numberOfVertices);
282
283   // Indices
284   const uint16_t indices[] = {0, 3, 1, 0, 2, 3};
285
286   // Create the geometry object
287   Geometry texturedQuadGeometry = Geometry::New();
288   texturedQuadGeometry.AddVertexBuffer(positionVertices);
289   texturedQuadGeometry.AddVertexBuffer(textureVertices);
290
291   texturedQuadGeometry.SetIndexBuffer(&indices[0], sizeof(indices) / sizeof(indices[0]));
292
293   return texturedQuadGeometry;
294 }
295
296 void MetaballRefracController::CreateMetaballActors()
297 {
298   const float aspect = mScreenSize.y / mScreenSize.x;
299
300   // Create the renderer for the metaballs
301   Shader   shader           = Shader::New(SHADER_METABALL_VERT, SHADER_METABALL_FRAG, Shader::Hint::MODIFIES_GEOMETRY);
302   Geometry metaballGeometry = CreateGeometry();
303   Renderer renderer         = Renderer::New(metaballGeometry, shader);
304   renderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
305   renderer.SetProperty(Renderer::Property::BLEND_FACTOR_SRC_RGB, BlendFactor::ONE);
306   renderer.SetProperty(Renderer::Property::BLEND_FACTOR_DEST_RGB, BlendFactor::ONE);
307   renderer.SetProperty(Renderer::Property::BLEND_FACTOR_SRC_ALPHA, BlendFactor::ONE);
308   renderer.SetProperty(Renderer::Property::BLEND_FACTOR_DEST_ALPHA, BlendFactor::ONE);
309
310   // Each metaball has a different radius
311   mMetaballs[0].radius = mMetaballs[0].initRadius = 0.0145f;
312   mMetaballs[1].radius = mMetaballs[1].initRadius = 0.012f;
313   mMetaballs[2].radius = mMetaballs[2].initRadius = 0.0135f;
314   mMetaballs[3].radius = mMetaballs[3].initRadius = 0.0135f;
315
316   // Initialization of each of the metaballs
317   for(uint32_t i = 0; i < METABALL_NUMBER; i++)
318   {
319     mMetaballs[i].position = Vector2(0.0f, 0.0f);
320
321     mMetaballs[i].actor = Actor::New();
322     mMetaballs[i].actor.SetProperty(Dali::Actor::Property::NAME, "Metaball");
323     mMetaballs[i].actor.SetProperty(Actor::Property::SCALE, 1.0f);
324     mMetaballs[i].actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
325
326     mMetaballs[i].actor.AddRenderer(renderer);
327
328     mMetaballs[i].positionIndex    = mMetaballs[i].actor.RegisterProperty("uPositionMetaball", mMetaballs[i].position);
329     mMetaballs[i].positionVarIndex = mMetaballs[i].actor.RegisterProperty("uPositionVar", Vector2(0.f, 0.f));
330     mMetaballs[i].gravityIndex     = mMetaballs[i].actor.RegisterProperty("uGravityVector", Vector2(0.f, 0.f));
331     mMetaballs[i].radiusIndex      = mMetaballs[i].actor.RegisterProperty("uRadius", mMetaballs[i].radius);
332     mMetaballs[i].radiusVarIndex   = mMetaballs[i].actor.RegisterProperty("uRadiusVar", 0.f);
333     mMetaballs[i].aspectIndex      = mMetaballs[i].actor.RegisterProperty("uAspect", aspect);
334   }
335
336   //Root creation
337   mMetaballRoot = Actor::New();
338   mMetaballRoot.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
339   for(uint32_t i = 0; i < METABALL_NUMBER; i++)
340   {
341     mMetaballRoot.Add(mMetaballs[i].actor);
342   }
343 }
344
345 void MetaballRefracController::CreateMetaballImage()
346 {
347   // Create an FBO and a render task to create to render the metaballs with a fragment shader
348   Window window = mApplication.GetWindow();
349   mMetaballFBO  = FrameBuffer::New(mScreenSize.x, mScreenSize.y);
350
351   window.Add(mMetaballRoot);
352
353   //Creation of the render task used to render the metaballs
354   RenderTaskList taskList = window.GetRenderTaskList();
355   RenderTask     task     = taskList.CreateTask();
356   task.SetRefreshRate(RenderTask::REFRESH_ALWAYS);
357   task.SetSourceActor(mMetaballRoot);
358   task.SetExclusive(true);
359   task.SetClearColor(Color::BLACK);
360   task.SetClearEnabled(true);
361   task.SetFrameBuffer(mMetaballFBO);
362 }
363
364 void MetaballRefracController::CreateComposition()
365 {
366   // Create Refraction shader and renderer
367   mShaderRefraction = Shader::New(SHADER_METABALL_VERT, SHADER_METABALL_REFRACTION_FRAG);
368
369   // Create new texture set
370   mTextureSetRefraction = TextureSet::New();
371   mTextureSetRefraction.SetTexture(0u, mBackgroundTexture);
372   mTextureSetRefraction.SetTexture(1u, mMetaballFBO.GetColorTexture());
373
374   // Create normal shader
375   mShaderNormal = Shader::New(SHADER_METABALL_VERT, SHADER_FRAGMENT_FRAG);
376
377   // Create new texture set
378   mTextureSetNormal = TextureSet::New();
379   mTextureSetNormal.SetTexture(0u, mBackgroundTexture);
380
381   // Create actor
382   mCompositionActor = Actor::New();
383   mCompositionActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
384   mCompositionActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 0.0f));
385   mCompositionActor.SetProperty(Actor::Property::SIZE, Vector2(mScreenSize.x, mScreenSize.y));
386
387   // Create geometry
388   Geometry metaballGeometry = CreateGeometry(false);
389   mRendererRefraction       = Renderer::New(metaballGeometry, mShaderNormal);
390   mRendererRefraction.SetTextures(mTextureSetNormal);
391   mCompositionActor.AddRenderer(mRendererRefraction);
392
393   Window window = mApplication.GetWindow();
394   window.Add(mCompositionActor);
395 }
396
397 void MetaballRefracController::CreateAnimations()
398 {
399   uint32_t i = 0;
400   float    key;
401
402   mPositionVarAnimation[1] = Animation::New(2.f);
403   mPositionVarAnimation[1].SetLooping(false);
404   mPositionVarAnimation[1].Pause();
405   mPositionVarAnimation[1].FinishedSignal().Connect(this, &MetaballRefracController::LaunchGetBackToPositionAnimation);
406
407   KeyFrames keySinCosVariation = KeyFrames::New();
408   Vector2   sinCosVariation(0, 0);
409   for(i = 0; i < 360; i++)
410   {
411     sinCosVariation.x = 0.05f * (-sinf(i * Math::PI_OVER_180) + cosf(i * Math::PI_OVER_180));
412     sinCosVariation.y = 0.05f * (sinf(i * Math::PI_OVER_180) - cosf(i * Math::PI_OVER_180));
413     key               = i / 360.f;
414     keySinCosVariation.Add(key, sinCosVariation);
415   }
416
417   mPositionVarAnimation[2] = Animation::New(6.f);
418   mPositionVarAnimation[2].AnimateBetween(Property(mMetaballs[2].actor, mMetaballs[2].positionVarIndex), keySinCosVariation);
419   mPositionVarAnimation[2].SetLooping(true);
420   mPositionVarAnimation[2].Pause();
421
422   KeyFrames keyCosSinVariation = KeyFrames::New();
423   Vector2   cosSinVariation(0, 0);
424   for(i = 0; i < 360; i++)
425   {
426     cosSinVariation.x = 0.05f * (-sinf(i * Math::PI_OVER_180) - cosf(i * Math::PI_OVER_180));
427     cosSinVariation.y = 0.05f * (sinf(i * Math::PI_OVER_180) + cosf(i * Math::PI_OVER_180));
428     key               = i / 360.f;
429     keyCosSinVariation.Add(key, cosSinVariation);
430   }
431
432   mPositionVarAnimation[3] = Animation::New(6.f);
433   mPositionVarAnimation[3].AnimateBetween(Property(mMetaballs[3].actor, mMetaballs[3].positionVarIndex), keyCosSinVariation);
434   mPositionVarAnimation[3].SetLooping(true);
435   mPositionVarAnimation[3].Pause();
436
437   //Animations for gravity
438   for(i = 0; i < METABALL_NUMBER; i++)
439   {
440     mGravityAnimation[i] = Animation::New(25.f);
441     mGravityAnimation[i].AnimateBy(Property(mMetaballs[i].actor, mMetaballs[i].gravityIndex), mGravity * 25.f * 3.f);
442     mGravityAnimation[i].SetLooping(false);
443     mGravityAnimation[i].Pause();
444   }
445
446   //Animation to decrease size of metaballs when there is no click
447   for(i = 0; i < METABALL_NUMBER; i++)
448   {
449     mRadiusDecAnimation[i] = Animation::New(25.f);
450     mRadiusDecAnimation[i].AnimateBy(Property(mMetaballs[i].actor, mMetaballs[i].radiusIndex), -0.004f * 25.f * 3.f);
451     mRadiusDecAnimation[i].SetLooping(false);
452     mRadiusDecAnimation[i].Pause();
453   }
454
455   // Animation to grow the size of the metaballs the first second of the click
456   for(i = 0; i < METABALL_NUMBER; i++)
457   {
458     mRadiusIncFastAnimation[i] = Animation::New(0.3f);
459     mRadiusIncFastAnimation[i].AnimateBy(Property(mMetaballs[i].actor, mMetaballs[i].radiusIndex), 0.06f);
460     mRadiusIncFastAnimation[i].SetLooping(false);
461     mRadiusIncFastAnimation[i].Pause();
462   }
463   mRadiusIncFastAnimation[0].FinishedSignal().Connect(this, &MetaballRefracController::LaunchRadiusIncSlowAnimations);
464
465   // Animation to grow the size of the metaballs afterwards
466   for(i = 0; i < METABALL_NUMBER; i++)
467   {
468     mRadiusIncSlowAnimation[i] = Animation::New(20.f);
469     mRadiusIncSlowAnimation[i].AnimateBy(Property(mMetaballs[i].actor, mMetaballs[i].radiusIndex), 0.04f);
470     mRadiusIncSlowAnimation[i].SetLooping(false);
471     mRadiusIncSlowAnimation[i].Pause();
472   }
473
474   // Keyframes of a sin function
475   KeyFrames keySin = KeyFrames::New();
476   float     val;
477   for(i = 0; i < 360; i++)
478   {
479     val = 0.01f * sin(i * Math::PI / 180.f);
480     key = i / 360.f;
481     keySin.Add(key, val);
482   }
483
484   //Animation to change the size of the metaball
485   mRadiusVarAnimation[2] = Animation::New(8.f);
486   mRadiusVarAnimation[2].AnimateBetween(Property(mMetaballs[2].actor, mMetaballs[2].radiusVarIndex), keySin);
487   mRadiusVarAnimation[2].SetLooping(true);
488
489   // Keyframes of a cos function
490   KeyFrames keyCos = KeyFrames::New();
491   for(i = 0; i < 360; i++)
492   {
493     val = 0.01f * cos(i * Math::PI / 180.f);
494     key = i / 360.f;
495     keyCos.Add(key, val);
496   }
497
498   //Animation to change the size of the metaball
499   mRadiusVarAnimation[3] = Animation::New(8.f);
500   mRadiusVarAnimation[3].AnimateBetween(Property(mMetaballs[3].actor, mMetaballs[3].radiusVarIndex), keyCos);
501   mRadiusVarAnimation[3].SetLooping(true);
502 }
503
504 void MetaballRefracController::LaunchGetBackToPositionAnimation(Animation& source)
505 {
506   mMetaballPosVariationTo = Vector2(0, 0);
507
508   mPositionVarAnimation[1] = Animation::New(1.f);
509   mPositionVarAnimation[1].SetLooping(false);
510   mPositionVarAnimation[1].AnimateTo(Property(mMetaballs[1].actor, mMetaballs[1].positionVarIndex), Vector2(0, 0));
511   mPositionVarAnimation[1].Play();
512 }
513
514 void MetaballRefracController::LaunchRadiusIncSlowAnimations(Animation& source)
515 {
516   for(uint32_t i = 0; i < METABALL_NUMBER; i++)
517   {
518     mRadiusIncSlowAnimation[i].Play();
519   }
520   mPositionVarAnimation[2].Play();
521   mPositionVarAnimation[3].Play();
522 }
523
524 void MetaballRefracController::StopClickAnimations()
525 {
526   for(uint32_t i = 0; i < METABALL_NUMBER; i++)
527   {
528     mRadiusIncSlowAnimation[i].Stop();
529     mRadiusIncFastAnimation[i].Stop();
530   }
531   mPositionVarAnimation[1].Stop();
532   mPositionVarAnimation[2].Stop();
533   mPositionVarAnimation[3].Stop();
534 }
535
536 void MetaballRefracController::StopAfterClickAnimations()
537 {
538   for(uint32_t i = 0; i < METABALL_NUMBER; i++)
539   {
540     mGravityAnimation[i].Stop();
541     mRadiusDecAnimation[i].Stop();
542
543     mMetaballs[i].radius = mMetaballs[i].initRadius;
544
545     mMetaballs[i].actor.SetProperty(mMetaballs[i].gravityIndex, Vector2(0, 0));
546     mMetaballs[i].actor.SetProperty(mMetaballs[i].radiusIndex, mMetaballs[i].radius);
547     mMetaballs[i].actor.SetProperty(mMetaballs[i].radiusVarIndex, 0.f);
548   }
549   mRadiusVarAnimation[2].Stop();
550   mRadiusVarAnimation[3].Stop();
551 }
552
553 void MetaballRefracController::ResetMetaballsState()
554 {
555   mRendererRefraction.SetTextures(mTextureSetNormal);
556   mRendererRefraction.SetShader(mShaderNormal);
557
558   for(uint32_t i = 0; i < METABALL_NUMBER; i++)
559   {
560     mMetaballs[i].radius = mMetaballs[i].initRadius;
561   }
562
563   mMetaballPosVariationTo   = Vector2(0, 0);
564   mMetaballPosVariationFrom = Vector2(0, 0);
565   mMetaballPosVariation     = Vector2(0, 0);
566   mGravityVar               = Vector2(0, 0);
567 }
568
569 void MetaballRefracController::SetPositionToMetaballs(const Vector2& metaballCenter)
570 {
571   //We set the position for the metaballs based on click position
572   for(uint32_t i = 0; i < METABALL_NUMBER; i++)
573   {
574     mMetaballs[i].position = metaballCenter;
575     mMetaballs[i].actor.SetProperty(mMetaballs[i].positionIndex, mMetaballs[i].position);
576   }
577 }
578
579 bool MetaballRefracController::OnTouch(Actor actor, const TouchEvent& touch)
580 {
581   const float aspect = mScreenSize.y / mScreenSize.x;
582   switch(touch.GetState(0))
583   {
584     case PointState::DOWN:
585     {
586       StopAfterClickAnimations();
587       for(uint32_t i = 0; i < METABALL_NUMBER; i++)
588       {
589         mRadiusIncFastAnimation[i].Play();
590       }
591       mRadiusVarAnimation[2].Play();
592       mRadiusVarAnimation[3].Play();
593
594       //We draw with the refraction-composition shader
595       mRendererRefraction.SetTextures(mTextureSetRefraction);
596       mRendererRefraction.SetShader(mShaderRefraction);
597       mCurrentTouchPosition = touch.GetScreenPosition(0);
598
599       //we use the click position for the metaballs
600       Vector2 metaballCenter = Vector2((mCurrentTouchPosition.x / mScreenSize.x) - 0.5f,
601                                        (aspect * (mScreenSize.y - mCurrentTouchPosition.y) / mScreenSize.y) - 0.5f) *
602                                2.0f;
603       SetPositionToMetaballs(metaballCenter);
604       break;
605     }
606     case PointState::MOTION:
607     {
608       Vector2 screen        = touch.GetScreenPosition(0);
609       Vector2 displacement  = screen - mCurrentTouchPosition;
610       mCurrentTouchPosition = screen;
611
612       mMetaballPosVariationTo.x += (displacement.x / mScreenSize.x) * 2.2f;
613       mMetaballPosVariationTo.y += (-displacement.y / mScreenSize.y) * 2.2f;
614
615       if(mPositionVarAnimation[1])
616       {
617         mPositionVarAnimation[1].FinishedSignal().Disconnect(this, &MetaballRefracController::LaunchGetBackToPositionAnimation);
618         mPositionVarAnimation[1].Stop();
619       }
620       mPositionVarAnimation[1] = Animation::New(1.f);
621       mPositionVarAnimation[1].SetLooping(false);
622       mPositionVarAnimation[1].AnimateTo(Property(mMetaballs[1].actor, mMetaballs[1].positionVarIndex), mMetaballPosVariationTo);
623       mPositionVarAnimation[1].FinishedSignal().Connect(this, &MetaballRefracController::LaunchGetBackToPositionAnimation);
624       mPositionVarAnimation[1].Play();
625
626       //we use the click position for the metaballs
627       Vector2 metaballCenter = Vector2((screen.x / mScreenSize.x) - 0.5f,
628                                        (aspect * (mScreenSize.y - screen.y) / mScreenSize.y) - 0.5f) *
629                                2.0f;
630       SetPositionToMetaballs(metaballCenter);
631       break;
632     }
633     case PointState::UP:
634     case PointState::LEAVE:
635     case PointState::INTERRUPTED:
636     {
637       //Stop click animations
638       StopClickAnimations();
639
640       //Launch out of screen animations
641       for(uint32_t i = 0; i < METABALL_NUMBER; i++)
642       {
643         mGravityAnimation[i].Play();
644       }
645
646       for(uint32_t i = 0; i < METABALL_NUMBER; i++)
647       {
648         mRadiusDecAnimation[i].Play();
649       }
650       break;
651     }
652     default:
653       break;
654   }
655   return true;
656 }
657
658 void MetaballRefracController::OnKeyEvent(const KeyEvent& event)
659 {
660   if(event.GetState() == KeyEvent::DOWN)
661   {
662     if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
663     {
664       mApplication.Quit();
665     }
666   }
667 }
668
669 /**
670  * Main entry point
671  */
672 int32_t DALI_EXPORT_API main(int argc, char** argv)
673 {
674   Application application = Application::New(&argc, &argv);
675
676   MetaballRefracController test(application);
677   application.MainLoop();
678
679   return 0;
680 }