3 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
20 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-twist-effect-impl.h>
24 namespace // unnamed namespace
27 const char * const EFFECT_TIME( "ScrollViewTwistEffect::EFFECT_TIME" );
28 const char * const EFFECT_REFERENCE( "ScrollViewTwistEffect::EFFECT_REFERENCE" );
29 const char * const EFFECT_DEPTH( "ScrollViewTwistEffect::EFFECT_DEPTH");
30 const char * const EFFECT_ACTIVATE( "ScrollViewTwistEffect::EFFECT_ACTIVATE");
32 const float TWISTEFFECT_ANIMATION_MAX_TIME = 60.0f; ///< Animation time (every time finishes, checks if it needs to go again)
33 const float TWISTEFFECT_DEFAULT_DROPOFF = 0.7f; ///< Default drop off amount
34 const float TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_X = 720.0f; ///< Default drop off distance
35 const float TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_Y = 1280.0f; ///< Default drop off distance
37 // Hop Easing equation.
38 // Starts with a -ve cosine ranging from 0 to pi.
40 // Then finishes with a -ve cosine ranging from pi to 0
41 // 0......(RISE).....PI (SUSTAIN) PI.....(FALL)......0
42 // xxxxxxxxxxxxxxxxxxxxx
51 const float HOP_RISE(0.25f);
52 const float HOP_FALL(0.5f);
53 const float DELAY(0.5f);
55 float HopEasing(float progress)
57 // progress from 0.0 - HOP_RISE (go from 0.0 to 1.0)
58 if(progress < HOP_RISE)
60 return 0.5f - cosf(progress/HOP_RISE * Math::PI) * 0.5f;
63 progress += HOP_FALL - 1.0f;
65 // progress from 0.0 - HOP_FALL (go from 1.0 to 0.0)
68 return 0.5f + cosf(progress/HOP_FALL * Math::PI) * 0.5f;
71 // progress at plateau.
76 * Gets a property index. If the property doesn't already exist, then
77 * it will create the property.
78 * @param[in] handle The handle that owns or will own the property
79 * @param[in] name The name for this property
80 * @param[in] propertyValue The initial value for this property
81 * @return The property index for this property is returned.
83 Property::Index SafeRegisterProperty( Handle& handle, const std::string& name, Property::Value propertyValue )
85 Property::Index index = handle.GetPropertyIndex( name );
87 if(index == Property::INVALID_INDEX)
89 index = handle.RegisterProperty( name, propertyValue );
96 * Re-scales input value x from x0 - x1, to linearly map
97 * over the values y0 - y1. Values outside of this range
98 * will also conform to the trend (gradient) set.
99 * @param[in] x input X value
100 * @param[in] x0 input minimum bound
101 * @param[in] x1 input maximum bound
102 * @param[in] y0 output minimum bound
103 * @param[in] y1 output maximum bound
104 * @return The result of the mapping is returned.
106 float Rescale(float x, float x0, float x1, float y0, float y1)
108 return y0 + (y1 - y0) * (x - x0) / (x1-x0);
112 * Returns the value of x chasing target.
113 * returns a value of x which is closer to target.
114 * but limited by maxDelta. #
119 * result is 30.0f (x is 20.0f units closer to target)
120 * However, if x is already within maxDelta units
121 * of target, x will equal target.
126 * result is 50.0f (x was already within 20.0f units of target)
128 float Chase( float x, float target, float maxDelta )
130 float delta = target - x;
134 x = std::min( x + maxDelta, target );
138 x = std::max( x - maxDelta, target );
144 // constraints ////////////////////////////////////////////////////////////////
147 * ScrollTwistRotationConstraint
149 * Rotate constraint adjusts the angle of the Actors
150 * based on actor's world-position relative to the middle of the screen.
151 * When at middle of screen Angles on X and Y Axes is 0.
152 * When one screen away from the middle Angle is 90 degrees (pi/2)
154 struct ScrollDropoffTwistRotationConstraint
157 * Constraint constructor
158 * @param[in] angleSwing The amount the Actor should revolve in radians
159 * for a given page worth of distance.
161 ScrollDropoffTwistRotationConstraint(const Vector2& angleSwing, const Vector2& dropOff, const Vector2& distance, AlphaFunction function)
162 : mAngleSwing(angleSwing),
164 mDropOffDistance(distance),
165 mDropOffFunction(function)
170 * @param[in] current The current orientation of this Actor
171 * @param[in] actorPositionProperty The actor's world-position property
172 * @param[in] scrollOvershootXProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_X_PROPERTY_NAME)
173 * @param[in] scrollOvershootYProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_Y_PROPERTY_NAME)
174 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
175 * @return The new orientation of this Actor.
177 Quaternion operator()(const Quaternion& current,
178 const PropertyInput& actorPositionProperty,
179 const PropertyInput& scrollablePositionProperty,
180 const PropertyInput& scrollOvershootXProperty,
181 const PropertyInput& scrollOvershootYProperty,
182 const PropertyInput& pageSizeProperty)
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 // get distance from centre of scrollable container
195 Vector2 distance = position.GetVectorXY() - parentPosition.GetVectorXY();
197 if( overshoot.x > 0.0f )
199 distance.x += pageSize.x * 0.5f;
203 distance.x -= pageSize.x * 0.5f;
205 distance.x = Clamp(fabsf(distance.x), 0.0f, mDropOffDistance.x);
207 if( overshoot.y > 0.0f )
209 distance.y += pageSize.y * 0.5f;
213 distance.y -= pageSize.y * 0.5f;
215 distance.y = Clamp(fabsf(distance.y), 0.0f, mDropOffDistance.y);
217 Vector2 angleMod = distance / mDropOffDistance;
220 angleMod.x = mDropOffFunction(angleMod.x);
221 angleMod.y = mDropOffFunction(angleMod.y);
223 angleMod = Vector2::ONE - (angleMod * mDropOff);
225 Vector2 angle = angleMod * mAngleSwing * overshoot;
227 Quaternion rotation = Quaternion(angle.x, Vector3::YAXIS) *
228 Quaternion(-angle.y, Vector3::XAXIS) *
234 const Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
235 const Vector2 mDropOff;
236 const Vector2 mDropOffDistance;
237 AlphaFunction mDropOffFunction;
241 * ScrollTwistRotationConstraint
243 * Rotate constraint adjusts the angle of the Actors
244 * based on actor's world-position relative to the middle of the screen.
245 * When at middle of screen Angles on X and Y Axes is 0.
246 * When one screen away from the middle Angle is 90 degrees (pi/2)
248 struct ScrollTwistRotationConstraint
251 * Constraint constructor
252 * @param[in] angleSwing The amount the Actor should revolve in radians
253 * for a given page worth of distance.
255 ScrollTwistRotationConstraint(const Vector2& angleSwing)
256 : mAngleSwing(angleSwing)
261 * @param[in] current The current orientation of this Actor
262 * @param[in] actorPositionProperty The actor's world-position property
263 * @param[in] scrollOvershootXProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_X_PROPERTY_NAME)
264 * @param[in] scrollOvershootYProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_Y_PROPERTY_NAME)
265 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
266 * @return The new orientation of this Actor.
268 Quaternion operator()(const Quaternion& current,
269 const PropertyInput& scrollOvershootXProperty,
270 const PropertyInput& scrollOvershootYProperty)
272 const Vector2 overshoot(scrollOvershootXProperty.GetFloat(), scrollOvershootYProperty.GetFloat());
274 if( fabsf(overshoot.x) < Math::MACHINE_EPSILON_0 && fabsf(overshoot.y) < Math::MACHINE_EPSILON_0 )
279 Quaternion rotation = Quaternion(overshoot.x * mAngleSwing.x, Vector3::YAXIS) *
280 Quaternion(-overshoot.y * mAngleSwing.y, Vector3::XAXIS) *
286 const Vector2 mAngleSwing;
290 * ScrollTwistPositionConstraint
292 * Position constraint adjusts the position of the Actors
293 * based on their parent page's position relative to the middle of the screen.
294 * When at middle of the screen the position is not altered.
295 * When one screen away from middle the position is rotated about it's origin + mAnchor
297 struct ScrollTwistPositionConstraint
300 * Constraint constructor
302 ScrollTwistPositionConstraint(float delayMin, float delayMax)
303 : mDelayMin(delayMin),
305 mCurrentDelayFactor(0.0f)
310 * @param[in] current The current position
311 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
312 * @param[in] effectReferenceProperty The point in the scroll-view where the user touched the screen
313 * @param[in] effectTimeProperty The current timer. Starting from 0.0 when scroll animation/dragging
314 * commences. Ensures that constraint is applied and processed every frame (to achieve the delay effect)
315 * @param[in] sizeProperty The size of the ScrollView.
316 * @return The new position of this Actor.
318 Vector3 operator()(const Vector3& current,
319 const PropertyInput& pagePositionProperty,
320 const PropertyInput& scrollPositionProperty,
321 const PropertyInput& effectReferenceProperty,
322 const PropertyInput& effectTimeProperty,
323 const PropertyInput& sizeProperty,
324 const PropertyInput& activateProperty)
326 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
327 const float& activate = activateProperty.GetFloat();
329 if(activate < Math::MACHINE_EPSILON_0)
331 mScrollPosition = scrollPosition;
332 return current + mScrollPosition;
334 const Vector3& pagePosition = pagePositionProperty.GetVector3();
335 const Vector3& referencePoint = effectReferenceProperty.GetVector3();
336 // Determine the relative position of the actor from the scrolling reference point.
337 // (the further away from the refernce, the longer the delay should be)
338 Vector3 relativePosition = pagePosition + current - referencePoint;
339 float f = relativePosition.x;
341 // f represents this absolute distance. Get as a relative distance and inverse exponential
342 // (as delay equation is has an exponential effect i.e. the closer delayFactor to 1.0f,
343 // the longer the delay would appear exponentially)
344 f = fabsf(f / sizeProperty.GetVector3().width);
345 f = std::min(f, 1.0f);
346 f = 1.0f - (1.0f - f) * (1.0f - f);
347 // at center delay factor is mDelayMin, at maximum (1.0) it is mDelayMax
348 f = Rescale(f, 0.0f, 1.0f, mDelayMin, mDelayMax);
350 // Will take 0.25s for current delay factor to equal target delay factor
351 // This prevents users quickly dragging from different points and noticing a jerk.
352 mCurrentDelayFactor = Chase( mCurrentDelayFactor, f, 4.0f/60.0f );
353 float delay = activate * mCurrentDelayFactor;
354 mScrollPosition = mScrollPosition * delay + scrollPosition * (1.0f-delay);
356 return current + mScrollPosition;
361 Vector3 mScrollPosition; ///< The current scroll position
364 float mCurrentDelayFactor;
369 * ScrollTwistScaleConstraint
371 * Scale constraint adjusts the scale of the Actors
372 * based on a supplied depth property value.
374 struct ScrollTwistScaleConstraint
377 * Constraint constructor
379 ScrollTwistScaleConstraint(float scaleAmount)
380 : mScaleAmount(scaleAmount)
385 * @param[in] current The current position
386 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
387 * @return The new position of this Actor.
389 Vector3 operator()(const Vector3& current,
390 const PropertyInput& depthProperty)
392 float depth = depthProperty.GetFloat();
394 return current * (1.0f - depth * mScaleAmount); // contract by mScaleAmount of original size.
402 } // unnamed namespace
413 ScrollViewTwistEffect::ScrollViewTwistEffect()
414 : mFlags(DefaultFlags),
415 mPropertyTime(Property::INVALID_INDEX),
417 mAdditionalEffects(false),
418 mPropertyReference(Property::INVALID_INDEX),
419 mPropertyActivate(Property::INVALID_INDEX),
420 mMinimumDistanceForShrink(Toolkit::ScrollViewTwistEffect::DEFAULT_MINIMUM_DISTANCE_FOR_SHRINK),
421 mMaxSwingAngle(Math::PI_2, Math::PI_2),
422 mDropOff(TWISTEFFECT_DEFAULT_DROPOFF, TWISTEFFECT_DEFAULT_DROPOFF),
423 mDropOffDistance(TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_X, TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_Y),
424 mDropOffFunction(NULL)
428 ScrollViewTwistEffect::~ScrollViewTwistEffect()
433 float ScrollViewTwistEffect::GetMinimumDistanceForShrink() const
435 return mMinimumDistanceForShrink;
438 void ScrollViewTwistEffect::SetMinimumDistanceForShrink(float distance)
440 mMinimumDistanceForShrink = distance;
443 void ScrollViewTwistEffect::EnableEffect(bool enableFlag)
445 mEnableEffect = enableFlag;
448 void ScrollViewTwistEffect::ApplyToActor(Actor child,
449 bool additionalEffects,
450 const Vector2& angleSwing,
455 mMaxSwingAngle = angleSwing;
456 mAdditionalEffects = additionalEffects;
457 mScaleFactor = scaleAmount;
458 mDelayMin = delayMin;
459 mDelayMax = delayMax;
460 if(mFlags & FlagDefaultDropOff)
462 Vector3 size = GetScrollView().GetCurrentSize();
463 // size may still be 0 if the effect is applied before scroll view hits the stage
464 if(size.x > Math::MACHINE_EPSILON_1)
466 mDropOffDistance.x = size.x;
468 if(size.y > Math::MACHINE_EPSILON_1)
470 mDropOffDistance.y = size.y;
473 if(scaleAmount > Math::MACHINE_EPSILON_0)
479 mFlags = mFlags & ~FlagScale;
481 if(mMaxSwingAngle.LengthSquared() > Math::MACHINE_EPSILON_0)
487 mFlags = mFlags & ~FlagTwist;
492 void ScrollViewTwistEffect::Apply(Actor child)
494 // Apply constraints to these actors //
495 Constraint constraint;
497 Toolkit::ScrollView scrollView = GetScrollView();
499 if( mFlags & FlagScale )
501 constraint = Constraint::New<Vector3>( Actor::SCALE,
502 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_DEPTH ) ),
503 ScrollTwistScaleConstraint(mScaleFactor) );
504 constraint.SetRemoveAction( Constraint::Discard );
505 child.ApplyConstraint( constraint );
508 constraint = Constraint::New<Vector3>( Actor::POSITION,
509 ParentSource(Actor::POSITION),
510 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
511 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_REFERENCE ) ),
512 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_TIME ) ),
513 Source(scrollView, Actor::SIZE),
514 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_ACTIVATE) ),
515 ScrollTwistPositionConstraint(mDelayMin, mDelayMax) );
516 constraint.SetRemoveAction( Constraint::Discard );
517 child.ApplyConstraint( constraint );
519 // use actor position to affect rotation
520 if(mFlags & FlagTwist)
522 if(mFlags & FlagDropOff)
524 constraint = Constraint::New<Quaternion>( Actor::ROTATION,
525 LocalSource(Actor::WORLD_POSITION),
526 Source(scrollView, Actor::WORLD_POSITION ),
527 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME ) ),
528 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME ) ),
529 Source(scrollView, Actor::SIZE ),
530 ScrollDropoffTwistRotationConstraint(mMaxSwingAngle, mDropOff, mDropOffDistance, mDropOffFunction) );
534 constraint = Constraint::New<Quaternion>( Actor::ROTATION,
535 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME ) ),
536 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME ) ),
537 ScrollTwistRotationConstraint(mMaxSwingAngle) );
539 constraint.SetRemoveAction( Constraint::Discard );
540 child.ApplyConstraint( constraint );
544 void ScrollViewTwistEffect::SetMaxSwingAngle(const Vector2& maxSwingAngle)
546 mMaxSwingAngle = maxSwingAngle;
549 Vector2 ScrollViewTwistEffect::GetMaxSwingAngle() const
551 return mMaxSwingAngle;
554 void ScrollViewTwistEffect::SetSwingDropOff(const Vector2& dropOff, const Vector2& distance, AlphaFunction function)
556 if( distance.LengthSquared() > Math::MACHINE_EPSILON_1 && dropOff.LengthSquared() > Math::MACHINE_EPSILON_1 )
558 mFlags |= FlagDropOff;
560 mDropOffDistance = distance;
561 mDropOffFunction = function;
565 mFlags = mFlags & ~FlagDropOff;
567 // can no longer use default dop off
568 mFlags = mFlags & ~FlagDefaultDropOff;
571 void ScrollViewTwistEffect::GetSwingDropOff( Vector2& dropOff, Vector2& distance, AlphaFunction& function ) const
574 distance = mDropOffDistance;
575 function = mDropOffFunction;
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, 0.0f);
588 // currently cant change overshoot snap back duration, use the constant one from ScrollView
589 mActivationTime = Toolkit::ScrollView::DEFAULT_SNAP_OVERSHOOT_DURATION;
591 // Connect to the scroll view signals
592 scrollView.ScrollStartedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollStart);
593 scrollView.SnapStartedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollSnap);
594 scrollView.ScrollUpdatedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollUpdate);
595 scrollView.ScrollCompletedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollComplete);
597 AttachActor(scrollView);
600 void ScrollViewTwistEffect::OnDetach(Toolkit::ScrollView& scrollView)
602 scrollView.ScrollStartedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollStart);
603 scrollView.SnapStartedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollSnap);
604 scrollView.ScrollUpdatedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollUpdate);
605 scrollView.ScrollCompletedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollComplete);
609 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
615 void ScrollViewTwistEffect::AttachActor(Actor actor)
620 void ScrollViewTwistEffect::DetachActor(Actor actor)
622 // TODO: remove the specific constraint defined in AttachActor (and possibly
623 // unregister property) - neither functionality exists in Dali.
626 void ScrollViewTwistEffect::ContinueAnimation(float endTime)
628 // continue animating
631 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
635 Actor scrollView = GetScrollView();
637 mAnimation = Animation::New(TWISTEFFECT_ANIMATION_MAX_TIME);
638 mAnimation.AnimateTo( Property(scrollView, mPropertyTime), endTime, AlphaFunctions::Linear );
639 mAnimation.FinishedSignal().Connect(this, &ScrollViewTwistEffect::OnAnimationFinished);
643 void ScrollViewTwistEffect::OnScrollStart( const Vector3& position )
645 if(mActivateAnimation)
647 // if the animation after Scroll complete not terminate before another scroll action, stop the animation before start again
648 mActivateAnimation.Stop();
649 mActivateAnimation.Clear();
650 mActivateAnimation = NULL;
653 GetScrollView().SetProperty(mPropertyTime, 0.0f);
656 GetScrollView().SetProperty(mPropertyActivate, 1.0f);
660 GetScrollView().SetProperty(mPropertyActivate, 0.0f);
662 GetScrollView().SetProperty(mPropertyReference, position);
664 ContinueAnimation(TWISTEFFECT_ANIMATION_MAX_TIME);
667 void ScrollViewTwistEffect::OnScrollUpdate( const Vector3& position )
672 void ScrollViewTwistEffect::OnScrollComplete( const Vector3& position )
676 OnActivateAnimationFinished(mAnimation);
679 Actor scrollView = GetScrollView();
680 scrollView.SetProperty(mPropertyActivate, 1.0f);
681 mActivateAnimation = Animation::New(mActivationTime);
682 mActivateAnimation.AnimateTo( Property(scrollView, mPropertyActivate), 0.0f, AlphaFunctions::Linear);
683 mActivateAnimation.FinishedSignal().Connect(this, &ScrollViewTwistEffect::OnActivateAnimationFinished);
684 mActivateAnimation.Play();
687 void ScrollViewTwistEffect::OnScrollSnap( const Toolkit::ScrollView::SnapEvent& event )
689 // If a Flicking snap is occuring and the distance is more than mMinimumDistanceForShrink
690 // then animate depth effect i.e. shrink actors and then bring back in to regular size.
691 // NOTE: ScrollView Snap returns a value opposite of GetCurrentScrollPosition
692 // i.e. if you've "scrolled 100 pixels right" (so content on screen has shifted 100 pixels left)
693 // then GetCurrentScrollPosition returns a positive value (100.0f, 0.0f) (position of where you're
694 // look, not where content has been moved to).
695 // event.position returns a negative value (-100.0f, 0.0f)
696 // Would be a good idea to change SnapEvent in the API so it reflects GetCurrentScrollPosition.
697 // TODO: Change scroll-view API, check if anything uses SnapEvent and change them correspondingly
698 Vector3 targetScrollPosition(-event.position);
700 Vector3 delta = targetScrollPosition - GetScrollView().GetCurrentScrollPosition();
702 if(event.type==Flick && delta.Length() > mMinimumDistanceForShrink)
704 Actor scrollView = GetScrollView();
706 Animation animation = Animation::New(event.duration);
707 animation.AnimateTo( Property(scrollView, mPropertyDepth), 1.0f, HopEasing);
712 void ScrollViewTwistEffect::OnAnimationFinished( Animation& animation )
714 // still unstable, so continue animating.
715 // TODO: Requires an instability check to ensure time animation finishes when delay is
716 // less noticeable. i.e. all present scrollPositions are approx the same as mScrollPosition in constraints.
717 // best solution for this is to switch to a single history vector of scroll position, and compare if
718 // position has not deviated >= 0.5 pixel for the past 1 second.
719 float endTime = GetScrollView().GetProperty<float>(mPropertyTime) + TWISTEFFECT_ANIMATION_MAX_TIME;
720 ContinueAnimation(endTime);
723 void ScrollViewTwistEffect::OnActivateAnimationFinished( Animation& animation )
727 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
734 } // namespace Internal
736 } // namespace Toolkit