Follow the include-order coding conventions
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scrollable / scroll-view / scroll-view-cube-effect-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 // EXTERNAL INCLUDES
19 #include <boost/bind.hpp>
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
23 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-cube-effect-impl.h>
24
25 using namespace Dali;
26
27 namespace // unnamed namespace
28 {
29
30 /**
31  * ScrollCubeEffectInfo
32  *
33  * Rotate constraint: adjusts the angle of the Actors
34  * based on their parent page's position relative to the middle of the screen.
35  * When at middle of screen Angles on X and Y Axes is 0.
36  * When one screen away from the middle Angle is 90 degrees (pi/2)
37  *
38  * Color constraint: adjusts the alpha of the Actors
39  * based on their parent page's position relative to the middle of the screen.
40  * When at middle of screen Alpha is 100% opacity.
41  * When one screen away from middle Alpha is at 0% opacity (invisble).
42  *
43  * Position constraint: adjusts the position of the Actors
44  * based on their parent page's position relative to the middle of the screen.
45  * When at middle of the screen the position is not altered.
46  * When one screen away from middle the position is rotated about it's origin + mAnchor
47  */
48 class ScrollCubeEffectInfo
49 {
50 public:
51
52   ScrollCubeEffectInfo(const Vector3& anchor,
53                        const Vector2& angleSwing,
54                        const Vector2& positionSwing)
55   : mAnchor(anchor),
56     mAngleSwing(angleSwing),
57     mPositionSwing(positionSwing)
58   {
59   }
60
61   /**
62    * @param[in] current The current orientation of this Actor
63    * @param[in] pagePositionProperty The page's position.
64    * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
65    * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
66    * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
67    * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
68    * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
69    * @return The new orientation of this Actor.
70    */
71   Quaternion RotationConstraint(const Quaternion& current,
72                                 const PropertyInput& pagePositionProperty,
73                                 const PropertyInput& scrollPositionProperty,
74                                 const PropertyInput& scrollPositionMin,
75                                 const PropertyInput& scrollPositionMax,
76                                 const PropertyInput& pageSizeProperty,
77                                 const PropertyInput& scrollWrap)
78   {
79     const Vector3& pagePosition = pagePositionProperty.GetVector3();
80     const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
81
82     // Get position of page.
83     Vector3 position = pagePosition + scrollPosition;
84
85     // short circuit: for orthognal view.
86     if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
87     {
88       return current;
89     }
90
91     const Vector3& pageSize = pageSizeProperty.GetVector3();
92     bool wrap = scrollWrap.GetBoolean();
93
94     if(wrap)
95     {
96       const Vector3& min = scrollPositionMin.GetVector3();
97       const Vector3& max = scrollPositionMax.GetVector3();
98
99       if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
100       {
101         // WRAP X (based on the position of the right side)
102         position.x = WrapInDomain(position.x + pageSize.x, min.x, max.x) - pageSize.x;
103       }
104
105       if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
106       {
107         // WRAP Y (based on the position of the bottom side)
108         position.y = WrapInDomain(position.y + pageSize.y, min.y, max.y) - pageSize.y;
109       }
110     }
111
112     // short circuit: for pages outside of view.
113     if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
114     {
115       return current;
116     }
117
118     position.x /= pageSize.x;
119     position.y /= pageSize.y;
120
121     Vector2 angle( Clamp(position.x, -1.0f,1.0f),
122                    Clamp(position.y, -1.0f,1.0f) );
123
124     Quaternion rotation = Quaternion(angle.x * mAngleSwing.x, Vector3::YAXIS) *
125                           Quaternion(-angle.y * mAngleSwing.y, Vector3::XAXIS) *
126                           current;
127
128     return rotation;
129   }
130
131   /**
132    * @param[in] current The current color of this Actor
133    * @param[in] pagePositionProperty The page's position.
134    * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
135    * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
136    * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
137    * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
138    * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
139    * @return The new color of this Actor.
140    */
141   Vector4 ColorConstraint(const Vector4& current,
142                           const PropertyInput& pagePositionProperty,
143                           const PropertyInput& scrollPositionProperty,
144                           const PropertyInput& scrollPositionMin,
145                           const PropertyInput& scrollPositionMax,
146                           const PropertyInput& pageSizeProperty,
147                           const PropertyInput& scrollWrap)
148   {
149     const Vector3& pagePosition = pagePositionProperty.GetVector3();
150     const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
151
152     // Get position of page.
153     Vector3 position = pagePosition + scrollPosition;
154
155     // short circuit: for orthognal view.
156     if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
157     {
158       return current;
159     }
160
161     const Vector3& pageSize = pageSizeProperty.GetVector3();
162     bool wrap = scrollWrap.GetBoolean();
163
164     if(wrap)
165     {
166       const Vector3& min = scrollPositionMin.GetVector3();
167       const Vector3& max = scrollPositionMax.GetVector3();
168
169       if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
170       {
171         // WRAP X (based on the position of the right side)
172         position.x = WrapInDomain(position.x + pageSize.x, min.x, max.x) - pageSize.x;
173       }
174
175       if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
176       {
177         // WRAP Y (based on the position of the bottom side)
178         position.y = WrapInDomain(position.y + pageSize.y, min.y, max.y) - pageSize.y;
179       }
180     }
181
182     // short circuit: for pages outside of view.
183     if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
184     {
185       // note preserve color channels incase there is a shader/further constraint
186       // that wishes to do something with that information.
187       return Vector4(current.r, current.g, current.b, 0.0f);
188     }
189
190     position.x /= pageSize.x;
191     position.y /= pageSize.y;
192
193     Vector2 angle( Clamp(position.x, -1.0f,1.0f),
194                    Clamp(position.y, -1.0f,1.0f) );
195
196     float f = (1.0f - fabsf(angle.x)) * (1.0f - fabsf(angle.y));
197     f = f*f;
198
199     Vector4 color = current;
200     color.a *= f;
201
202     return color;
203   }
204
205   /**
206    * @param[in] current The current position
207    * @param[in] pagePositionProperty The page's position.
208    * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
209    * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
210    * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
211    * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
212    * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
213    * @return The new position of this Actor.
214    */
215   Vector3 PositionConstraint(const Vector3& current,
216                              const PropertyInput& pagePositionProperty,
217                              const PropertyInput& scrollPositionProperty,
218                              const PropertyInput& scrollPositionMin,
219                              const PropertyInput& scrollPositionMax,
220                              const PropertyInput& pageSizeProperty,
221                              const PropertyInput& scrollWrap)
222   {
223     const Vector3& pagePosition = pagePositionProperty.GetVector3();
224     const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
225
226     // Get position of page.
227     Vector3 relativePosition = pagePosition + scrollPosition;
228
229     // short circuit: for orthognal view.
230     if( (fabsf(relativePosition.x) < Math::MACHINE_EPSILON_1) && (fabsf(relativePosition.y) < Math::MACHINE_EPSILON_1) )
231     {
232       return current + scrollPosition;
233     }
234
235     const Vector3& pageSize = pageSizeProperty.GetVector3();
236     bool wrap = scrollWrap.GetBoolean();
237
238     if(wrap)
239     {
240       const Vector3& min = scrollPositionMin.GetVector3();
241       const Vector3& max = scrollPositionMax.GetVector3();
242
243       if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
244       {
245         // WRAP X (based on the position of the right side)
246         relativePosition.x = WrapInDomain(relativePosition.x + pageSize.x, min.x, max.x) - pageSize.x;
247       }
248
249       if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
250       {
251         // WRAP Y (based on the position of the bottom side)
252         relativePosition.y = WrapInDomain(relativePosition.y + pageSize.y, min.y, max.y) - pageSize.y;
253       }
254     }
255
256     // short circuit: for pages outside of view.
257     if( (fabsf(relativePosition.x) >= pageSize.x) || (fabsf(relativePosition.y) >= pageSize.y) )
258     {
259       // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this)
260       // they will be invisible so doesn't have to be precise, just away from stage.
261       return current + scrollPosition;
262     }
263
264     relativePosition.x /= pageSize.x;
265     relativePosition.y /= pageSize.y;
266     relativePosition.z = 0.0f;
267
268     Vector3 angle( Clamp(relativePosition.x, -1.0f,1.0f) * mAngleSwing.x,
269                    Clamp(relativePosition.y, -1.0f,1.0f) * mAngleSwing.y,
270                    0.0f);
271
272     // Rotate position (current) about point.
273     Vector3 position = current - mAnchor;
274     Quaternion rotatorY(angle.x, Vector3::YAXIS);
275     position = rotatorY.Rotate(position);
276     Quaternion rotatorX(-angle.y, Vector3::XAXIS);
277     position = rotatorX.Rotate(position);
278     position += mAnchor;
279     position += relativePosition * mPositionSwing;
280
281     return position - pagePosition;
282   }
283
284   Vector3 mAnchor;                                        ///< Anchor point where Actor should rotate about.
285   Vector2 mAngleSwing;                                    ///< Maximum amount in X and Y axes to rotate.
286   Vector3 mPositionSwing;                                 ///< Maximum amount in X and Y axes to alter position.
287 };
288
289 /**
290  * Helper: Applies the 3D scroll cube constraints to the child actor
291  *
292  * @param[in] scrollView The ScrollView containing the pages.
293  * @param[in] child The child to be affected with the 3D Effect.
294  * @param[in] info The effect info for the constraints
295  */
296 void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView,
297                                 Actor child,
298                                 Actor parentPage,
299                                 const ScrollCubeEffectInfo& info)
300 {
301   // Apply constraints to this actor //
302   Constraint constraint;
303   constraint = Constraint::New<Quaternion>( Actor::ROTATION,
304                                          Source(parentPage, Actor::POSITION),
305                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
306                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
307                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
308                                          Source(scrollView, Actor::SIZE ),
309                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
310                                          boost::bind( &ScrollCubeEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
311
312   constraint.SetRemoveAction( Constraint::Discard );
313   child.ApplyConstraint( constraint );
314
315   constraint = Constraint::New<Vector4>( Actor::COLOR,
316                                          Source(parentPage, Actor::POSITION),
317                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
318                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
319                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
320                                          Source(scrollView, Actor::SIZE ),
321                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
322                                          boost::bind( &ScrollCubeEffectInfo::ColorConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
323
324   constraint.SetRemoveAction( Constraint::Discard );
325   child.ApplyConstraint( constraint );
326
327   constraint = Constraint::New<Vector3>( Actor::POSITION,
328                                          Source(parentPage, Actor::POSITION),
329                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
330                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
331                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
332                                          Source(scrollView, Actor::SIZE ),
333                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
334                                          boost::bind( &ScrollCubeEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
335
336   constraint.SetRemoveAction( Constraint::Discard );
337   child.ApplyConstraint( constraint );
338 }
339
340 } // unnamed namespace
341
342 namespace Dali
343 {
344
345 namespace Toolkit
346 {
347
348 namespace Internal
349 {
350
351 ScrollViewCubeEffect::ScrollViewCubeEffect()
352 {
353
354 }
355
356 ScrollViewCubeEffect::~ScrollViewCubeEffect()
357 {
358 }
359
360 void ScrollViewCubeEffect::ApplyToActor(Actor child,
361                                         const Vector3& anchor,
362                                         const Vector2& angleSwing,
363                                         const Vector2& positionSwing)
364 {
365   ScrollCubeEffectInfo info( anchor, angleSwing, positionSwing );
366
367   ApplyScrollCubeConstraints( GetScrollView(), child, child.GetParent(), info );
368 }
369
370 void ScrollViewCubeEffect::ApplyToActor(Actor child,
371                                         Actor parentPage,
372                                         const Vector3& anchor,
373                                         const Vector2& angleSwing,
374                                         const Vector2& positionSwing)
375 {
376   ScrollCubeEffectInfo info( anchor, angleSwing, positionSwing );
377
378   ApplyScrollCubeConstraints( GetScrollView(), child, parentPage, info );
379 }
380
381 void ScrollViewCubeEffect::OnAttach(Toolkit::ScrollView& scrollView)
382 {
383 }
384
385 void ScrollViewCubeEffect::OnDetach(Toolkit::ScrollView& scrollView)
386 {
387 }
388
389 } // namespace Internal
390
391 } // namespace Toolkit
392
393 } // namespace Dali