2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "radial-sweep-view-impl.h"
20 #include <dali/devel-api/rendering/renderer.h>
28 const char* VERTEX_SHADER_PREFIX( "#define MATH_PI_2 1.570796\n#define MATH_PI_4 0.785398\n" );
30 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
31 attribute mediump float aAngleIndex;\n
32 attribute mediump vec2 aPosition1;\n
33 attribute mediump vec2 aPosition2;\n
34 uniform mediump mat4 uMvpMatrix;\n
35 uniform mediump float uStartAngle;\n
36 uniform mediump float uRotationAngle;\n
40 float currentAngle = uStartAngle + uRotationAngle;\n
41 float angleInterval1 = MATH_PI_4 * aAngleIndex;\n
42 vec4 vertexPosition = vec4(0.0, 0.0, 0.0, 1.0);\n
43 if( currentAngle >= angleInterval1)\n
45 float angleInterval2 = angleInterval1 + MATH_PI_2;\n
46 float angle = currentAngle < angleInterval2 ? currentAngle : angleInterval2;\n
48 if( mod( aAngleIndex+4.0, 4.0) < 2.0 )\n
50 delta = 0.5 - 0.5*cos(angle) / sin(angle);\n
54 delta = 0.5 + 0.5*sin(angle) / cos(angle);\n
56 vertexPosition.xy = mix( aPosition1, aPosition2, delta );\n
58 gl_Position = uMvpMatrix * vertexPosition;\n
62 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
63 uniform lowp vec4 uColor;\n
67 gl_FragColor = uColor;\n
71 float HoldZeroFastEaseInOutHoldOne(float progress)
77 else if(progress < 0.5f)
79 progress = (progress-0.2) / 0.3f;
80 return progress*progress*progress*0.5f;
82 else if(progress < 0.8f)
84 progress = ((progress - 0.5f) / 0.3f) - 1.0f;
85 return (progress*progress*progress+1.0f) * 0.5f + 0.5f;
93 } // anonymous namespace
96 RadialSweepView RadialSweepViewImpl::New( )
98 return New( 2.0f, 100.0f, ANGLE_0, ANGLE_0, ANGLE_0, ANGLE_360 );
102 RadialSweepView RadialSweepViewImpl::New( float duration, float diameter, Radian initialAngle, Radian finalAngle, Radian initialSector, Radian finalSector )
104 RadialSweepViewImpl* impl= new RadialSweepViewImpl(duration, diameter, initialAngle, finalAngle, initialSector, finalSector);
105 RadialSweepView handle = RadialSweepView(*impl);
109 RadialSweepViewImpl::RadialSweepViewImpl( float duration, float diameter, Radian initialAngle, Radian finalAngle, Radian initialSector, Radian finalSector )
110 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
113 mInitialAngle(initialAngle),
114 mFinalAngle(finalAngle),
115 mInitialSector(initialSector),
116 mFinalSector(finalSector),
117 mInitialActorAngle(0),
119 mEasingFunction(HoldZeroFastEaseInOutHoldOne),
120 mStartAngleIndex(Property::INVALID_INDEX),
121 mRotationAngleIndex(Property::INVALID_INDEX),
122 mRotateActorsWithStencil(false),
127 void RadialSweepViewImpl::SetDuration(float duration)
129 mDuration = duration;
132 void RadialSweepViewImpl::SetEasingFunction( Dali::AlphaFunction easingFunction )
134 mEasingFunction = easingFunction;
137 void RadialSweepViewImpl::SetDiameter(float diameter)
139 mDiameter = diameter;
142 void RadialSweepViewImpl::SetInitialAngle( Dali::Radian initialAngle)
144 mInitialAngle = initialAngle;
147 void RadialSweepViewImpl::SetFinalAngle( Dali::Radian finalAngle)
149 mFinalAngle = finalAngle;
152 void RadialSweepViewImpl::SetInitialSector( Dali::Radian initialSector)
154 mInitialSector = initialSector;
157 void RadialSweepViewImpl::SetFinalSector( Dali::Radian finalSector)
159 mFinalSector = finalSector;
162 void RadialSweepViewImpl::SetInitialActorAngle( Dali::Radian initialAngle )
164 mInitialActorAngle = initialAngle;
165 mRotateActors = true;
168 void RadialSweepViewImpl::SetFinalActorAngle( Dali::Radian finalAngle )
170 mFinalActorAngle = finalAngle;
171 mRotateActors = true;
174 float RadialSweepViewImpl::GetDuration( )
179 float RadialSweepViewImpl::GetDiameter( )
184 Dali::Radian RadialSweepViewImpl::GetInitialAngle( )
186 return mInitialAngle;
189 Dali::Radian RadialSweepViewImpl::GetFinalAngle( )
194 Dali::Radian RadialSweepViewImpl::GetInitialSector( )
196 return mInitialSector;
199 Dali::Radian RadialSweepViewImpl::GetFinalSector( )
204 Dali::Radian RadialSweepViewImpl::GetInitialActorAngle( )
206 return mInitialActorAngle;
209 Dali::Radian RadialSweepViewImpl::GetFinalActorAngle( )
211 return mFinalActorAngle;
214 void RadialSweepViewImpl::RotateActorsWithStencil(bool rotate)
216 mRotateActorsWithStencil = rotate;
219 void RadialSweepViewImpl::Add(Actor actor)
223 mLayer = Layer::New();
225 mLayer.SetSize( Stage::GetCurrent().GetSize() );
226 mLayer.SetParentOrigin( ParentOrigin::CENTER );
232 void RadialSweepViewImpl::Activate( Animation anim, float offsetTime, float duration )
234 bool startAnimation=false;
237 mAnim = Animation::New( mDuration );
239 startAnimation = true;
242 if( ! mStencilActor )
244 CreateStencil( mInitialSector );
245 mLayer.Add( mStencilActor );
246 mStencilActor.SetScale(mDiameter);
249 mStencilActor.SetOrientation( mInitialAngle, Vector3::ZAXIS );
250 mStencilActor.SetProperty( mRotationAngleIndex, mInitialSector.radian );
254 for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
256 Actor actor = mLayer.GetChildAt(i);
257 if( actor != mStencilActor )
259 anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mInitialActorAngle ), Vector3::ZAXIS ) );
264 anim.AnimateTo( Property( mStencilActor, mRotationAngleIndex ), mFinalSector.radian, mEasingFunction, TimePeriod( offsetTime, duration ) );
265 anim.AnimateTo( Property( mStencilActor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalAngle ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
267 if( mRotateActorsWithStencil )
269 for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
271 Actor actor = mLayer.GetChildAt(i);
272 if( actor != mStencilActor )
274 anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalAngle.radian - mInitialAngle.radian ) , Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
278 else if( mRotateActors )
280 for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
282 Actor actor = mLayer.GetChildAt(i);
283 if( actor != mStencilActor )
285 anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalActorAngle ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
293 anim.SetLooping(true);
299 void RadialSweepViewImpl::Deactivate()
307 void RadialSweepViewImpl::CreateStencil( Radian initialSector )
309 // Create the stencil mesh geometry
316 struct VertexPosition { float angleIndex; Vector2 position1; Vector2 position2; };
317 VertexPosition vertexData[7] = { // With X coordinate inverted to make the animation go anti clockwise from left center
318 { 9.f, Vector2( 0.f, 0.f ), Vector2( 0.f, 0.f ) }, // center point, keep static
319 { 0.f, Vector2( -0.5f, 0.f ), Vector2( -0.5f, 0.f ) }, // vertex 1, 0 degree, keep static
320 { -1.f, Vector2( -0.5f, 0.5f ), Vector2( -0.5f, -0.5f ) }, // -45 ~ 45 degrees ( 0 ~ 45)
321 { 1.f, Vector2( -0.5f, -0.5f ), Vector2( 0.5f, -0.5f ) }, // 45 ~ 135 degrees
322 { 3.f, Vector2( 0.5f, -0.5f ), Vector2( 0.5f, 0.5f ) }, // 135 ~ 225 degrees
323 { 5.f, Vector2( 0.5f, 0.5f ), Vector2( -0.5f, 0.5f ) }, // 225 ~ 315 degrees
324 { 7.f, Vector2( -0.5f, 0.5f ), Vector2( -0.5f, -0.5f ) } // 315 ~ 405 degrees ( 315 ~ 359.999 )
326 Property::Map vertexFormat;
327 vertexFormat["aAngleIndex"] = Property::FLOAT;
328 vertexFormat["aPosition1"] = Property::VECTOR2;
329 vertexFormat["aPosition2"] = Property::VECTOR2;
330 PropertyBuffer vertices = PropertyBuffer::New( vertexFormat );
331 vertices.SetData( vertexData, 7u );
333 unsigned short indexData[15] = { 0,1,2,0,2,3,0,3,4,0,4,5,0,5,6 };
335 Geometry meshGeometry = Geometry::New();
336 meshGeometry.AddVertexBuffer( vertices );
337 meshGeometry.SetIndexBuffer( &indexData[0], sizeof( indexData )/sizeof(indexData[0]) );
340 std::ostringstream vertexShaderStringStream;
341 vertexShaderStringStream<<VERTEX_SHADER_PREFIX<<VERTEX_SHADER;
342 Shader shader = Shader::New( vertexShaderStringStream.str(), FRAGMENT_SHADER );
345 Renderer renderer = Renderer::New( meshGeometry, shader );
347 mStencilActor = Actor::New();
348 mStencilActor.AddRenderer( renderer );
349 mStencilActor.SetSize(1.f, 1.f);
351 // register properties
352 mStartAngleIndex = mStencilActor.RegisterProperty("uStartAngle", 0.f);
353 mRotationAngleIndex = mStencilActor.RegisterProperty("uRotationAngle", initialSector.radian);
355 mStencilActor.SetDrawMode( DrawMode::STENCIL );
356 mStencilActor.SetParentOrigin( ParentOrigin::CENTER );