2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 // http://floralicense.org/license/
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.
18 #include <boost/bind.hpp>
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-cube-effect-impl.h>
25 namespace // unnamed namespace
29 * ScrollCubeEffectInfo
31 * Rotate constraint: adjusts the angle of the Actors
32 * based on their parent page's position relative to the middle of the screen.
33 * When at middle of screen Angles on X and Y Axes is 0.
34 * When one screen away from the middle Angle is 90 degrees (pi/2)
36 * Color constraint: adjusts the alpha of the Actors
37 * based on their parent page's position relative to the middle of the screen.
38 * When at middle of screen Alpha is 100% opacity.
39 * When one screen away from middle Alpha is at 0% opacity (invisble).
41 * Position constraint: adjusts the position of the Actors
42 * based on their parent page's position relative to the middle of the screen.
43 * When at middle of the screen the position is not altered.
44 * When one screen away from middle the position is rotated about it's origin + mAnchor
46 class ScrollCubeEffectInfo : public Dali::RefObject
50 ScrollCubeEffectInfo(const Vector3& anchor,
51 const Vector2& angleSwing,
52 const Vector2& positionSwing)
54 mAngleSwing(angleSwing),
55 mPositionSwing(positionSwing)
60 * @param[in] current The current orientation of this Actor
61 * @param[in] pagePositionProperty The page's position.
62 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
63 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
64 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
65 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
66 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
67 * @return The new orientation of this Actor.
69 Quaternion RotationConstraint(const Quaternion& current,
70 const PropertyInput& pagePositionProperty,
71 const PropertyInput& scrollPositionProperty,
72 const PropertyInput& scrollPositionMin,
73 const PropertyInput& scrollPositionMax,
74 const PropertyInput& pageSizeProperty,
75 const PropertyInput& scrollWrap)
77 const Vector3& pagePosition = pagePositionProperty.GetVector3();
78 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
80 // Get position of page.
81 Vector3 position = pagePosition + scrollPosition;
83 // short circuit: for orthognal view.
84 if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
89 const Vector3& pageSize = pageSizeProperty.GetVector3();
90 bool wrap = scrollWrap.GetBoolean();
94 const Vector3& min = scrollPositionMin.GetVector3();
95 const Vector3& max = scrollPositionMax.GetVector3();
97 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
99 // WRAP X (based on the position of the right side)
100 position.x = WrapInDomain(position.x + pageSize.x, min.x, max.x) - pageSize.x;
103 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
105 // WRAP Y (based on the position of the bottom side)
106 position.y = WrapInDomain(position.y + pageSize.y, min.y, max.y) - pageSize.y;
110 // short circuit: for pages outside of view.
111 if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
116 position.x /= pageSize.x;
117 position.y /= pageSize.y;
119 Vector2 angle( Clamp(position.x, -1.0f,1.0f),
120 Clamp(position.y, -1.0f,1.0f) );
122 Quaternion rotation = Quaternion(angle.x * mAngleSwing.x, Vector3::YAXIS) *
123 Quaternion(-angle.y * mAngleSwing.y, Vector3::XAXIS) *
130 * @param[in] current The current color of this Actor
131 * @param[in] pagePositionProperty The page's position.
132 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
133 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
134 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
135 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
136 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
137 * @return The new color of this Actor.
139 Vector4 ColorConstraint(const Vector4& current,
140 const PropertyInput& pagePositionProperty,
141 const PropertyInput& scrollPositionProperty,
142 const PropertyInput& scrollPositionMin,
143 const PropertyInput& scrollPositionMax,
144 const PropertyInput& pageSizeProperty,
145 const PropertyInput& scrollWrap)
147 const Vector3& pagePosition = pagePositionProperty.GetVector3();
148 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
150 // Get position of page.
151 Vector3 position = pagePosition + scrollPosition;
153 // short circuit: for orthognal view.
154 if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
159 const Vector3& pageSize = pageSizeProperty.GetVector3();
160 bool wrap = scrollWrap.GetBoolean();
164 const Vector3& min = scrollPositionMin.GetVector3();
165 const Vector3& max = scrollPositionMax.GetVector3();
167 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
169 // WRAP X (based on the position of the right side)
170 position.x = WrapInDomain(position.x + pageSize.x, min.x, max.x) - pageSize.x;
173 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
175 // WRAP Y (based on the position of the bottom side)
176 position.y = WrapInDomain(position.y + pageSize.y, min.y, max.y) - pageSize.y;
180 // short circuit: for pages outside of view.
181 if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
183 // note preserve color channels incase there is a shader/further constraint
184 // that wishes to do something with that information.
185 return Vector4(current.r, current.g, current.b, 0.0f);
188 position.x /= pageSize.x;
189 position.y /= pageSize.y;
191 Vector2 angle( Clamp(position.x, -1.0f,1.0f),
192 Clamp(position.y, -1.0f,1.0f) );
194 float f = (1.0f - fabsf(angle.x)) * (1.0f - fabsf(angle.y));
197 Vector4 color = current;
204 * @param[in] current The current position
205 * @param[in] pagePositionProperty The page's position.
206 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
207 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
208 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
209 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
210 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
211 * @return The new position of this Actor.
213 Vector3 PositionConstraint(const Vector3& current,
214 const PropertyInput& pagePositionProperty,
215 const PropertyInput& scrollPositionProperty,
216 const PropertyInput& scrollPositionMin,
217 const PropertyInput& scrollPositionMax,
218 const PropertyInput& pageSizeProperty,
219 const PropertyInput& scrollWrap)
221 const Vector3& pagePosition = pagePositionProperty.GetVector3();
222 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
224 // Get position of page.
225 Vector3 relativePosition = pagePosition + scrollPosition;
227 // short circuit: for orthognal view.
228 if( (fabsf(relativePosition.x) < Math::MACHINE_EPSILON_1) && (fabsf(relativePosition.y) < Math::MACHINE_EPSILON_1) )
230 return current + scrollPosition;
233 const Vector3& pageSize = pageSizeProperty.GetVector3();
234 bool wrap = scrollWrap.GetBoolean();
238 const Vector3& min = scrollPositionMin.GetVector3();
239 const Vector3& max = scrollPositionMax.GetVector3();
241 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
243 // WRAP X (based on the position of the right side)
244 relativePosition.x = WrapInDomain(relativePosition.x + pageSize.x, min.x, max.x) - pageSize.x;
247 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
249 // WRAP Y (based on the position of the bottom side)
250 relativePosition.y = WrapInDomain(relativePosition.y + pageSize.y, min.y, max.y) - pageSize.y;
254 // short circuit: for pages outside of view.
255 if( (fabsf(relativePosition.x) >= pageSize.x) || (fabsf(relativePosition.y) >= pageSize.y) )
257 // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this)
258 // they will be invisible so doesn't have to be precise, just away from stage.
259 return current + scrollPosition;
262 relativePosition.x /= pageSize.x;
263 relativePosition.y /= pageSize.y;
264 relativePosition.z = 0.0f;
266 Vector3 angle( Clamp(relativePosition.x, -1.0f,1.0f) * mAngleSwing.x,
267 Clamp(relativePosition.y, -1.0f,1.0f) * mAngleSwing.y,
270 // Rotate position (current) about point.
271 Vector3 position = current - mAnchor;
272 Quaternion rotatorY(angle.x, Vector3::YAXIS);
273 position = rotatorY.Rotate(position);
274 Quaternion rotatorX(-angle.y, Vector3::XAXIS);
275 position = rotatorX.Rotate(position);
277 position += relativePosition * mPositionSwing;
279 return position - pagePosition;
282 Vector3 mAnchor; ///< Anchor point where Actor should rotate about.
283 Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
284 Vector3 mPositionSwing; ///< Maximum amount in X and Y axes to alter position.
287 typedef IntrusivePtr<ScrollCubeEffectInfo> ScrollCubeEffectInfoPtr;
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 ScrollCubeEffectInfoPtr 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 ScrollCubeEffectInfoPtr info(new ScrollCubeEffectInfo(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 ScrollCubeEffectInfoPtr info(new ScrollCubeEffectInfo(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