2 * Copyright (c) 2014 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"
26 * Method to project a point on a circle of radius halfSide at given
27 * angle onto a square of side 2 * halfSide
29 void CircleSquareProjection( Vector3& position, Degree angle, float halfSide )
31 Radian angleInRadians(angle);
40 if( angle >= 45.0f && angle < 135.0f )
42 position.x = halfSide * cosf(angleInRadians) / sinf(angleInRadians);
43 position.y = -halfSide;
45 else if( angle >= 135.0f && angle < 225.0f )
47 position.x = -halfSide;
48 position.y = halfSide * sinf(angleInRadians) / cosf(angleInRadians);
50 else if( angle >= 225.0f && angle < 315.0f )
52 position.x = -halfSide * cosf(angleInRadians) / sinf(angleInRadians);
53 position.y = halfSide;
57 position.x = halfSide;
58 position.y = -halfSide * sinf(angleInRadians) / cosf(angleInRadians);
64 float HoldZeroFastEaseInOutHoldOne(float progress)
70 else if(progress < 0.5f)
72 return AlphaFunctions::EaseIn((progress-0.2) / 0.3f) * 0.5f;
74 else if(progress < 0.8f)
76 return AlphaFunctions::EaseOut((progress - 0.5f) / 0.3f) * 0.5f + 0.5f;
84 struct SquareFanConstraint
86 SquareFanConstraint(int sideIndex)
87 : mSideIndex(sideIndex)
91 void operator()( Vector3& current, const PropertyInputContainer& inputs )
93 float degree = fmodf((inputs[0]->GetFloat() + inputs[1]->GetFloat()), 360.0f);
99 float startAngle = (90.0f*mSideIndex)-45.0f;
100 float endAngle = (90.0f*mSideIndex)+45.0f;
101 if(degree < startAngle)
103 current = Vector3::ZERO;
107 if( degree >= endAngle )
111 CircleSquareProjection( current, Degree(degree), 0.5f );
112 current.x = -current.x; // Inverting X makes the animation go anti clockwise from left center
119 } // anonymous namespace
122 RadialSweepView RadialSweepViewImpl::New( )
124 return New( 2.0f, 100.0f, Degree(0.0f), Degree(0.0f), Degree(0.0f), Degree(359.999f) );
128 RadialSweepView RadialSweepViewImpl::New( float duration, float diameter, Degree initialAngle, Degree finalAngle, Degree initialSector, Degree finalSector )
130 RadialSweepViewImpl* impl= new RadialSweepViewImpl(duration, diameter, initialAngle, finalAngle, initialSector, finalSector);
131 RadialSweepView handle = RadialSweepView(*impl);
135 RadialSweepViewImpl::RadialSweepViewImpl( float duration, float diameter, Degree initialAngle, Degree finalAngle, Degree initialSector, Degree finalSector )
136 : Control( CONTROL_BEHAVIOUR_NONE ),
139 mInitialAngle(initialAngle),
140 mFinalAngle(finalAngle),
141 mInitialSector(initialSector),
142 mFinalSector(finalSector),
143 mInitialActorAngle(0),
145 mEasingFunction(HoldZeroFastEaseInOutHoldOne),
146 mStartAngleIndex(Property::INVALID_INDEX),
147 mRotationAngleIndex(Property::INVALID_INDEX),
148 mRotateActorsWithStencil(false),
153 void RadialSweepViewImpl::SetDuration(float duration)
155 mDuration = duration;
158 void RadialSweepViewImpl::SetEasingFunction( Dali::AlphaFunction easingFunction )
160 mEasingFunction = easingFunction;
163 void RadialSweepViewImpl::SetDiameter(float diameter)
165 mDiameter = diameter;
168 void RadialSweepViewImpl::SetInitialAngle( Dali::Degree initialAngle)
170 mInitialAngle = initialAngle;
173 void RadialSweepViewImpl::SetFinalAngle( Dali::Degree finalAngle)
175 mFinalAngle = finalAngle;
178 void RadialSweepViewImpl::SetInitialSector( Dali::Degree initialSector)
180 mInitialSector = initialSector;
183 void RadialSweepViewImpl::SetFinalSector( Dali::Degree finalSector)
185 mFinalSector = finalSector;
188 void RadialSweepViewImpl::SetInitialActorAngle( Dali::Degree initialAngle )
190 mInitialActorAngle = initialAngle;
191 mRotateActors = true;
194 void RadialSweepViewImpl::SetFinalActorAngle( Dali::Degree finalAngle )
196 mFinalActorAngle = finalAngle;
197 mRotateActors = true;
200 float RadialSweepViewImpl::GetDuration( )
205 float RadialSweepViewImpl::GetDiameter( )
210 Dali::Degree RadialSweepViewImpl::GetInitialAngle( )
212 return mInitialAngle;
215 Dali::Degree RadialSweepViewImpl::GetFinalAngle( )
220 Dali::Degree RadialSweepViewImpl::GetInitialSector( )
222 return mInitialSector;
225 Dali::Degree RadialSweepViewImpl::GetFinalSector( )
230 Dali::Degree RadialSweepViewImpl::GetInitialActorAngle( )
232 return mInitialActorAngle;
235 Dali::Degree RadialSweepViewImpl::GetFinalActorAngle( )
237 return mFinalActorAngle;
240 void RadialSweepViewImpl::RotateActorsWithStencil(bool rotate)
242 mRotateActorsWithStencil = rotate;
245 void RadialSweepViewImpl::Add(Actor actor)
249 mLayer = Layer::New();
251 mLayer.SetSize( Stage::GetCurrent().GetSize() );
252 mLayer.SetPositionInheritanceMode(USE_PARENT_POSITION);
258 void RadialSweepViewImpl::Activate( Animation anim, float offsetTime, float duration )
260 bool startAnimation=false;
263 mAnim = Animation::New( mDuration );
265 startAnimation = true;
268 if( ! mStencilActor )
270 CreateStencil( mInitialSector );
271 mLayer.Add( mStencilActor );
272 mStencilActor.SetSize(mDiameter, mDiameter);
275 mStencilActor.SetOrientation( Degree(mInitialAngle), Vector3::ZAXIS );
276 mStencilActor.SetProperty( mRotationAngleIndex, static_cast<float>(mInitialSector) );
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( Degree( mInitialActorAngle ) ), Vector3::ZAXIS ) );
290 anim.AnimateTo( Property( mStencilActor, mRotationAngleIndex ), static_cast<float>(mFinalSector), mEasingFunction, TimePeriod( offsetTime, duration ) );
291 anim.AnimateTo( Property( mStencilActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( mFinalAngle ) ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
293 if( mRotateActorsWithStencil )
295 for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
297 Actor actor = mLayer.GetChildAt(i);
298 if( actor != mStencilActor )
300 anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( mFinalAngle - mInitialAngle ) ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
304 else if( mRotateActors )
306 for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
308 Actor actor = mLayer.GetChildAt(i);
309 if( actor != mStencilActor )
311 anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( mFinalActorAngle ) ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
319 anim.SetLooping(true);
325 void RadialSweepViewImpl::Deactivate()
331 // mLayer.Remove( mStencilActor );
332 // mStencilActor.Reset();
334 // mMaterial.Reset();
337 void RadialSweepViewImpl::CreateStencil( Degree initialSector )
339 mMaterial = Material::New("Material");
340 mMaterial.SetDiffuseColor(Color::WHITE);
341 mMaterial.SetAmbientColor(Vector4(0.0, 0.1, 0.1, 1.0));
343 // Generate a square mesh with a point at the center:
345 AnimatableMesh::Faces faces;
346 // Create triangles joining up the verts
347 faces.push_back(0); faces.push_back(1); faces.push_back(2);
348 faces.push_back(0); faces.push_back(2); faces.push_back(3);
349 faces.push_back(0); faces.push_back(3); faces.push_back(4);
350 faces.push_back(0); faces.push_back(4); faces.push_back(5);
351 faces.push_back(0); faces.push_back(5); faces.push_back(6);
353 mMesh = AnimatableMesh::New(7, faces, mMaterial);
354 mMesh[0].SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) ); // Center pt
356 mStencilActor = MeshActor::New(mMesh);
357 mStencilActor.SetCullFace(CullNone); // Allow clockwise & anticlockwise faces
359 mStartAngleIndex = mStencilActor.RegisterProperty("start-angle", Property::Value(0.0f));
360 mRotationAngleIndex = mStencilActor.RegisterProperty("rotation-angle", Property::Value(initialSector));
362 Source srcStart( mStencilActor, mStartAngleIndex );
363 Source srcRot( mStencilActor, mRotationAngleIndex );
365 // Constrain the vertices of the square mesh to sweep out a sector as the
366 // rotation angle is animated.
367 Constraint constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(1, AnimatableVertex::Property::POSITION), SquareFanConstraint(0) );
368 constraint.AddSource( srcStart );
369 constraint.AddSource( srcStart );
372 constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(2, AnimatableVertex::Property::POSITION), SquareFanConstraint(0) );
373 constraint.AddSource( srcStart );
374 constraint.AddSource( srcRot );
377 constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(3, AnimatableVertex::Property::POSITION), SquareFanConstraint(1) );
378 constraint.AddSource( srcStart );
379 constraint.AddSource( srcRot );
382 constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(4, AnimatableVertex::Property::POSITION), SquareFanConstraint(2) );
383 constraint.AddSource( srcStart );
384 constraint.AddSource( srcRot );
387 constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(5, AnimatableVertex::Property::POSITION), SquareFanConstraint(3) );
388 constraint.AddSource( srcStart );
389 constraint.AddSource( srcRot );
392 constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(6, AnimatableVertex::Property::POSITION), SquareFanConstraint(4) );
393 constraint.AddSource( srcStart );
394 constraint.AddSource( srcRot );
397 mStencilActor.SetDrawMode( DrawMode::STENCIL );
398 mStencilActor.SetPositionInheritanceMode(USE_PARENT_POSITION);