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 <dali/public-api/animation/constraint.h>
23 #include <dali/public-api/object/property-input.h>
26 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-helper-functions.h>
37 namespace // unnamed namespace
40 using namespace ScrollViewHelperFunctions;
43 * ScrollPageCubeEffectInfo
45 * Rotate constraint: adjusts the angle of the page based on its position relative to the middle of
47 * When at middle of screen Angles on X and Y Axes is 0.
48 * When one screen away from the middle Angle is 90 degrees (pi/2)
50 * Color constraint: adjusts the alpha of the page based on their parent page's position relative
51 * to the middle of the screen.
52 * When at middle of screen Alpha is 100% opacity.
53 * When outside the viewable area, the opacity is 0%.
55 * Position constraint: adjusts the position of the page based on their parent page's position
56 * relative to the middle of the screen.
57 * When at middle of the screen the position is not altered.
58 * When one screen away from middle the position is rotated as per expected in a 3D inner cube.
60 class ScrollPageCubeEffectInfo
64 ScrollPageCubeEffectInfo( const Vector2& angleSwing )
65 : mAngleSwing(angleSwing)
70 * @param[in,out] current The current orientation of this Actor
71 * @param[in] inputs Contains:
72 * The page's position.
73 * The scroll-view's position property (SCROLL_POSITION)
74 * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN)
75 * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN)
76 * The size of the page. (scrollView SIZE)
77 * Whether scroll wrap has been enabled or not (SCROLL_WRAP)
78 * @return The new orientation of this Actor.
80 void RotationConstraint( Quaternion& current, const PropertyInputContainer& inputs )
82 const Vector3& pagePosition = inputs[0]->GetVector3();
83 const Vector3& scrollPosition = inputs[1]->GetVector3();
85 // Get position of page.
86 Vector3 position = pagePosition + scrollPosition;
88 // short circuit: if we're looking straight on at the page.
89 if( IsStraightOnView( position ) )
94 const Vector3& pageSize = inputs[4]->GetVector3();
96 if( inputs[5]->GetBoolean() )
98 WrapPositionWithinDomain( position, pageSize, inputs[2]->GetVector3(), inputs[3]->GetVector3() );
101 // short circuit: for pages outside of view.
102 if( IsOutsideView( position, pageSize ) )
107 // Our target is a 90 degree (PI/2) rotation per page, so calculate the angle we should be rotate
108 // our page by calculating the amount we've moved as a fraction of the total size of the page.
109 Vector2 angle( position / pageSize * Dali::Math::PI_2 );
111 current = Quaternion( -angle.x * mAngleSwing.x, Vector3::YAXIS ) *
112 Quaternion( angle.y * mAngleSwing.y, Vector3::XAXIS ) *
117 * @param[in,out] current The current color of this Actor
118 * @param[in] inputs Contains:
119 * The page's position.
120 * The scroll-view's position property (SCROLL_POSITION)
121 * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN)
122 * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN)
123 * The size of the page. (scrollView SIZE)
124 * Whether scroll wrap has been enabled or not (SCROLL_WRAP)
125 * @return The new color of this Actor.
127 void ColorConstraint( Vector4& current, const PropertyInputContainer& inputs )
129 const Vector3& pagePosition = inputs[0]->GetVector3();
130 const Vector3& scrollPosition = inputs[1]->GetVector3();
132 // Get position of page.
133 Vector3 position = pagePosition + scrollPosition;
135 // short circuit: if we're looking straight on at the page.
136 if( IsStraightOnView( position ) )
141 const Vector3& pageSize = inputs[4]->GetVector3();
143 if( inputs[5]->GetBoolean() )
145 WrapPositionWithinDomain( position, pageSize, inputs[2]->GetVector3(), inputs[3]->GetVector3() );
148 // short circuit: for pages outside of view.
149 if( IsOutsideView( position, pageSize ) )
151 // note preserve color channels incase there is a shader/further constraint
152 // that wishes to do something with that information.
157 // Calculate the distance of this page from our view and ensure it falls within the appropriate
159 // If it does not, then the opacity is set to 0.0f.
160 position.x /= pageSize.width;
161 position.y /= pageSize.height;
162 float distanceFactor = sqrt( position.x * position.x + position.y * position.y );
164 if ( distanceFactor > 1.0f )
171 * @param[in,out] current The current position
172 * @param[in] inputs Contains:
173 * The page's position.
174 * The scroll-view's position property (SCROLL_POSITION)
175 * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN)
176 * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN)
177 * The size of the page. (scrollView SIZE)
178 * Whether scroll wrap has been enabled or not (SCROLL_WRAP)
179 * @return The new position of this Actor.
181 void PositionConstraint( Vector3& current, const PropertyInputContainer& inputs )
183 const Vector3& pagePosition = inputs[0]->GetVector3();
184 const Vector3& scrollPosition = inputs[1]->GetVector3();
186 // Get position of page.
187 Vector3 position = pagePosition + scrollPosition;
189 // short circuit: if we're looking straight on at the page.
190 if( IsStraightOnView( position ) )
192 current += scrollPosition;
196 const Vector3& pageSize = inputs[4]->GetVector3();
198 if( inputs[5]->GetBoolean() )
200 WrapPositionWithinDomain( position, pageSize, inputs[2]->GetVector3(), inputs[3]->GetVector3() );
203 // short circuit: for pages outside of view.
204 if( IsOutsideView( position, pageSize ) )
206 // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this)
207 // they will be invisible so doesn't have to be precise, just away from stage.
208 current += scrollPosition;
212 // Our target when scrolling is moving from the origin to the following points around a curve:
213 // Right To Left: (-pageWidth, 0, pageWidth)
214 // Left To Right: ( pageWidth, 0, pageWidth)
215 // Down To Up: ( 0, -pageHeight, pageWidth)
216 // Up To Down: ( 0, pageHeight, pageWidth)
218 Vector2 angle( position / pageSize * Dali::Math::PI_2 );
219 Vector2 radius( pageSize * 0.5 );
221 current.x = radius.x * sin( angle.x );
222 current.y = radius.y * sin( angle.y );
223 current.z = ( radius.x - ( radius.x * cos( angle.x ) ) ) + ( radius.y - ( radius.y * cos( angle.y ) ) );
226 Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
230 * Helper: Applies the 3D scroll cube constraints to the child actor
232 * @param[in] scrollView The ScrollView containing the pages.
233 * @param[in] child The child to be affected with the 3D Effect.
234 * @param[in] info The effect info for the constraints
236 void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView,
238 ScrollPageCubeEffectInfo& info)
240 // Apply constraints to this actor //
241 Constraint constraint;
242 constraint = Constraint::New<Quaternion>( child, Actor::Property::ORIENTATION, info, &ScrollPageCubeEffectInfo::RotationConstraint );
243 constraint.AddSource( LocalSource(Actor::Property::POSITION) );
244 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) );
245 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) );
246 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) );
247 constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) );
248 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) );
249 constraint.SetRemoveAction( Constraint::Discard );
252 constraint = Constraint::New<Vector4>( child, Actor::Property::COLOR, info, &ScrollPageCubeEffectInfo::ColorConstraint );
253 constraint.AddSource( LocalSource(Actor::Property::POSITION) );
254 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) );
255 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) );
256 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) );
257 constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) );
258 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) );
259 constraint.SetRemoveAction( Constraint::Discard );
262 constraint = Constraint::New<Vector3>( child, Actor::Property::POSITION, info, &ScrollPageCubeEffectInfo::PositionConstraint );
263 constraint.AddSource( LocalSource(Actor::Property::POSITION) );
264 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) );
265 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) );
266 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) );
267 constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) );
268 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) );
269 constraint.SetRemoveAction( Constraint::Discard );
273 } // unnamed namespace
275 ScrollViewPageCubeEffect::ScrollViewPageCubeEffect()
280 ScrollViewPageCubeEffect::~ScrollViewPageCubeEffect()
284 void ScrollViewPageCubeEffect::ApplyToPage( Actor page, const Vector2& angleSwing )
286 ScrollPageCubeEffectInfo info( angleSwing );
288 ApplyScrollCubeConstraints( GetScrollView(), page, info );
291 void ScrollViewPageCubeEffect::OnAttach(Toolkit::ScrollView& scrollView)
295 void ScrollViewPageCubeEffect::OnDetach(Toolkit::ScrollView& scrollView)
299 } // namespace Internal
301 } // namespace Toolkit