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 <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-cube-effect-impl.h>
21 #include <boost/bind.hpp>
24 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-helper-functions.h>
35 namespace // unnamed namespace
38 using namespace ScrollViewHelperFunctions;
41 * ScrollPageCubeEffectInfo
43 * Rotate constraint: adjusts the angle of the page based on its position relative to the middle of
45 * When at middle of screen Angles on X and Y Axes is 0.
46 * When one screen away from the middle Angle is 90 degrees (pi/2)
48 * Color constraint: adjusts the alpha of the page based on their parent page's position relative
49 * to the middle of the screen.
50 * When at middle of screen Alpha is 100% opacity.
51 * When outside the viewable area, the opacity is 0%.
53 * Position constraint: adjusts the position of the page based on their parent page's position
54 * relative to the middle of the screen.
55 * When at middle of the screen the position is not altered.
56 * When one screen away from middle the position is rotated as per expected in a 3D inner cube.
58 class ScrollPageCubeEffectInfo : public Dali::RefObject
62 ScrollPageCubeEffectInfo( const Vector2& angleSwing )
63 : mAngleSwing(angleSwing)
68 * @param[in] current The current orientation of this Actor
69 * @param[in] pagePositionProperty The page's position.
70 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
71 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
72 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
73 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
74 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
75 * @return The new orientation of this Actor.
77 Quaternion RotationConstraint(const Quaternion& current,
78 const PropertyInput& pagePositionProperty,
79 const PropertyInput& scrollPositionProperty,
80 const PropertyInput& scrollPositionMin,
81 const PropertyInput& scrollPositionMax,
82 const PropertyInput& pageSizeProperty,
83 const PropertyInput& scrollWrap)
85 const Vector3& pagePosition = pagePositionProperty.GetVector3();
86 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
88 // Get position of page.
89 Vector3 position = pagePosition + scrollPosition;
91 // short circuit: if we're looking straight on at the page.
92 if( IsStraightOnView( position ) )
97 const Vector3& pageSize = pageSizeProperty.GetVector3();
99 if( scrollWrap.GetBoolean() )
101 WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() );
104 // short circuit: for pages outside of view.
105 if( IsOutsideView( position, pageSize ) )
110 // Our target is a 90 degree (PI/2) rotation per page, so calculate the angle we should be rotate
111 // our page by calculating the amount we've moved as a fraction of the total size of the page.
112 Vector2 angle( position / pageSize * Dali::Math::PI_2 );
114 Quaternion rotation = Quaternion( -angle.x * mAngleSwing.x, Vector3::YAXIS ) *
115 Quaternion( angle.y * mAngleSwing.y, Vector3::XAXIS ) *
122 * @param[in] current The current color of this Actor
123 * @param[in] pagePositionProperty The page's position.
124 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
125 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
126 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
127 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
128 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
129 * @return The new color of this Actor.
131 Vector4 ColorConstraint(const Vector4& current,
132 const PropertyInput& pagePositionProperty,
133 const PropertyInput& scrollPositionProperty,
134 const PropertyInput& scrollPositionMin,
135 const PropertyInput& scrollPositionMax,
136 const PropertyInput& pageSizeProperty,
137 const PropertyInput& scrollWrap)
139 const Vector3& pagePosition = pagePositionProperty.GetVector3();
140 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
142 // Get position of page.
143 Vector3 position = pagePosition + scrollPosition;
145 // short circuit: if we're looking straight on at the page.
146 if( IsStraightOnView( position ) )
151 const Vector3& pageSize = pageSizeProperty.GetVector3();
153 if( scrollWrap.GetBoolean() )
155 WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() );
158 // short circuit: for pages outside of view.
159 if( IsOutsideView( position, pageSize ) )
161 // note preserve color channels incase there is a shader/further constraint
162 // that wishes to do something with that information.
163 return Vector4(current.r, current.g, current.b, 0.0f);
166 // Calculate the distance of this page from our view and ensure it falls within the appropriate
168 // If it does not, then the opacity is set to 0.0f.
169 position.x /= pageSize.width;
170 position.y /= pageSize.height;
171 float distanceFactor = sqrt( position.x * position.x + position.y * position.y );
173 if ( distanceFactor > 1.0f )
175 return Vector4(current.r, current.g, current.b, 0.0f);
182 * @param[in] current The current position
183 * @param[in] pagePositionProperty The page's position.
184 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
185 * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
186 * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME)
187 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
188 * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME)
189 * @return The new position of this Actor.
191 Vector3 PositionConstraint(const Vector3& current,
192 const PropertyInput& pagePositionProperty,
193 const PropertyInput& scrollPositionProperty,
194 const PropertyInput& scrollPositionMin,
195 const PropertyInput& scrollPositionMax,
196 const PropertyInput& pageSizeProperty,
197 const PropertyInput& scrollWrap)
199 const Vector3& pagePosition = pagePositionProperty.GetVector3();
200 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
202 // Get position of page.
203 Vector3 position = pagePosition + scrollPosition;
205 // short circuit: if we're looking straight on at the page.
206 if( IsStraightOnView( position ) )
208 return current + scrollPosition;
211 const Vector3& pageSize = pageSizeProperty.GetVector3();
213 if( scrollWrap.GetBoolean() )
215 WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() );
218 // short circuit: for pages outside of view.
219 if( IsOutsideView( position, pageSize ) )
221 // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this)
222 // they will be invisible so doesn't have to be precise, just away from stage.
223 return current + scrollPosition;
226 // Our target when scrolling is moving from the origin to the following points around a curve:
227 // Right To Left: (-pageWidth, 0, pageWidth)
228 // Left To Right: ( pageWidth, 0, pageWidth)
229 // Down To Up: ( 0, -pageHeight, pageWidth)
230 // Up To Down: ( 0, pageHeight, pageWidth)
232 Vector2 angle( position / pageSize * Dali::Math::PI_2 );
233 Vector2 radius( pageSize * 0.5 );
235 position.x = radius.x * sin( angle.x );
236 position.y = radius.y * sin( angle.y );
237 position.z = ( radius.x - ( radius.x * cos( angle.x ) ) ) + ( radius.y - ( radius.y * cos( angle.y ) ) );
242 Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
245 typedef IntrusivePtr<ScrollPageCubeEffectInfo> ScrollPageCubeEffectInfoPtr;
248 * Helper: Applies the 3D scroll cube constraints to the child actor
250 * @param[in] scrollView The ScrollView containing the pages.
251 * @param[in] child The child to be affected with the 3D Effect.
252 * @param[in] info The effect info for the constraints
254 void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView,
256 ScrollPageCubeEffectInfoPtr info)
258 // Apply constraints to this actor //
259 Constraint constraint;
260 constraint = Constraint::New<Quaternion>( Actor::ROTATION,
261 LocalSource(Actor::POSITION),
262 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
263 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
264 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
265 Source(scrollView, Actor::SIZE ),
266 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
267 boost::bind( &ScrollPageCubeEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
269 constraint.SetRemoveAction( Constraint::Discard );
270 child.ApplyConstraint( constraint );
272 constraint = Constraint::New<Vector4>( Actor::COLOR,
273 LocalSource(Actor::POSITION),
274 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
275 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
276 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
277 Source(scrollView, Actor::SIZE ),
278 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
279 boost::bind( &ScrollPageCubeEffectInfo::ColorConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
281 constraint.SetRemoveAction( Constraint::Discard );
282 child.ApplyConstraint( constraint );
284 constraint = Constraint::New<Vector3>( Actor::POSITION,
285 LocalSource(Actor::POSITION),
286 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ),
287 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
288 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
289 Source(scrollView, Actor::SIZE ),
290 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
291 boost::bind( &ScrollPageCubeEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6, _7) );
293 constraint.SetRemoveAction( Constraint::Discard );
294 child.ApplyConstraint( constraint );
297 } // unnamed namespace
299 ScrollViewPageCubeEffect::ScrollViewPageCubeEffect()
304 ScrollViewPageCubeEffect::~ScrollViewPageCubeEffect()
308 void ScrollViewPageCubeEffect::ApplyToPage( Actor page, const Vector2& angleSwing )
310 ScrollPageCubeEffectInfoPtr info(new ScrollPageCubeEffectInfo( angleSwing ));
312 ApplyScrollCubeConstraints( GetScrollView(), page, info );
315 void ScrollViewPageCubeEffect::OnAttach(Toolkit::ScrollView& scrollView)
319 void ScrollViewPageCubeEffect::OnDetach(Toolkit::ScrollView& scrollView)
323 } // namespace Internal
325 } // namespace Toolkit