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,
183 const PropertyInput& activateProperty)
185 const Vector3& position = actorPositionProperty.GetVector3();
186 const Vector3& parentPosition = scrollablePositionProperty.GetVector3();
187 const Vector3& pageSize = pageSizeProperty.GetVector3();
188 const Vector2 overshoot(scrollOvershootXProperty.GetFloat(), scrollOvershootYProperty.GetFloat());
190 if(fabsf(overshoot.x) < Math::MACHINE_EPSILON_0 && fabsf(overshoot.y) < Math::MACHINE_EPSILON_0)
195 const float& activate = activateProperty.GetFloat();
197 if(activate < Math::MACHINE_EPSILON_0)
202 // get distance from centre of scrollable container
203 Vector2 distance = position.GetVectorXY() - parentPosition.GetVectorXY();
205 if( overshoot.x > 0.0f )
207 distance.x += pageSize.x * 0.5f;
211 distance.x -= pageSize.x * 0.5f;
213 distance.x = Clamp(fabsf(distance.x), 0.0f, mDropOffDistance.x);
215 if( overshoot.y > 0.0f )
217 distance.y += pageSize.y * 0.5f;
221 distance.y -= pageSize.y * 0.5f;
223 distance.y = Clamp(fabsf(distance.y), 0.0f, mDropOffDistance.y);
225 Vector2 angleMod = distance / mDropOffDistance;
228 angleMod.x = mDropOffFunction(angleMod.x);
229 angleMod.y = mDropOffFunction(angleMod.y);
231 angleMod = Vector2::ONE - (angleMod * mDropOff);
233 Vector2 angle = angleMod * mAngleSwing * overshoot;
235 Quaternion rotation = Quaternion(angle.x, Vector3::YAXIS) *
236 Quaternion(-angle.y, Vector3::XAXIS) *
242 const Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate.
243 const Vector2 mDropOff;
244 const Vector2 mDropOffDistance;
245 AlphaFunction mDropOffFunction;
249 * ScrollTwistRotationConstraint
251 * Rotate constraint adjusts the angle of the Actors
252 * based on actor's world-position relative to the middle of the screen.
253 * When at middle of screen Angles on X and Y Axes is 0.
254 * When one screen away from the middle Angle is 90 degrees (pi/2)
256 struct ScrollTwistRotationConstraint
259 * Constraint constructor
260 * @param[in] angleSwing The amount the Actor should revolve in radians
261 * for a given page worth of distance.
263 ScrollTwistRotationConstraint(const Vector2& angleSwing)
264 : mAngleSwing(angleSwing)
269 * @param[in] current The current orientation of this Actor
270 * @param[in] actorPositionProperty The actor's world-position property
271 * @param[in] scrollOvershootXProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_X_PROPERTY_NAME)
272 * @param[in] scrollOvershootYProperty The scroll-view's overshoot property (SCROLL_OVERSHOOT_Y_PROPERTY_NAME)
273 * @param[in] pageSizeProperty The size of the page. (scrollView SIZE)
274 * @return The new orientation of this Actor.
276 Quaternion operator()(const Quaternion& current,
277 const PropertyInput& scrollOvershootXProperty,
278 const PropertyInput& scrollOvershootYProperty,
279 const PropertyInput& activateProperty)
281 const Vector2 overshoot(scrollOvershootXProperty.GetFloat(), scrollOvershootYProperty.GetFloat());
283 if(fabsf(overshoot.x) < Math::MACHINE_EPSILON_0 && fabsf(overshoot.y) < Math::MACHINE_EPSILON_0)
288 const float& activate = activateProperty.GetFloat();
290 if(activate < Math::MACHINE_EPSILON_0)
295 Quaternion rotation = Quaternion(overshoot.x * mAngleSwing.x, Vector3::YAXIS) *
296 Quaternion(-overshoot.y * mAngleSwing.y, Vector3::XAXIS) *
302 const Vector2 mAngleSwing;
306 * ScrollTwistPositionConstraint
308 * Position constraint adjusts the position of the Actors
309 * based on their parent page's position relative to the middle of the screen.
310 * When at middle of the screen the position is not altered.
311 * When one screen away from middle the position is rotated about it's origin + mAnchor
313 struct ScrollTwistPositionConstraint
316 * Constraint constructor
318 ScrollTwistPositionConstraint(float delayMin, float delayMax)
319 : mDelayMin(delayMin),
321 mCurrentDelayFactor(0.0f)
326 * @param[in] current The current position
327 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
328 * @param[in] effectReferenceProperty The point in the scroll-view where the user touched the screen
329 * @param[in] effectTimeProperty The current timer. Starting from 0.0 when scroll animation/dragging
330 * commences. Ensures that constraint is applied and processed every frame (to achieve the delay effect)
331 * @param[in] sizeProperty The size of the ScrollView.
332 * @return The new position of this Actor.
334 Vector3 operator()(const Vector3& current,
335 const PropertyInput& pagePositionProperty,
336 const PropertyInput& scrollPositionProperty,
337 const PropertyInput& effectReferenceProperty,
338 const PropertyInput& effectTimeProperty,
339 const PropertyInput& sizeProperty,
340 const PropertyInput& activateProperty)
342 const Vector3& scrollPosition = scrollPositionProperty.GetVector3();
343 const float& activate = activateProperty.GetFloat();
345 if(activate < Math::MACHINE_EPSILON_0)
347 mScrollPosition = scrollPosition;
348 return current + mScrollPosition;
350 const Vector3& pagePosition = pagePositionProperty.GetVector3();
351 const Vector3& referencePoint = effectReferenceProperty.GetVector3();
352 // Determine the relative position of the actor from the scrolling reference point.
353 // (the further away from the refernce, the longer the delay should be)
354 Vector3 relativePosition = pagePosition + current - referencePoint;
355 float f = relativePosition.x;
357 // f represents this absolute distance. Get as a relative distance and inverse exponential
358 // (as delay equation is has an exponential effect i.e. the closer delayFactor to 1.0f,
359 // the longer the delay would appear exponentially)
360 f = fabsf(f / sizeProperty.GetVector3().width);
361 f = std::min(f, 1.0f);
362 f = 1.0f - (1.0f - f) * (1.0f - f);
363 // at center delay factor is mDelayMin, at maximum (1.0) it is mDelayMax
364 f = Rescale(f, 0.0f, 1.0f, mDelayMin, mDelayMax);
366 // Will take 0.25s for current delay factor to equal target delay factor
367 // This prevents users quickly dragging from different points and noticing a jerk.
368 mCurrentDelayFactor = Chase( mCurrentDelayFactor, f, 4.0f/60.0f );
369 float delay = activate * mCurrentDelayFactor;
370 mScrollPosition = mScrollPosition * delay + scrollPosition * (1.0f-delay);
372 return current + mScrollPosition;
377 Vector3 mScrollPosition; ///< The current scroll position
380 float mCurrentDelayFactor;
385 * ScrollTwistScaleConstraint
387 * Scale constraint adjusts the scale of the Actors
388 * based on a supplied depth property value.
390 struct ScrollTwistScaleConstraint
393 * Constraint constructor
395 ScrollTwistScaleConstraint(float scaleAmount)
396 : mScaleAmount(scaleAmount)
401 * @param[in] current The current position
402 * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME)
403 * @return The new position of this Actor.
405 Vector3 operator()(const Vector3& current,
406 const PropertyInput& depthProperty)
408 float depth = depthProperty.GetFloat();
410 return current * (1.0f - depth * mScaleAmount); // contract by mScaleAmount of original size.
418 } // unnamed namespace
429 ScrollViewTwistEffect::ScrollViewTwistEffect()
430 : mFlags(DefaultFlags),
431 mPropertyTime(Property::INVALID_INDEX),
433 mAdditionalEffects(false),
434 mPropertyReference(Property::INVALID_INDEX),
435 mPropertyActivate(Property::INVALID_INDEX),
436 mMinimumDistanceForShrink(Toolkit::ScrollViewTwistEffect::DEFAULT_MINIMUM_DISTANCE_FOR_SHRINK),
437 mMaxSwingAngle(Math::PI_2, Math::PI_2),
438 mDropOff(TWISTEFFECT_DEFAULT_DROPOFF, TWISTEFFECT_DEFAULT_DROPOFF),
439 mDropOffDistance(TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_X, TWISTEFFECT_DEFAULT_DROPOFF_DISTANCE_Y),
440 mDropOffFunction(NULL)
444 ScrollViewTwistEffect::~ScrollViewTwistEffect()
449 float ScrollViewTwistEffect::GetMinimumDistanceForShrink() const
451 return mMinimumDistanceForShrink;
454 void ScrollViewTwistEffect::SetMinimumDistanceForShrink(float distance)
456 mMinimumDistanceForShrink = distance;
459 void ScrollViewTwistEffect::EnableEffect(bool enableFlag)
461 mEnableEffect = enableFlag;
464 void ScrollViewTwistEffect::ApplyToActor(Actor child,
465 bool additionalEffects,
466 const Vector2& angleSwing,
471 mMaxSwingAngle = angleSwing;
472 mAdditionalEffects = additionalEffects;
473 mScaleFactor = scaleAmount;
474 mDelayMin = delayMin;
475 mDelayMax = delayMax;
476 if(mFlags & FlagDefaultDropOff)
478 Vector3 size = GetScrollView().GetCurrentSize();
479 // size may still be 0 if the effect is applied before scroll view hits the stage
480 if(size.x > Math::MACHINE_EPSILON_1)
482 mDropOffDistance.x = size.x;
484 if(size.y > Math::MACHINE_EPSILON_1)
486 mDropOffDistance.y = size.y;
489 if(scaleAmount > Math::MACHINE_EPSILON_0)
495 mFlags = mFlags & ~FlagScale;
497 if(mMaxSwingAngle.LengthSquared() > Math::MACHINE_EPSILON_0)
503 mFlags = mFlags & ~FlagTwist;
508 void ScrollViewTwistEffect::Apply(Actor child)
510 // Apply constraints to these actors //
511 Constraint constraint;
513 Toolkit::ScrollView scrollView = GetScrollView();
515 if( mFlags & FlagScale )
517 constraint = Constraint::New<Vector3>( Actor::SCALE,
518 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_DEPTH ) ),
519 ScrollTwistScaleConstraint(mScaleFactor) );
520 constraint.SetRemoveAction( Constraint::Discard );
521 child.ApplyConstraint( constraint );
524 constraint = Constraint::New<Vector3>( Actor::POSITION,
525 ParentSource(Actor::POSITION),
526 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
527 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_REFERENCE ) ),
528 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_TIME ) ),
529 Source(scrollView, Actor::SIZE),
530 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_ACTIVATE) ),
531 ScrollTwistPositionConstraint(mDelayMin, mDelayMax) );
532 constraint.SetRemoveAction( Constraint::Discard );
533 child.ApplyConstraint( constraint );
535 // use actor position to affect rotation
536 if(mFlags & FlagTwist)
538 if(mFlags & FlagDropOff)
540 constraint = Constraint::New<Quaternion>( Actor::ROTATION,
541 LocalSource(Actor::WORLD_POSITION),
542 Source(scrollView, Actor::WORLD_POSITION ),
543 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME ) ),
544 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME ) ),
545 Source(scrollView, Actor::SIZE ),
546 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_ACTIVATE) ),
547 ScrollDropoffTwistRotationConstraint(mMaxSwingAngle, mDropOff, mDropOffDistance, mDropOffFunction) );
551 constraint = Constraint::New<Quaternion>( Actor::ROTATION,
552 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME ) ),
553 Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME ) ),
554 Source(scrollView, scrollView.GetPropertyIndex( EFFECT_ACTIVATE) ),
555 ScrollTwistRotationConstraint(mMaxSwingAngle) );
557 constraint.SetRemoveAction( Constraint::Discard );
558 child.ApplyConstraint( constraint );
562 void ScrollViewTwistEffect::SetSwingDropOff(const Vector2& dropOff, const Vector2& distance, AlphaFunction function)
564 if( mDropOffDistance.LengthSquared() > Math::MACHINE_EPSILON_1 && mDropOff.LengthSquared() > Math::MACHINE_EPSILON_1 )
566 mFlags |= FlagDropOff;
568 mDropOffDistance = distance;
569 mDropOffFunction = function;
573 mFlags = mFlags & ~FlagDropOff;
575 // can no longer use default dop off
576 mFlags = mFlags & ~FlagDefaultDropOff;
579 void ScrollViewTwistEffect::OnAttach(Toolkit::ScrollView& scrollView)
581 // Create effect-time property if not already created.
582 if(mPropertyTime == Property::INVALID_INDEX)
584 mPropertyTime = SafeRegisterProperty( scrollView, EFFECT_TIME, 0.0f );
585 mPropertyReference = SafeRegisterProperty( scrollView, EFFECT_REFERENCE, Vector3::ZERO );
586 mPropertyDepth = SafeRegisterProperty( scrollView, EFFECT_DEPTH, 0.0f);
587 mPropertyActivate = SafeRegisterProperty(scrollView, EFFECT_ACTIVATE, 1.0f);
590 // Connect to the scroll view signals
591 scrollView.ScrollStartedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollStart);
592 scrollView.SnapStartedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollSnap);
593 scrollView.ScrollUpdatedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollUpdate);
594 scrollView.ScrollCompletedSignal().Connect(this, &ScrollViewTwistEffect::OnScrollComplete);
596 AttachActor(scrollView);
599 void ScrollViewTwistEffect::OnDetach(Toolkit::ScrollView& scrollView)
601 scrollView.ScrollStartedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollStart);
602 scrollView.SnapStartedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollSnap);
603 scrollView.ScrollUpdatedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollUpdate);
604 scrollView.ScrollCompletedSignal().Disconnect(this, &ScrollViewTwistEffect::OnScrollComplete);
608 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
614 void ScrollViewTwistEffect::AttachActor(Actor actor)
619 void ScrollViewTwistEffect::DetachActor(Actor actor)
621 // TODO: remove the specific constraint defined in AttachActor (and possibly
622 // unregister property) - neither functionality exists in Dali.
625 void ScrollViewTwistEffect::ContinueAnimation(float endTime)
627 // continue animating
630 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
634 Actor scrollView = GetScrollView();
636 mAnimation = Animation::New(TWISTEFFECT_ANIMATION_MAX_TIME);
637 mAnimation.AnimateTo( Property(scrollView, mPropertyTime), endTime, AlphaFunctions::Linear );
638 mAnimation.FinishedSignal().Connect(this, &ScrollViewTwistEffect::OnAnimationFinished);
642 void ScrollViewTwistEffect::OnScrollStart( const Vector3& position )
644 if(mActivateAnimation)
646 // if the animation after Scroll complete not terminate before another scroll action, stop the animation before start again
647 mActivateAnimation.Stop();
648 mActivateAnimation.Clear();
649 mActivateAnimation = NULL;
652 GetScrollView().SetProperty(mPropertyTime, 0.0f);
655 GetScrollView().SetProperty(mPropertyActivate, 1.0f);
659 GetScrollView().SetProperty(mPropertyActivate, 0.0f);
661 GetScrollView().SetProperty(mPropertyReference, position);
663 ContinueAnimation(TWISTEFFECT_ANIMATION_MAX_TIME);
666 void ScrollViewTwistEffect::OnScrollUpdate( const Vector3& position )
671 void ScrollViewTwistEffect::OnScrollComplete( const Vector3& position )
675 OnActivateAnimationFinished(mAnimation);
678 Actor scrollView = GetScrollView();
679 scrollView.SetProperty(mPropertyActivate, 1.0f);
680 mActivateAnimation = Animation::New(DELAY);
681 mActivateAnimation.AnimateTo( Property(scrollView, mPropertyActivate), 0.0f, AlphaFunctions::Linear);
682 mActivateAnimation.FinishedSignal().Connect(this, &ScrollViewTwistEffect::OnActivateAnimationFinished);
683 mActivateAnimation.Play();
686 void ScrollViewTwistEffect::OnScrollSnap( const Toolkit::ScrollView::SnapEvent& event )
688 // If a Flicking snap is occuring and the distance is more than mMinimumDistanceForShrink
689 // then animate depth effect i.e. shrink actors and then bring back in to regular size.
690 // NOTE: ScrollView Snap returns a value opposite of GetCurrentScrollPosition
691 // i.e. if you've "scrolled 100 pixels right" (so content on screen has shifted 100 pixels left)
692 // then GetCurrentScrollPosition returns a positive value (100.0f, 0.0f) (position of where you're
693 // look, not where content has been moved to).
694 // event.position returns a negative value (-100.0f, 0.0f)
695 // Would be a good idea to change SnapEvent in the API so it reflects GetCurrentScrollPosition.
696 // TODO: Change scroll-view API, check if anything uses SnapEvent and change them correspondingly
697 Vector3 targetScrollPosition(-event.position);
699 Vector3 delta = targetScrollPosition - GetScrollView().GetCurrentScrollPosition();
701 if(event.type==Flick && delta.Length() > mMinimumDistanceForShrink)
703 Actor scrollView = GetScrollView();
705 Animation animation = Animation::New(event.duration);
706 animation.AnimateTo( Property(scrollView, mPropertyDepth), 1.0f, HopEasing);
711 void ScrollViewTwistEffect::OnAnimationFinished( Animation& animation )
713 // still unstable, so continue animating.
714 // TODO: Requires an instability check to ensure time animation finishes when delay is
715 // less noticeable. i.e. all present scrollPositions are approx the same as mScrollPosition in constraints.
716 // best solution for this is to switch to a single history vector of scroll position, and compare if
717 // position has not deviated >= 0.5 pixel for the past 1 second.
718 float endTime = GetScrollView().GetProperty<float>(mPropertyTime) + TWISTEFFECT_ANIMATION_MAX_TIME;
719 ContinueAnimation(endTime);
722 void ScrollViewTwistEffect::OnActivateAnimationFinished( Animation& animation )
726 mAnimation.FinishedSignal().Disconnect(this, &ScrollViewTwistEffect::OnAnimationFinished);
733 } // namespace Internal
735 } // namespace Toolkit