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>
20 #include <dali/public-api/animation/active-constraint.h>
21 #include <dali/public-api/animation/constraint.h>
22 #include <dali/public-api/object/property-input.h>
25 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
26 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-cube-effect-impl.h>
30 namespace // unnamed namespace
34 * ScrollCubeEffectInfo
36 * Rotate constraint: adjusts the angle of the Actors
37 * based on their parent page's position relative to the middle of the screen.
38 * When at middle of screen Angles on X and Y Axes is 0.
39 * When one screen away from the middle Angle is 90 degrees (pi/2)
41 * Color constraint: adjusts the alpha of the Actors
42 * based on their parent page's position relative to the middle of the screen.
43 * When at middle of screen Alpha is 100% opacity.
44 * When one screen away from middle Alpha is at 0% opacity (invisble).
46 * Position constraint: adjusts the position of the Actors
47 * based on their parent page's position relative to the middle of the screen.
48 * When at middle of the screen the position is not altered.
49 * When one screen away from middle the position is rotated about it's origin + mAnchor
51 class ScrollCubeEffectInfo
55 ScrollCubeEffectInfo(const Vector3& anchor,
56 const Vector2& angleSwing,
57 const Vector2& positionSwing)
59 mAngleSwing(angleSwing),
60 mPositionSwing(positionSwing)
65 * @param[in] current The current orientation of this Actor
66 * @param[in] pagePositionProperty The page's position.
67 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
68 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
69 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
70 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
71 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
72 * @return The new orientation of this Actor.
74 Quaternion RotationConstraint(const Quaternion& current,
75 const PropertyInput& pagePositionProperty,
76 const PropertyInput& scrollPositionProperty,
77 const PropertyInput& scrollPositionMin,
78 const PropertyInput& scrollPositionMax,
79 const PropertyInput& pageSizeProperty,
80 const PropertyInput& scrollWrap)
82 const Vector3& pagePosition = pagePositionProperty.GetVector3();
83 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
85 // Get position of page.
86 Vector3 position = pagePosition + scrollPosition;
88 // short circuit: for orthognal view.
89 if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
94 const Vector3& pageSize = pageSizeProperty.GetVector3();
95 bool wrap = scrollWrap.GetBoolean();
99 const Vector3& min = scrollPositionMin.GetVector3();
100 const Vector3& max = scrollPositionMax.GetVector3();
102 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
104 // WRAP X (based on the position of the right side)
105 position.x = WrapInDomain(position.x + pageSize.x, min.x, max.x) - pageSize.x;
108 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
110 // WRAP Y (based on the position of the bottom side)
111 position.y = WrapInDomain(position.y + pageSize.y, min.y, max.y) - pageSize.y;
115 // short circuit: for pages outside of view.
116 if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
121 position.x /= pageSize.x;
122 position.y /= pageSize.y;
124 Vector2 angle( Clamp(position.x, -1.0f,1.0f),
125 Clamp(position.y, -1.0f,1.0f) );
127 Quaternion rotation = Quaternion(angle.x * mAngleSwing.x, Vector3::YAXIS) *
128 Quaternion(-angle.y * mAngleSwing.y, Vector3::XAXIS) *
135 * @param[in] current The current color of this Actor
136 * @param[in] pagePositionProperty The page's position.
137 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
138 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
139 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
140 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
141 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
142 * @return The new color of this Actor.
144 Vector4 ColorConstraint(const Vector4& current,
145 const PropertyInput& pagePositionProperty,
146 const PropertyInput& scrollPositionProperty,
147 const PropertyInput& scrollPositionMin,
148 const PropertyInput& scrollPositionMax,
149 const PropertyInput& pageSizeProperty,
150 const PropertyInput& scrollWrap)
152 const Vector3& pagePosition = pagePositionProperty.GetVector3();
153 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
155 // Get position of page.
156 Vector3 position = pagePosition + scrollPosition;
158 // short circuit: for orthognal view.
159 if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
164 const Vector3& pageSize = pageSizeProperty.GetVector3();
165 bool wrap = scrollWrap.GetBoolean();
169 const Vector3& min = scrollPositionMin.GetVector3();
170 const Vector3& max = scrollPositionMax.GetVector3();
172 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
174 // WRAP X (based on the position of the right side)
175 position.x = WrapInDomain(position.x + pageSize.x, min.x, max.x) - pageSize.x;
178 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
180 // WRAP Y (based on the position of the bottom side)
181 position.y = WrapInDomain(position.y + pageSize.y, min.y, max.y) - pageSize.y;
185 // short circuit: for pages outside of view.
186 if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
188 // note preserve color channels incase there is a shader/further constraint
189 // that wishes to do something with that information.
190 return Vector4(current.r, current.g, current.b, 0.0f);
193 position.x /= pageSize.x;
194 position.y /= pageSize.y;
196 Vector2 angle( Clamp(position.x, -1.0f,1.0f),
197 Clamp(position.y, -1.0f,1.0f) );
199 float f = (1.0f - fabsf(angle.x)) * (1.0f - fabsf(angle.y));
202 Vector4 color = current;
209 * @param[in] current The current position
210 * @param[in] pagePositionProperty The page's position.
211 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
212 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
213 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
214 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
215 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
216 * @return The new position of this Actor.
218 Vector3 PositionConstraint(const Vector3& current,
219 const PropertyInput& pagePositionProperty,
220 const PropertyInput& scrollPositionProperty,
221 const PropertyInput& scrollPositionMin,
222 const PropertyInput& scrollPositionMax,
223 const PropertyInput& pageSizeProperty,
224 const PropertyInput& scrollWrap)
226 const Vector3& pagePosition = pagePositionProperty.GetVector3();
227 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
229 // Get position of page.
230 Vector3 relativePosition = pagePosition + scrollPosition;
232 // short circuit: for orthognal view.
233 if( (fabsf(relativePosition.x) < Math::MACHINE_EPSILON_1) && (fabsf(relativePosition.y) < Math::MACHINE_EPSILON_1) )
235 return current + scrollPosition;
238 const Vector3& pageSize = pageSizeProperty.GetVector3();
239 bool wrap = scrollWrap.GetBoolean();
243 const Vector3& min = scrollPositionMin.GetVector3();
244 const Vector3& max = scrollPositionMax.GetVector3();
246 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
248 // WRAP X (based on the position of the right side)
249 relativePosition.x = WrapInDomain(relativePosition.x + pageSize.x, min.x, max.x) - pageSize.x;
252 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
254 // WRAP Y (based on the position of the bottom side)
255 relativePosition.y = WrapInDomain(relativePosition.y + pageSize.y, min.y, max.y) - pageSize.y;
259 // short circuit: for pages outside of view.
260 if( (fabsf(relativePosition.x) >= pageSize.x) || (fabsf(relativePosition.y) >= pageSize.y) )
262 // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this)
263 // they will be invisible so doesn't have to be precise, just away from stage.
264 return current + scrollPosition;
267 relativePosition.x /= pageSize.x;
268 relativePosition.y /= pageSize.y;
269 relativePosition.z = 0.0f;
271 Vector3 angle( Clamp(relativePosition.x, -1.0f,1.0f) * mAngleSwing.x,
272 Clamp(relativePosition.y, -1.0f,1.0f) * mAngleSwing.y,
275 // Rotate position (current) about point.
276 Vector3 position = current - mAnchor;
277 Quaternion rotatorY(angle.x, Vector3::YAXIS);
278 position = rotatorY.Rotate(position);
279 Quaternion rotatorX(-angle.y, Vector3::XAXIS);
280 position = rotatorX.Rotate(position);
282 position += relativePosition * mPositionSwing;
284 return position - pagePosition;
287 Vector3 mAnchor; ///< Anchor point where Actor should rotate about.
288 Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
289 Vector3 mPositionSwing; ///< Maximum amount in X and Y axes to alter position.
293 * Helper: Applies the 3D scroll cube constraints to the child actor
295 * @param[in] scrollView The ScrollView containing the pages.
296 * @param[in] child The child to be affected with the 3D Effect.
297 * @param[in] info The effect info for the constraints
299 void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView,
302 const ScrollCubeEffectInfo& info)
304 // Apply constraints to this actor //
305 Constraint constraint;
306 constraint = Constraint::New<Quaternion>( Actor::Property::ROTATION,
307 Source(parentPage, Actor::Property::POSITION),
308 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
309 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
310 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
311 Source(scrollView, Actor::Property::SIZE ),
312 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
313 boost::bind( &ScrollCubeEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
315 constraint.SetRemoveAction( Constraint::Discard );
316 child.ApplyConstraint( constraint );
318 constraint = Constraint::New<Vector4>( Actor::Property::COLOR,
319 Source(parentPage, Actor::Property::POSITION),
320 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
321 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
322 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
323 Source(scrollView, Actor::Property::SIZE ),
324 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
325 boost::bind( &ScrollCubeEffectInfo::ColorConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
327 constraint.SetRemoveAction( Constraint::Discard );
328 child.ApplyConstraint( constraint );
330 constraint = Constraint::New<Vector3>( Actor::Property::POSITION,
331 Source(parentPage, Actor::Property::POSITION),
332 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
333 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
334 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
335 Source(scrollView, Actor::Property::SIZE ),
336 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
337 boost::bind( &ScrollCubeEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
339 constraint.SetRemoveAction( Constraint::Discard );
340 child.ApplyConstraint( constraint );
343 } // unnamed namespace
354 ScrollViewCubeEffect::ScrollViewCubeEffect()
359 ScrollViewCubeEffect::~ScrollViewCubeEffect()
363 void ScrollViewCubeEffect::ApplyToActor(Actor child,
364 const Vector3& anchor,
365 const Vector2& angleSwing,
366 const Vector2& positionSwing)
368 ScrollCubeEffectInfo info( anchor, angleSwing, positionSwing );
370 ApplyScrollCubeConstraints( GetScrollView(), child, child.GetParent(), info );
373 void ScrollViewCubeEffect::ApplyToActor(Actor child,
375 const Vector3& anchor,
376 const Vector2& angleSwing,
377 const Vector2& positionSwing)
379 ScrollCubeEffectInfo info( anchor, angleSwing, positionSwing );
381 ApplyScrollCubeConstraints( GetScrollView(), child, parentPage, info );
384 void ScrollViewCubeEffect::OnAttach(Toolkit::ScrollView& scrollView)
388 void ScrollViewCubeEffect::OnDetach(Toolkit::ScrollView& scrollView)
392 } // namespace Internal
394 } // namespace Toolkit