Add 'ExclusiveArch: armv7l' limit build to arm architecture
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / scrollable / scroll-view / scroll-view-carousel-effect-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // EXTERNAL INCLUDES
18 #include <boost/bind.hpp>
19
20 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
21 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-carousel-effect-impl.h>
22
23 using namespace Dali;
24
25 namespace // unnamed namespace
26 {
27
28 /**
29  * Gets a property index. If the property doesn't already exist, then
30  * it will create the property.
31  * @param[in] handle The handle that owns or will own the property
32  * @param[in] name The name for this property
33  * @param[in] propertyValue The initial value for this property
34  * @return The property index for this property is returned.
35  */
36 Property::Index SafeRegisterProperty( Handle& handle, const std::string& name, Property::Value propertyValue )
37 {
38   Property::Index index = handle.GetPropertyIndex( name );
39
40   if(index == Property::INVALID_INDEX)
41   {
42     index = handle.RegisterProperty( name, propertyValue );
43   }
44
45   return index;
46 }
47
48 /**
49  * ScrollCarouselEffectInfo
50  *
51  * Visibility constraint: switches off the visibility when Actor
52  * is outside of bounds, for performance reasons.
53  *
54  * Rotate constraint: adjusts the angle of the Actors
55  * based on their position relative to the edges of the screen.
56  * When in the middle portion of the screen Angle does not change.
57  * When leaving the edge of the screen screen rotation changes.
58  *
59  * Position constraint: adjusts the position of the Actors
60  * based on their parent page's position relative to the edges of the screen.
61  * The position constraint compensates for the rotation which would otherwise
62  * move the Actor's edge visually away from the neighboring actor, as they rotate
63  * around their default anchor point.
64  */
65 class ScrollCarouselEffectInfo : public Dali::RefObject
66 {
67 public:
68
69   ScrollCarouselEffectInfo(const Vector2& angleSwing)
70   : mAngleSwing(angleSwing),
71     mCanvasMargin( 0.0f, 0.0f ),
72     mVisibilityThreshold( 1.0f, 1.0f )
73   {
74   }
75
76   /**
77    * @param[in] current The current visibility of this Actor
78    * @param[in] positionProperty The Actor's Position.
79    * @param[in] scaleProperty The Actor's Scale.
80    * @param[in] sizeProperty The Actor's Size
81    * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
82    * @param[in] scrollSizeProperty The size of the scroll-view (scrollView SIZE)
83    * @return The new visibility of this Actor.
84    */
85   bool VisibilityConstraint(const bool& current,
86                                   const PropertyInput& positionProperty,
87                                   const PropertyInput& scaleProperty,
88                                   const PropertyInput& sizeProperty,
89                                   const PropertyInput& scrollPositionProperty,
90                                   const PropertyInput& scrollSizeProperty)
91   {
92     const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY());
93     Vector2 position(positionProperty.GetVector3() + scrollPositionProperty.GetVector3());
94     Vector2 scaledSize(sizeProperty.GetVector3() * scaleProperty.GetVector3());
95
96     Vector2 domain(scrollSizeProperty.GetVector3());
97
98     position -= (anchor - mVisibilityThreshold) * scaledSize;
99     domain -= (Vector2::ONE - mVisibilityThreshold * 2.0f) * scaledSize;
100
101     return ( position.x >= 0 &&
102              position.x <= domain.x &&
103              position.y >= 0 &&
104              position.y <= domain.y );
105   }
106
107   /**
108    * @param[in] current The current orientation of this Actor
109    * @param[in] positionProperty The Actor's Position.
110    * @param[in] scaleProperty The Actor's Scale.
111    * @param[in] sizeProperty The Actor's Size
112    * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
113    * @param[in] scrollSizeProperty The size of the scroll-view (scrollView SIZE)
114    * @param[in] activateProperty Activation value (0 - normal, 1.0 - full effect)
115    * @return The new orientation of this Actor.
116    */
117   Quaternion RotationConstraint(const Quaternion& current,
118                                 const PropertyInput& positionProperty,
119                                 const PropertyInput& scaleProperty,
120                                 const PropertyInput& sizeProperty,
121                                 const PropertyInput& scrollPositionProperty,
122                                 const PropertyInput& scrollSizeProperty,
123                                 const PropertyInput& activateProperty)
124   {
125     const float activate(activateProperty.GetFloat());
126
127     if(activate <= Math::MACHINE_EPSILON_0)
128     {
129       return current;
130     }
131
132     const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY());
133     Vector2 position(positionProperty.GetVector3() + scrollPositionProperty.GetVector3());
134     Vector2 scaledSize(sizeProperty.GetVector3() * scaleProperty.GetVector3());
135     Vector2 domain(scrollSizeProperty.GetVector3());
136
137     position -= (anchor - mCanvasMargin) * scaledSize;
138     domain -= (Vector2::ONE - mCanvasMargin * 2.0f) * scaledSize;
139
140     Vector2 angle;
141
142     if( position.y < 0 )
143     {
144       angle.y = (-position.y / scaledSize.height) * mAngleSwing.y;
145     }
146     else if( position.y > domain.y )
147     {
148       angle.y = ((domain.y - position.y) / scaledSize.height) * mAngleSwing.y;
149     }
150
151     angle *= activate;
152
153     return Quaternion(-angle.x, Vector3::YAXIS) *
154            Quaternion(angle.y, Vector3::XAXIS) *
155            current;
156   }
157
158   /**
159    * @param[in] current The current position of this Actor
160    * @param[in] scaleProperty The Actor's Scale.
161    * @param[in] sizeProperty The Actor's Size
162    * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
163    * @param[in] scrollSizeProperty The size of the scroll-view (scrollView SIZE)
164    * @param[in] activateProperty Activation value (0 - normal, 1.0 - full effect)
165    * @return The new position of this Actor.
166    */
167   Vector3 PositionConstraint(const Vector3& current,
168                              const PropertyInput& scaleProperty,
169                              const PropertyInput& sizeProperty,
170                              const PropertyInput& scrollPositionProperty,
171                              const PropertyInput& scrollSizeProperty,
172                              const PropertyInput& activateProperty)
173   {
174     const float activate(activateProperty.GetFloat());
175     Vector3 position(current + scrollPositionProperty.GetVector3());
176
177     if(activate <= Math::MACHINE_EPSILON_0)
178     {
179       return position;
180     }
181
182     const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY());
183     Vector2 scaledSize(sizeProperty.GetVector3() * scaleProperty.GetVector3());
184     Vector2 domain(scrollSizeProperty.GetVector3());
185
186     position.GetVectorXY() -= (anchor - mCanvasMargin) * scaledSize;
187     domain -= (Vector2::ONE - mCanvasMargin * 2.0f) * scaledSize;
188
189     Vector2 angle;
190
191     if(position.y < 0)
192     {
193       angle.y = (-position.y / scaledSize.height) * mAngleSwing.y * activate;
194       position.y += (1.0f - cosf(angle.y)) * scaledSize.height * 0.5f;
195       position.z -= sinf(angle.y) * scaledSize.height * 0.5f;
196     }
197     else if(position.y > domain.y)
198     {
199       angle.y = ((domain.y - position.y) / scaledSize.height) * mAngleSwing.y * activate;
200       position.y -= (1.0f - cosf(angle.y)) * scaledSize.height * 0.5f;
201       position.z -= sinf(-angle.y) * scaledSize.height * 0.5f;
202     }
203
204     position.GetVectorXY() += (anchor - mCanvasMargin) * scaledSize;
205
206     return position;
207   }
208
209   Vector2 mAngleSwing;                                    ///< Maximum amount in X and Y axes to rotate.
210   Vector2 mCanvasMargin;                                  ///< Margin around the canvas for when to start rotating
211   Vector2 mVisibilityThreshold;                           ///< Threshold for when to to switch off visibility of Actor (for performance)
212 };
213
214 typedef IntrusivePtr<ScrollCarouselEffectInfo> ScrollCarouselEffectInfoPtr;
215
216 /**
217  * Helper: Applies the 3D scroll carousel constraints to the child actor
218  *
219  * @param[in] scrollView The ScrollView containing the pages.
220  * @param[in] child The child to be affected with the 3D Effect.
221  * @param[in] info The effect info for the constraints
222  */
223 void ApplyScrollCarouselConstraints(Toolkit::ScrollView scrollView,
224                                     Actor child,
225                                     ScrollCarouselEffectInfoPtr info)
226 {
227   // Apply constraints to this actor //
228   Constraint constraint;
229
230   constraint = Constraint::New<bool>( Actor::VISIBLE,
231                                       LocalSource( Actor::POSITION ),
232                                       LocalSource( Actor::SCALE ),
233                                       LocalSource( Actor::SIZE ),
234                                       Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
235                                       Source(scrollView, Actor::SIZE ),
236                                       Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ),
237                                       boost::bind( &ScrollCarouselEffectInfo::VisibilityConstraint, info, _1, _2, _3, _4, _5, _6) );
238   constraint.SetRemoveAction( Constraint::Discard );
239   child.ApplyConstraint( constraint );
240
241   constraint = Constraint::New<Quaternion>( Actor::ROTATION,
242                                             LocalSource( Actor::POSITION ),
243                                             LocalSource( Actor::SCALE ),
244                                             LocalSource( Actor::SIZE ),
245                                             Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
246                                             Source(scrollView, Actor::SIZE ),
247                                             Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ),
248                                             boost::bind( &ScrollCarouselEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
249   constraint.SetRemoveAction( Constraint::Discard );
250   child.ApplyConstraint( constraint );
251
252   constraint = Constraint::New<Vector3>( Actor::POSITION,
253                                          LocalSource( Actor::SCALE ),
254                                          LocalSource( Actor::SIZE ),
255                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
256                                          Source(scrollView, Actor::SIZE ),
257                                          Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ),
258                                          boost::bind( &ScrollCarouselEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6) );
259
260   constraint.SetRemoveAction( Constraint::Discard );
261   child.ApplyConstraint( constraint );
262 }
263
264 } // unnamed namespace
265
266 namespace Dali
267 {
268
269 namespace Toolkit
270 {
271
272 namespace Internal
273 {
274
275 ScrollViewCarouselEffect::ScrollViewCarouselEffect()
276 : mPropertyActivate(Property::INVALID_INDEX)
277 {
278 }
279
280 ScrollViewCarouselEffect::~ScrollViewCarouselEffect()
281 {
282 }
283
284 void ScrollViewCarouselEffect::ApplyToActor(Actor child, const Vector2& angleSwing)
285 {
286   ScrollCarouselEffectInfoPtr info(new ScrollCarouselEffectInfo(angleSwing));
287
288   ApplyScrollCarouselConstraints( GetScrollView(), child, info );
289 }
290
291 void ScrollViewCarouselEffect::OnAttach(Toolkit::ScrollView& scrollView)
292 {
293   if(mPropertyActivate == Property::INVALID_INDEX)
294   {
295     mPropertyActivate = SafeRegisterProperty( scrollView, Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE, 1.0f );
296   }
297 }
298
299 void ScrollViewCarouselEffect::OnDetach(Toolkit::ScrollView& scrollView)
300 {
301 }
302
303 } // namespace Internal
304
305 } // namespace Toolkit
306
307 } // namespace Dali