Updates after deprecated APIs removed from Toolkit
[platform/core/uifw/dali-demo.git] / examples / radial-menu / radial-sweep-view-impl.cpp
1 /*
2  * Copyright (c) 2014 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 using namespace Dali;
21
22 namespace
23 {
24
25 /**
26  * Method to project a point on a circle of radius halfSide at given
27  * angle onto a square of side 2 * halfSide
28  */
29 Vector3 CircleSquareProjection( Degree angle, float halfSide )
30 {
31   Vector3 position(0.0f, 0.0f, 0.0f);
32   Radian angleInRadians(angle);
33
34   //  135  90   45
35   //     +--+--+
36   //     | \|/ |
37   // 180 +--+--+ 0
38   //     | /|\ |
39   //     +--+--+
40   //  225  270  315
41   if( angle >= 45.0f && angle < 135.0f )
42   {
43     position.x = halfSide * cosf(angleInRadians) / sinf(angleInRadians);
44     position.y = -halfSide;
45   }
46   else if( angle >= 135.0f && angle < 225.0f )
47   {
48     position.x = -halfSide;
49     position.y = halfSide * sinf(angleInRadians) / cosf(angleInRadians);
50   }
51   else if( angle >= 225.0f && angle < 315.0f )
52   {
53     position.x = -halfSide * cosf(angleInRadians) / sinf(angleInRadians);
54     position.y =  halfSide;
55   }
56   else
57   {
58     position.x = halfSide;
59     position.y = -halfSide * sinf(angleInRadians) / cosf(angleInRadians);
60   }
61   return position;
62 }
63
64 float HoldZeroFastEaseInOutHoldOne(float progress)
65 {
66   if( progress < 0.2f)
67   {
68     return 0.0f;
69   }
70   else if(progress < 0.5f)
71   {
72     return AlphaFunctions::EaseIn((progress-0.2) / 0.3f) * 0.5f;
73   }
74   else if(progress < 0.8f)
75   {
76     return AlphaFunctions::EaseOut((progress - 0.5f) / 0.3f) * 0.5f + 0.5f;
77   }
78   else
79   {
80     return 1.0f;
81   }
82 }
83
84 struct SquareFanConstraint
85 {
86   SquareFanConstraint(int sideIndex)
87   : mSideIndex(sideIndex)
88   {
89   }
90
91   Vector3 operator()( const Vector3& current, const PropertyInput& start, const PropertyInput& rotation )
92   {
93     float degree = fmodf((start.GetFloat() + rotation.GetFloat()), 360.0f);
94     if(degree < 0.0f)
95     {
96       degree += 360.0f;
97     }
98
99     float startAngle = (90.0f*mSideIndex)-45.0f;
100     float endAngle = (90.0f*mSideIndex)+45.0f;
101     if(degree < startAngle)
102     {
103       return Vector3::ZERO;
104     }
105     else if( degree >= endAngle )
106     {
107       degree = endAngle;
108     }
109     Vector3 pos = CircleSquareProjection(Degree(degree), 0.5f);
110     pos.x = -pos.x; // Inverting X makes the animation go anti clockwise from left center
111     return pos;
112   }
113
114   int mSideIndex;
115 };
116
117 } // anonymous namespace
118
119
120 RadialSweepView RadialSweepViewImpl::New( )
121 {
122   return New( 2.0f, 100.0f, Degree(0.0f), Degree(0.0f), Degree(0.0f), Degree(359.999f) );
123 }
124
125
126 RadialSweepView RadialSweepViewImpl::New( float duration, float diameter, Degree initialAngle, Degree finalAngle, Degree initialSector, Degree finalSector )
127 {
128   RadialSweepViewImpl* impl= new RadialSweepViewImpl(duration, diameter, initialAngle, finalAngle, initialSector, finalSector);
129   RadialSweepView handle = RadialSweepView(*impl);
130   return handle;
131 }
132
133 RadialSweepViewImpl::RadialSweepViewImpl( float duration, float diameter, Degree initialAngle, Degree finalAngle, Degree initialSector, Degree finalSector )
134 : Control( CONTROL_BEHAVIOUR_NONE ),
135   mDuration(duration),
136   mDiameter(diameter),
137   mInitialAngle(initialAngle),
138   mFinalAngle(finalAngle),
139   mInitialSector(initialSector),
140   mFinalSector(finalSector),
141   mInitialActorAngle(0),
142   mFinalActorAngle(0),
143   mEasingFunction(HoldZeroFastEaseInOutHoldOne),
144   mRotateActorsWithStencil(false),
145   mRotateActors(false)
146 {
147 }
148
149 void RadialSweepViewImpl::SetDuration(float duration)
150 {
151   mDuration = duration;
152 }
153
154 void RadialSweepViewImpl::SetEasingFunction( Dali::AlphaFunction easingFunction )
155 {
156   mEasingFunction = easingFunction;
157 }
158
159 void RadialSweepViewImpl::SetDiameter(float diameter)
160 {
161   mDiameter = diameter;
162 }
163
164 void RadialSweepViewImpl::SetInitialAngle( Dali::Degree initialAngle)
165 {
166   mInitialAngle = initialAngle;
167 }
168
169 void RadialSweepViewImpl::SetFinalAngle( Dali::Degree finalAngle)
170 {
171   mFinalAngle = finalAngle;
172 }
173
174 void RadialSweepViewImpl::SetInitialSector( Dali::Degree initialSector)
175 {
176   mInitialSector = initialSector;
177 }
178
179 void RadialSweepViewImpl::SetFinalSector( Dali::Degree finalSector)
180 {
181   mFinalSector = finalSector;
182 }
183
184 void RadialSweepViewImpl::SetInitialActorAngle( Dali::Degree initialAngle )
185 {
186   mInitialActorAngle = initialAngle;
187   mRotateActors = true;
188 }
189
190 void RadialSweepViewImpl::SetFinalActorAngle( Dali::Degree finalAngle )
191 {
192   mFinalActorAngle = finalAngle;
193   mRotateActors = true;
194 }
195
196 float RadialSweepViewImpl::GetDuration( )
197 {
198   return mDuration;
199 }
200
201 float RadialSweepViewImpl::GetDiameter( )
202 {
203   return mDiameter;
204 }
205
206 Dali::Degree RadialSweepViewImpl::GetInitialAngle( )
207 {
208   return mInitialAngle;
209 }
210
211 Dali::Degree RadialSweepViewImpl::GetFinalAngle( )
212 {
213   return mFinalAngle;
214 }
215
216 Dali::Degree RadialSweepViewImpl::GetInitialSector( )
217 {
218   return mInitialSector;
219 }
220
221 Dali::Degree RadialSweepViewImpl::GetFinalSector( )
222 {
223   return mFinalSector;
224 }
225
226 Dali::Degree RadialSweepViewImpl::GetInitialActorAngle( )
227 {
228   return mInitialActorAngle;
229 }
230
231 Dali::Degree RadialSweepViewImpl::GetFinalActorAngle(  )
232 {
233   return mFinalActorAngle;
234 }
235
236 void RadialSweepViewImpl::RotateActorsWithStencil(bool rotate)
237 {
238   mRotateActorsWithStencil = rotate;
239 }
240
241 void RadialSweepViewImpl::Add(Actor actor)
242 {
243   if( ! mLayer )
244   {
245     mLayer = Layer::New();
246     Self().Add(mLayer);
247     mLayer.SetSize( Stage::GetCurrent().GetSize() );
248     mLayer.SetPositionInheritanceMode(USE_PARENT_POSITION);
249   }
250
251   mLayer.Add(actor);
252 }
253
254 void RadialSweepViewImpl::Activate( Animation anim, float offsetTime, float duration )
255 {
256   bool startAnimation=false;
257   if( ! anim )
258   {
259     mAnim = Animation::New( mDuration );
260     anim = mAnim;
261     startAnimation = true;
262   }
263
264   if( ! mStencilActor )
265   {
266     CreateStencil( mInitialSector );
267     mLayer.Add( mStencilActor );
268     mStencilActor.SetSize(mDiameter, mDiameter);
269   }
270
271   mStencilActor.SetRotation( Degree(mInitialAngle), Vector3::ZAXIS );
272   mStencilActor.SetProperty( mRotationAngleIndex, static_cast<float>(mInitialSector) );
273
274   if( mRotateActors )
275   {
276     for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
277     {
278       Actor actor = mLayer.GetChildAt(i);
279       if( actor != mStencilActor )
280       {
281         anim.RotateTo( actor, mInitialActorAngle, Vector3::ZAXIS );
282       }
283     }
284   }
285
286   anim.AnimateTo( Property( mStencilActor, mRotationAngleIndex ), static_cast<float>(mFinalSector), mEasingFunction, TimePeriod( offsetTime, duration) );
287   anim.RotateTo( mStencilActor, mFinalAngle, Vector3::ZAXIS, mEasingFunction, offsetTime, duration );
288
289   if( mRotateActorsWithStencil )
290   {
291     for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
292     {
293       Actor actor = mLayer.GetChildAt(i);
294       if( actor != mStencilActor )
295       {
296         anim.RotateTo( actor, Degree(mFinalAngle - mInitialAngle), Vector3::ZAXIS, mEasingFunction, offsetTime, duration );
297       }
298     }
299   }
300   else if( mRotateActors )
301   {
302     for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++)
303     {
304       Actor actor = mLayer.GetChildAt(i);
305       if( actor != mStencilActor )
306       {
307         anim.RotateTo( actor, mFinalActorAngle, Vector3::ZAXIS, mEasingFunction, offsetTime, duration );
308       }
309     }
310   }
311
312
313   if( startAnimation )
314   {
315     anim.SetLooping(true);
316     anim.Play();
317   }
318 }
319
320
321 void RadialSweepViewImpl::Deactivate()
322 {
323   if( mAnim )
324   {
325     mAnim.Stop();
326   }
327   // mLayer.Remove( mStencilActor );
328   // mStencilActor.Reset();
329   // mMesh.Reset();
330   // mMaterial.Reset();
331 }
332
333 void RadialSweepViewImpl::CreateStencil( Degree initialSector )
334 {
335   mMaterial = Material::New("Material");
336   mMaterial.SetDiffuseColor(Color::WHITE);
337   mMaterial.SetAmbientColor(Vector4(0.0, 0.1, 0.1, 1.0));
338
339   // Generate a square mesh with a point at the center:
340
341   AnimatableMesh::Faces faces;
342   // Create triangles joining up the verts
343   faces.push_back(0); faces.push_back(1); faces.push_back(2);
344   faces.push_back(0); faces.push_back(2); faces.push_back(3);
345   faces.push_back(0); faces.push_back(3); faces.push_back(4);
346   faces.push_back(0); faces.push_back(4); faces.push_back(5);
347   faces.push_back(0); faces.push_back(5); faces.push_back(6);
348
349   mMesh = AnimatableMesh::New(7, faces, mMaterial);
350   mMesh[0].SetPosition( Vector3(  0.0f,  0.0f, 0.0f ) ); // Center pt
351
352   mStencilActor = MeshActor::New(mMesh);
353   mStencilActor.SetAffectedByLighting(false);
354   mStencilActor.SetCullFace(CullNone); // Allow clockwise & anticlockwise faces
355
356   mStartAngleIndex = mStencilActor.RegisterProperty("start-angle", Property::Value(0.0f));
357   mRotationAngleIndex = mStencilActor.RegisterProperty("rotation-angle", Property::Value(initialSector));
358
359   Source srcStart( mStencilActor, mStartAngleIndex );
360   Source srcRot( mStencilActor, mRotationAngleIndex );
361
362   // Constrain the vertices of the square mesh to sweep out a sector as the
363   // rotation angle is animated.
364   mMesh.ApplyConstraint(Constraint::New<Vector3>( mMesh.GetPropertyIndex(1, AnimatableVertex::POSITION),
365                                                   srcStart, srcStart, SquareFanConstraint(0)));
366   mMesh.ApplyConstraint(Constraint::New<Vector3>( mMesh.GetPropertyIndex(2, AnimatableVertex::POSITION),
367                                                   srcStart, srcRot, SquareFanConstraint(0)));
368   mMesh.ApplyConstraint(Constraint::New<Vector3>( mMesh.GetPropertyIndex(3, AnimatableVertex::POSITION),
369                                                   srcStart, srcRot, SquareFanConstraint(1)));
370   mMesh.ApplyConstraint(Constraint::New<Vector3>( mMesh.GetPropertyIndex(4, AnimatableVertex::POSITION),
371                                                   srcStart, srcRot, SquareFanConstraint(2)));
372   mMesh.ApplyConstraint(Constraint::New<Vector3>( mMesh.GetPropertyIndex(5, AnimatableVertex::POSITION),
373                                                   srcStart, srcRot, SquareFanConstraint(3)));
374   mMesh.ApplyConstraint(Constraint::New<Vector3>( mMesh.GetPropertyIndex(6, AnimatableVertex::POSITION),
375                                                   srcStart, srcRot, SquareFanConstraint(4)));
376
377   mStencilActor.SetDrawMode( DrawMode::STENCIL );
378   mStencilActor.SetPositionInheritanceMode(USE_PARENT_POSITION);
379 }