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/public-api/animation/constraint.h>
20 #include <dali/public-api/object/property-input.h>
23 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
24 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-cube-effect-impl.h>
28 namespace // unnamed namespace
32 * ScrollCubeEffectInfo
34 * Rotate constraint: adjusts the angle of the Actors
35 * based on their parent page's position relative to the middle of the screen.
36 * When at middle of screen Angles on X and Y Axes is 0.
37 * When one screen away from the middle Angle is 90 degrees (pi/2)
39 * Color constraint: adjusts the alpha of the Actors
40 * based on their parent page's position relative to the middle of the screen.
41 * When at middle of screen Alpha is 100% opacity.
42 * When one screen away from middle Alpha is at 0% opacity (invisble).
44 * Position constraint: adjusts the position of the Actors
45 * based on their parent page's position relative to the middle of the screen.
46 * When at middle of the screen the position is not altered.
47 * When one screen away from middle the position is rotated about it's origin + mAnchor
49 class ScrollCubeEffectInfo
53 ScrollCubeEffectInfo(const Vector3& anchor,
54 const Vector2& angleSwing,
55 const Vector2& positionSwing)
57 mAngleSwing(angleSwing),
58 mPositionSwing(positionSwing)
63 * @param[in,out] current The current orientation of this Actor
64 * @param[in] inputs Contains:
65 * The page's position.
66 * The scroll-view's position property (SCROLL_POSITION)
67 * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN)
68 * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN)
69 * The size of the page. (scrollView SIZE)
70 * Whether scroll wrap has been enabled or not (SCROLL_WRAP)
71 * @return The new orientation of this Actor.
73 void RotationConstraint( Quaternion& current, const PropertyInputContainer& inputs )
75 const Vector3& pagePosition = inputs[0]->GetVector3();
76 const Vector3& scrollPosition = Vector3(inputs[1]->GetVector2());
78 // Get position of page.
79 Vector3 position = pagePosition + scrollPosition;
81 // short circuit: for orthognal view.
82 if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
87 const Vector3& pageSize = inputs[4]->GetVector3();
88 bool wrap = inputs[5]->GetBoolean();
92 const Vector2& min = inputs[2]->GetVector2();
93 const Vector2& max = inputs[3]->GetVector2();
95 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
97 // WRAP X (based on the position of the right side)
98 position.x = WrapInDomain(position.x + pageSize.x, min.x, max.x) - pageSize.x;
101 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
103 // WRAP Y (based on the position of the bottom side)
104 position.y = WrapInDomain(position.y + pageSize.y, min.y, max.y) - pageSize.y;
108 // short circuit: for pages outside of view.
109 if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
114 position.x /= pageSize.x;
115 position.y /= pageSize.y;
117 Vector2 angle( Clamp(position.x, -1.0f,1.0f),
118 Clamp(position.y, -1.0f,1.0f) );
120 current = Quaternion( Radian( angle.x * mAngleSwing.x ), Vector3::YAXIS ) *
121 Quaternion( Radian( -angle.y * mAngleSwing.y ), Vector3::XAXIS ) *
126 * @param[in,out] current The current color of this Actor
127 * @param[in] inputs Contains:
128 * The page's position.
129 * The scroll-view's position property (SCROLL_POSITION)
130 * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN)
131 * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN)
132 * The size of the page. (scrollView SIZE)
133 * Whether scroll wrap has been enabled or not (SCROLL_WRAP)
134 * @return The new color of this Actor.
136 void ColorConstraint( Vector4& current, const PropertyInputContainer& inputs )
138 const Vector3& pagePosition = inputs[0]->GetVector3();
139 const Vector3& scrollPosition = Vector3(inputs[1]->GetVector2());
141 // Get position of page.
142 Vector3 position = pagePosition + scrollPosition;
144 // short circuit: for orthognal view.
145 if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) )
150 const Vector3& pageSize = inputs[4]->GetVector3();
151 bool wrap = inputs[5]->GetBoolean();
155 const Vector2& min = inputs[2]->GetVector2();
156 const Vector2& max = inputs[3]->GetVector2();
158 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
160 // WRAP X (based on the position of the right side)
161 position.x = WrapInDomain(position.x + pageSize.x, min.x, max.x) - pageSize.x;
164 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
166 // WRAP Y (based on the position of the bottom side)
167 position.y = WrapInDomain(position.y + pageSize.y, min.y, max.y) - pageSize.y;
171 // short circuit: for pages outside of view.
172 if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) )
174 // note preserve color channels incase there is a shader/further constraint
175 // that wishes to do something with that information.
180 position.x /= pageSize.x;
181 position.y /= pageSize.y;
183 Vector2 angle( Clamp(position.x, -1.0f,1.0f),
184 Clamp(position.y, -1.0f,1.0f) );
186 float f = (1.0f - fabsf(angle.x)) * (1.0f - fabsf(angle.y));
193 * @param[in,out] current The current position
194 * @param[in] inputs Contains:
195 * The page's position.
196 * The scroll-view's position property (SCROLL_POSITION)
197 * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN)
198 * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN)
199 * The size of the page. (scrollView SIZE)
200 * Whether scroll wrap has been enabled or not (SCROLL_WRAP)
201 * @return The new position of this Actor.
203 void PositionConstraint( Vector3& current, const PropertyInputContainer& inputs )
205 const Vector3& pagePosition = inputs[0]->GetVector3();
206 const Vector3& scrollPosition = Vector3(inputs[1]->GetVector2());
208 // Get position of page.
209 Vector3 relativePosition = pagePosition + scrollPosition;
211 // short circuit: for orthognal view.
212 if( (fabsf(relativePosition.x) < Math::MACHINE_EPSILON_1) && (fabsf(relativePosition.y) < Math::MACHINE_EPSILON_1) )
214 current.x += scrollPosition.x;
215 current.y += scrollPosition.y;
219 const Vector3& pageSize = inputs[4]->GetVector3();
220 bool wrap = inputs[5]->GetBoolean();
224 const Vector2& min = inputs[2]->GetVector2();
225 const Vector2& max = inputs[3]->GetVector2();
227 if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
229 // WRAP X (based on the position of the right side)
230 relativePosition.x = WrapInDomain(relativePosition.x + pageSize.x, min.x, max.x) - pageSize.x;
233 if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
235 // WRAP Y (based on the position of the bottom side)
236 relativePosition.y = WrapInDomain(relativePosition.y + pageSize.y, min.y, max.y) - pageSize.y;
240 // short circuit: for pages outside of view.
241 if( (fabsf(relativePosition.x) >= pageSize.x) || (fabsf(relativePosition.y) >= pageSize.y) )
243 // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this)
244 // they will be invisible so doesn't have to be precise, just away from stage.
245 current += scrollPosition;
249 relativePosition.x /= pageSize.x;
250 relativePosition.y /= pageSize.y;
252 Vector3 angle( Clamp(relativePosition.x, -1.0f,1.0f) * mAngleSwing.x,
253 Clamp(relativePosition.y, -1.0f,1.0f) * mAngleSwing.y,
256 // Rotate position (current) about point.
257 Vector3 position = current - mAnchor;
258 Quaternion rotatorY( Radian( angle.x ), Vector3::YAXIS);
259 position = rotatorY.Rotate(position);
260 Quaternion rotatorX( Radian( -angle.y ), Vector3::XAXIS);
261 position = rotatorX.Rotate(position);
263 position += relativePosition * mPositionSwing;
265 current = position - pagePosition;
268 Vector3 mAnchor; ///< Anchor point where Actor should rotate about.
269 Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
270 Vector3 mPositionSwing; ///< Maximum amount in X and Y axes to alter position.
274 * Helper: Applies the 3D scroll cube constraints to the child actor
276 * @param[in] scrollView The ScrollView containing the pages.
277 * @param[in] child The child to be affected with the 3D Effect.
278 * @param[in] info The effect info for the constraints
280 void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView,
283 const ScrollCubeEffectInfo& info)
285 // Apply constraints to this actor //
286 Constraint constraint;
287 constraint = Constraint::New<Quaternion>( child, Actor::Property::ORIENTATION, info, &ScrollCubeEffectInfo::RotationConstraint );
288 constraint.AddSource( Source(parentPage, Actor::Property::POSITION) );
289 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) );
290 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) );
291 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) );
292 constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) );
293 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) );
294 constraint.SetRemoveAction( Constraint::Discard );
297 constraint = Constraint::New<Vector4>( child, Actor::Property::COLOR, info, &ScrollCubeEffectInfo::ColorConstraint );
298 constraint.AddSource( Source(parentPage, Actor::Property::POSITION) );
299 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) );
300 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) );
301 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) );
302 constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) );
303 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) );
304 constraint.SetRemoveAction( Constraint::Discard );
307 constraint = Constraint::New<Vector3>( child, Actor::Property::POSITION, info, &ScrollCubeEffectInfo::PositionConstraint );
308 constraint.AddSource( Source(parentPage, Actor::Property::POSITION) );
309 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) );
310 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) );
311 constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) );
312 constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) );
313 constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) );
314 constraint.SetRemoveAction( Constraint::Discard );
318 } // unnamed namespace
329 ScrollViewCubeEffect::ScrollViewCubeEffect()
334 ScrollViewCubeEffect::~ScrollViewCubeEffect()
338 void ScrollViewCubeEffect::ApplyToActor(Actor child,
339 const Vector3& anchor,
340 const Vector2& angleSwing,
341 const Vector2& positionSwing)
343 ScrollCubeEffectInfo info( anchor, angleSwing, positionSwing );
345 ApplyScrollCubeConstraints( GetScrollView(), child, child.GetParent(), info );
348 void ScrollViewCubeEffect::ApplyToActor(Actor child,
350 const Vector3& anchor,
351 const Vector2& angleSwing,
352 const Vector2& positionSwing)
354 ScrollCubeEffectInfo info( anchor, angleSwing, positionSwing );
356 ApplyScrollCubeConstraints( GetScrollView(), child, parentPage, info );
359 void ScrollViewCubeEffect::OnAttach(Toolkit::ScrollView& scrollView)
363 void ScrollViewCubeEffect::OnDetach(Toolkit::ScrollView& scrollView)
367 } // namespace Internal
369 } // namespace Toolkit