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 <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-cube-effect-impl.h>
22 #include <boost/bind.hpp>
23 #include <dali/public-api/animation/active-constraint.h>
24 #include <dali/public-api/animation/constraint.h>
25 #include <dali/public-api/object/property-input.h>
28 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-helper-functions.h>
39 namespace // unnamed namespace
42 using namespace ScrollViewHelperFunctions;
45 * ScrollPageCubeEffectInfo
47 * Rotate constraint: adjusts the angle of the page based on its position relative to the middle of
49 * When at middle of screen Angles on X and Y Axes is 0.
50 * When one screen away from the middle Angle is 90 degrees (pi/2)
52 * Color constraint: adjusts the alpha of the page based on their parent page's position relative
53 * to the middle of the screen.
54 * When at middle of screen Alpha is 100% opacity.
55 * When outside the viewable area, the opacity is 0%.
57 * Position constraint: adjusts the position of the page based on their parent page's position
58 * relative to the middle of the screen.
59 * When at middle of the screen the position is not altered.
60 * When one screen away from middle the position is rotated as per expected in a 3D inner cube.
62 class ScrollPageCubeEffectInfo
66 ScrollPageCubeEffectInfo( const Vector2& angleSwing )
67 : mAngleSwing(angleSwing)
72 * @param[in] current The current orientation of this Actor
73 * @param[in] pagePositionProperty The page's position.
74 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
75 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
76 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
77 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
78 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
79 * @return The new orientation of this Actor.
81 Quaternion RotationConstraint(const Quaternion& current,
82 const PropertyInput& pagePositionProperty,
83 const PropertyInput& scrollPositionProperty,
84 const PropertyInput& scrollPositionMin,
85 const PropertyInput& scrollPositionMax,
86 const PropertyInput& pageSizeProperty,
87 const PropertyInput& scrollWrap)
89 const Vector3& pagePosition = pagePositionProperty.GetVector3();
90 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
92 // Get position of page.
93 Vector3 position = pagePosition + scrollPosition;
95 // short circuit: if we're looking straight on at the page.
96 if( IsStraightOnView( position ) )
101 const Vector3& pageSize = pageSizeProperty.GetVector3();
103 if( scrollWrap.GetBoolean() )
105 WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() );
108 // short circuit: for pages outside of view.
109 if( IsOutsideView( position, pageSize ) )
114 // Our target is a 90 degree (PI/2) rotation per page, so calculate the angle we should be rotate
115 // our page by calculating the amount we've moved as a fraction of the total size of the page.
116 Vector2 angle( position / pageSize * Dali::Math::PI_2 );
118 Quaternion rotation = Quaternion( -angle.x * mAngleSwing.x, Vector3::YAXIS ) *
119 Quaternion( angle.y * mAngleSwing.y, Vector3::XAXIS ) *
126 * @param[in] current The current color of this Actor
127 * @param[in] pagePositionProperty The page's position.
128 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
129 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
130 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
131 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
132 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
133 * @return The new color of this Actor.
135 Vector4 ColorConstraint(const Vector4& current,
136 const PropertyInput& pagePositionProperty,
137 const PropertyInput& scrollPositionProperty,
138 const PropertyInput& scrollPositionMin,
139 const PropertyInput& scrollPositionMax,
140 const PropertyInput& pageSizeProperty,
141 const PropertyInput& scrollWrap)
143 const Vector3& pagePosition = pagePositionProperty.GetVector3();
144 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
146 // Get position of page.
147 Vector3 position = pagePosition + scrollPosition;
149 // short circuit: if we're looking straight on at the page.
150 if( IsStraightOnView( position ) )
155 const Vector3& pageSize = pageSizeProperty.GetVector3();
157 if( scrollWrap.GetBoolean() )
159 WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() );
162 // short circuit: for pages outside of view.
163 if( IsOutsideView( position, pageSize ) )
165 // note preserve color channels incase there is a shader/further constraint
166 // that wishes to do something with that information.
167 return Vector4(current.r, current.g, current.b, 0.0f);
170 // Calculate the distance of this page from our view and ensure it falls within the appropriate
172 // If it does not, then the opacity is set to 0.0f.
173 position.x /= pageSize.width;
174 position.y /= pageSize.height;
175 float distanceFactor = sqrt( position.x * position.x + position.y * position.y );
177 if ( distanceFactor > 1.0f )
179 return Vector4(current.r, current.g, current.b, 0.0f);
186 * @param[in] current The current position
187 * @param[in] pagePositionProperty The page's position.
188 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
189 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
190 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
191 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
192 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
193 * @return The new position of this Actor.
195 Vector3 PositionConstraint(const Vector3& current,
196 const PropertyInput& pagePositionProperty,
197 const PropertyInput& scrollPositionProperty,
198 const PropertyInput& scrollPositionMin,
199 const PropertyInput& scrollPositionMax,
200 const PropertyInput& pageSizeProperty,
201 const PropertyInput& scrollWrap)
203 const Vector3& pagePosition = pagePositionProperty.GetVector3();
204 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
206 // Get position of page.
207 Vector3 position = pagePosition + scrollPosition;
209 // short circuit: if we're looking straight on at the page.
210 if( IsStraightOnView( position ) )
212 return current + scrollPosition;
215 const Vector3& pageSize = pageSizeProperty.GetVector3();
217 if( scrollWrap.GetBoolean() )
219 WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() );
222 // short circuit: for pages outside of view.
223 if( IsOutsideView( position, pageSize ) )
225 // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this)
226 // they will be invisible so doesn't have to be precise, just away from stage.
227 return current + scrollPosition;
230 // Our target when scrolling is moving from the origin to the following points around a curve:
231 // Right To Left: (-pageWidth, 0, pageWidth)
232 // Left To Right: ( pageWidth, 0, pageWidth)
233 // Down To Up: ( 0, -pageHeight, pageWidth)
234 // Up To Down: ( 0, pageHeight, pageWidth)
236 Vector2 angle( position / pageSize * Dali::Math::PI_2 );
237 Vector2 radius( pageSize * 0.5 );
239 position.x = radius.x * sin( angle.x );
240 position.y = radius.y * sin( angle.y );
241 position.z = ( radius.x - ( radius.x * cos( angle.x ) ) ) + ( radius.y - ( radius.y * cos( angle.y ) ) );
246 Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
250 * Helper: Applies the 3D scroll cube constraints to the child actor
252 * @param[in] scrollView The ScrollView containing the pages.
253 * @param[in] child The child to be affected with the 3D Effect.
254 * @param[in] info The effect info for the constraints
256 void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView,
258 ScrollPageCubeEffectInfo& info)
260 // Apply constraints to this actor //
261 Constraint constraint;
262 constraint = Constraint::New<Quaternion>( Actor::Property::ROTATION,
263 LocalSource(Actor::Property::POSITION),
264 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
265 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
266 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
267 Source(scrollView, Actor::Property::SIZE ),
268 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
269 boost::bind( &ScrollPageCubeEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
271 constraint.SetRemoveAction( Constraint::Discard );
272 child.ApplyConstraint( constraint );
274 constraint = Constraint::New<Vector4>( Actor::Property::COLOR,
275 LocalSource(Actor::Property::POSITION),
276 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
277 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
278 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
279 Source(scrollView, Actor::Property::SIZE ),
280 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
281 boost::bind( &ScrollPageCubeEffectInfo::ColorConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
283 constraint.SetRemoveAction( Constraint::Discard );
284 child.ApplyConstraint( constraint );
286 constraint = Constraint::New<Vector3>( Actor::Property::POSITION,
287 LocalSource(Actor::Property::POSITION),
288 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
289 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
290 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
291 Source(scrollView, Actor::Property::SIZE ),
292 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
293 boost::bind( &ScrollPageCubeEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
295 constraint.SetRemoveAction( Constraint::Discard );
296 child.ApplyConstraint( constraint );
299 } // unnamed namespace
301 ScrollViewPageCubeEffect::ScrollViewPageCubeEffect()
306 ScrollViewPageCubeEffect::~ScrollViewPageCubeEffect()
310 void ScrollViewPageCubeEffect::ApplyToPage( Actor page, const Vector2& angleSwing )
312 ScrollPageCubeEffectInfo info( angleSwing );
314 ApplyScrollCubeConstraints( GetScrollView(), page, info );
317 void ScrollViewPageCubeEffect::OnAttach(Toolkit::ScrollView& scrollView)
321 void ScrollViewPageCubeEffect::OnDetach(Toolkit::ScrollView& scrollView)
325 } // namespace Internal
327 } // namespace Toolkit