Update refraction-effect & radial-menu to use new mesh 57/39357/7
authorXiangyin Ma <x1.ma@samsung.com>
Wed, 13 May 2015 12:53:10 +0000 (13:53 +0100)
committerXiangyin Ma <x1.ma@samsung.com>
Thu, 21 May 2015 16:02:01 +0000 (17:02 +0100)
Change-Id: I6007af3cd1f01b9e8845b9edf8cbbffdf2eef6c6

examples/radial-menu/radial-menu-example.cpp [new file with mode: 0644]
examples/radial-menu/radial-sweep-view-impl.cpp [new file with mode: 0644]
examples/radial-menu/radial-sweep-view-impl.h [new file with mode: 0644]
examples/radial-menu/radial-sweep-view.cpp [new file with mode: 0644]
examples/radial-menu/radial-sweep-view.h [new file with mode: 0644]
examples/refraction-effect/refraction-effect-example.cpp [new file with mode: 0644]

diff --git a/examples/radial-menu/radial-menu-example.cpp b/examples/radial-menu/radial-menu-example.cpp
new file mode 100644 (file)
index 0000000..be8d6ee
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/dali.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include "shared/view.h"
+#include "radial-sweep-view.h"
+#include "radial-sweep-view-impl.h"
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+namespace
+{
+const char* TEST_OUTER_RING_FILENAME = DALI_IMAGE_DIR "layer2.png"; // Image to be masked
+const char* TEST_INNER_RING_FILENAME = DALI_IMAGE_DIR "layer1.png"; // Image to be masked
+const char* TEST_MENU_FILENAME = DALI_IMAGE_DIR "layer3.png"; // Image to be masked
+const char* TEST_DIAL_FILENAME = DALI_IMAGE_DIR "layer4.png"; // Image to be masked
+const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" ); // Background for toolbar
+const char* APPLICATION_TITLE( "Radial Menu" );
+const char * const PLAY_ICON( DALI_IMAGE_DIR "icon-play.png" );
+const char * const STOP_ICON( DALI_IMAGE_DIR "icon-stop.png" );
+}
+
+
+/********************************************************************************
+ * Application controller class
+ */
+
+// This example shows how to create a mesh actor for use as a stencil buffer
+class RadialMenuExample : public ConnectionTracker
+{
+public:
+  /**
+   * Constructor
+   * @param[in] app The application handle
+   */
+  RadialMenuExample(Application app);
+
+  /**
+   * Destructor
+   */
+  ~RadialMenuExample();
+
+private:
+
+  /**
+   * Initialization signal handler - all actor initialization should happen here
+   * @param[in] app The application handle
+   */
+  void OnInit(Application& app);
+
+  /**
+   * Create a sweep view with the given image and parameters
+   */
+  RadialSweepView CreateSweepView( std::string imageName, Degree initial, Degree final );
+
+  /**
+   * Start the sweep animation on the menu
+   */
+  void StartAnimation();
+
+  /**
+   * Play or pause the animation when the button is clicked
+   */
+  bool OnButtonClicked( Toolkit::Button button );
+
+  /**
+   * Update the state flag and change the button icon when the animation is finished
+   */
+  void OnAnimationFinished( Animation& source );
+
+  /**
+   * Main key event handler
+   *
+   * @param[in] event The key event to respond to
+   */
+  void OnKeyEvent(const KeyEvent& event);
+
+private: // Member variables
+  enum AnimState
+  {
+    STOPPED,
+    PAUSED,
+    PLAYING
+  };
+
+  Application     mApplication; ///< The application handle
+  Toolkit::Control mView;        ///< The toolbar view
+  Layer           mContents;    ///< The toolbar contents pane
+  ImageActor      mImageActor;  ///< Image actor shown by stencil mask
+  Animation       mAnimation;
+  AnimState       mAnimationState;
+
+  Image               mIconPlay;
+  Image               mIconStop;
+  Toolkit::PushButton mPlayStopButton;
+  ImageActor      mDialActor;
+  RadialSweepView mRadialSweepView1;
+  RadialSweepView mRadialSweepView2;
+  RadialSweepView mRadialSweepView3;
+};
+
+RadialMenuExample::RadialMenuExample(Application app)
+: mApplication( app ),
+  mAnimationState(STOPPED)
+{
+  // Connect to the Application's Init signal
+  app.InitSignal().Connect(this, &RadialMenuExample::OnInit);
+}
+
+RadialMenuExample::~RadialMenuExample()
+{
+  // Nothing to do here; actor handles will clean up themselves.
+}
+
+void RadialMenuExample::OnInit(Application& app)
+{
+  DemoHelper::RequestThemeChange();
+
+  Stage stage = Dali::Stage::GetCurrent();
+
+  // The Init signal is received once (only) during the Application lifetime
+  stage.KeyEventSignal().Connect(this, &RadialMenuExample::OnKeyEvent);
+
+  // Create toolbar & view
+  Toolkit::ToolBar toolBar;
+  mContents = DemoHelper::CreateView( mApplication,
+                                      mView,
+                                      toolBar,
+                                      "",
+                                      TOOLBAR_IMAGE,
+                                      APPLICATION_TITLE );
+
+  mIconPlay = ResourceImage::New( PLAY_ICON );
+  mIconStop = ResourceImage::New( STOP_ICON );
+  mPlayStopButton = Toolkit::PushButton::New();
+  mPlayStopButton.SetBackgroundImage( mIconStop );
+
+  mPlayStopButton.ClickedSignal().Connect( this, &RadialMenuExample::OnButtonClicked );
+
+  toolBar.AddControl( mPlayStopButton,
+                      DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
+                      Toolkit::Alignment::HorizontalRight,
+                      DemoHelper::DEFAULT_PLAY_PADDING );
+
+
+  const ImageDimensions intImgSize = ResourceImage::GetImageSize(TEST_OUTER_RING_FILENAME);
+  Vector2 imgSize = Vector2( intImgSize.GetWidth(), intImgSize.GetHeight() );
+  Vector2 stageSize = stage.GetSize();
+  float scale = stageSize.width / imgSize.width;
+  float availableHeight = stageSize.height - DemoHelper::DEFAULT_VIEW_STYLE.mToolBarHeight * 2.0f;
+  if(availableHeight <= stageSize.width)
+  {
+    scale = availableHeight / imgSize.width;
+  }
+
+  mRadialSweepView1 = CreateSweepView( TEST_OUTER_RING_FILENAME, Degree(-90.0f), Degree(-90.0f));
+  mRadialSweepView2 = CreateSweepView( TEST_INNER_RING_FILENAME, Degree(90.0f),  Degree(0.0f));
+  mRadialSweepView3 = CreateSweepView( TEST_MENU_FILENAME, Degree(100.0f), Degree(0.0f));
+  mRadialSweepView3.SetInitialActorAngle(Degree(-110));
+  mRadialSweepView3.SetFinalActorAngle(Degree(0));
+
+  Image dial = ResourceImage::New( TEST_DIAL_FILENAME );
+  mDialActor = ImageActor::New( dial );
+  mDialActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+  mDialActor.SetPositionInheritanceMode(USE_PARENT_POSITION);
+  mDialActor.SetScale(scale);
+  Layer dialLayer = Layer::New();
+
+  dialLayer.Add(mDialActor);
+  dialLayer.SetPositionInheritanceMode(USE_PARENT_POSITION);
+  dialLayer.SetSize(stage.GetSize());
+  mContents.Add(dialLayer);
+
+  mRadialSweepView1.SetScale(scale);
+  mRadialSweepView2.SetScale(scale);
+  mRadialSweepView3.SetScale(scale);
+
+  StartAnimation();
+}
+
+void RadialMenuExample::StartAnimation()
+{
+  mDialActor.SetOpacity(0.0f);
+  mRadialSweepView1.SetOpacity(0.0f);
+  mAnimation = Animation::New(6.0f);
+  mRadialSweepView1.Activate(mAnimation, 0.0f, 3.0f);
+  mRadialSweepView2.Activate(mAnimation, 1.5f, 3.0f);
+  mRadialSweepView3.Activate(mAnimation, 3.0f, 3.0f);
+  mAnimation.AnimateTo( Property( mDialActor, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN, TimePeriod( 0.0f, 0.8f ) );
+  mAnimation.AnimateTo( Property( mRadialSweepView1, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN, TimePeriod( 0.0f, 0.5f ) );
+  mAnimation.FinishedSignal().Connect( this, &RadialMenuExample::OnAnimationFinished );
+
+  mAnimationState = PLAYING;
+  mAnimation.Play();
+}
+
+bool RadialMenuExample::OnButtonClicked( Toolkit::Button button )
+{
+  switch( mAnimationState )
+  {
+    case PLAYING:
+    {
+      mAnimation.Pause();
+      mAnimationState = PAUSED;
+      mPlayStopButton.SetBackgroundImage( mIconPlay );
+    }
+    break;
+
+    case PAUSED:
+    {
+      mAnimation.Play();
+      mAnimationState = PLAYING;
+      mPlayStopButton.SetBackgroundImage( mIconStop );
+    }
+    break;
+
+    case STOPPED:
+    {
+      mPlayStopButton.SetBackgroundImage( mIconStop );
+      mRadialSweepView1.Deactivate();
+      mRadialSweepView2.Deactivate();
+      mRadialSweepView3.Deactivate();
+      StartAnimation();
+    }
+  }
+  return false;
+}
+
+void RadialMenuExample::OnAnimationFinished( Animation& source )
+{
+  mAnimationState = STOPPED;
+  mPlayStopButton.SetBackgroundImage( mIconPlay );
+}
+
+RadialSweepView RadialMenuExample::CreateSweepView( std::string imageName,
+                                                    Degree initialAngle,
+                                                    Degree finalAngle)
+{
+  // Create the image
+  Image image = ResourceImage::New(imageName);
+  mImageActor = ImageActor::New(image);
+  mImageActor.SetParentOrigin(ParentOrigin::CENTER);
+  mImageActor.SetAnchorPoint(AnchorPoint::CENTER);
+  mImageActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+
+  // Create the stencil
+  const ImageDimensions imageSize = ResourceImage::GetImageSize(imageName);
+  float diameter = std::max(imageSize.GetWidth(), imageSize.GetHeight());
+  RadialSweepView radialSweepView = RadialSweepView::New();
+  radialSweepView.SetDiameter( diameter );
+  radialSweepView.SetInitialAngle( initialAngle );
+  radialSweepView.SetFinalAngle( finalAngle );
+  radialSweepView.SetInitialSector( Degree(0.0f) );
+  radialSweepView.SetFinalSector( Degree(359.999f) );
+  radialSweepView.SetSize( Stage::GetCurrent().GetSize());
+  radialSweepView.SetEasingFunction( Dali::AlphaFunction::EASE_IN_OUT );
+  radialSweepView.SetPositionInheritanceMode(USE_PARENT_POSITION);
+  mContents.Add(radialSweepView);
+  radialSweepView.Add( mImageActor );
+  mImageActor.SetPositionInheritanceMode(USE_PARENT_POSITION);
+
+  return radialSweepView;
+}
+
+
+void RadialMenuExample::OnKeyEvent(const KeyEvent& event)
+{
+  if(event.state == KeyEvent::Down)
+  {
+    if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
+    {
+      mApplication.Quit();
+    }
+  }
+}
+
+void RunTest(Application app)
+{
+  RadialMenuExample test(app);
+
+  app.MainLoop();
+}
+
+// Entry point for Linux & Tizen applications
+int main(int argc, char **argv)
+{
+  Application app = Application::New(&argc, &argv);
+
+  RunTest(app);
+
+  return 0;
+}
diff --git a/examples/radial-menu/radial-sweep-view-impl.cpp b/examples/radial-menu/radial-sweep-view-impl.cpp
new file mode 100644 (file)
index 0000000..f13d58a
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "radial-sweep-view-impl.h"
+
+#include <sstream>
+
+using namespace Dali;
+
+namespace
+{
+
+const char* VERTEX_SHADER_PREFIX( "#define MATH_PI_2 1.570796\n#define MATH_PI_4 0.785398\n" );
+
+const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
+attribute mediump float   aAngleIndex;\n
+attribute mediump vec2    aPosition1;\n
+attribute mediump vec2    aPosition2;\n
+uniform   mediump mat4    uMvpMatrix;\n
+uniform   mediump float   uStartAngle;\n
+uniform   mediump float   uRotationAngle;\n
+\n
+void main()\n
+{\n
+  float currentAngle = uStartAngle + uRotationAngle;\n
+  float angleInterval1 =  MATH_PI_4 * aAngleIndex;\n
+  vec4 vertexPosition = vec4(0.0, 0.0, 0.0, 1.0);\n
+  if( currentAngle >=  angleInterval1)\n
+  {\n
+    float angleInterval2 =  angleInterval1 + MATH_PI_2;\n
+    float angle = currentAngle < angleInterval2 ? currentAngle : angleInterval2;\n
+    float delta;\n
+    if( mod( aAngleIndex+4.0, 4.0) < 2.0  )\n
+    {\n
+      delta = 0.5 - 0.5*cos(angle) / sin(angle);\n
+    }\n
+    else\n
+    {\n
+      delta = 0.5 + 0.5*sin(angle) / cos(angle);\n
+    }\n
+    vertexPosition.xy = mix( aPosition1, aPosition2, delta );\n
+  }\n
+  gl_Position = uMvpMatrix * vertexPosition;\n
+}
+);
+
+const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+uniform lowp  vec4    uColor;\n
+\n
+void main()\n
+{\n
+  gl_FragColor = uColor;\n
+}\n
+);
+
+float HoldZeroFastEaseInOutHoldOne(float progress)
+{
+  if( progress < 0.2f)
+  {
+    return 0.0f;
+  }
+  else if(progress < 0.5f)
+  {
+    progress = (progress-0.2) / 0.3f;
+    return  progress*progress*progress*0.5f;
+  }
+  else if(progress < 0.8f)
+  {
+    progress = ((progress - 0.5f) / 0.3f) - 1.0f;
+    return (progress*progress*progress+1.0f) * 0.5f + 0.5f;
+  }
+  else
+  {
+    return 1.0f;
+  }
+}
+
+} // anonymous namespace
+
+
+RadialSweepView RadialSweepViewImpl::New( )
+{
+  return New( 2.0f, 100.0f, ANGLE_0, ANGLE_0, ANGLE_0, ANGLE_360 );
+}
+
+
+RadialSweepView RadialSweepViewImpl::New( float duration, float diameter, Radian initialAngle, Radian finalAngle, Radian initialSector, Radian finalSector )
+{
+  RadialSweepViewImpl* impl= new RadialSweepViewImpl(duration, diameter, initialAngle, finalAngle, initialSector, finalSector);
+  RadialSweepView handle = RadialSweepView(*impl);
+  return handle;
+}
+
+RadialSweepViewImpl::RadialSweepViewImpl( float duration, float diameter, Radian initialAngle, Radian finalAngle, Radian initialSector, Radian finalSector )
+: Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
+  mDuration(duration),
+  mDiameter(diameter),
+  mInitialAngle(initialAngle),
+  mFinalAngle(finalAngle),
+  mInitialSector(initialSector),
+  mFinalSector(finalSector),
+  mInitialActorAngle(0),
+  mFinalActorAngle(0),
+  mEasingFunction(HoldZeroFastEaseInOutHoldOne),
+  mStartAngleIndex(Property::INVALID_INDEX),
+  mRotationAngleIndex(Property::INVALID_INDEX),
+  mRotateActorsWithStencil(false),
+  mRotateActors(false)
+{
+}
+
+void RadialSweepViewImpl::SetDuration(float duration)
+{
+  mDuration = duration;
+}
+
+void RadialSweepViewImpl::SetEasingFunction( Dali::AlphaFunction easingFunction )
+{
+  mEasingFunction = easingFunction;
+}
+
+void RadialSweepViewImpl::SetDiameter(float diameter)
+{
+  mDiameter = diameter;
+}
+
+void RadialSweepViewImpl::SetInitialAngle( Dali::Radian initialAngle)
+{
+  mInitialAngle = initialAngle;
+}
+
+void RadialSweepViewImpl::SetFinalAngle( Dali::Radian finalAngle)
+{
+  mFinalAngle = finalAngle;
+}
+
+void RadialSweepViewImpl::SetInitialSector( Dali::Radian initialSector)
+{
+  mInitialSector = initialSector;
+}
+
+void RadialSweepViewImpl::SetFinalSector( Dali::Radian finalSector)
+{
+  mFinalSector = finalSector;
+}
+
+void RadialSweepViewImpl::SetInitialActorAngle( Dali::Radian initialAngle )
+{
+  mInitialActorAngle = initialAngle;
+  mRotateActors = true;
+}
+
+void RadialSweepViewImpl::SetFinalActorAngle( Dali::Radian finalAngle )
+{
+  mFinalActorAngle = finalAngle;
+  mRotateActors = true;
+}
+
+float RadialSweepViewImpl::GetDuration( )
+{
+  return mDuration;
+}
+
+float RadialSweepViewImpl::GetDiameter( )
+{
+  return mDiameter;
+}
+
+Dali::Radian RadialSweepViewImpl::GetInitialAngle( )
+{
+  return mInitialAngle;
+}
+
+Dali::Radian RadialSweepViewImpl::GetFinalAngle( )
+{
+  return mFinalAngle;
+}
+
+Dali::Radian RadialSweepViewImpl::GetInitialSector( )
+{
+  return mInitialSector;
+}
+
+Dali::Radian RadialSweepViewImpl::GetFinalSector( )
+{
+  return mFinalSector;
+}
+
+Dali::Radian RadialSweepViewImpl::GetInitialActorAngle( )
+{
+  return mInitialActorAngle;
+}
+
+Dali::Radian RadialSweepViewImpl::GetFinalActorAngle(  )
+{
+  return mFinalActorAngle;
+}
+
+void RadialSweepViewImpl::RotateActorsWithStencil(bool rotate)
+{
+  mRotateActorsWithStencil = rotate;
+}
+
+void RadialSweepViewImpl::Add(Actor actor)
+{
+  if( ! mLayer )
+  {
+    mLayer = Layer::New();
+    Self().Add(mLayer);
+    mLayer.SetSize( Stage::GetCurrent().GetSize() );
+    mLayer.SetPositionInheritanceMode(USE_PARENT_POSITION);
+  }
+
+  mLayer.Add(actor);
+}
+
+void RadialSweepViewImpl::Activate( Animation anim, float offsetTime, float duration )
+{
+  bool startAnimation=false;
+  if( ! anim )
+  {
+    mAnim = Animation::New( mDuration );
+    anim = mAnim;
+    startAnimation = true;
+  }
+
+  if( ! mStencilActor )
+  {
+    CreateStencil( mInitialSector );
+    mLayer.Add( mStencilActor );
+    mStencilActor.SetScale(mDiameter);
+  }
+
+  mStencilActor.SetOrientation( mInitialAngle, Vector3::ZAXIS );
+  mStencilActor.SetProperty( mRotationAngleIndex, mInitialSector.radian );
+
+  if( mRotateActors )
+  {
+    for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
+    {
+      Actor actor = mLayer.GetChildAt(i);
+      if( actor != mStencilActor )
+      {
+        anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mInitialActorAngle ), Vector3::ZAXIS ) );
+      }
+    }
+  }
+
+  anim.AnimateTo( Property( mStencilActor, mRotationAngleIndex ), mFinalSector.radian, mEasingFunction, TimePeriod( offsetTime, duration ) );
+  anim.AnimateTo( Property( mStencilActor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalAngle ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
+
+  if( mRotateActorsWithStencil )
+  {
+    for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
+    {
+      Actor actor = mLayer.GetChildAt(i);
+      if( actor != mStencilActor )
+      {
+        anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalAngle.radian - mInitialAngle.radian ) , Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
+      }
+    }
+  }
+  else if( mRotateActors )
+  {
+    for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
+    {
+      Actor actor = mLayer.GetChildAt(i);
+      if( actor != mStencilActor )
+      {
+        anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalActorAngle ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
+      }
+    }
+  }
+
+
+  if( startAnimation )
+  {
+    anim.SetLooping(true);
+    anim.Play();
+  }
+}
+
+
+void RadialSweepViewImpl::Deactivate()
+{
+  if( mAnim )
+  {
+    mAnim.Stop();
+  }
+  // mLayer.Remove( mStencilActor );
+  // mStencilActor.Reset();
+  // mMesh.Reset();
+  // mMaterial.Reset();
+}
+
+void RadialSweepViewImpl::CreateStencil( Radian initialSector )
+{
+  // Create the stencil mesh geometry
+  //     3-----2
+  //     | \ / |
+  //     |  0--1 , 6
+  //     | / \ |
+  //     4-----5
+
+  struct VertexPosition { float angleIndex; Vector2 position1; Vector2 position2; };
+  VertexPosition vertexData[7] = { // With X coordinate inverted to make the animation go anti clockwise from left center
+      { 9.f,  Vector2( 0.f, 0.f ),     Vector2( 0.f, 0.f )     }, // center point, keep static
+      { 0.f,  Vector2( -0.5f, 0.f ),   Vector2( -0.5f, 0.f )   }, // vertex 1, 0 degree, keep static
+      { -1.f, Vector2( -0.5f, 0.5f ),  Vector2( -0.5f, -0.5f ) }, // -45 ~ 45 degrees  ( 0 ~ 45)
+      { 1.f,  Vector2( -0.5f, -0.5f ), Vector2( 0.5f, -0.5f )  }, // 45 ~ 135 degrees
+      { 3.f,  Vector2( 0.5f, -0.5f ),  Vector2( 0.5f, 0.5f )   }, // 135 ~ 225 degrees
+      { 5.f,  Vector2( 0.5f, 0.5f ),   Vector2( -0.5f, 0.5f )  }, // 225 ~ 315 degrees
+      { 7.f,  Vector2( -0.5f, 0.5f ),  Vector2( -0.5f, -0.5f ) }  // 315 ~ 405 degrees ( 315 ~ 359.999 )
+  };
+  Property::Map vertexFormat;
+  vertexFormat["aAngleIndex"] = Property::FLOAT;
+  vertexFormat["aPosition1"] = Property::VECTOR2;
+  vertexFormat["aPosition2"] = Property::VECTOR2;
+  PropertyBuffer vertices = PropertyBuffer::New( PropertyBuffer::STATIC, vertexFormat, 7u );
+  vertices.SetData( vertexData );
+
+  unsigned int indexData[15] = { 0,1,2,0,2,3,0,3,4,0,4,5,0,5,6 };
+  Property::Map indexFormat;
+  indexFormat["indices"] = Property::UNSIGNED_INTEGER;
+  PropertyBuffer indices = PropertyBuffer::New( PropertyBuffer::STATIC, indexFormat, 15u );
+  indices.SetData( indexData );
+
+  Geometry meshGeometry = Geometry::New();
+  meshGeometry.AddVertexBuffer( vertices );
+  meshGeometry.SetIndexBuffer( indices );
+
+  // Create material
+  std::ostringstream vertexShaderStringStream;
+  vertexShaderStringStream<<VERTEX_SHADER_PREFIX<<VERTEX_SHADER;
+  Shader shader = Shader::New( vertexShaderStringStream.str(), FRAGMENT_SHADER );
+  Material material = Material::New( shader );
+
+  // Create renderer
+  Renderer renderer = Renderer::New( meshGeometry, material );
+
+  mStencilActor = Actor::New();
+  mStencilActor.AddRenderer( renderer );
+  mStencilActor.SetSize(1.f, 1.f);
+
+  // register properties
+  mStartAngleIndex = mStencilActor.RegisterProperty("start-angle", 0.f);
+  mStencilActor.AddUniformMapping( mStartAngleIndex, "uStartAngle " );
+  mRotationAngleIndex = mStencilActor.RegisterProperty("rotation-angle", initialSector.radian);
+  mStencilActor.AddUniformMapping( mRotationAngleIndex, "uRotationAngle" );
+
+  mStencilActor.SetDrawMode( DrawMode::STENCIL );
+  mStencilActor.SetPositionInheritanceMode(USE_PARENT_POSITION);
+}
diff --git a/examples/radial-menu/radial-sweep-view-impl.h b/examples/radial-menu/radial-sweep-view-impl.h
new file mode 100644 (file)
index 0000000..5089c78
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef DALI_DEMO_RADIAL_SWEEP_VIEW_IMPL_H
+#define DALI_DEMO_RADIAL_SWEEP_VIEW_IMPL_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit/dali-toolkit.h>
+#include "radial-sweep-view.h"
+
+
+/********************************************************************************
+ * Class to implement a layer with a radial sweep stencil mask and an actor tree
+ */
+class RadialSweepViewImpl : public Dali::Toolkit::Internal::Control
+{
+public:
+  static RadialSweepView New();
+
+  static RadialSweepView New( float duration,
+                              float diameter,
+                              Dali::Radian initialAngle,
+                              Dali::Radian finalAngle,
+                              Dali::Radian initialSector,
+                              Dali::Radian finalSector );
+
+  RadialSweepViewImpl( float duration,
+                       float diameter,
+                       Dali::Radian initialAngle,
+                       Dali::Radian finalAngle,
+                       Dali::Radian initialSector,
+                       Dali::Radian finalSector );
+
+  void SetDuration(float duration);
+  void SetEasingFunction( Dali::AlphaFunction easingFunction );
+
+  void SetDiameter(float diameter);
+  void SetInitialAngle( Dali::Radian initialAngle);
+  void SetFinalAngle( Dali::Radian finalAngle);
+  void SetInitialSector( Dali::Radian initialSector);
+  void SetFinalSector( Dali::Radian finalSector);
+  void SetInitialActorAngle( Dali::Radian initialAngle );
+  void SetFinalActorAngle( Dali::Radian finalAngle );
+
+  float GetDuration( );
+  float GetDiameter( );
+  Dali::Radian GetInitialAngle( );
+  Dali::Radian GetFinalAngle( );
+  Dali::Radian GetInitialSector( );
+  Dali::Radian GetFinalSector( );
+  Dali::Radian GetInitialActorAngle( );
+  Dali::Radian GetFinalActorAngle( );
+
+  void RotateActorsWithStencil(bool rotate);
+
+  void Add( Dali::Actor actor );
+
+  void Activate( Dali::Animation anim = Dali::Animation(), float offsetTime=0, float duration=2.0f );
+
+  void Deactivate();
+
+private:
+
+  /**
+   * Create the stencil mask
+   */
+  void CreateStencil(Dali::Radian initialSector );
+
+private:
+  Dali::Layer           mLayer;
+  Dali::Animation       mAnim;
+  float                 mDuration;
+  float                 mDiameter;
+  Dali::Radian          mInitialAngle;
+  Dali::Radian          mFinalAngle;
+  Dali::Radian          mInitialSector;
+  Dali::Radian          mFinalSector;
+  Dali::Radian          mInitialActorAngle;
+  Dali::Radian          mFinalActorAngle;
+  Dali::AlphaFunction   mEasingFunction;
+  Dali::Actor           mStencilActor;       ///< Stencil actor which generates mask
+  Dali::Property::Index mStartAngleIndex;    ///< Index of start-angle property
+  Dali::Property::Index mRotationAngleIndex; ///< Index of rotation-angle property
+  bool                  mRotateActorsWithStencil:1;
+  bool                  mRotateActors;
+};
+
+
+inline RadialSweepViewImpl& GetImpl( RadialSweepView& obj )
+{
+  DALI_ASSERT_ALWAYS(obj);
+  Dali::RefObject& handle = obj.GetImplementation();
+  return static_cast<RadialSweepViewImpl&>(handle);
+}
+
+inline const RadialSweepViewImpl& GetImpl( const RadialSweepView& obj )
+{
+  DALI_ASSERT_ALWAYS(obj);
+  const Dali::RefObject& handle = obj.GetImplementation();
+  return static_cast<const RadialSweepViewImpl&>(handle);
+}
+
+
+
+#endif // DALI_DEMO_RADIAL_SWEEP_VIEW_IMPL_H
diff --git a/examples/radial-menu/radial-sweep-view.cpp b/examples/radial-menu/radial-sweep-view.cpp
new file mode 100644 (file)
index 0000000..46e2609
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "radial-sweep-view.h"
+#include "radial-sweep-view-impl.h"
+
+using namespace Dali;
+
+RadialSweepView::RadialSweepView()
+{
+}
+
+RadialSweepView::RadialSweepView(const RadialSweepView& handle)
+: Control(handle)
+{
+}
+
+RadialSweepView& RadialSweepView::operator=(const RadialSweepView& rhs)
+{
+  if( &rhs != this )
+  {
+    Control::operator=(rhs);
+  }
+  return *this;
+}
+
+RadialSweepView::~RadialSweepView()
+{
+}
+
+RadialSweepView RadialSweepView::DownCast( BaseHandle handle )
+{
+  return Control::DownCast<RadialSweepView, RadialSweepViewImpl>(handle);
+}
+
+RadialSweepView RadialSweepView::New( )
+{
+  return RadialSweepViewImpl::New();
+}
+
+RadialSweepView RadialSweepView::New( float duration,
+                                      float diameter,
+                                      Radian initialAngle,
+                                      Radian finalAngle,
+                                      Radian initialSector,
+                                      Radian finalSector )
+{
+  return RadialSweepViewImpl::New(duration, diameter, initialAngle, finalAngle, initialSector, finalSector );
+}
+
+RadialSweepView::RadialSweepView( RadialSweepViewImpl& impl )
+: Control( impl )
+{
+}
+
+RadialSweepView::RadialSweepView( Dali::Internal::CustomActor* impl )
+: Control( impl )
+{
+  VerifyCustomActorPointer<RadialSweepViewImpl>(impl);
+}
+
+void RadialSweepView::SetDuration(float duration)
+{
+  GetImpl(*this).SetDuration(duration);
+}
+
+void RadialSweepView::SetEasingFunction( Dali::AlphaFunction easingFunction )
+{
+  GetImpl(*this).SetEasingFunction( easingFunction );
+}
+
+void RadialSweepView::SetDiameter(float diameter)
+{
+  GetImpl(*this).SetDiameter(diameter);
+}
+
+void RadialSweepView::SetInitialAngle( Dali::Radian initialAngle)
+{
+  GetImpl(*this).SetInitialAngle(initialAngle);
+}
+
+void RadialSweepView::SetFinalAngle( Dali::Radian finalAngle)
+{
+  GetImpl(*this).SetFinalAngle(finalAngle);
+}
+
+void RadialSweepView::SetInitialSector( Dali::Radian initialSector)
+{
+  GetImpl(*this).SetInitialSector(initialSector);
+}
+
+void RadialSweepView::SetFinalSector( Dali::Radian finalSector)
+{
+  GetImpl(*this).SetFinalSector(finalSector);
+}
+
+void RadialSweepView::SetInitialActorAngle( Dali::Radian initialAngle )
+{
+  GetImpl(*this).SetInitialActorAngle(initialAngle);
+}
+
+void RadialSweepView::SetFinalActorAngle( Dali::Radian finalAngle )
+{
+  GetImpl(*this).SetFinalActorAngle(finalAngle);
+}
+
+float RadialSweepView::GetDuration( )
+{
+  return GetImpl(*this).GetDuration();
+}
+
+float RadialSweepView::GetDiameter( )
+{
+  return GetImpl(*this).GetDiameter();
+}
+
+Dali::Radian RadialSweepView::GetInitialAngle( )
+{
+  return GetImpl(*this).GetInitialAngle();
+}
+
+Dali::Radian RadialSweepView::GetFinalAngle( )
+{
+  return GetImpl(*this).GetFinalAngle();
+}
+
+Dali::Radian RadialSweepView::GetInitialSector( )
+{
+  return GetImpl(*this).GetInitialSector();
+}
+
+Dali::Radian RadialSweepView::GetFinalSector( )
+{
+  return GetImpl(*this).GetFinalSector();
+}
+
+Dali::Radian RadialSweepView::GetInitialActorAngle( )
+{
+  return GetImpl(*this).GetInitialActorAngle();
+}
+
+Dali::Radian RadialSweepView::GetFinalActorAngle( )
+{
+  return GetImpl(*this).GetFinalActorAngle();
+}
+
+void RadialSweepView::RotateActorsWithStencil(bool rotate)
+{
+  GetImpl(*this).RotateActorsWithStencil(rotate);
+}
+
+void RadialSweepView::Add(Actor actor)
+{
+  GetImpl(*this).Add(actor);
+}
+
+void RadialSweepView::Activate()
+{
+  GetImpl(*this).Activate();
+}
+
+void RadialSweepView::Activate( Dali::Animation anim, float offsetTime, float duration )
+{
+  GetImpl(*this).Activate(anim, offsetTime, duration);
+}
+
+void RadialSweepView::Deactivate()
+{
+  GetImpl(*this).Deactivate();
+}
diff --git a/examples/radial-menu/radial-sweep-view.h b/examples/radial-menu/radial-sweep-view.h
new file mode 100644 (file)
index 0000000..3abdcb0
--- /dev/null
@@ -0,0 +1,150 @@
+#ifndef DALI_DEMO_RADIAL_SWEEP_VIEW_H
+#define DALI_DEMO_RADIAL_SWEEP_VIEW_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit/dali-toolkit.h>
+
+class RadialSweepViewImpl;
+
+
+/********************************************************************************
+ * Handle to RadialSweepView implementation
+ */
+class RadialSweepView : public Dali::Toolkit::Control
+{
+public:
+  /**
+   * Create a new RadialSweepView with default parameters (2 second animation,
+   * no rotation, sweeping out a full circle).
+   */
+  static RadialSweepView New( );
+
+  /**
+   * Create a new RadialSweepView.
+   * @param[in] duration The duration of the sweep animation
+   * @param[in] diameter The diameter of the stencil mask
+   * @param[in] initialAngle The initial angle of the anticlockwise line of the sweep sector
+   * @param[in] finalAngle The final angle of the anticlockwise line of the sweep sector
+   * @param[in] initialSector The angle of the starting sector
+   * @param[in] finalSector The angle of the sector at the end of the animation.
+   * Note, to cover the entire circle, use a value of 359.9999 degrees, not zero or 360 degrees.
+   *
+   *            initial sector
+   *             \   |  .
+   *              \  |    .
+   * initialAngle  \ |     .   final sector
+   *                \|      _|
+   *                 .________
+   */
+  static RadialSweepView New( float duration,
+                              float diameter,
+                              Dali::Radian initialAngle,
+                              Dali::Radian finalAngle,
+                              Dali::Radian initialSector,
+                              Dali::Radian finalSector );
+
+  void SetDuration(float duration);
+
+  void SetEasingFunction( Dali::AlphaFunction easingFunction );
+
+  void SetDiameter(float diameter);
+
+  void SetInitialAngle( Dali::Radian initialAngle);
+
+  void SetFinalAngle( Dali::Radian finalAngle);
+
+  void SetInitialSector( Dali::Radian initialSector);
+
+  void SetFinalSector( Dali::Radian finalSector);
+
+  void SetInitialActorAngle( Dali::Radian initialAngle );
+
+  void SetFinalActorAngle( Dali::Radian finalAngle );
+
+  float GetDuration( );
+
+  float GetDiameter( );
+
+  Dali::Radian GetInitialAngle( );
+
+  Dali::Radian GetFinalAngle( );
+
+  Dali::Radian GetInitialSector( );
+
+  Dali::Radian GetFinalSector( );
+
+  Dali::Radian GetInitialActorAngle( );
+
+  Dali::Radian GetFinalActorAngle( );
+
+  /**
+   * @param[in] rotate True if the actors should rotate with the stencil
+   */
+  void RotateActorsWithStencil(bool rotate);
+
+  /**
+   * Add actors to the view
+   */
+  void Add(Actor actor);
+
+  /**
+   * Activate the sweep animation
+   */
+  void Activate( );
+
+  void Activate( Dali::Animation anim, float offsetTime, float duration );
+
+  /**
+   * Deactivate the sweep animation
+   */
+  void Deactivate();
+
+  /**
+   * Default constructor. Create an uninitialized handle.
+   */
+  RadialSweepView();
+
+  /**
+   * Copy constructor
+   */
+  RadialSweepView(const RadialSweepView& handle);
+
+  /**
+   * Assignment operator
+   */
+  RadialSweepView& operator=(const RadialSweepView& rhs);
+
+  /**
+   * Destructor
+   */
+  ~RadialSweepView();
+
+  /**
+   * Downcast method
+   */
+  static RadialSweepView DownCast( BaseHandle handle );
+
+public: // Not for use by application developers
+
+  RadialSweepView( RadialSweepViewImpl& impl );
+
+  RadialSweepView( Dali::Internal::CustomActor* impl );
+};
+
+#endif
diff --git a/examples/refraction-effect/refraction-effect-example.cpp b/examples/refraction-effect/refraction-effect-example.cpp
new file mode 100644 (file)
index 0000000..8a82398
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/dali.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include "shared/view.h"
+
+#include <fstream>
+#include <sstream>
+#include <limits>
+
+using namespace Dali;
+
+namespace
+{
+const char * const APPLICATION_TITLE( "Refraction Effect" );
+const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
+const char * const CHANGE_TEXTURE_ICON( DALI_IMAGE_DIR "icon-change.png" );
+const char * const CHANGE_MESH_ICON( DALI_IMAGE_DIR "icon-replace.png" );
+
+const char* MESH_FILES[] =
+{
+ DALI_MODEL_DIR "surface_pattern_v01.obj",
+ DALI_MODEL_DIR "surface_pattern_v02.obj"
+};
+const unsigned int NUM_MESH_FILES( sizeof( MESH_FILES ) / sizeof( MESH_FILES[0] ) );
+
+const char* TEXTURE_IMAGES[]=
+{
+  DALI_IMAGE_DIR "background-1.jpg",
+  DALI_IMAGE_DIR "background-2.jpg",
+  DALI_IMAGE_DIR "background-3.jpg",
+  DALI_IMAGE_DIR "background-4.jpg"
+};
+const unsigned int NUM_TEXTURE_IMAGES( sizeof( TEXTURE_IMAGES ) / sizeof( TEXTURE_IMAGES[0] ) );
+
+struct LightOffsetConstraint
+{
+  LightOffsetConstraint( float radius )
+  : mRadius( radius )
+  {
+  }
+
+  void operator()( Vector2& current, const PropertyInputContainer& inputs )
+  {
+    float spinAngle = inputs[0]->GetFloat();
+    current.x = cos( spinAngle );
+    current.y = sin( spinAngle );
+
+    current *= mRadius;
+  }
+
+  float mRadius;
+};
+
+/**
+ * @brief Load an image, scaled-down to no more than the stage dimensions.
+ *
+ * Uses image scaling mode SCALE_TO_FILL to resize the image at
+ * load time to cover the entire stage with pixels with no borders,
+ * and filter mode BOX_THEN_LINEAR to sample the image with maximum quality.
+ */
+ResourceImage LoadStageFillingImage( const char * const imagePath )
+{
+  Size stageSize = Stage::GetCurrent().GetSize();
+  return ResourceImage::New( imagePath, ImageDimensions( stageSize.x, stageSize.y ), Dali::FittingMode::SCALE_TO_FILL, Dali::SamplingMode::BOX_THEN_LINEAR );
+}
+
+/**
+ * structure of the vertex in the mesh
+ */
+struct Vertex
+{
+  Vector3 position;
+  Vector3 normal;
+  Vector2 textureCoord;
+
+  Vertex()
+  {}
+
+  Vertex( const Vector3& position, const Vector3& normal, const Vector2& textureCoord )
+  : position( position ), normal( normal ), textureCoord( textureCoord )
+  {}
+};
+
+/************************************************************************************************
+ *** The shader source is used when the MeshActor is not touched***
+ ************************************************************************************************/
+const char* VERTEX_SHADER_FLAT = DALI_COMPOSE_SHADER(
+attribute mediump vec3    aPosition;\n
+attribute mediump vec3    aNormal;\n
+attribute highp   vec2    aTexCoord;\n
+uniform   mediump mat4    uMvpMatrix;\n
+varying   mediump vec2    vTexCoord;\n
+void main()\n
+{\n
+  gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n
+  vTexCoord = aTexCoord.xy;\n
+}\n
+);
+
+const char* FRAGMENT_SHADER_FLAT = DALI_COMPOSE_SHADER(
+uniform lowp    vec4  uColor;\n
+uniform sampler2D     sTexture;\n
+varying mediump vec2  vTexCoord;\n
+void main()\n
+{\n
+  gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
+}\n
+);
+
+/************************************************************
+ ** Custom refraction effect shader***************************
+ ************************************************************/
+const char* VERTEX_SHADER_REFRACTION = DALI_COMPOSE_SHADER(
+attribute mediump vec3    aPosition;\n
+attribute mediump vec3    aNormal;\n
+attribute highp   vec2    aTexCoord;\n
+uniform   mediump mat4    uMvpMatrix;\n
+varying   mediump vec4    vVertex;\n
+varying   mediump vec3    vNormal;\n
+varying   mediump vec2    vTexCoord;\n
+varying   mediump vec2    vTextureOffset;\n
+void main()\n
+{\n
+  gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n
+  vTexCoord = aTexCoord.xy;\n
+
+  vNormal = aNormal;\n
+  vVertex = vec4( aPosition, 1.0 );\n
+  float length = max(0.01, length(aNormal.xy)) * 40.0;\n
+  vTextureOffset = aNormal.xy / length;\n
+}\n
+);
+
+const char* FRAGMENT_SHADER_REFRACTION = DALI_COMPOSE_SHADER(
+precision mediump float;\n
+uniform   mediump float  uEffectStrength;\n
+uniform   mediump vec3   uLightPosition;\n
+uniform   mediump vec2   uLightXYOffset;\n
+uniform   mediump vec2   uLightSpinOffset;\n
+uniform   mediump float  uLightIntensity;\n
+uniform   lowp    vec4   uColor;\n
+uniform   sampler2D      sTexture;\n
+varying   mediump vec4   vVertex;\n
+varying   mediump vec3   vNormal;\n
+varying   mediump vec2   vTexCoord;\n
+varying   mediump vec2   vTextureOffset;\n
+
+vec3 rgb2hsl(vec3 rgb)\n
+{\n
+  float epsilon = 1.0e-10;\n
+  vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n
+  vec4 P = mix(vec4(rgb.bg, K.wz), vec4(rgb.gb, K.xy), step(rgb.b, rgb.g));\n
+  vec4 Q = mix(vec4(P.xyw, rgb.r), vec4(rgb.r, P.yzx), step(P.x, rgb.r));\n
+  \n
+  // RGB -> HCV
+  float value = Q.x;\n
+  float chroma = Q.x - min(Q.w, Q.y);\n
+  float hue = abs(Q.z + (Q.w-Q.y) / (6.0*chroma+epsilon));\n
+  // HCV -> HSL
+  float lightness = value - chroma*0.5;\n
+  return vec3( hue, chroma/max( 1.0-abs(lightness*2.0-1.0), 1.0e-1 ), lightness );\n
+}\n
+
+vec3 hsl2rgb( vec3 hsl )\n
+{\n
+  // pure hue->RGB
+  vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n
+  vec3 p = abs(fract(hsl.xxx + K.xyz) * 6.0 - K.www);\n
+  vec3 RGB = clamp(p - K.xxx, 0.0, 1.0);\n
+  \n
+  float chroma = ( 1.0 - abs( hsl.z*2.0-1.0 ) ) * hsl.y;\n
+  return ( RGB - 0.5 ) * chroma + hsl.z;\n
+}\n
+
+void main()\n
+{\n
+  vec3 normal = normalize( vNormal);\n
+
+  vec3 lightPosition = uLightPosition + vec3(uLightXYOffset+uLightSpinOffset, 0.0);\n
+  mediump vec3 vecToLight = normalize( (lightPosition - vVertex.xyz) * 0.01 );\n
+  mediump float spotEffect = pow( max(0.05, vecToLight.z ) - 0.05, 8.0);\n
+
+  spotEffect = spotEffect * uEffectStrength;\n
+  mediump float lightDiffuse = ( ( dot( vecToLight, normal )-0.75 ) *uLightIntensity  ) * spotEffect;\n
+
+  lowp vec4 color = texture2D( sTexture, vTexCoord + vTextureOffset * spotEffect );\n
+  vec3 lightedColor =  hsl2rgb( rgb2hsl(color.rgb) + vec3(0.0,0.0,lightDiffuse) );\n
+
+  gl_FragColor = vec4( lightedColor, color.a ) * uColor;\n
+}\n
+);
+
+} // namespace
+
+
+/*************************************************/
+/*Demo using RefractionEffect*****************/
+/*************************************************/
+class RefractionEffectExample : public ConnectionTracker
+{
+public:
+  RefractionEffectExample( Application &application )
+  : mApplication( application ),
+    mCurrentTextureId( 1 ),
+    mCurrentMeshId( 0 )
+  {
+    // Connect to the Application's Init signal
+    application.InitSignal().Connect(this, &RefractionEffectExample::Create);
+  }
+
+  ~RefractionEffectExample()
+  {
+  }
+
+private:
+
+  // The Init signal is received once (only) during the Application lifetime
+  void Create(Application& application)
+  {
+    DemoHelper::RequestThemeChange();
+
+    Stage stage = Stage::GetCurrent();
+    Vector2 stageSize = stage.GetSize();
+
+    stage.KeyEventSignal().Connect(this, &RefractionEffectExample::OnKeyEvent);
+
+    // Creates a default view with a default tool bar.
+    // The view is added to the stage.
+    Toolkit::ToolBar toolBar;
+    Toolkit::Control    view;
+    mContent = DemoHelper::CreateView( application,
+        view,
+        toolBar,
+        "",
+        TOOLBAR_IMAGE,
+        APPLICATION_TITLE );
+
+    // Add a button to change background. (right of toolbar)
+    mChangeTextureButton = Toolkit::PushButton::New();
+    mChangeTextureButton.SetBackgroundImage( ResourceImage::New( CHANGE_TEXTURE_ICON ) );
+    mChangeTextureButton.ClickedSignal().Connect( this, &RefractionEffectExample::OnChangeTexture );
+    toolBar.AddControl( mChangeTextureButton,
+                        DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
+                        Toolkit::Alignment::HorizontalRight,
+                        DemoHelper::DEFAULT_MODE_SWITCH_PADDING  );
+    // Add a button to change mesh pattern. ( left of bar )
+    mChangeMeshButton = Toolkit::PushButton::New();
+    mChangeMeshButton.SetBackgroundImage( ResourceImage::New( CHANGE_MESH_ICON ) );
+    mChangeMeshButton.ClickedSignal().Connect( this, &RefractionEffectExample::OnChangeMesh );
+    toolBar.AddControl( mChangeMeshButton,
+                        DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage,
+                        Toolkit::Alignment::HorizontalLeft,
+                        DemoHelper::DEFAULT_MODE_SWITCH_PADDING  );
+
+
+
+    // shader used when the screen is not touched, render a flat surface
+    mShaderFlat = Shader::New( VERTEX_SHADER_FLAT, FRAGMENT_SHADER_FLAT );
+    mGeometry = CreateGeometry( MESH_FILES[mCurrentMeshId] );
+
+    Image texture = LoadStageFillingImage( TEXTURE_IMAGES[mCurrentTextureId] );
+    mSampler = Sampler::New( texture, "sTexture" );
+    mMaterial = Material::New( mShaderFlat );
+    mMaterial.AddSampler( mSampler );
+
+    mRenderer = Renderer::New( mGeometry, mMaterial );
+
+    mMeshActor = Actor::New();
+    mMeshActor.AddRenderer( mRenderer );
+    mMeshActor.SetSize( stageSize );
+    mMeshActor.SetParentOrigin(ParentOrigin::CENTER);
+    mContent.Add( mMeshActor );
+
+    // Connect the callback to the touch signal on the mesh actor
+    mContent.TouchedSignal().Connect( this, &RefractionEffectExample::OnTouch );
+
+    // shader used when the finger is touching the screen. render refraction effect
+    mShaderRefraction = Shader::New( VERTEX_SHADER_REFRACTION, FRAGMENT_SHADER_REFRACTION );
+
+    // register uniforms
+    mLightXYOffsetIndex = mMeshActor.RegisterProperty( "light-XY-offset", Vector2::ZERO );
+    mMeshActor.AddUniformMapping( mLightXYOffsetIndex, "uLightXYOffset" );
+
+    mLightIntensityIndex = mMeshActor.RegisterProperty( "light-intensity", 2.5f );
+    mMeshActor.AddUniformMapping( mLightIntensityIndex, "uLightIntensity" );
+
+    mEffectStrengthIndex = mMeshActor.RegisterProperty( "effect-strength",  0.f );
+    mMeshActor.AddUniformMapping( mEffectStrengthIndex, "uEffectStrength" );
+
+    Vector3 lightPosition( -stageSize.x*0.5f, -stageSize.y*0.5f, stageSize.x*0.5f ); // top_left
+    Property::Index lightPositionIndex = mMeshActor.RegisterProperty( "light-position", lightPosition );
+    mMeshActor.AddUniformMapping( lightPositionIndex,  "uLightPosition");
+
+    Property::Index lightSpinOffsetIndex = mMeshActor.RegisterProperty( "light-spin-offset", Vector2::ZERO );
+    mMeshActor.AddUniformMapping( lightSpinOffsetIndex, "uLightSpinOffset" );
+
+    mSpinAngleIndex = mMeshActor.RegisterProperty("spin-angle", 0.f );
+    Constraint constraint = Constraint::New<Vector2>( mMeshActor, lightSpinOffsetIndex, LightOffsetConstraint(stageSize.x*0.1f) );
+    constraint.AddSource( LocalSource(mSpinAngleIndex) );
+    constraint.Apply();
+
+    // the animation which spin the light around the finger touch position
+    mLightAnimation = Animation::New(2.f);
+    mLightAnimation.AnimateTo( Property( mMeshActor, mSpinAngleIndex ), Math::PI*2.f );
+    mLightAnimation.SetLooping( true );
+    mLightAnimation.Pause();
+  }
+
+  void SetLightXYOffset( const Vector2& offset )
+  {
+    mMeshActor.SetProperty( mLightXYOffsetIndex,  offset );
+  }
+
+  /**
+   * Create a mesh actor with different geometry to replace the current one
+   */
+  bool OnChangeMesh( Toolkit::Button button  )
+  {
+    mCurrentMeshId = ( mCurrentMeshId + 1 ) % NUM_MESH_FILES;
+    mGeometry = CreateGeometry( MESH_FILES[mCurrentMeshId] );
+    mRenderer.SetGeometry( mGeometry );
+
+    return true;
+  }
+
+  bool OnChangeTexture( Toolkit::Button button )
+  {
+    mCurrentTextureId = ( mCurrentTextureId + 1 ) % NUM_TEXTURE_IMAGES;
+    Image texture = LoadStageFillingImage( TEXTURE_IMAGES[mCurrentTextureId] );
+    mSampler.SetImage( texture );
+    return true;
+  }
+
+  bool OnTouch( Actor actor , const TouchEvent& event )
+  {
+    const TouchPoint &point = event.GetPoint(0);
+    switch(point.state)
+    {
+      case TouchPoint::Down:
+      {
+        mMaterial.SetShader( mShaderRefraction );
+
+        SetLightXYOffset( point.screen );
+
+        mLightAnimation.Play();
+
+        if( mStrenghAnimation )
+        {
+          mStrenghAnimation.Clear();
+        }
+
+        mStrenghAnimation= Animation::New(0.5f);
+        mStrenghAnimation.AnimateTo( Property( mMeshActor, mEffectStrengthIndex ), 1.f );
+        mStrenghAnimation.Play();
+
+        break;
+      }
+      case TouchPoint::Motion:
+      {
+        // make the light position following the finger movement
+        SetLightXYOffset( point.screen );
+        break;
+      }
+      case TouchPoint::Up:
+      case TouchPoint::Leave:
+      case TouchPoint::Interrupted:
+      {
+        mLightAnimation.Pause();
+
+        if( mStrenghAnimation )
+        {
+          mStrenghAnimation.Clear();
+        }
+        mStrenghAnimation = Animation::New(0.5f);
+        mStrenghAnimation.AnimateTo( Property( mMeshActor, mEffectStrengthIndex ), 0.f );
+        mStrenghAnimation.FinishedSignal().Connect( this, &RefractionEffectExample::OnTouchFinished );
+        mStrenghAnimation.Play();
+        break;
+      }
+      case TouchPoint::Stationary:
+      case TouchPoint::Last:
+      default:
+      {
+        break;
+      }
+    }
+
+    return true;
+  }
+
+  void OnTouchFinished( Animation& source )
+  {
+    mMaterial.SetShader( mShaderFlat );
+    SetLightXYOffset( Vector2::ZERO );
+  }
+
+  Geometry CreateGeometry(const std::string& objFileName)
+  {
+    std::vector<Vector3> vertexPositions;
+    Vector<unsigned int> faceIndices;
+    Vector<float> boundingBox;
+    // read the vertice and faces from the .obj file, and record the bounding box
+    ReadObjFile( objFileName, boundingBox, vertexPositions, faceIndices );
+
+    std::vector<Vector2> textureCoordinates;
+    // align the mesh, scale it to fit the screen size, and calculate the texture coordinate for each vertex
+    ShapeResizeAndTexureCoordinateCalculation( boundingBox, vertexPositions, textureCoordinates );
+
+    // re-organize the mesh, the vertices are duplicated, each vertex only belongs to one triangle.
+    // Without sharing vertex between triangle, so we can manipulate the texture offset on each triangle conveniently.
+    std::vector<Vertex> vertices;
+
+    std::size_t size = faceIndices.Size();
+    vertices.reserve( size );
+
+    for( std::size_t i=0; i<size; i=i+3 )
+    {
+      Vector3 edge1 = vertexPositions[ faceIndices[i+2] ] - vertexPositions[ faceIndices[i] ];
+      Vector3 edge2 = vertexPositions[ faceIndices[i+1] ] - vertexPositions[ faceIndices[i] ];
+      Vector3 normal = edge1.Cross(edge2);
+      normal.Normalize();
+
+      // make sure all the faces are front-facing
+      if( normal.z > 0 )
+      {
+        vertices.push_back( Vertex( vertexPositions[ faceIndices[i] ], normal, textureCoordinates[ faceIndices[i] ] ) );
+        vertices.push_back( Vertex( vertexPositions[ faceIndices[i+1] ], normal, textureCoordinates[ faceIndices[i+1] ] ) );
+        vertices.push_back( Vertex( vertexPositions[ faceIndices[i+2] ], normal, textureCoordinates[ faceIndices[i+2] ] ) );
+      }
+      else
+      {
+        normal *= -1.f;
+        vertices.push_back( Vertex( vertexPositions[ faceIndices[i] ], normal, textureCoordinates[ faceIndices[i] ] ) );
+        vertices.push_back( Vertex( vertexPositions[ faceIndices[i+2] ], normal, textureCoordinates[ faceIndices[i+2] ] ) );
+        vertices.push_back( Vertex( vertexPositions[ faceIndices[i+1] ], normal, textureCoordinates[ faceIndices[i+1] ] ) );
+      }
+    }
+
+    Property::Map vertexFormat;
+    vertexFormat["aPosition"] = Property::VECTOR3;
+    vertexFormat["aNormal"] = Property::VECTOR3;
+    vertexFormat["aTexCoord"] = Property::VECTOR2;
+    PropertyBuffer surfaceVertices = PropertyBuffer::New( PropertyBuffer::STATIC, vertexFormat, vertices.size() );
+    surfaceVertices.SetData( &vertices[0] );
+
+    Geometry surface = Geometry::New();
+    surface.AddVertexBuffer( surfaceVertices );
+
+    return surface;
+  }
+
+  void ReadObjFile( const std::string& objFileName,
+      Vector<float>& boundingBox,
+      std::vector<Vector3>& vertexPositions,
+      Vector<unsigned int>& faceIndices)
+  {
+    std::ifstream ifs( objFileName.c_str(), std::ios::in );
+
+    boundingBox.Resize( 6 );
+    boundingBox[0]=boundingBox[2]=boundingBox[4] = std::numeric_limits<float>::max();
+    boundingBox[1]=boundingBox[3]=boundingBox[5] = -std::numeric_limits<float>::max();
+
+    std::string line;
+    while( std::getline( ifs, line ) )
+    {
+      if( line[0] == 'v' && std::isspace(line[1]))  // vertex
+      {
+        std::istringstream iss(line.substr(2), std::istringstream::in);
+        unsigned int i = 0;
+        Vector3 vertex;
+        while( iss >> vertex[i++] && i < 3);
+        if( vertex.x < boundingBox[0] )  boundingBox[0] = vertex.x;
+        if( vertex.x > boundingBox[1] )  boundingBox[1] = vertex.x;
+        if( vertex.y < boundingBox[2] )  boundingBox[2] = vertex.y;
+        if( vertex.y > boundingBox[3] )  boundingBox[3] = vertex.y;
+        if( vertex.z < boundingBox[4] )  boundingBox[4] = vertex.z;
+        if( vertex.z > boundingBox[5] )  boundingBox[5] = vertex.z;
+        vertexPositions.push_back( vertex );
+      }
+      else if( line[0] == 'f' ) //face
+      {
+        unsigned int numOfInt = 3;
+        while( true )
+        {
+          std::size_t found  = line.find('/');
+          if( found == std::string::npos )
+          {
+            break;
+          }
+          line[found] = ' ';
+          numOfInt++;
+        }
+
+        std::istringstream iss(line.substr(2), std::istringstream::in);
+        unsigned int indices[ numOfInt ];
+        unsigned int i=0;
+        while( iss >> indices[i++] && i < numOfInt);
+        unsigned int step = (i+1) / 3;
+        faceIndices.PushBack( indices[0]-1 );
+        faceIndices.PushBack( indices[step]-1 );
+        faceIndices.PushBack( indices[2*step]-1 );
+      }
+    }
+
+    ifs.close();
+  }
+
+  void ShapeResizeAndTexureCoordinateCalculation( const Vector<float>& boundingBox,
+      std::vector<Vector3>& vertexPositions,
+      std::vector<Vector2>& textureCoordinates)
+  {
+    Vector3 bBoxSize( boundingBox[1] - boundingBox[0], boundingBox[3] - boundingBox[2], boundingBox[5] - boundingBox[4]);
+    Vector3 bBoxMinCorner( boundingBox[0], boundingBox[2], boundingBox[4] );
+
+    Vector2 stageSize = Stage::GetCurrent().GetSize();
+    Vector3 scale( stageSize.x / bBoxSize.x, stageSize.y / bBoxSize.y, 1.f );
+    scale.z = (scale.x + scale.y)/2.f;
+
+    textureCoordinates.reserve(vertexPositions.size());
+
+    for( std::vector<Vector3>::iterator iter = vertexPositions.begin(); iter != vertexPositions.end(); iter++ )
+    {
+      Vector3 newPosition(  (*iter) - bBoxMinCorner ) ;
+
+     textureCoordinates.push_back( Vector2( newPosition.x / bBoxSize.x, newPosition.y / bBoxSize.y ) );
+
+      newPosition -= bBoxSize * 0.5f;
+      (*iter) = newPosition * scale;
+    }
+  }
+
+  /**
+   * Main key event handler
+   */
+  void OnKeyEvent(const KeyEvent& event)
+  {
+    if(event.state == KeyEvent::Down)
+    {
+      if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
+      {
+        mApplication.Quit();
+      }
+    }
+  }
+
+private:
+
+  Application&   mApplication;
+  Layer          mContent;
+
+  Sampler        mSampler;
+  Material       mMaterial;
+  Geometry       mGeometry;
+  Renderer       mRenderer;
+  Actor          mMeshActor;
+
+  Shader         mShaderFlat;
+  Shader         mShaderRefraction;
+
+  Animation      mLightAnimation;
+  Animation      mStrenghAnimation;
+
+  Property::Index mLightXYOffsetIndex;
+  Property::Index mSpinAngleIndex;
+  Property::Index mLightIntensityIndex;
+  Property::Index mEffectStrengthIndex;
+
+  Toolkit::PushButton        mChangeTextureButton;
+  Toolkit::PushButton        mChangeMeshButton;
+  unsigned int               mCurrentTextureId;
+  unsigned int               mCurrentMeshId;
+};
+
+/*****************************************************************************/
+
+static void
+RunTest(Application& app)
+{
+  RefractionEffectExample theApp(app);
+  app.MainLoop();
+}
+
+/*****************************************************************************/
+
+int
+main(int argc, char **argv)
+{
+  Application app = Application::New(&argc, &argv);
+
+  RunTest(app);
+
+  return 0;
+}