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, Radian angle, float halfSide )
38 if( angle >= Dali::ANGLE_45 && angle < Dali::ANGLE_135 )
40 position.x = halfSide * cosf(angle) / sinf(angle);
41 position.y = -halfSide;
43 else if( angle >= Dali::ANGLE_135 && angle < Dali::ANGLE_225 )
45 position.x = -halfSide;
46 position.y = halfSide * sinf(angle) / cosf(angle);
48 else if( angle >= Dali::ANGLE_225 && angle < Dali::ANGLE_315 )
50 position.x = -halfSide * cosf(angle) / sinf(angle);
51 position.y = halfSide;
55 position.x = halfSide;
56 position.y = -halfSide * sinf(angle) / cosf(angle);
62 float HoldZeroFastEaseInOutHoldOne(float progress)
68 else if(progress < 0.5f)
70 return AlphaFunctions::EaseIn((progress-0.2) / 0.3f) * 0.5f;
72 else if(progress < 0.8f)
74 return AlphaFunctions::EaseOut((progress - 0.5f) / 0.3f) * 0.5f + 0.5f;
82 struct SquareFanConstraint
84 SquareFanConstraint(int sideIndex)
85 : mSideIndex(sideIndex)
89 void operator()( Vector3& current, const PropertyInputContainer& inputs )
91 float degree = fmodf((inputs[0]->GetFloat() + inputs[1]->GetFloat()), 360.0f);
97 float startAngle = (90.0f*mSideIndex)-45.0f;
98 float endAngle = (90.0f*mSideIndex)+45.0f;
99 if(degree < startAngle)
101 current = Vector3::ZERO;
105 if( degree >= endAngle )
109 CircleSquareProjection( current, Degree(degree), 0.5f );
110 current.x = -current.x; // Inverting X makes the animation go anti clockwise from left center
117 } // anonymous namespace
120 RadialSweepView RadialSweepViewImpl::New( )
122 return New( 2.0f, 100.0f, Degree(0.0f), Degree(0.0f), Degree(0.0f), Degree(359.999f) );
126 RadialSweepView RadialSweepViewImpl::New( float duration, float diameter, Degree initialAngle, Degree finalAngle, Degree initialSector, Degree finalSector )
128 RadialSweepViewImpl* impl= new RadialSweepViewImpl(duration, diameter, initialAngle, finalAngle, initialSector, finalSector);
129 RadialSweepView handle = RadialSweepView(*impl);
133 RadialSweepViewImpl::RadialSweepViewImpl( float duration, float diameter, Degree initialAngle, Degree finalAngle, Degree initialSector, Degree finalSector )
134 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
137 mInitialAngle(initialAngle),
138 mFinalAngle(finalAngle),
139 mInitialSector(initialSector),
140 mFinalSector(finalSector),
141 mInitialActorAngle(0),
143 mEasingFunction(HoldZeroFastEaseInOutHoldOne),
144 mStartAngleIndex(Property::INVALID_INDEX),
145 mRotationAngleIndex(Property::INVALID_INDEX),
146 mRotateActorsWithStencil(false),
151 void RadialSweepViewImpl::SetDuration(float duration)
153 mDuration = duration;
156 void RadialSweepViewImpl::SetEasingFunction( Dali::AlphaFunction easingFunction )
158 mEasingFunction = easingFunction;
161 void RadialSweepViewImpl::SetDiameter(float diameter)
163 mDiameter = diameter;
166 void RadialSweepViewImpl::SetInitialAngle( Dali::Degree initialAngle)
168 mInitialAngle = initialAngle;
171 void RadialSweepViewImpl::SetFinalAngle( Dali::Degree finalAngle)
173 mFinalAngle = finalAngle;
176 void RadialSweepViewImpl::SetInitialSector( Dali::Degree initialSector)
178 mInitialSector = initialSector;
181 void RadialSweepViewImpl::SetFinalSector( Dali::Degree finalSector)
183 mFinalSector = finalSector;
186 void RadialSweepViewImpl::SetInitialActorAngle( Dali::Degree initialAngle )
188 mInitialActorAngle = initialAngle;
189 mRotateActors = true;
192 void RadialSweepViewImpl::SetFinalActorAngle( Dali::Degree finalAngle )
194 mFinalActorAngle = finalAngle;
195 mRotateActors = true;
198 float RadialSweepViewImpl::GetDuration( )
203 float RadialSweepViewImpl::GetDiameter( )
208 Dali::Degree RadialSweepViewImpl::GetInitialAngle( )
210 return mInitialAngle;
213 Dali::Degree RadialSweepViewImpl::GetFinalAngle( )
218 Dali::Degree RadialSweepViewImpl::GetInitialSector( )
220 return mInitialSector;
223 Dali::Degree RadialSweepViewImpl::GetFinalSector( )
228 Dali::Degree RadialSweepViewImpl::GetInitialActorAngle( )
230 return mInitialActorAngle;
233 Dali::Degree RadialSweepViewImpl::GetFinalActorAngle( )
235 return mFinalActorAngle;
238 void RadialSweepViewImpl::RotateActorsWithStencil(bool rotate)
240 mRotateActorsWithStencil = rotate;
243 void RadialSweepViewImpl::Add(Actor actor)
247 mLayer = Layer::New();
249 mLayer.SetSize( Stage::GetCurrent().GetSize() );
250 mLayer.SetPositionInheritanceMode(USE_PARENT_POSITION);
256 void RadialSweepViewImpl::Activate( Animation anim, float offsetTime, float duration )
258 bool startAnimation=false;
261 mAnim = Animation::New( mDuration );
263 startAnimation = true;
266 if( ! mStencilActor )
268 CreateStencil( mInitialSector );
269 mLayer.Add( mStencilActor );
270 mStencilActor.SetSize(mDiameter, mDiameter);
273 mStencilActor.SetOrientation( Degree(mInitialAngle), Vector3::ZAXIS );
274 mStencilActor.SetProperty( mRotationAngleIndex, mInitialSector.degree );
278 for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
280 Actor actor = mLayer.GetChildAt(i);
281 if( actor != mStencilActor )
283 anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mInitialActorAngle ), Vector3::ZAXIS ) );
288 anim.AnimateTo( Property( mStencilActor, mRotationAngleIndex ), mFinalSector.degree, mEasingFunction, TimePeriod( offsetTime, duration ) );
289 anim.AnimateTo( Property( mStencilActor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalAngle ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
291 if( mRotateActorsWithStencil )
293 for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
295 Actor actor = mLayer.GetChildAt(i);
296 if( actor != mStencilActor )
298 anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( mFinalAngle.degree - mInitialAngle.degree ) ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
302 else if( mRotateActors )
304 for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
306 Actor actor = mLayer.GetChildAt(i);
307 if( actor != mStencilActor )
309 anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalActorAngle ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) );
317 anim.SetLooping(true);
323 void RadialSweepViewImpl::Deactivate()
329 // mLayer.Remove( mStencilActor );
330 // mStencilActor.Reset();
332 // mMaterial.Reset();
335 void RadialSweepViewImpl::CreateStencil( Degree initialSector )
337 mMaterial = Material::New("Material");
338 mMaterial.SetDiffuseColor(Color::WHITE);
339 mMaterial.SetAmbientColor(Vector4(0.0, 0.1, 0.1, 1.0));
341 // Generate a square mesh with a point at the center:
343 AnimatableMesh::Faces faces;
344 // Create triangles joining up the verts
345 faces.push_back(0); faces.push_back(1); faces.push_back(2);
346 faces.push_back(0); faces.push_back(2); faces.push_back(3);
347 faces.push_back(0); faces.push_back(3); faces.push_back(4);
348 faces.push_back(0); faces.push_back(4); faces.push_back(5);
349 faces.push_back(0); faces.push_back(5); faces.push_back(6);
351 mMesh = AnimatableMesh::New(7, faces, mMaterial);
352 mMesh[0].SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) ); // Center pt
354 mStencilActor = MeshActor::New(mMesh);
355 mStencilActor.SetCullFace(CullNone); // Allow clockwise & anticlockwise faces
357 mStartAngleIndex = mStencilActor.RegisterProperty("start-angle", Property::Value(0.0f));
358 mRotationAngleIndex = mStencilActor.RegisterProperty("rotation-angle", Property::Value(initialSector.degree));
360 Source srcStart( mStencilActor, mStartAngleIndex );
361 Source srcRotation( mStencilActor, mRotationAngleIndex );
363 // Constrain the vertices of the square mesh to sweep out a sector as the
364 // rotation angle is animated.
365 Constraint constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(1, AnimatableVertex::Property::POSITION), SquareFanConstraint(0) );
366 constraint.AddSource( srcStart );
367 constraint.AddSource( srcStart );
370 constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(2, AnimatableVertex::Property::POSITION), SquareFanConstraint(0) );
371 constraint.AddSource( srcStart );
372 constraint.AddSource( srcRotation );
375 constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(3, AnimatableVertex::Property::POSITION), SquareFanConstraint(1) );
376 constraint.AddSource( srcStart );
377 constraint.AddSource( srcRotation );
380 constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(4, AnimatableVertex::Property::POSITION), SquareFanConstraint(2) );
381 constraint.AddSource( srcStart );
382 constraint.AddSource( srcRotation );
385 constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(5, AnimatableVertex::Property::POSITION), SquareFanConstraint(3) );
386 constraint.AddSource( srcStart );
387 constraint.AddSource( srcRotation );
390 constraint = Constraint::New<Vector3>( mMesh, mMesh.GetPropertyIndex(6, AnimatableVertex::Property::POSITION), SquareFanConstraint(4) );
391 constraint.AddSource( srcStart );
392 constraint.AddSource( srcRotation );
395 mStencilActor.SetDrawMode( DrawMode::STENCIL );
396 mStencilActor.SetPositionInheritanceMode(USE_PARENT_POSITION);