3 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://floralicense.org/license/
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
18 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
19 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-twist-effect-impl.h>
23 namespace // unnamed namespace
26 const char * const EFFECT_TIME( "ScrollViewTwistEffect::EFFECT_TIME" );
27 const char * const EFFECT_REFERENCE( "ScrollViewTwistEffect::EFFECT_REFERENCE" );
28 const char * const EFFECT_DEPTH( "ScrollViewTwistEffect::EFFECT_DEPTH");
29 const char * const EFFECT_ACTIVATE( "ScrollViewTwistEffect::EFFECT_ACTIVATE");
31 const float TWISTEFFECT_ANIMATION_MAX_TIME = 60.0f; ///< Animation time (every time finishes, checks if it needs to go again)
32 const float TWISTEFFECT_DEFAULT_DROPOFF = 0.7f; ///< Default drop off amount
33 const float TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_X = 720.0f; ///< Default drop off distance
34 const float TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_Y = 1280.0f; ///< Default drop off distance
36 // Hop Easing equation.
37 // Starts with a -ve cosine ranging from 0 to pi.
39 // Then finishes with a -ve cosine ranging from pi to 0
40 // 0......(RISE).....PI (SUSTAIN) PI.....(FALL)......0
41 // xxxxxxxxxxxxxxxxxxxxx
50 const float HOP_RISE(0.25f);
51 const float HOP_FALL(0.5f);
52 const float DELAY(0.5f);
54 float HopEasing(float progress)
56 // progress from 0.0 - HOP_RISE (go from 0.0 to 1.0)
57 if(progress < HOP_RISE)
59 return 0.5f - cosf(progress/HOP_RISE * Math::PI) * 0.5f;
62 progress += HOP_FALL - 1.0f;
64 // progress from 0.0 - HOP_FALL (go from 1.0 to 0.0)
67 return 0.5f + cosf(progress/HOP_FALL * Math::PI) * 0.5f;
70 // progress at plateau.
75 * Gets a property index. If the property doesn't already exist, then
76 * it will create the property.
77 * @param[in] handle The handle that owns or will own the property
78 * @param[in] name The name for this property
79 * @param[in] propertyValue The initial value for this property
80 * @return The property index for this property is returned.
82 Property::Index SafeRegisterProperty( Handle& handle, const std::string& name, Property::Value propertyValue )
84 Property::Index index = handle.GetPropertyIndex( name );
86 if(index == Property::INVALID_INDEX)
88 index = handle.RegisterProperty( name, propertyValue );
95 * Re-scales input value x from x0 - x1, to linearly map
96 * over the values y0 - y1. Values outside of this range
97 * will also conform to the trend (gradient) set.
98 * @param[in] x input X value
99 * @param[in] x0 input minimum bound
100 * @param[in] x1 input maximum bound
101 * @param[in] y0 output minimum bound
102 * @param[in] y1 output maximum bound
103 * @return The result of the mapping is returned.
105 float Rescale(float x, float x0, float x1, float y0, float y1)
107 return y0 + (y1 - y0) * (x - x0) / (x1-x0);
111 * Returns the value of x chasing target.
112 * returns a value of x which is closer to target.
113 * but limited by maxDelta. #
118 * result is 30.0f (x is 20.0f units closer to target)
119 * However, if x is already within maxDelta units
120 * of target, x will equal target.
125 * result is 50.0f (x was already within 20.0f units of target)
127 float Chase( float x, float target, float maxDelta )
129 float delta = target - x;
133 x = std::min( x + maxDelta, target );
137 x = std::max( x - maxDelta, target );
143 // constraints ////////////////////////////////////////////////////////////////
146 * ScrollTwistRotationConstraint
148 * Rotate constraint adjusts the angle of the Actors
149 * based on actor's world-position relative to the middle of the screen.
150 * When at middle of screen Angles on X and Y Axes is 0.
151 * When one screen away from the middle Angle is 90 degrees (pi/2)
153 struct ScrollDropoffTwistRotationConstraint
156 * Constraint constructor
157 * @param[in] angleSwing The amount the Actor should revolve in radians
158 * for a given page worth of distance.
160 ScrollDropoffTwistRotationConstraint(const Vector2& angleSwing, const Vector2& dropOff, const Vector2& distance, AlphaFunction function)
161 : mAngleSwing(angleSwing),
163 mDropOffDistance(distance),
164 mDropOffFunction(function)
169 * @param[in] current The current orientation of this Actor
170 * @param[in] actorPositionProperty The actor's world-position property
171 * @param[in] scrollOvershootXProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_X_PROPERTY_NAME)
172 * @param[in] scrollOvershootYProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_Y_PROPERTY_NAME)
173 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
174 * @return The new orientation of this Actor.
176 Quaternion operator()(const Quaternion& current,
177 const PropertyInput& actorPositionProperty,
178 const PropertyInput& scrollablePositionProperty,
179 const PropertyInput& scrollOvershootXProperty,
180 const PropertyInput& scrollOvershootYProperty,
181 const PropertyInput& pageSizeProperty,
182 const PropertyInput& activateProperty)
184 const Vector3& position = actorPositionProperty.GetVector3();
185 const Vector3& parentPosition = scrollablePositionProperty.GetVector3();
186 const Vector3& pageSize = pageSizeProperty.GetVector3();
187 const Vector2 overshoot(scrollOvershootXProperty.GetFloat(), scrollOvershootYProperty.GetFloat());
189 if(fabsf(overshoot.x) < Math::MACHINE_EPSILON_0 && fabsf(overshoot.y) < Math::MACHINE_EPSILON_0)
194 const float& activate = activateProperty.GetFloat();
196 if(activate < Math::MACHINE_EPSILON_0)
201 // get distance from centre of scrollable container
202 Vector2 distance = position.GetVectorXY() - parentPosition.GetVectorXY();
204 if( overshoot.x > 0.0f )
206 distance.x += pageSize.x * 0.5f;
210 distance.x -= pageSize.x * 0.5f;
212 distance.x = Clamp(fabsf(distance.x), 0.0f, mDropOffDistance.x);
214 if( overshoot.y > 0.0f )
216 distance.y += pageSize.y * 0.5f;
220 distance.y -= pageSize.y * 0.5f;
222 distance.y = Clamp(fabsf(distance.y), 0.0f, mDropOffDistance.y);
224 Vector2 angleMod = distance / mDropOffDistance;
227 angleMod.x = mDropOffFunction(angleMod.x);
228 angleMod.y = mDropOffFunction(angleMod.y);
230 angleMod = Vector2::ONE - (angleMod * mDropOff);
232 Vector2 angle = angleMod * mAngleSwing * overshoot;
234 Quaternion rotation = Quaternion(angle.x, Vector3::YAXIS) *
235 Quaternion(-angle.y, Vector3::XAXIS) *
241 const Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
242 const Vector2 mDropOff;
243 const Vector2 mDropOffDistance;
244 AlphaFunction mDropOffFunction;
248 * ScrollTwistRotationConstraint
250 * Rotate constraint adjusts the angle of the Actors
251 * based on actor's world-position relative to the middle of the screen.
252 * When at middle of screen Angles on X and Y Axes is 0.
253 * When one screen away from the middle Angle is 90 degrees (pi/2)
255 struct ScrollTwistRotationConstraint
258 * Constraint constructor
259 * @param[in] angleSwing The amount the Actor should revolve in radians
260 * for a given page worth of distance.
262 ScrollTwistRotationConstraint(const Vector2& angleSwing)
263 : mAngleSwing(angleSwing)
268 * @param[in] current The current orientation of this Actor
269 * @param[in] actorPositionProperty The actor's world-position property
270 * @param[in] scrollOvershootXProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_X_PROPERTY_NAME)
271 * @param[in] scrollOvershootYProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_Y_PROPERTY_NAME)
272 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
273 * @return The new orientation of this Actor.
275 Quaternion operator()(const Quaternion& current,
276 const PropertyInput& scrollOvershootXProperty,
277 const PropertyInput& scrollOvershootYProperty,
278 const PropertyInput& activateProperty)
280 const Vector2 overshoot(scrollOvershootXProperty.GetFloat(), scrollOvershootYProperty.GetFloat());
282 if(fabsf(overshoot.x) < Math::MACHINE_EPSILON_0 && fabsf(overshoot.y) < Math::MACHINE_EPSILON_0)
287 const float& activate = activateProperty.GetFloat();
289 if(activate < Math::MACHINE_EPSILON_0)
294 Quaternion rotation = Quaternion(overshoot.x * mAngleSwing.x, Vector3::YAXIS) *
295 Quaternion(-overshoot.y * mAngleSwing.y, Vector3::XAXIS) *
301 const Vector2 mAngleSwing;
305 * ScrollTwistPositionConstraint
307 * Position constraint adjusts the position of the Actors
308 * based on their parent page's position relative to the middle of the screen.
309 * When at middle of the screen the position is not altered.
310 * When one screen away from middle the position is rotated about it's origin + mAnchor
312 struct ScrollTwistPositionConstraint
315 * Constraint constructor
317 ScrollTwistPositionConstraint(float delayMin, float delayMax)
318 : mDelayMin(delayMin),
320 mCurrentDelayFactor(0.0f)
325 * @param[in] current The current position
326 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
327 * @param[in] effectReferenceProperty The point in the scroll-view where the user touched the screen
328 * @param[in] effectTimeProperty The current timer. Starting from 0.0 when scroll animation/dragging
329 * commences. Ensures that constraint is applied and processed every frame (to achieve the delay effect)
330 * @param[in] sizeProperty The size of the ScrollView.
331 * @return The new position of this Actor.
333 Vector3 operator()(const Vector3& current,
334 const PropertyInput& pagePositionProperty,
335 const PropertyInput& scrollPositionProperty,
336 const PropertyInput& effectReferenceProperty,
337 const PropertyInput& effectTimeProperty,
338 const PropertyInput& sizeProperty,
339 const PropertyInput& activateProperty)
341 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
342 const float& activate = activateProperty.GetFloat();
344 if(activate < Math::MACHINE_EPSILON_0)
346 mScrollPosition = scrollPosition;
347 return current + mScrollPosition;
349 const Vector3& pagePosition = pagePositionProperty.GetVector3();
350 const Vector3& referencePoint = effectReferenceProperty.GetVector3();
351 // Determine the relative position of the actor from the scrolling reference point.
352 // (the further away from the refernce, the longer the delay should be)
353 Vector3 relativePosition = pagePosition + current - referencePoint;
354 float f = relativePosition.x;
356 // f represents this absolute distance. Get as a relative distance and inverse exponential
357 // (as delay equation is has an exponential effect i.e. the closer delayFactor to 1.0f,
358 // the longer the delay would appear exponentially)
359 f = fabsf(f / sizeProperty.GetVector3().width);
360 f = std::min(f, 1.0f);
361 f = 1.0f - (1.0f - f) * (1.0f - f);
362 // at center delay factor is mDelayMin, at maximum (1.0) it is mDelayMax
363 f = Rescale(f, 0.0f, 1.0f, mDelayMin, mDelayMax);
365 // Will take 0.25s for current delay factor to equal target delay factor
366 // This prevents users quickly dragging from different points and noticing a jerk.
367 mCurrentDelayFactor = Chase( mCurrentDelayFactor, f, 4.0f/60.0f );
368 float delay = activate * mCurrentDelayFactor;
369 mScrollPosition = mScrollPosition * delay + scrollPosition * (1.0f-delay);
371 return current + mScrollPosition;
376 Vector3 mScrollPosition; ///< The current scroll position
379 float mCurrentDelayFactor;
384 * ScrollTwistScaleConstraint
386 * Scale constraint adjusts the scale of the Actors
387 * based on a supplied depth property value.
389 struct ScrollTwistScaleConstraint
392 * Constraint constructor
394 ScrollTwistScaleConstraint(float scaleAmount)
395 : mScaleAmount(scaleAmount)
400 * @param[in] current The current position
401 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
402 * @return The new position of this Actor.
404 Vector3 operator()(const Vector3& current,
405 const PropertyInput& depthProperty)
407 float depth = depthProperty.GetFloat();
409 return current * (1.0f - depth * mScaleAmount); // contract by mScaleAmount of original size.
417 } // unnamed namespace
428 ScrollViewTwistEffect::ScrollViewTwistEffect()
429 : mFlags(DefaultFlags),
430 mPropertyTime(Property::INVALID_INDEX),
432 mAdditionalEffects(false),
433 mPropertyReference(Property::INVALID_INDEX),
434 mPropertyActivate(Property::INVALID_INDEX),
435 mMinimumDistanceForShrink(Toolkit::ScrollViewTwistEffect::DEFAULT_MINIMUM_DISTANCE_FOR_SHRINK),
436 mMaxSwingAngle(Math::PI_2, Math::PI_2),
437 mDropOff(TWISTEFFECT_DEFAULT_DROPOFF, TWISTEFFECT_DEFAULT_DROPOFF),
438 mDropOffDistance(TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_X, TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_Y),
439 mDropOffFunction(NULL)
443 ScrollViewTwistEffect::~ScrollViewTwistEffect()
448 float ScrollViewTwistEffect::GetMinimumDistanceForShrink() const
450 return mMinimumDistanceForShrink;
453 void ScrollViewTwistEffect::SetMinimumDistanceForShrink(float distance)
455 mMinimumDistanceForShrink = distance;
458 void ScrollViewTwistEffect::EnableEffect(bool enableFlag)
460 mEnableEffect = enableFlag;
463 void ScrollViewTwistEffect::ApplyToActor(Actor child,
464 bool additionalEffects,
465 const Vector2& angleSwing,
470 mMaxSwingAngle = angleSwing;
471 mAdditionalEffects = additionalEffects;
472 mScaleFactor = scaleAmount;
473 mDelayMin = delayMin;
474 mDelayMax = delayMax;
475 if(mFlags & FlagDefaultDropOff)
477 Vector3 size = GetScrollView().GetCurrentSize();
478 // size may still be 0 if the effect is applied before scroll view hits the stage
479 if(size.x > Math::MACHINE_EPSILON_1)
481 mDropOffDistance.x = size.x;
483 if(size.y > Math::MACHINE_EPSILON_1)
485 mDropOffDistance.y = size.y;
488 if(scaleAmount > Math::MACHINE_EPSILON_0)
494 mFlags = mFlags & ~FlagScale;
496 if(mMaxSwingAngle.LengthSquared() > Math::MACHINE_EPSILON_0)
502 mFlags = mFlags & ~FlagTwist;
507 void ScrollViewTwistEffect::Apply(Actor child)
509 // Apply constraints to these actors //
510 Constraint constraint;
512 Toolkit::ScrollView scrollView = GetScrollView();
514 if( mFlags & FlagScale )
516 constraint = Constraint::New<Vector3>( Actor::SCALE,
517 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_DEPTH ) ),
518 ScrollTwistScaleConstraint(mScaleFactor) );
519 constraint.SetRemoveAction( Constraint::Discard );
520 child.ApplyConstraint( constraint );
523 constraint = Constraint::New<Vector3>( Actor::POSITION,
524 ParentSource(Actor::POSITION),
525 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
526 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_REFERENCE ) ),
527 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_TIME ) ),
528 Source(scrollView, Actor::SIZE),
529 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_ACTIVATE) ),
530 ScrollTwistPositionConstraint(mDelayMin, mDelayMax) );
531 constraint.SetRemoveAction( Constraint::Discard );
532 child.ApplyConstraint( constraint );
534 // use actor position to affect rotation
535 if(mFlags & FlagTwist)
537 if(mFlags & FlagDropOff)
539 constraint = Constraint::New<Quaternion>( Actor::ROTATION,
540 LocalSource(Actor::WORLD_POSITION),
541 Source(scrollView, Actor::WORLD_POSITION ),
542 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME ) ),
543 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME ) ),
544 Source(scrollView, Actor::SIZE ),
545 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_ACTIVATE) ),
546 ScrollDropoffTwistRotationConstraint(mMaxSwingAngle, mDropOff, mDropOffDistance, mDropOffFunction) );
550 constraint = Constraint::New<Quaternion>( Actor::ROTATION,
551 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME ) ),
552 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME ) ),
553 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_ACTIVATE) ),
554 ScrollTwistRotationConstraint(mMaxSwingAngle) );
556 constraint.SetRemoveAction( Constraint::Discard );
557 child.ApplyConstraint( constraint );
561 void ScrollViewTwistEffect::SetSwingDropOff(const Vector2& dropOff, const Vector2& distance, AlphaFunction function)
563 if( mDropOffDistance.LengthSquared() > Math::MACHINE_EPSILON_1 && mDropOff.LengthSquared() > Math::MACHINE_EPSILON_1 )
565 mFlags |= FlagDropOff;
567 mDropOffDistance = distance;
568 mDropOffFunction = function;
572 mFlags = mFlags & ~FlagDropOff;
574 // can no longer use default dop off
575 mFlags = mFlags & ~FlagDefaultDropOff;
578 void ScrollViewTwistEffect::OnAttach(Toolkit::ScrollView& scrollView)
580 // Create effect-time property if not already created.
581 if(mPropertyTime == Property::INVALID_INDEX)
583 mPropertyTime = SafeRegisterProperty( scrollView, EFFECT_TIME, 0.0f );
584 mPropertyReference = SafeRegisterProperty( scrollView, EFFECT_REFERENCE, Vector3::ZERO );
585 mPropertyDepth = SafeRegisterProperty( scrollView, EFFECT_DEPTH, 0.0f);
586 mPropertyActivate = SafeRegisterProperty(scrollView, EFFECT_ACTIVATE, 1.0f);
589 // Connect to the scroll view signals
590 scrollView.ScrollStartedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollStart);
591 scrollView.SnapStartedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollSnap);
592 scrollView.ScrollUpdatedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollUpdate);
593 scrollView.ScrollCompletedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollComplete);
595 AttachActor(scrollView);
598 void ScrollViewTwistEffect::OnDetach(Toolkit::ScrollView& scrollView)
600 scrollView.ScrollStartedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollStart);
601 scrollView.SnapStartedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollSnap);
602 scrollView.ScrollUpdatedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollUpdate);
603 scrollView.ScrollCompletedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollComplete);
607 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
613 void ScrollViewTwistEffect::AttachActor(Actor actor)
618 void ScrollViewTwistEffect::DetachActor(Actor actor)
620 // TODO: remove the specific constraint defined in AttachActor (and possibly
621 // unregister property) - neither functionality exists in Dali.
624 void ScrollViewTwistEffect::ContinueAnimation(float endTime)
626 // continue animating
629 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
633 Actor scrollView = GetScrollView();
635 mAnimation = Animation::New(TWISTEFFECT_ANIMATION_MAX_TIME);
636 mAnimation.AnimateTo( Property(scrollView, mPropertyTime), endTime, AlphaFunctions::Linear );
637 mAnimation.FinishedSignal().Connect(this, &ScrollViewTwistEffect::OnAnimationFinished);
641 void ScrollViewTwistEffect::OnScrollStart( const Vector3& position )
643 if(mActivateAnimation)
645 // if the animation after Scroll complete not terminate before another scroll action, stop the animation before start again
646 mActivateAnimation.Stop();
647 mActivateAnimation.Clear();
648 mActivateAnimation = NULL;
651 GetScrollView().SetProperty(mPropertyTime, 0.0f);
654 GetScrollView().SetProperty(mPropertyActivate, 1.0f);
658 GetScrollView().SetProperty(mPropertyActivate, 0.0f);
660 GetScrollView().SetProperty(mPropertyReference, position);
662 ContinueAnimation(TWISTEFFECT_ANIMATION_MAX_TIME);
665 void ScrollViewTwistEffect::OnScrollUpdate( const Vector3& position )
670 void ScrollViewTwistEffect::OnScrollComplete( const Vector3& position )
674 OnActivateAnimationFinished(mAnimation);
677 Actor scrollView = GetScrollView();
678 scrollView.SetProperty(mPropertyActivate, 1.0f);
679 mActivateAnimation = Animation::New(DELAY);
680 mActivateAnimation.AnimateTo( Property(scrollView, mPropertyActivate), 0.0f, AlphaFunctions::Linear);
681 mActivateAnimation.FinishedSignal().Connect(this, &ScrollViewTwistEffect::OnActivateAnimationFinished);
682 mActivateAnimation.Play();
685 void ScrollViewTwistEffect::OnScrollSnap( const Toolkit::ScrollView::SnapEvent& event )
687 // If a Flicking snap is occuring and the distance is more than mMinimumDistanceForShrink
688 // then animate depth effect i.e. shrink actors and then bring back in to regular size.
689 // NOTE: ScrollView Snap returns a value opposite of GetCurrentScrollPosition
690 // i.e. if you've "scrolled 100 pixels right" (so content on screen has shifted 100 pixels left)
691 // then GetCurrentScrollPosition returns a positive value (100.0f, 0.0f) (position of where you're
692 // look, not where content has been moved to).
693 // event.position returns a negative value (-100.0f, 0.0f)
694 // Would be a good idea to change SnapEvent in the API so it reflects GetCurrentScrollPosition.
695 // TODO: Change scroll-view API, check if anything uses SnapEvent and change them correspondingly
696 Vector3 targetScrollPosition(-event.position);
698 Vector3 delta = targetScrollPosition - GetScrollView().GetCurrentScrollPosition();
700 if(event.type==Flick && delta.Length() > mMinimumDistanceForShrink)
702 Actor scrollView = GetScrollView();
704 Animation animation = Animation::New(event.duration);
705 animation.AnimateTo( Property(scrollView, mPropertyDepth), 1.0f, HopEasing);
710 void ScrollViewTwistEffect::OnAnimationFinished( Animation& animation )
712 // still unstable, so continue animating.
713 // TODO: Requires an instability check to ensure time animation finishes when delay is
714 // less noticeable. i.e. all present scrollPositions are approx the same as mScrollPosition in constraints.
715 // best solution for this is to switch to a single history vector of scroll position, and compare if
716 // position has not deviated >= 0.5 pixel for the past 1 second.
717 float endTime = GetScrollView().GetProperty<float>(mPropertyTime) + TWISTEFFECT_ANIMATION_MAX_TIME;
718 ContinueAnimation(endTime);
721 void ScrollViewTwistEffect::OnActivateAnimationFinished( Animation& animation )
725 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
732 } // namespace Internal
734 } // namespace Toolkit