Update refraction-effect & radial-menu to use new mesh
[platform/core/uifw/dali-demo.git] / examples / radial-menu / radial-sweep-view-impl.cpp
1 /*
2  * Copyright (c) 2015 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 "radial-sweep-view-impl.h"
19
20 #include <sstream>
21
22 using namespace Dali;
23
24 namespace
25 {
26
27 const char* VERTEX_SHADER_PREFIX( "#define MATH_PI_2 1.570796\n#define MATH_PI_4 0.785398\n" );
28
29 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
30 attribute mediump float   aAngleIndex;\n
31 attribute mediump vec2    aPosition1;\n
32 attribute mediump vec2    aPosition2;\n
33 uniform   mediump mat4    uMvpMatrix;\n
34 uniform   mediump float   uStartAngle;\n
35 uniform   mediump float   uRotationAngle;\n
36 \n
37 void main()\n
38 {\n
39   float currentAngle = uStartAngle + uRotationAngle;\n
40   float angleInterval1 =  MATH_PI_4 * aAngleIndex;\n
41   vec4 vertexPosition = vec4(0.0, 0.0, 0.0, 1.0);\n
42   if( currentAngle >=  angleInterval1)\n
43   {\n
44     float angleInterval2 =  angleInterval1 + MATH_PI_2;\n
45     float angle = currentAngle < angleInterval2 ? currentAngle : angleInterval2;\n
46     float delta;\n
47     if( mod( aAngleIndex+4.0, 4.0) < 2.0  )\n
48     {\n
49       delta = 0.5 - 0.5*cos(angle) / sin(angle);\n
50     }\n
51     else\n
52     {\n
53       delta = 0.5 + 0.5*sin(angle) / cos(angle);\n
54     }\n
55     vertexPosition.xy = mix( aPosition1, aPosition2, delta );\n
56   }\n
57   gl_Position = uMvpMatrix * vertexPosition;\n
58 }
59 );
60
61 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
62 uniform lowp  vec4    uColor;\n
63 \n
64 void main()\n
65 {\n
66   gl_FragColor = uColor;\n
67 }\n
68 );
69
70 float HoldZeroFastEaseInOutHoldOne(float progress)
71 {
72   if( progress < 0.2f)
73   {
74     return 0.0f;
75   }
76   else if(progress < 0.5f)
77   {
78     progress = (progress-0.2) / 0.3f;
79     return  progress*progress*progress*0.5f;
80   }
81   else if(progress < 0.8f)
82   {
83     progress = ((progress - 0.5f) / 0.3f) - 1.0f;
84     return (progress*progress*progress+1.0f) * 0.5f + 0.5f;
85   }
86   else
87   {
88     return 1.0f;
89   }
90 }
91
92 } // anonymous namespace
93
94
95 RadialSweepView RadialSweepViewImpl::New( )
96 {
97   return New( 2.0f, 100.0f, ANGLE_0, ANGLE_0, ANGLE_0, ANGLE_360 );
98 }
99
100
101 RadialSweepView RadialSweepViewImpl::New( float duration, float diameter, Radian initialAngle, Radian finalAngle, Radian initialSector, Radian finalSector )
102 {
103   RadialSweepViewImpl* impl= new RadialSweepViewImpl(duration, diameter, initialAngle, finalAngle, initialSector, finalSector);
104   RadialSweepView handle = RadialSweepView(*impl);
105   return handle;
106 }
107
108 RadialSweepViewImpl::RadialSweepViewImpl( float duration, float diameter, Radian initialAngle, Radian finalAngle, Radian initialSector, Radian finalSector )
109 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
110   mDuration(duration),
111   mDiameter(diameter),
112   mInitialAngle(initialAngle),
113   mFinalAngle(finalAngle),
114   mInitialSector(initialSector),
115   mFinalSector(finalSector),
116   mInitialActorAngle(0),
117   mFinalActorAngle(0),
118   mEasingFunction(HoldZeroFastEaseInOutHoldOne),
119   mStartAngleIndex(Property::INVALID_INDEX),
120   mRotationAngleIndex(Property::INVALID_INDEX),
121   mRotateActorsWithStencil(false),
122   mRotateActors(false)
123 {
124 }
125
126 void RadialSweepViewImpl::SetDuration(float duration)
127 {
128   mDuration = duration;
129 }
130
131 void RadialSweepViewImpl::SetEasingFunction( Dali::AlphaFunction easingFunction )
132 {
133   mEasingFunction = easingFunction;
134 }
135
136 void RadialSweepViewImpl::SetDiameter(float diameter)
137 {
138   mDiameter = diameter;
139 }
140
141 void RadialSweepViewImpl::SetInitialAngle( Dali::Radian initialAngle)
142 {
143   mInitialAngle = initialAngle;
144 }
145
146 void RadialSweepViewImpl::SetFinalAngle( Dali::Radian finalAngle)
147 {
148   mFinalAngle = finalAngle;
149 }
150
151 void RadialSweepViewImpl::SetInitialSector( Dali::Radian initialSector)
152 {
153   mInitialSector = initialSector;
154 }
155
156 void RadialSweepViewImpl::SetFinalSector( Dali::Radian finalSector)
157 {
158   mFinalSector = finalSector;
159 }
160
161 void RadialSweepViewImpl::SetInitialActorAngle( Dali::Radian initialAngle )
162 {
163   mInitialActorAngle = initialAngle;
164   mRotateActors = true;
165 }
166
167 void RadialSweepViewImpl::SetFinalActorAngle( Dali::Radian finalAngle )
168 {
169   mFinalActorAngle = finalAngle;
170   mRotateActors = true;
171 }
172
173 float RadialSweepViewImpl::GetDuration( )
174 {
175   return mDuration;
176 }
177
178 float RadialSweepViewImpl::GetDiameter( )
179 {
180   return mDiameter;
181 }
182
183 Dali::Radian RadialSweepViewImpl::GetInitialAngle( )
184 {
185   return mInitialAngle;
186 }
187
188 Dali::Radian RadialSweepViewImpl::GetFinalAngle( )
189 {
190   return mFinalAngle;
191 }
192
193 Dali::Radian RadialSweepViewImpl::GetInitialSector( )
194 {
195   return mInitialSector;
196 }
197
198 Dali::Radian RadialSweepViewImpl::GetFinalSector( )
199 {
200   return mFinalSector;
201 }
202
203 Dali::Radian RadialSweepViewImpl::GetInitialActorAngle( )
204 {
205   return mInitialActorAngle;
206 }
207
208 Dali::Radian RadialSweepViewImpl::GetFinalActorAngle(  )
209 {
210   return mFinalActorAngle;
211 }
212
213 void RadialSweepViewImpl::RotateActorsWithStencil(bool rotate)
214 {
215   mRotateActorsWithStencil = rotate;
216 }
217
218 void RadialSweepViewImpl::Add(Actor actor)
219 {
220   if( ! mLayer )
221   {
222     mLayer = Layer::New();
223     Self().Add(mLayer);
224     mLayer.SetSize( Stage::GetCurrent().GetSize() );
225     mLayer.SetPositionInheritanceMode(USE_PARENT_POSITION);
226   }
227
228   mLayer.Add(actor);
229 }
230
231 void RadialSweepViewImpl::Activate( Animation anim, float offsetTime, float duration )
232 {
233   bool startAnimation=false;
234   if( ! anim )
235   {
236     mAnim = Animation::New( mDuration );
237     anim = mAnim;
238     startAnimation = true;
239   }
240
241   if( ! mStencilActor )
242   {
243     CreateStencil( mInitialSector );
244     mLayer.Add( mStencilActor );
245     mStencilActor.SetScale(mDiameter);
246   }
247
248   mStencilActor.SetOrientation( mInitialAngle, Vector3::ZAXIS );
249   mStencilActor.SetProperty( mRotationAngleIndex, mInitialSector.radian );
250
251   if( mRotateActors )
252   {
253     for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
254     {
255       Actor actor = mLayer.GetChildAt(i);
256       if( actor != mStencilActor )
257       {
258         anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mInitialActorAngle ), Vector3::ZAXIS ) );
259       }
260     }
261   }
262
263   anim.AnimateTo( Property( mStencilActor, mRotationAngleIndex ), mFinalSector.radian, mEasingFunction, TimePeriod( offsetTime, duration ) );
264   anim.AnimateTo( Property( mStencilActor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalAngle ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
265
266   if( mRotateActorsWithStencil )
267   {
268     for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
269     {
270       Actor actor = mLayer.GetChildAt(i);
271       if( actor != mStencilActor )
272       {
273         anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalAngle.radian - mInitialAngle.radian ) , Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
274       }
275     }
276   }
277   else if( mRotateActors )
278   {
279     for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
280     {
281       Actor actor = mLayer.GetChildAt(i);
282       if( actor != mStencilActor )
283       {
284         anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalActorAngle ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
285       }
286     }
287   }
288
289
290   if( startAnimation )
291   {
292     anim.SetLooping(true);
293     anim.Play();
294   }
295 }
296
297
298 void RadialSweepViewImpl::Deactivate()
299 {
300   if( mAnim )
301   {
302     mAnim.Stop();
303   }
304   // mLayer.Remove( mStencilActor );
305   // mStencilActor.Reset();
306   // mMesh.Reset();
307   // mMaterial.Reset();
308 }
309
310 void RadialSweepViewImpl::CreateStencil( Radian initialSector )
311 {
312   // Create the stencil mesh geometry
313   //     3-----2
314   //     | \ / |
315   //     |  0--1 , 6
316   //     | / \ |
317   //     4-----5
318
319   struct VertexPosition { float angleIndex; Vector2 position1; Vector2 position2; };
320   VertexPosition vertexData[7] = { // With X coordinate inverted to make the animation go anti clockwise from left center
321       { 9.f,  Vector2( 0.f, 0.f ),     Vector2( 0.f, 0.f )     }, // center point, keep static
322       { 0.f,  Vector2( -0.5f, 0.f ),   Vector2( -0.5f, 0.f )   }, // vertex 1, 0 degree, keep static
323       { -1.f, Vector2( -0.5f, 0.5f ),  Vector2( -0.5f, -0.5f ) }, // -45 ~ 45 degrees  ( 0 ~ 45)
324       { 1.f,  Vector2( -0.5f, -0.5f ), Vector2( 0.5f, -0.5f )  }, // 45 ~ 135 degrees
325       { 3.f,  Vector2( 0.5f, -0.5f ),  Vector2( 0.5f, 0.5f )   }, // 135 ~ 225 degrees
326       { 5.f,  Vector2( 0.5f, 0.5f ),   Vector2( -0.5f, 0.5f )  }, // 225 ~ 315 degrees
327       { 7.f,  Vector2( -0.5f, 0.5f ),  Vector2( -0.5f, -0.5f ) }  // 315 ~ 405 degrees ( 315 ~ 359.999 )
328   };
329   Property::Map vertexFormat;
330   vertexFormat["aAngleIndex"] = Property::FLOAT;
331   vertexFormat["aPosition1"] = Property::VECTOR2;
332   vertexFormat["aPosition2"] = Property::VECTOR2;
333   PropertyBuffer vertices = PropertyBuffer::New( PropertyBuffer::STATIC, vertexFormat, 7u );
334   vertices.SetData( vertexData );
335
336   unsigned int indexData[15] = { 0,1,2,0,2,3,0,3,4,0,4,5,0,5,6 };
337   Property::Map indexFormat;
338   indexFormat["indices"] = Property::UNSIGNED_INTEGER;
339   PropertyBuffer indices = PropertyBuffer::New( PropertyBuffer::STATIC, indexFormat, 15u );
340   indices.SetData( indexData );
341
342   Geometry meshGeometry = Geometry::New();
343   meshGeometry.AddVertexBuffer( vertices );
344   meshGeometry.SetIndexBuffer( indices );
345
346   // Create material
347   std::ostringstream vertexShaderStringStream;
348   vertexShaderStringStream<<VERTEX_SHADER_PREFIX<<VERTEX_SHADER;
349   Shader shader = Shader::New( vertexShaderStringStream.str(), FRAGMENT_SHADER );
350   Material material = Material::New( shader );
351
352   // Create renderer
353   Renderer renderer = Renderer::New( meshGeometry, material );
354
355   mStencilActor = Actor::New();
356   mStencilActor.AddRenderer( renderer );
357   mStencilActor.SetSize(1.f, 1.f);
358
359   // register properties
360   mStartAngleIndex = mStencilActor.RegisterProperty("start-angle", 0.f);
361   mStencilActor.AddUniformMapping( mStartAngleIndex, "uStartAngle " );
362   mRotationAngleIndex = mStencilActor.RegisterProperty("rotation-angle", initialSector.radian);
363   mStencilActor.AddUniformMapping( mRotationAngleIndex, "uRotationAngle" );
364
365   mStencilActor.SetDrawMode( DrawMode::STENCIL );
366   mStencilActor.SetPositionInheritanceMode(USE_PARENT_POSITION);
367 }