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.
19 #include <boost/bind.hpp>
21 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
22 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-cube-effect-impl.h>
26 namespace // unnamed namespace
30 * ScrollCubeEffectInfo
32 * Rotate constraint: adjusts the angle of the Actors
33 * based on their parent page's position relative to the middle of the screen.
34 * When at middle of screen Angles on X and Y Axes is 0.
35 * When one screen away from the middle Angle is 90 degrees (pi/2)
37 * Color constraint: adjusts the alpha of the Actors
38 * based on their parent page's position relative to the middle of the screen.
39 * When at middle of screen Alpha is 100% opacity.
40 * When one screen away from middle Alpha is at 0% opacity (invisble).
42 * Position constraint: adjusts the position of the Actors
43 * based on their parent page's position relative to the middle of the screen.
44 * When at middle of the screen the position is not altered.
45 * When one screen away from middle the position is rotated about it's origin + mAnchor
47 class ScrollCubeEffectInfo
51 ScrollCubeEffectInfo(const Vector3& anchor,
52 const Vector2& angleSwing,
53 const Vector2& positionSwing)
55 mAngleSwing(angleSwing),
56 mPositionSwing(positionSwing)
61 * @param[in] current The current orientation of this Actor
62 * @param[in] pagePositionProperty The page's position.
63 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
64 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
65 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
66 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
67 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
68 * @return The new orientation of this Actor.
70 Quaternion RotationConstraint(const Quaternion& current,
71 const PropertyInput& pagePositionProperty,
72 const PropertyInput& scrollPositionProperty,
73 const PropertyInput& scrollPositionMin,
74 const PropertyInput& scrollPositionMax,
75 const PropertyInput& pageSizeProperty,
76 const PropertyInput& scrollWrap)
78 const Vector3& pagePosition = pagePositionProperty.GetVector3();
79 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
81 // Get position of page.
82 Vector3 position = pagePosition + scrollPosition;
84 // short circuit: for orthognal view.
85 if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
90 const Vector3& pageSize = pageSizeProperty.GetVector3();
91 bool wrap = scrollWrap.GetBoolean();
95 const Vector3& min = scrollPositionMin.GetVector3();
96 const Vector3& max = scrollPositionMax.GetVector3();
98 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
100 // WRAP X (based on the position of the right side)
101 position.x = WrapInDomain(position.x + pageSize.x, min.x, max.x) - pageSize.x;
104 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
106 // WRAP Y (based on the position of the bottom side)
107 position.y = WrapInDomain(position.y + pageSize.y, min.y, max.y) - pageSize.y;
111 // short circuit: for pages outside of view.
112 if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
117 position.x /= pageSize.x;
118 position.y /= pageSize.y;
120 Vector2 angle( Clamp(position.x, -1.0f,1.0f),
121 Clamp(position.y, -1.0f,1.0f) );
123 Quaternion rotation = Quaternion(angle.x * mAngleSwing.x, Vector3::YAXIS) *
124 Quaternion(-angle.y * mAngleSwing.y, Vector3::XAXIS) *
131 * @param[in] current The current color of this Actor
132 * @param[in] pagePositionProperty The page's position.
133 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
134 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
135 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
136 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
137 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
138 * @return The new color of this Actor.
140 Vector4 ColorConstraint(const Vector4& current,
141 const PropertyInput& pagePositionProperty,
142 const PropertyInput& scrollPositionProperty,
143 const PropertyInput& scrollPositionMin,
144 const PropertyInput& scrollPositionMax,
145 const PropertyInput& pageSizeProperty,
146 const PropertyInput& scrollWrap)
148 const Vector3& pagePosition = pagePositionProperty.GetVector3();
149 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
151 // Get position of page.
152 Vector3 position = pagePosition + scrollPosition;
154 // short circuit: for orthognal view.
155 if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
160 const Vector3& pageSize = pageSizeProperty.GetVector3();
161 bool wrap = scrollWrap.GetBoolean();
165 const Vector3& min = scrollPositionMin.GetVector3();
166 const Vector3& max = scrollPositionMax.GetVector3();
168 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
170 // WRAP X (based on the position of the right side)
171 position.x = WrapInDomain(position.x + pageSize.x, min.x, max.x) - pageSize.x;
174 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
176 // WRAP Y (based on the position of the bottom side)
177 position.y = WrapInDomain(position.y + pageSize.y, min.y, max.y) - pageSize.y;
181 // short circuit: for pages outside of view.
182 if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
184 // note preserve color channels incase there is a shader/further constraint
185 // that wishes to do something with that information.
186 return Vector4(current.r, current.g, current.b, 0.0f);
189 position.x /= pageSize.x;
190 position.y /= pageSize.y;
192 Vector2 angle( Clamp(position.x, -1.0f,1.0f),
193 Clamp(position.y, -1.0f,1.0f) );
195 float f = (1.0f - fabsf(angle.x)) * (1.0f - fabsf(angle.y));
198 Vector4 color = current;
205 * @param[in] current The current position
206 * @param[in] pagePositionProperty The page's position.
207 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
208 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
209 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
210 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
211 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
212 * @return The new position of this Actor.
214 Vector3 PositionConstraint(const Vector3& current,
215 const PropertyInput& pagePositionProperty,
216 const PropertyInput& scrollPositionProperty,
217 const PropertyInput& scrollPositionMin,
218 const PropertyInput& scrollPositionMax,
219 const PropertyInput& pageSizeProperty,
220 const PropertyInput& scrollWrap)
222 const Vector3& pagePosition = pagePositionProperty.GetVector3();
223 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
225 // Get position of page.
226 Vector3 relativePosition = pagePosition + scrollPosition;
228 // short circuit: for orthognal view.
229 if( (fabsf(relativePosition.x) < Math::MACHINE_EPSILON_1) && (fabsf(relativePosition.y) < Math::MACHINE_EPSILON_1) )
231 return current + scrollPosition;
234 const Vector3& pageSize = pageSizeProperty.GetVector3();
235 bool wrap = scrollWrap.GetBoolean();
239 const Vector3& min = scrollPositionMin.GetVector3();
240 const Vector3& max = scrollPositionMax.GetVector3();
242 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
244 // WRAP X (based on the position of the right side)
245 relativePosition.x = WrapInDomain(relativePosition.x + pageSize.x, min.x, max.x) - pageSize.x;
248 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
250 // WRAP Y (based on the position of the bottom side)
251 relativePosition.y = WrapInDomain(relativePosition.y + pageSize.y, min.y, max.y) - pageSize.y;
255 // short circuit: for pages outside of view.
256 if( (fabsf(relativePosition.x) >= pageSize.x) || (fabsf(relativePosition.y) >= pageSize.y) )
258 // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this)
259 // they will be invisible so doesn't have to be precise, just away from stage.
260 return current + scrollPosition;
263 relativePosition.x /= pageSize.x;
264 relativePosition.y /= pageSize.y;
265 relativePosition.z = 0.0f;
267 Vector3 angle( Clamp(relativePosition.x, -1.0f,1.0f) * mAngleSwing.x,
268 Clamp(relativePosition.y, -1.0f,1.0f) * mAngleSwing.y,
271 // Rotate position (current) about point.
272 Vector3 position = current - mAnchor;
273 Quaternion rotatorY(angle.x, Vector3::YAXIS);
274 position = rotatorY.Rotate(position);
275 Quaternion rotatorX(-angle.y, Vector3::XAXIS);
276 position = rotatorX.Rotate(position);
278 position += relativePosition * mPositionSwing;
280 return position - pagePosition;
283 Vector3 mAnchor; ///< Anchor point where Actor should rotate about.
284 Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
285 Vector3 mPositionSwing; ///< Maximum amount in X and Y axes to alter position.
289 * Helper: Applies the 3D scroll cube constraints to the child actor
291 * @param[in] scrollView The ScrollView containing the pages.
292 * @param[in] child The child to be affected with the 3D Effect.
293 * @param[in] info The effect info for the constraints
295 void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView,
298 const ScrollCubeEffectInfo& info)
300 // Apply constraints to this actor //
301 Constraint constraint;
302 constraint = Constraint::New<Quaternion>( Actor::ROTATION,
303 Source(parentPage, Actor::POSITION),
304 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
305 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
306 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
307 Source(scrollView, Actor::SIZE ),
308 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
309 boost::bind( &ScrollCubeEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
311 constraint.SetRemoveAction( Constraint::Discard );
312 child.ApplyConstraint( constraint );
314 constraint = Constraint::New<Vector4>( Actor::COLOR,
315 Source(parentPage, Actor::POSITION),
316 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
317 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
318 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
319 Source(scrollView, Actor::SIZE ),
320 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
321 boost::bind( &ScrollCubeEffectInfo::ColorConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
323 constraint.SetRemoveAction( Constraint::Discard );
324 child.ApplyConstraint( constraint );
326 constraint = Constraint::New<Vector3>( Actor::POSITION,
327 Source(parentPage, Actor::POSITION),
328 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
329 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
330 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
331 Source(scrollView, Actor::SIZE ),
332 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
333 boost::bind( &ScrollCubeEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
335 constraint.SetRemoveAction( Constraint::Discard );
336 child.ApplyConstraint( constraint );
339 } // unnamed namespace
350 ScrollViewCubeEffect::ScrollViewCubeEffect()
355 ScrollViewCubeEffect::~ScrollViewCubeEffect()
359 void ScrollViewCubeEffect::ApplyToActor(Actor child,
360 const Vector3& anchor,
361 const Vector2& angleSwing,
362 const Vector2& positionSwing)
364 ScrollCubeEffectInfo info( anchor, angleSwing, positionSwing );
366 ApplyScrollCubeConstraints( GetScrollView(), child, child.GetParent(), info );
369 void ScrollViewCubeEffect::ApplyToActor(Actor child,
371 const Vector3& anchor,
372 const Vector2& angleSwing,
373 const Vector2& positionSwing)
375 ScrollCubeEffectInfo info( anchor, angleSwing, positionSwing );
377 ApplyScrollCubeConstraints( GetScrollView(), child, parentPage, info );
380 void ScrollViewCubeEffect::OnAttach(Toolkit::ScrollView& scrollView)
384 void ScrollViewCubeEffect::OnDetach(Toolkit::ScrollView& scrollView)
388 } // namespace Internal
390 } // namespace Toolkit