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>
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>
27 namespace // unnamed namespace
31 * ScrollCubeEffectInfo
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)
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).
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
48 class ScrollCubeEffectInfo
52 ScrollCubeEffectInfo(const Vector3& anchor,
53 const Vector2& angleSwing,
54 const Vector2& positionSwing)
56 mAngleSwing(angleSwing),
57 mPositionSwing(positionSwing)
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.
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)
79 const Vector3& pagePosition = pagePositionProperty.GetVector3();
80 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
82 // Get position of page.
83 Vector3 position = pagePosition + scrollPosition;
85 // short circuit: for orthognal view.
86 if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
91 const Vector3& pageSize = pageSizeProperty.GetVector3();
92 bool wrap = scrollWrap.GetBoolean();
96 const Vector3& min = scrollPositionMin.GetVector3();
97 const Vector3& max = scrollPositionMax.GetVector3();
99 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
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;
105 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
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;
112 // short circuit: for pages outside of view.
113 if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
118 position.x /= pageSize.x;
119 position.y /= pageSize.y;
121 Vector2 angle( Clamp(position.x, -1.0f,1.0f),
122 Clamp(position.y, -1.0f,1.0f) );
124 Quaternion rotation = Quaternion(angle.x * mAngleSwing.x, Vector3::YAXIS) *
125 Quaternion(-angle.y * mAngleSwing.y, Vector3::XAXIS) *
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.
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)
149 const Vector3& pagePosition = pagePositionProperty.GetVector3();
150 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
152 // Get position of page.
153 Vector3 position = pagePosition + scrollPosition;
155 // short circuit: for orthognal view.
156 if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
161 const Vector3& pageSize = pageSizeProperty.GetVector3();
162 bool wrap = scrollWrap.GetBoolean();
166 const Vector3& min = scrollPositionMin.GetVector3();
167 const Vector3& max = scrollPositionMax.GetVector3();
169 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
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;
175 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
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;
182 // short circuit: for pages outside of view.
183 if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
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);
190 position.x /= pageSize.x;
191 position.y /= pageSize.y;
193 Vector2 angle( Clamp(position.x, -1.0f,1.0f),
194 Clamp(position.y, -1.0f,1.0f) );
196 float f = (1.0f - fabsf(angle.x)) * (1.0f - fabsf(angle.y));
199 Vector4 color = current;
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.
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)
223 const Vector3& pagePosition = pagePositionProperty.GetVector3();
224 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
226 // Get position of page.
227 Vector3 relativePosition = pagePosition + scrollPosition;
229 // short circuit: for orthognal view.
230 if( (fabsf(relativePosition.x) < Math::MACHINE_EPSILON_1) && (fabsf(relativePosition.y) < Math::MACHINE_EPSILON_1) )
232 return current + scrollPosition;
235 const Vector3& pageSize = pageSizeProperty.GetVector3();
236 bool wrap = scrollWrap.GetBoolean();
240 const Vector3& min = scrollPositionMin.GetVector3();
241 const Vector3& max = scrollPositionMax.GetVector3();
243 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
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;
249 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
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;
256 // short circuit: for pages outside of view.
257 if( (fabsf(relativePosition.x) >= pageSize.x) || (fabsf(relativePosition.y) >= pageSize.y) )
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;
264 relativePosition.x /= pageSize.x;
265 relativePosition.y /= pageSize.y;
266 relativePosition.z = 0.0f;
268 Vector3 angle( Clamp(relativePosition.x, -1.0f,1.0f) * mAngleSwing.x,
269 Clamp(relativePosition.y, -1.0f,1.0f) * mAngleSwing.y,
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);
279 position += relativePosition * mPositionSwing;
281 return position - pagePosition;
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.
290 * Helper: Applies the 3D scroll cube constraints to the child actor
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
296 void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView,
299 const ScrollCubeEffectInfo& info)
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) );
312 constraint.SetRemoveAction( Constraint::Discard );
313 child.ApplyConstraint( constraint );
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) );
324 constraint.SetRemoveAction( Constraint::Discard );
325 child.ApplyConstraint( constraint );
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) );
336 constraint.SetRemoveAction( Constraint::Discard );
337 child.ApplyConstraint( constraint );
340 } // unnamed namespace
351 ScrollViewCubeEffect::ScrollViewCubeEffect()
356 ScrollViewCubeEffect::~ScrollViewCubeEffect()
360 void ScrollViewCubeEffect::ApplyToActor(Actor child,
361 const Vector3& anchor,
362 const Vector2& angleSwing,
363 const Vector2& positionSwing)
365 ScrollCubeEffectInfo info( anchor, angleSwing, positionSwing );
367 ApplyScrollCubeConstraints( GetScrollView(), child, child.GetParent(), info );
370 void ScrollViewCubeEffect::ApplyToActor(Actor child,
372 const Vector3& anchor,
373 const Vector2& angleSwing,
374 const Vector2& positionSwing)
376 ScrollCubeEffectInfo info( anchor, angleSwing, positionSwing );
378 ApplyScrollCubeConstraints( GetScrollView(), child, parentPage, info );
381 void ScrollViewCubeEffect::OnAttach(Toolkit::ScrollView& scrollView)
385 void ScrollViewCubeEffect::OnDetach(Toolkit::ScrollView& scrollView)
389 } // namespace Internal
391 } // namespace Toolkit